19391bb9cSRapkiewicz, Pawel /* 29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 39391bb9cSRapkiewicz, Pawel // 49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License. 69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at 79391bb9cSRapkiewicz, Pawel // 89391bb9cSRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 99391bb9cSRapkiewicz, Pawel // 109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and 149391bb9cSRapkiewicz, Pawel // limitations under the License. 159391bb9cSRapkiewicz, Pawel */ 169391bb9cSRapkiewicz, Pawel #pragma once 179391bb9cSRapkiewicz, Pawel 183ccb3adbSEd Tanous #include "app.hpp" 193ccb3adbSEd Tanous #include "dbus_singleton.hpp" 207a1dbc48SGeorge Liu #include "dbus_utility.hpp" 213ccb3adbSEd Tanous #include "error_messages.hpp" 222c5875a2SEd Tanous #include "human_sort.hpp" 233ccb3adbSEd Tanous #include "query.hpp" 243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 25033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 263ccb3adbSEd Tanous #include "utils/json_utils.hpp" 27033f1e4dSEd Tanous 28ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp> 29ef4c65b7SEd Tanous #include <boost/url/format.hpp> 301214b7e7SGunnar Mills 317a1dbc48SGeorge Liu #include <array> 323dfed536SEd Tanous #include <cstddef> 33ce73d5c8SSunitha Harish #include <memory> 34a24526dcSEd Tanous #include <optional> 353544d2a7SEd Tanous #include <ranges> 36ab6554f1SJoshi-Mansi #include <regex> 377a1dbc48SGeorge Liu #include <string_view> 383dfed536SEd Tanous #include <variant> 3977179532SEd Tanous #include <vector> 409391bb9cSRapkiewicz, Pawel 411abe55efSEd Tanous namespace redfish 421abe55efSEd Tanous { 439391bb9cSRapkiewicz, Pawel 444a0cb85cSEd Tanous enum class LinkType 454a0cb85cSEd Tanous { 464a0cb85cSEd Tanous Local, 474a0cb85cSEd Tanous Global 484a0cb85cSEd Tanous }; 499391bb9cSRapkiewicz, Pawel 50743eb1c0SJohnathan Mantey enum class IpVersion 51743eb1c0SJohnathan Mantey { 52743eb1c0SJohnathan Mantey IpV4, 53743eb1c0SJohnathan Mantey IpV6 54743eb1c0SJohnathan Mantey }; 55743eb1c0SJohnathan Mantey 569391bb9cSRapkiewicz, Pawel /** 579391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 589391bb9cSRapkiewicz, Pawel */ 591abe55efSEd Tanous struct IPv4AddressData 601abe55efSEd Tanous { 61179db1d7SKowalski, Kamil std::string id; 624a0cb85cSEd Tanous std::string address; 634a0cb85cSEd Tanous std::string domain; 644a0cb85cSEd Tanous std::string gateway; 659391bb9cSRapkiewicz, Pawel std::string netmask; 669391bb9cSRapkiewicz, Pawel std::string origin; 6777179532SEd Tanous LinkType linktype{}; 6877179532SEd Tanous bool isActive{}; 699391bb9cSRapkiewicz, Pawel }; 709391bb9cSRapkiewicz, Pawel 719391bb9cSRapkiewicz, Pawel /** 72e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 73e48c0fc5SRavi Teja */ 74e48c0fc5SRavi Teja struct IPv6AddressData 75e48c0fc5SRavi Teja { 76e48c0fc5SRavi Teja std::string id; 77e48c0fc5SRavi Teja std::string address; 78e48c0fc5SRavi Teja std::string origin; 7977179532SEd Tanous uint8_t prefixLength = 0; 80e48c0fc5SRavi Teja }; 81ce73d5c8SSunitha Harish 82ce73d5c8SSunitha Harish /** 83ce73d5c8SSunitha Harish * Structure for keeping static route data required by Redfish 84ce73d5c8SSunitha Harish */ 85ce73d5c8SSunitha Harish struct StaticGatewayData 86ce73d5c8SSunitha Harish { 87ce73d5c8SSunitha Harish std::string id; 88ce73d5c8SSunitha Harish std::string gateway; 89ce73d5c8SSunitha Harish size_t prefixLength = 0; 90ce73d5c8SSunitha Harish std::string protocol; 91ce73d5c8SSunitha Harish }; 92ce73d5c8SSunitha Harish 93e48c0fc5SRavi Teja /** 949391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 959391bb9cSRapkiewicz, Pawel * available from DBus 969391bb9cSRapkiewicz, Pawel */ 971abe55efSEd Tanous struct EthernetInterfaceData 981abe55efSEd Tanous { 994a0cb85cSEd Tanous uint32_t speed; 10035fb5311STejas Patil size_t mtuSize; 10182695a5bSJiaqing Zhao bool autoNeg; 102e4588158SJishnu CM bool dnsv4Enabled; 103e4588158SJishnu CM bool dnsv6Enabled; 10491c441ecSRavi Teja bool domainv4Enabled; 10591c441ecSRavi Teja bool domainv6Enabled; 106e4588158SJishnu CM bool ntpv4Enabled; 107e4588158SJishnu CM bool ntpv6Enabled; 108e4588158SJishnu CM bool hostNamev4Enabled; 109e4588158SJishnu CM bool hostNamev6Enabled; 110aa05fb27SJohnathan Mantey bool linkUp; 111eeedda23SJohnathan Mantey bool nicEnabled; 112b10d8db0SRavi Teja bool ipv6AcceptRa; 11382695a5bSJiaqing Zhao std::string dhcpEnabled; 1141f8c7b5dSJohnathan Mantey std::string operatingMode; 11582695a5bSJiaqing Zhao std::string hostName; 11682695a5bSJiaqing Zhao std::string defaultGateway; 11782695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 118ce73d5c8SSunitha Harish std::string ipv6StaticDefaultGateway; 11982695a5bSJiaqing Zhao std::string macAddress; 12017e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 1210f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 1220f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 123d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1249391bb9cSRapkiewicz, Pawel }; 1259391bb9cSRapkiewicz, Pawel 1261f8c7b5dSJohnathan Mantey struct DHCPParameters 1271f8c7b5dSJohnathan Mantey { 1281f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 12982695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 13082695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 13182695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1321f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1331f8c7b5dSJohnathan Mantey }; 1341f8c7b5dSJohnathan Mantey 1359391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1369391bb9cSRapkiewicz, Pawel // into full dot notation 1371abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1381abe55efSEd Tanous { 1399391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1409391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1419391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1429391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1439391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1449391bb9cSRapkiewicz, Pawel return netmask; 1459391bb9cSRapkiewicz, Pawel } 1469391bb9cSRapkiewicz, Pawel 14782695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1481f8c7b5dSJohnathan Mantey bool isIPv4) 1491f8c7b5dSJohnathan Mantey { 1501f8c7b5dSJohnathan Mantey if (isIPv4) 1511f8c7b5dSJohnathan Mantey { 1521f8c7b5dSJohnathan Mantey return ( 1531f8c7b5dSJohnathan Mantey (inputDHCP == 1541f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1551f8c7b5dSJohnathan Mantey (inputDHCP == 1561f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1571f8c7b5dSJohnathan Mantey } 1581f8c7b5dSJohnathan Mantey return ((inputDHCP == 1591f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1601f8c7b5dSJohnathan Mantey (inputDHCP == 1611f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1621f8c7b5dSJohnathan Mantey } 1631f8c7b5dSJohnathan Mantey 1642c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1651f8c7b5dSJohnathan Mantey { 1661f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1671f8c7b5dSJohnathan Mantey { 1681f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1691f8c7b5dSJohnathan Mantey } 1703174e4dfSEd Tanous if (isIPv4) 1711f8c7b5dSJohnathan Mantey { 1721f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1731f8c7b5dSJohnathan Mantey } 1743174e4dfSEd Tanous if (isIPv6) 1751f8c7b5dSJohnathan Mantey { 1761f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1771f8c7b5dSJohnathan Mantey } 1781f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1791f8c7b5dSJohnathan Mantey } 1801f8c7b5dSJohnathan Mantey 1814a0cb85cSEd Tanous inline std::string 1824a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string& inputOrigin, 1834a0cb85cSEd Tanous bool isIPv4) 1841abe55efSEd Tanous { 1854a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1861abe55efSEd Tanous { 1874a0cb85cSEd Tanous return "Static"; 1889391bb9cSRapkiewicz, Pawel } 1894a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1901abe55efSEd Tanous { 1914a0cb85cSEd Tanous if (isIPv4) 1921abe55efSEd Tanous { 1934a0cb85cSEd Tanous return "IPv4LinkLocal"; 1941abe55efSEd Tanous } 1954a0cb85cSEd Tanous return "LinkLocal"; 1969391bb9cSRapkiewicz, Pawel } 1974a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1981abe55efSEd Tanous { 1994a0cb85cSEd Tanous if (isIPv4) 2004a0cb85cSEd Tanous { 2014a0cb85cSEd Tanous return "DHCP"; 2024a0cb85cSEd Tanous } 2034a0cb85cSEd Tanous return "DHCPv6"; 2044a0cb85cSEd Tanous } 2054a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 2064a0cb85cSEd Tanous { 2074a0cb85cSEd Tanous return "SLAAC"; 2084a0cb85cSEd Tanous } 2094a0cb85cSEd Tanous return ""; 2104a0cb85cSEd Tanous } 2114a0cb85cSEd Tanous 21202cad96eSEd Tanous inline bool extractEthernetInterfaceData( 21302cad96eSEd Tanous const std::string& ethifaceId, 21402cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 2154a0cb85cSEd Tanous EthernetInterfaceData& ethData) 2164a0cb85cSEd Tanous { 2174c9afe43SEd Tanous bool idFound = false; 21802cad96eSEd Tanous for (const auto& objpath : dbusData) 2194a0cb85cSEd Tanous { 22002cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 2214a0cb85cSEd Tanous { 22281ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 223029573d4SEd Tanous { 2244c9afe43SEd Tanous idFound = true; 2254a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2264a0cb85cSEd Tanous { 2274a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2284a0cb85cSEd Tanous { 2294a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2304a0cb85cSEd Tanous { 2314a0cb85cSEd Tanous const std::string* mac = 232abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2334a0cb85cSEd Tanous if (mac != nullptr) 2344a0cb85cSEd Tanous { 23582695a5bSJiaqing Zhao ethData.macAddress = *mac; 2364a0cb85cSEd Tanous } 2374a0cb85cSEd Tanous } 2384a0cb85cSEd Tanous } 2394a0cb85cSEd Tanous } 2404a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2414a0cb85cSEd Tanous { 2424a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2434a0cb85cSEd Tanous { 2444a0cb85cSEd Tanous if (propertyPair.first == "Id") 2454a0cb85cSEd Tanous { 2461b6b96c5SEd Tanous const uint32_t* id = 247abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2484a0cb85cSEd Tanous if (id != nullptr) 2494a0cb85cSEd Tanous { 25017e22024SJiaqing Zhao ethData.vlanId = *id; 2514a0cb85cSEd Tanous } 2524a0cb85cSEd Tanous } 2534a0cb85cSEd Tanous } 2544a0cb85cSEd Tanous } 2554a0cb85cSEd Tanous else if (ifacePair.first == 2564a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2574a0cb85cSEd Tanous { 2584a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2594a0cb85cSEd Tanous { 2604a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2614a0cb85cSEd Tanous { 2622c70f800SEd Tanous const bool* autoNeg = 263abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2642c70f800SEd Tanous if (autoNeg != nullptr) 2654a0cb85cSEd Tanous { 26682695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2674a0cb85cSEd Tanous } 2684a0cb85cSEd Tanous } 2694a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2704a0cb85cSEd Tanous { 2714a0cb85cSEd Tanous const uint32_t* speed = 272abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2734a0cb85cSEd Tanous if (speed != nullptr) 2744a0cb85cSEd Tanous { 2754a0cb85cSEd Tanous ethData.speed = *speed; 2764a0cb85cSEd Tanous } 2774a0cb85cSEd Tanous } 27835fb5311STejas Patil else if (propertyPair.first == "MTU") 27935fb5311STejas Patil { 2803e7a8da6SAnthony const size_t* mtuSize = 2813e7a8da6SAnthony std::get_if<size_t>(&propertyPair.second); 28235fb5311STejas Patil if (mtuSize != nullptr) 28335fb5311STejas Patil { 28435fb5311STejas Patil ethData.mtuSize = *mtuSize; 28535fb5311STejas Patil } 28635fb5311STejas Patil } 287aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 288aa05fb27SJohnathan Mantey { 289aa05fb27SJohnathan Mantey const bool* linkUp = 290aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 291aa05fb27SJohnathan Mantey if (linkUp != nullptr) 292aa05fb27SJohnathan Mantey { 293aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 294aa05fb27SJohnathan Mantey } 295aa05fb27SJohnathan Mantey } 296eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 297eeedda23SJohnathan Mantey { 298eeedda23SJohnathan Mantey const bool* nicEnabled = 299eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 300eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 301eeedda23SJohnathan Mantey { 302eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 303eeedda23SJohnathan Mantey } 304eeedda23SJohnathan Mantey } 305b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 306b10d8db0SRavi Teja { 307b10d8db0SRavi Teja const bool* ipv6AcceptRa = 308b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 309b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 310b10d8db0SRavi Teja { 311b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 312b10d8db0SRavi Teja } 313b10d8db0SRavi Teja } 314f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 315029573d4SEd Tanous { 316029573d4SEd Tanous const std::vector<std::string>* nameservers = 3178d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 318029573d4SEd Tanous &propertyPair.second); 319029573d4SEd Tanous if (nameservers != nullptr) 320029573d4SEd Tanous { 321f23b7296SEd Tanous ethData.nameServers = *nameservers; 3220f6efdc1Smanojkiran.eda@gmail.com } 3230f6efdc1Smanojkiran.eda@gmail.com } 3240f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3250f6efdc1Smanojkiran.eda@gmail.com { 3260f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3278d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3280f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3290f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3300f6efdc1Smanojkiran.eda@gmail.com { 331f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3324a0cb85cSEd Tanous } 3334a0cb85cSEd Tanous } 3342a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3352a133282Smanojkiraneda { 3362c70f800SEd Tanous const std::string* dhcpEnabled = 3371f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3382c70f800SEd Tanous if (dhcpEnabled != nullptr) 3392a133282Smanojkiraneda { 34082695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3412a133282Smanojkiraneda } 3422a133282Smanojkiraneda } 343d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 344d24bfc7aSJennifer Lee { 345d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3468d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 347d24bfc7aSJennifer Lee &propertyPair.second); 348d24bfc7aSJennifer Lee if (domainNames != nullptr) 349d24bfc7aSJennifer Lee { 350f23b7296SEd Tanous ethData.domainnames = *domainNames; 351d24bfc7aSJennifer Lee } 352d24bfc7aSJennifer Lee } 3539010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3549010ec2eSRavi Teja { 3559010ec2eSRavi Teja const std::string* defaultGateway = 3569010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3579010ec2eSRavi Teja if (defaultGateway != nullptr) 3589010ec2eSRavi Teja { 3599010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3609010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3619010ec2eSRavi Teja { 36282695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3639010ec2eSRavi Teja } 3649010ec2eSRavi Teja else 3659010ec2eSRavi Teja { 36682695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3679010ec2eSRavi Teja } 3689010ec2eSRavi Teja } 3699010ec2eSRavi Teja } 3709010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3719010ec2eSRavi Teja { 3729010ec2eSRavi Teja const std::string* defaultGateway6 = 3739010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3749010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3759010ec2eSRavi Teja { 3769010ec2eSRavi Teja std::string defaultGateway6Str = 3779010ec2eSRavi Teja *defaultGateway6; 3789010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3799010ec2eSRavi Teja { 38082695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3819010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3829010ec2eSRavi Teja } 3839010ec2eSRavi Teja else 3849010ec2eSRavi Teja { 38582695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3869010ec2eSRavi Teja defaultGateway6Str; 3879010ec2eSRavi Teja } 3889010ec2eSRavi Teja } 3899010ec2eSRavi Teja } 390029573d4SEd Tanous } 391029573d4SEd Tanous } 392029573d4SEd Tanous } 3931f8c7b5dSJohnathan Mantey 394e4588158SJishnu CM sdbusplus::message::object_path path( 395e4588158SJishnu CM "/xyz/openbmc_project/network"); 396e4588158SJishnu CM sdbusplus::message::object_path dhcp4Path = path / ethifaceId / 397e4588158SJishnu CM "dhcp4"; 398e4588158SJishnu CM 399e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp4Path) 4001f8c7b5dSJohnathan Mantey { 4011f8c7b5dSJohnathan Mantey if (ifacePair.first == 4021f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 4031f8c7b5dSJohnathan Mantey { 4041f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 4051f8c7b5dSJohnathan Mantey { 4061f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 4071f8c7b5dSJohnathan Mantey { 4082c70f800SEd Tanous const bool* dnsEnabled = 4091f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4102c70f800SEd Tanous if (dnsEnabled != nullptr) 4111f8c7b5dSJohnathan Mantey { 412e4588158SJishnu CM ethData.dnsv4Enabled = *dnsEnabled; 4131f8c7b5dSJohnathan Mantey } 4141f8c7b5dSJohnathan Mantey } 41591c441ecSRavi Teja else if (propertyPair.first == "DomainEnabled") 41691c441ecSRavi Teja { 41791c441ecSRavi Teja const bool* domainEnabled = 41891c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 41991c441ecSRavi Teja if (domainEnabled != nullptr) 42091c441ecSRavi Teja { 42191c441ecSRavi Teja ethData.domainv4Enabled = *domainEnabled; 42291c441ecSRavi Teja } 42391c441ecSRavi Teja } 4241f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 4251f8c7b5dSJohnathan Mantey { 4262c70f800SEd Tanous const bool* ntpEnabled = 4271f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4282c70f800SEd Tanous if (ntpEnabled != nullptr) 4291f8c7b5dSJohnathan Mantey { 430e4588158SJishnu CM ethData.ntpv4Enabled = *ntpEnabled; 4311f8c7b5dSJohnathan Mantey } 4321f8c7b5dSJohnathan Mantey } 4331f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 4341f8c7b5dSJohnathan Mantey { 4352c70f800SEd Tanous const bool* hostNameEnabled = 4361f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4372c70f800SEd Tanous if (hostNameEnabled != nullptr) 4381f8c7b5dSJohnathan Mantey { 439e4588158SJishnu CM ethData.hostNamev4Enabled = *hostNameEnabled; 440e4588158SJishnu CM } 441e4588158SJishnu CM } 442e4588158SJishnu CM } 443e4588158SJishnu CM } 444e4588158SJishnu CM } 445e4588158SJishnu CM 446e4588158SJishnu CM sdbusplus::message::object_path dhcp6Path = path / ethifaceId / 447e4588158SJishnu CM "dhcp6"; 448e4588158SJishnu CM 449e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp6Path) 450e4588158SJishnu CM { 451e4588158SJishnu CM if (ifacePair.first == 452e4588158SJishnu CM "xyz.openbmc_project.Network.DHCPConfiguration") 453e4588158SJishnu CM { 454e4588158SJishnu CM for (const auto& propertyPair : ifacePair.second) 455e4588158SJishnu CM { 456e4588158SJishnu CM if (propertyPair.first == "DNSEnabled") 457e4588158SJishnu CM { 458e4588158SJishnu CM const bool* dnsEnabled = 459e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 460e4588158SJishnu CM if (dnsEnabled != nullptr) 461e4588158SJishnu CM { 462e4588158SJishnu CM ethData.dnsv6Enabled = *dnsEnabled; 463e4588158SJishnu CM } 464e4588158SJishnu CM } 46591c441ecSRavi Teja if (propertyPair.first == "DomainEnabled") 46691c441ecSRavi Teja { 46791c441ecSRavi Teja const bool* domainEnabled = 46891c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 46991c441ecSRavi Teja if (domainEnabled != nullptr) 47091c441ecSRavi Teja { 47191c441ecSRavi Teja ethData.domainv6Enabled = *domainEnabled; 47291c441ecSRavi Teja } 47391c441ecSRavi Teja } 474e4588158SJishnu CM else if (propertyPair.first == "NTPEnabled") 475e4588158SJishnu CM { 476e4588158SJishnu CM const bool* ntpEnabled = 477e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 478e4588158SJishnu CM if (ntpEnabled != nullptr) 479e4588158SJishnu CM { 480e4588158SJishnu CM ethData.ntpv6Enabled = *ntpEnabled; 481e4588158SJishnu CM } 482e4588158SJishnu CM } 483e4588158SJishnu CM else if (propertyPair.first == "HostNameEnabled") 484e4588158SJishnu CM { 485e4588158SJishnu CM const bool* hostNameEnabled = 486e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 487e4588158SJishnu CM if (hostNameEnabled != nullptr) 488e4588158SJishnu CM { 489e4588158SJishnu CM ethData.hostNamev6Enabled = *hostNameEnabled; 4901f8c7b5dSJohnathan Mantey } 4911f8c7b5dSJohnathan Mantey } 4921f8c7b5dSJohnathan Mantey } 4931f8c7b5dSJohnathan Mantey } 4941f8c7b5dSJohnathan Mantey } 495029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 496029573d4SEd Tanous // to check eth number 497029573d4SEd Tanous if (ifacePair.first == 4984a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 4994a0cb85cSEd Tanous { 5004a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 5014a0cb85cSEd Tanous { 5024a0cb85cSEd Tanous if (propertyPair.first == "HostName") 5034a0cb85cSEd Tanous { 5044a0cb85cSEd Tanous const std::string* hostname = 5058d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 5064a0cb85cSEd Tanous if (hostname != nullptr) 5074a0cb85cSEd Tanous { 50882695a5bSJiaqing Zhao ethData.hostName = *hostname; 5094a0cb85cSEd Tanous } 5104a0cb85cSEd Tanous } 5114a0cb85cSEd Tanous } 5124a0cb85cSEd Tanous } 5134a0cb85cSEd Tanous } 5144a0cb85cSEd Tanous } 5154c9afe43SEd Tanous return idFound; 5164a0cb85cSEd Tanous } 5174a0cb85cSEd Tanous 518e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 51977179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 520711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 52177179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 522e48c0fc5SRavi Teja { 52389492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 52489492a15SPatrick Williams ethifaceId; 525e48c0fc5SRavi Teja 526e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 527e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 52881ce609eSEd Tanous for (const auto& objpath : dbusData) 529e48c0fc5SRavi Teja { 530e48c0fc5SRavi Teja // Check if proper pattern for object path appears 531353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 532e48c0fc5SRavi Teja { 5339eb808c1SEd Tanous for (const auto& interface : objpath.second) 534e48c0fc5SRavi Teja { 535e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 536e48c0fc5SRavi Teja { 5373544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 538353163e9STony Lee [](const auto& property) { 539353163e9STony Lee return property.first == "Type"; 540353163e9STony Lee }); 541353163e9STony Lee if (type == interface.second.end()) 542353163e9STony Lee { 543353163e9STony Lee continue; 544353163e9STony Lee } 545353163e9STony Lee 546353163e9STony Lee const std::string* typeStr = 547353163e9STony Lee std::get_if<std::string>(&type->second); 548353163e9STony Lee 549353163e9STony Lee if (typeStr == nullptr || 550353163e9STony Lee (*typeStr != 551353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 552353163e9STony Lee { 553353163e9STony Lee continue; 554353163e9STony Lee } 555353163e9STony Lee 556e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 557e48c0fc5SRavi Teja // appropriate 55877179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 5592c70f800SEd Tanous ipv6Address.id = 560353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5619eb808c1SEd Tanous for (const auto& property : interface.second) 562e48c0fc5SRavi Teja { 563e48c0fc5SRavi Teja if (property.first == "Address") 564e48c0fc5SRavi Teja { 565e48c0fc5SRavi Teja const std::string* address = 566e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 567e48c0fc5SRavi Teja if (address != nullptr) 568e48c0fc5SRavi Teja { 5692c70f800SEd Tanous ipv6Address.address = *address; 570e48c0fc5SRavi Teja } 571e48c0fc5SRavi Teja } 572e48c0fc5SRavi Teja else if (property.first == "Origin") 573e48c0fc5SRavi Teja { 574e48c0fc5SRavi Teja const std::string* origin = 575e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 576e48c0fc5SRavi Teja if (origin != nullptr) 577e48c0fc5SRavi Teja { 5782c70f800SEd Tanous ipv6Address.origin = 579e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 580e48c0fc5SRavi Teja false); 581e48c0fc5SRavi Teja } 582e48c0fc5SRavi Teja } 583e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 584e48c0fc5SRavi Teja { 585e48c0fc5SRavi Teja const uint8_t* prefix = 586e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 587e48c0fc5SRavi Teja if (prefix != nullptr) 588e48c0fc5SRavi Teja { 5892c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 590e48c0fc5SRavi Teja } 591e48c0fc5SRavi Teja } 592889ff694SAsmitha Karunanithi else if (property.first == "Type" || 593889ff694SAsmitha Karunanithi property.first == "Gateway") 594889ff694SAsmitha Karunanithi { 595889ff694SAsmitha Karunanithi // Type & Gateway is not used 596889ff694SAsmitha Karunanithi } 597e48c0fc5SRavi Teja else 598e48c0fc5SRavi Teja { 59962598e31SEd Tanous BMCWEB_LOG_ERROR( 60062598e31SEd Tanous "Got extra property: {} on the {} object", 60162598e31SEd Tanous property.first, objpath.first.str); 602e48c0fc5SRavi Teja } 603e48c0fc5SRavi Teja } 604e48c0fc5SRavi Teja } 605e48c0fc5SRavi Teja } 606e48c0fc5SRavi Teja } 607e48c0fc5SRavi Teja } 608e48c0fc5SRavi Teja } 609e48c0fc5SRavi Teja 6104a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 61177179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 612711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 61377179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 6144a0cb85cSEd Tanous { 61589492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 61689492a15SPatrick Williams ethifaceId; 6174a0cb85cSEd Tanous 6184a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 6194a0cb85cSEd Tanous // single ethernet interface, loop over all of them 62081ce609eSEd Tanous for (const auto& objpath : dbusData) 6214a0cb85cSEd Tanous { 6224a0cb85cSEd Tanous // Check if proper pattern for object path appears 623353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 6244a0cb85cSEd Tanous { 6259eb808c1SEd Tanous for (const auto& interface : objpath.second) 6264a0cb85cSEd Tanous { 6274a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 6284a0cb85cSEd Tanous { 6293544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 630353163e9STony Lee [](const auto& property) { 631353163e9STony Lee return property.first == "Type"; 632353163e9STony Lee }); 633353163e9STony Lee if (type == interface.second.end()) 634353163e9STony Lee { 635353163e9STony Lee continue; 636353163e9STony Lee } 637353163e9STony Lee 638353163e9STony Lee const std::string* typeStr = 639353163e9STony Lee std::get_if<std::string>(&type->second); 640353163e9STony Lee 641353163e9STony Lee if (typeStr == nullptr || 642353163e9STony Lee (*typeStr != 643353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 644353163e9STony Lee { 645353163e9STony Lee continue; 646353163e9STony Lee } 647353163e9STony Lee 6484a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 6494a0cb85cSEd Tanous // appropriate 65077179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 6512c70f800SEd Tanous ipv4Address.id = 652353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 6539eb808c1SEd Tanous for (const auto& property : interface.second) 6544a0cb85cSEd Tanous { 6554a0cb85cSEd Tanous if (property.first == "Address") 6564a0cb85cSEd Tanous { 6574a0cb85cSEd Tanous const std::string* address = 658abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6594a0cb85cSEd Tanous if (address != nullptr) 6604a0cb85cSEd Tanous { 6612c70f800SEd Tanous ipv4Address.address = *address; 6624a0cb85cSEd Tanous } 6634a0cb85cSEd Tanous } 6644a0cb85cSEd Tanous else if (property.first == "Origin") 6654a0cb85cSEd Tanous { 6664a0cb85cSEd Tanous const std::string* origin = 667abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6684a0cb85cSEd Tanous if (origin != nullptr) 6694a0cb85cSEd Tanous { 6702c70f800SEd Tanous ipv4Address.origin = 6714a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 6724a0cb85cSEd Tanous true); 6734a0cb85cSEd Tanous } 6744a0cb85cSEd Tanous } 6754a0cb85cSEd Tanous else if (property.first == "PrefixLength") 6764a0cb85cSEd Tanous { 6774a0cb85cSEd Tanous const uint8_t* mask = 678abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 6794a0cb85cSEd Tanous if (mask != nullptr) 6804a0cb85cSEd Tanous { 6814a0cb85cSEd Tanous // convert it to the string 6822c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 6834a0cb85cSEd Tanous } 6844a0cb85cSEd Tanous } 685889ff694SAsmitha Karunanithi else if (property.first == "Type" || 686889ff694SAsmitha Karunanithi property.first == "Gateway") 687889ff694SAsmitha Karunanithi { 688889ff694SAsmitha Karunanithi // Type & Gateway is not used 689889ff694SAsmitha Karunanithi } 6904a0cb85cSEd Tanous else 6914a0cb85cSEd Tanous { 69262598e31SEd Tanous BMCWEB_LOG_ERROR( 69362598e31SEd Tanous "Got extra property: {} on the {} object", 69462598e31SEd Tanous property.first, objpath.first.str); 6954a0cb85cSEd Tanous } 6964a0cb85cSEd Tanous } 6974a0cb85cSEd Tanous // Check if given address is local, or global 6982c70f800SEd Tanous ipv4Address.linktype = 69911ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 70018659d10SJohnathan Mantey ? LinkType::Local 70118659d10SJohnathan Mantey : LinkType::Global; 7024a0cb85cSEd Tanous } 7034a0cb85cSEd Tanous } 7044a0cb85cSEd Tanous } 7054a0cb85cSEd Tanous } 7064a0cb85cSEd Tanous } 707588c3f0dSKowalski, Kamil 708588c3f0dSKowalski, Kamil /** 709743eb1c0SJohnathan Mantey * @brief Modifies the default gateway assigned to the NIC 710743eb1c0SJohnathan Mantey * 711743eb1c0SJohnathan Mantey * @param[in] ifaceId Id of network interface whose default gateway is to be 712743eb1c0SJohnathan Mantey * changed 713743eb1c0SJohnathan Mantey * @param[in] gateway The new gateway value. Assigning an empty string 714743eb1c0SJohnathan Mantey * causes the gateway to be deleted 715743eb1c0SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 716743eb1c0SJohnathan Mantey * 717743eb1c0SJohnathan Mantey * @return None 718743eb1c0SJohnathan Mantey */ 719743eb1c0SJohnathan Mantey inline void updateIPv4DefaultGateway( 720743eb1c0SJohnathan Mantey const std::string& ifaceId, const std::string& gateway, 721743eb1c0SJohnathan Mantey const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 722743eb1c0SJohnathan Mantey { 723743eb1c0SJohnathan Mantey setDbusProperty( 724743eb1c0SJohnathan Mantey asyncResp, "xyz.openbmc_project.Network", 725743eb1c0SJohnathan Mantey sdbusplus::message::object_path("/xyz/openbmc_project/network") / 726743eb1c0SJohnathan Mantey ifaceId, 727743eb1c0SJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 728743eb1c0SJohnathan Mantey "Gateway", gateway); 729743eb1c0SJohnathan Mantey } 730743eb1c0SJohnathan Mantey 731743eb1c0SJohnathan Mantey /** 732743eb1c0SJohnathan Mantey * @brief Deletes given static IP address for the interface 733179db1d7SKowalski, Kamil * 734179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 735179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 736179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 737179db1d7SKowalski, Kamil * 738179db1d7SKowalski, Kamil * @return None 739179db1d7SKowalski, Kamil */ 7409c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 7419c5e585cSRavi Teja const std::string& ipHash, 7428d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7431abe55efSEd Tanous { 74455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7455e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 7461abe55efSEd Tanous if (ec) 7471abe55efSEd Tanous { 748a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7491abe55efSEd Tanous } 750179db1d7SKowalski, Kamil }, 751179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 7529c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 753179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 754179db1d7SKowalski, Kamil } 755179db1d7SKowalski, Kamil 756179db1d7SKowalski, Kamil /** 75701784826SJohnathan Mantey * @brief Creates a static IPv4 entry 758179db1d7SKowalski, Kamil * 75901784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 76001784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 76101784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 76201784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 763179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 764179db1d7SKowalski, Kamil * 765179db1d7SKowalski, Kamil * @return None 766179db1d7SKowalski, Kamil */ 767cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 768cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7698d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7701abe55efSEd Tanous { 7715a39f77aSPatrick Williams auto createIpHandler = [asyncResp, ifaceId, 7725a39f77aSPatrick Williams gateway](const boost::system::error_code& ec) { 7731abe55efSEd Tanous if (ec) 7741abe55efSEd Tanous { 775a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7769010ec2eSRavi Teja return; 777179db1d7SKowalski, Kamil } 7789010ec2eSRavi Teja }; 7799010ec2eSRavi Teja 7809010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 7819010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 782179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 783179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 78401784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 785179db1d7SKowalski, Kamil gateway); 786179db1d7SKowalski, Kamil } 787e48c0fc5SRavi Teja 788e48c0fc5SRavi Teja /** 789743eb1c0SJohnathan Mantey * @brief Deletes the IP entry for this interface and creates a replacement 790743eb1c0SJohnathan Mantey * static entry 79101784826SJohnathan Mantey * 79201784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 79301784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 794743eb1c0SJohnathan Mantey * @param[in] prefixLength Prefix syntax for the subnet mask 795743eb1c0SJohnathan Mantey * @param[in] address Address to assign to this interface 796743eb1c0SJohnathan Mantey * @param[in] numStaticAddrs Count of IPv4 static addresses 79701784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 79801784826SJohnathan Mantey * 79901784826SJohnathan Mantey * @return None 80001784826SJohnathan Mantey */ 8019c5e585cSRavi Teja 8029c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 8039c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 8048d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 8059c5e585cSRavi Teja const std::string& gateway, 8068d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 80701784826SJohnathan Mantey { 80801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8099c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 8109c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 81101784826SJohnathan Mantey if (ec) 81201784826SJohnathan Mantey { 81301784826SJohnathan Mantey messages::internalError(asyncResp->res); 81401784826SJohnathan Mantey } 8159c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 8169c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 81701784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8185e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 81923a21a1cSEd Tanous if (ec2) 82001784826SJohnathan Mantey { 82101784826SJohnathan Mantey messages::internalError(asyncResp->res); 82201784826SJohnathan Mantey } 82301784826SJohnathan Mantey }, 82401784826SJohnathan Mantey "xyz.openbmc_project.Network", 82501784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 8269c5e585cSRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address, 8279c5e585cSRavi Teja prefixLength, gateway); 82801784826SJohnathan Mantey }, 82901784826SJohnathan Mantey "xyz.openbmc_project.Network", 8309c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 83101784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 83201784826SJohnathan Mantey } 83301784826SJohnathan Mantey 834ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData( 835ce73d5c8SSunitha Harish const std::string& ethifaceId, 836ce73d5c8SSunitha Harish const dbus::utility::ManagedObjectType& dbusData, 837ce73d5c8SSunitha Harish std::vector<StaticGatewayData>& staticGatewayConfig) 838ce73d5c8SSunitha Harish { 839ce73d5c8SSunitha Harish std::string staticGatewayPathStart("/xyz/openbmc_project/network/"); 840ce73d5c8SSunitha Harish staticGatewayPathStart += ethifaceId; 841ce73d5c8SSunitha Harish 842ce73d5c8SSunitha Harish for (const auto& objpath : dbusData) 843ce73d5c8SSunitha Harish { 844ce73d5c8SSunitha Harish if (!std::string_view(objpath.first.str) 845ce73d5c8SSunitha Harish .starts_with(staticGatewayPathStart)) 846ce73d5c8SSunitha Harish { 847ce73d5c8SSunitha Harish continue; 848ce73d5c8SSunitha Harish } 849ce73d5c8SSunitha Harish for (const auto& interface : objpath.second) 850ce73d5c8SSunitha Harish { 851ce73d5c8SSunitha Harish if (interface.first != "xyz.openbmc_project.Network.StaticGateway") 852ce73d5c8SSunitha Harish { 853ce73d5c8SSunitha Harish continue; 854ce73d5c8SSunitha Harish } 855ce73d5c8SSunitha Harish StaticGatewayData& staticGateway = 856ce73d5c8SSunitha Harish staticGatewayConfig.emplace_back(); 857ce73d5c8SSunitha Harish staticGateway.id = objpath.first.filename(); 858ce73d5c8SSunitha Harish 859ce73d5c8SSunitha Harish bool success = sdbusplus::unpackPropertiesNoThrow( 860ce73d5c8SSunitha Harish redfish::dbus_utils::UnpackErrorPrinter(), interface.second, 861ce73d5c8SSunitha Harish "Gateway", staticGateway.gateway, "PrefixLength", 862ce73d5c8SSunitha Harish staticGateway.prefixLength, "ProtocolType", 863ce73d5c8SSunitha Harish staticGateway.protocol); 864ce73d5c8SSunitha Harish if (!success) 865ce73d5c8SSunitha Harish { 866ce73d5c8SSunitha Harish return false; 867ce73d5c8SSunitha Harish } 868ce73d5c8SSunitha Harish } 869ce73d5c8SSunitha Harish } 870ce73d5c8SSunitha Harish return true; 871ce73d5c8SSunitha Harish } 872ce73d5c8SSunitha Harish 87301784826SJohnathan Mantey /** 874e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 875e48c0fc5SRavi Teja * 876e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 877e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 878e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 879e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 880e48c0fc5SRavi Teja * 881e48c0fc5SRavi Teja * @return None 882e48c0fc5SRavi Teja */ 88301784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 88401784826SJohnathan Mantey const std::string& address, 8858d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 886e48c0fc5SRavi Teja { 887ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 888ce73d5c8SSunitha Harish path /= ifaceId; 889ce73d5c8SSunitha Harish 8905a39f77aSPatrick Williams auto createIpHandler = [asyncResp, 8915a39f77aSPatrick Williams address](const boost::system::error_code& ec) { 892e48c0fc5SRavi Teja if (ec) 893e48c0fc5SRavi Teja { 894fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 895fc23ef8aSNitin Kumar Kotania { 896fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 897fc23ef8aSNitin Kumar Kotania "Address"); 898fc23ef8aSNitin Kumar Kotania } 899fc23ef8aSNitin Kumar Kotania else 900fc23ef8aSNitin Kumar Kotania { 901e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 902e48c0fc5SRavi Teja } 903fc23ef8aSNitin Kumar Kotania } 904e48c0fc5SRavi Teja }; 905ce73d5c8SSunitha Harish // Passing null for gateway, as per redfish spec IPv6StaticAddresses 906ce73d5c8SSunitha Harish // object does not have associated gateway property 907e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 908ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 909e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 910e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 911e48c0fc5SRavi Teja ""); 912e48c0fc5SRavi Teja } 913e48c0fc5SRavi Teja 914179db1d7SKowalski, Kamil /** 915ce73d5c8SSunitha Harish * @brief Deletes given IPv6 Static Gateway 916ce73d5c8SSunitha Harish * 917ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be deleted 918ce73d5c8SSunitha Harish * @param[in] ipHash DBus Hash id of IP that should be deleted 919ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 920ce73d5c8SSunitha Harish * 921ce73d5c8SSunitha Harish * @return None 922ce73d5c8SSunitha Harish */ 923ce73d5c8SSunitha Harish inline void 924ce73d5c8SSunitha Harish deleteIPv6Gateway(std::string_view gatewayId, 925ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 926ce73d5c8SSunitha Harish { 927ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 928ce73d5c8SSunitha Harish path /= gatewayId; 929ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 930ce73d5c8SSunitha Harish [asyncResp](const boost::system::error_code& ec) { 931ce73d5c8SSunitha Harish if (ec) 932ce73d5c8SSunitha Harish { 933ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 934ce73d5c8SSunitha Harish } 935ce73d5c8SSunitha Harish }, 936ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 937ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 938ce73d5c8SSunitha Harish } 939ce73d5c8SSunitha Harish 940ce73d5c8SSunitha Harish /** 941ce73d5c8SSunitha Harish * @brief Creates IPv6 static default gateway with given data 942ce73d5c8SSunitha Harish * 943ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be added 944ce73d5c8SSunitha Harish * @param[in] prefixLength Prefix length that needs to be added 945ce73d5c8SSunitha Harish * @param[in] gateway Gateway address that needs to be added 946ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 947ce73d5c8SSunitha Harish * 948ce73d5c8SSunitha Harish * @return None 949ce73d5c8SSunitha Harish */ 950ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway( 951ce73d5c8SSunitha Harish std::string_view ifaceId, size_t prefixLength, std::string_view gateway, 952ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 953ce73d5c8SSunitha Harish { 954ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 955ce73d5c8SSunitha Harish path /= ifaceId; 956ce73d5c8SSunitha Harish auto createIpHandler = [asyncResp](const boost::system::error_code& ec) { 957ce73d5c8SSunitha Harish if (ec) 958ce73d5c8SSunitha Harish { 959ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 960ce73d5c8SSunitha Harish } 961ce73d5c8SSunitha Harish }; 962ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 963ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 964ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway", 965ce73d5c8SSunitha Harish gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6"); 966ce73d5c8SSunitha Harish } 967ce73d5c8SSunitha Harish 968ce73d5c8SSunitha Harish /** 969ce73d5c8SSunitha Harish * @brief Deletes the IPv6 default gateway entry for this interface and 970ce73d5c8SSunitha Harish * creates a replacement IPv6 default gateway entry 971ce73d5c8SSunitha Harish * 972ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface upon which to create the IPv6 973ce73d5c8SSunitha Harish * entry 974ce73d5c8SSunitha Harish * @param[in] gateway IPv6 gateway to assign to this interface 975ce73d5c8SSunitha Harish * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 976ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 977ce73d5c8SSunitha Harish * 978ce73d5c8SSunitha Harish * @return None 979ce73d5c8SSunitha Harish */ 980ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway( 981ce73d5c8SSunitha Harish std::string_view ifaceId, std::string_view gatewayId, 982ce73d5c8SSunitha Harish std::string_view gateway, size_t prefixLength, 983ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 984ce73d5c8SSunitha Harish { 985ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 986ce73d5c8SSunitha Harish path /= gatewayId; 987ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 988ce73d5c8SSunitha Harish [asyncResp, ifaceId, gateway, 989ce73d5c8SSunitha Harish prefixLength](const boost::system::error_code& ec) { 990ce73d5c8SSunitha Harish if (ec) 991ce73d5c8SSunitha Harish { 992ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 993ce73d5c8SSunitha Harish return; 994ce73d5c8SSunitha Harish } 995ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp); 996ce73d5c8SSunitha Harish }, 997ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 998ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 999ce73d5c8SSunitha Harish } 1000ce73d5c8SSunitha Harish 1001ce73d5c8SSunitha Harish /** 1002ce73d5c8SSunitha Harish * @brief Sets IPv6 default gateway with given data 1003ce73d5c8SSunitha Harish * 1004ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose gateway should be added 1005ce73d5c8SSunitha Harish * @param[in] input Contains address that needs to be added 1006ce73d5c8SSunitha Harish * @param[in] staticGatewayData Current static gateways in the system 1007ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 1008ce73d5c8SSunitha Harish * 1009ce73d5c8SSunitha Harish * @return None 1010ce73d5c8SSunitha Harish */ 1011ce73d5c8SSunitha Harish 1012ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway( 10133dfed536SEd Tanous const std::string& ifaceId, 10143dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1015ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& staticGatewayData, 1016ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1017ce73d5c8SSunitha Harish { 1018ce73d5c8SSunitha Harish size_t entryIdx = 1; 1019ce73d5c8SSunitha Harish std::vector<StaticGatewayData>::const_iterator staticGatewayEntry = 1020ce73d5c8SSunitha Harish staticGatewayData.begin(); 1021ce73d5c8SSunitha Harish 10223dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 10233dfed536SEd Tanous input) 1024ce73d5c8SSunitha Harish { 1025ce73d5c8SSunitha Harish // find the next gateway entry 1026ce73d5c8SSunitha Harish while (staticGatewayEntry != staticGatewayData.end()) 1027ce73d5c8SSunitha Harish { 1028ce73d5c8SSunitha Harish if (staticGatewayEntry->protocol == 1029ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.IP.Protocol.IPv6") 1030ce73d5c8SSunitha Harish { 1031ce73d5c8SSunitha Harish break; 1032ce73d5c8SSunitha Harish } 1033ce73d5c8SSunitha Harish staticGatewayEntry++; 1034ce73d5c8SSunitha Harish } 1035ce73d5c8SSunitha Harish std::string pathString = "IPv6StaticDefaultGateways/" + 1036ce73d5c8SSunitha Harish std::to_string(entryIdx); 10373dfed536SEd Tanous nlohmann::json::object_t* obj = 10383dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 10393dfed536SEd Tanous if (obj == nullptr) 1040ce73d5c8SSunitha Harish { 1041ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1042ce73d5c8SSunitha Harish { 1043ce73d5c8SSunitha Harish messages::resourceCannotBeDeleted(asyncResp->res); 1044ce73d5c8SSunitha Harish return; 1045ce73d5c8SSunitha Harish } 1046ce73d5c8SSunitha Harish deleteIPv6Gateway(staticGatewayEntry->id, asyncResp); 1047ce73d5c8SSunitha Harish return; 1048ce73d5c8SSunitha Harish } 10493dfed536SEd Tanous if (obj->empty()) 1050ce73d5c8SSunitha Harish { 1051ce73d5c8SSunitha Harish // Do nothing, but make sure the entry exists. 1052ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1053ce73d5c8SSunitha Harish { 10543dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 1055ce73d5c8SSunitha Harish pathString); 1056ce73d5c8SSunitha Harish return; 1057ce73d5c8SSunitha Harish } 1058ce73d5c8SSunitha Harish } 1059ce73d5c8SSunitha Harish std::optional<std::string> address; 1060ce73d5c8SSunitha Harish std::optional<size_t> prefixLength; 1061ce73d5c8SSunitha Harish 10623dfed536SEd Tanous if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address, 10633dfed536SEd Tanous "PrefixLength", prefixLength)) 1064ce73d5c8SSunitha Harish { 1065ce73d5c8SSunitha Harish return; 1066ce73d5c8SSunitha Harish } 1067ce73d5c8SSunitha Harish const std::string* addr = nullptr; 1068ce73d5c8SSunitha Harish size_t prefix = 0; 1069ce73d5c8SSunitha Harish if (address) 1070ce73d5c8SSunitha Harish { 1071ce73d5c8SSunitha Harish addr = &(*address); 1072ce73d5c8SSunitha Harish } 1073ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1074ce73d5c8SSunitha Harish { 1075ce73d5c8SSunitha Harish addr = &(staticGatewayEntry->gateway); 1076ce73d5c8SSunitha Harish } 1077ce73d5c8SSunitha Harish else 1078ce73d5c8SSunitha Harish { 1079ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, pathString + "/Address"); 1080ce73d5c8SSunitha Harish return; 1081ce73d5c8SSunitha Harish } 1082ce73d5c8SSunitha Harish if (prefixLength) 1083ce73d5c8SSunitha Harish { 1084ce73d5c8SSunitha Harish prefix = *prefixLength; 1085ce73d5c8SSunitha Harish } 1086ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1087ce73d5c8SSunitha Harish { 1088ce73d5c8SSunitha Harish prefix = staticGatewayEntry->prefixLength; 1089ce73d5c8SSunitha Harish } 1090ce73d5c8SSunitha Harish else 1091ce73d5c8SSunitha Harish { 1092ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, 1093ce73d5c8SSunitha Harish pathString + "/PrefixLength"); 1094ce73d5c8SSunitha Harish return; 1095ce73d5c8SSunitha Harish } 1096ce73d5c8SSunitha Harish if (staticGatewayEntry != staticGatewayData.end()) 1097ce73d5c8SSunitha Harish { 1098ce73d5c8SSunitha Harish deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id, 1099ce73d5c8SSunitha Harish *addr, prefix, asyncResp); 1100ce73d5c8SSunitha Harish staticGatewayEntry++; 1101ce73d5c8SSunitha Harish } 1102ce73d5c8SSunitha Harish else 1103ce73d5c8SSunitha Harish { 1104ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp); 1105ce73d5c8SSunitha Harish } 1106ce73d5c8SSunitha Harish entryIdx++; 1107ce73d5c8SSunitha Harish } 1108ce73d5c8SSunitha Harish } 1109ce73d5c8SSunitha Harish 1110ce73d5c8SSunitha Harish /** 1111179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 1112179db1d7SKowalski, Kamil * Object 1113179db1d7SKowalski, Kamil * from EntityManager Network Manager 11144a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 1115179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 1116179db1d7SKowalski, Kamil * into JSON 1117179db1d7SKowalski, Kamil */ 1118179db1d7SKowalski, Kamil template <typename CallbackFunc> 111981ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 11201abe55efSEd Tanous CallbackFunc&& callback) 11211abe55efSEd Tanous { 1122f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1123f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1124f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1125f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 11268cb2c024SEd Tanous callback = std::forward<CallbackFunc>(callback)]( 11278b24275dSEd Tanous const boost::system::error_code& ec, 11283dfed536SEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 112955c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 113077179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 113177179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 1132ce73d5c8SSunitha Harish std::vector<StaticGatewayData> ipv6GatewayData; 1133179db1d7SKowalski, Kamil 11348b24275dSEd Tanous if (ec) 11351abe55efSEd Tanous { 1136ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1137179db1d7SKowalski, Kamil return; 1138179db1d7SKowalski, Kamil } 1139179db1d7SKowalski, Kamil 1140002d39b4SEd Tanous bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); 11414c9afe43SEd Tanous if (!found) 11424c9afe43SEd Tanous { 1143ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 11444c9afe43SEd Tanous return; 11454c9afe43SEd Tanous } 11464c9afe43SEd Tanous 11472c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 1148179db1d7SKowalski, Kamil // Fix global GW 11491abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 11501abe55efSEd Tanous { 1151c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 1152c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 11539010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 11541abe55efSEd Tanous { 115582695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 1156179db1d7SKowalski, Kamil } 1157179db1d7SKowalski, Kamil } 1158179db1d7SKowalski, Kamil 11592c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 1160ce73d5c8SSunitha Harish if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData)) 1161ce73d5c8SSunitha Harish { 1162ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1163ce73d5c8SSunitha Harish } 11644e0453b1SGunnar Mills // Finally make a callback with useful data 1165ce73d5c8SSunitha Harish callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1166f5892d0dSGeorge Liu }); 1167271584abSEd Tanous } 1168179db1d7SKowalski, Kamil 1169179db1d7SKowalski, Kamil /** 11709391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 11719391bb9cSRapkiewicz, Pawel * Manager 11721abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 11731abe55efSEd Tanous * into JSON. 11749391bb9cSRapkiewicz, Pawel */ 11759391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 11761abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 11771abe55efSEd Tanous { 1178f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1179f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1180f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 11818cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 11828b24275dSEd Tanous const boost::system::error_code& ec, 1183f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 11841abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 11851abe55efSEd Tanous // ethernet interfaces 118677179532SEd Tanous std::vector<std::string> ifaceList; 11872c70f800SEd Tanous ifaceList.reserve(resp.size()); 11888b24275dSEd Tanous if (ec) 11891abe55efSEd Tanous { 11902c70f800SEd Tanous callback(false, ifaceList); 11919391bb9cSRapkiewicz, Pawel return; 11929391bb9cSRapkiewicz, Pawel } 11939391bb9cSRapkiewicz, Pawel 11949391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 11954a0cb85cSEd Tanous for (const auto& objpath : resp) 11961abe55efSEd Tanous { 11979391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 11984a0cb85cSEd Tanous for (const auto& interface : objpath.second) 11991abe55efSEd Tanous { 12001abe55efSEd Tanous // If interface is 12014a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 12024a0cb85cSEd Tanous // what we're looking for. 12039391bb9cSRapkiewicz, Pawel if (interface.first == 12041abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 12051abe55efSEd Tanous { 12062dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 12072dfd18efSEd Tanous if (ifaceId.empty()) 12081abe55efSEd Tanous { 12092dfd18efSEd Tanous continue; 12109391bb9cSRapkiewicz, Pawel } 12112dfd18efSEd Tanous // and put it into output vector. 121277179532SEd Tanous ifaceList.emplace_back(ifaceId); 12139391bb9cSRapkiewicz, Pawel } 12149391bb9cSRapkiewicz, Pawel } 12159391bb9cSRapkiewicz, Pawel } 12162c5875a2SEd Tanous 12173544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 12182c5875a2SEd Tanous 1219a434f2bdSEd Tanous // Finally make a callback with useful data 12202c70f800SEd Tanous callback(true, ifaceList); 1221f5892d0dSGeorge Liu }); 1222271584abSEd Tanous } 12239391bb9cSRapkiewicz, Pawel 12244f48d5f6SEd Tanous inline void 12254f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 12268d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12271abe55efSEd Tanous { 1228ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 1229ab6554f1SJoshi-Mansi if (hostname.length() > 255) 1230ab6554f1SJoshi-Mansi { 1231ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 1232ab6554f1SJoshi-Mansi "HostName"); 1233ab6554f1SJoshi-Mansi return; 1234ab6554f1SJoshi-Mansi } 1235d02aad39SEd Tanous setDbusProperty( 1236d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1237d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network/config"), 1238d02aad39SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1239d02aad39SEd Tanous "HostName", hostname); 1240588c3f0dSKowalski, Kamil } 1241588c3f0dSKowalski, Kamil 12424f48d5f6SEd Tanous inline void 124335fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 124435fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 124535fb5311STejas Patil { 1246d02aad39SEd Tanous sdbusplus::message::object_path objPath("/xyz/openbmc_project/network"); 1247d02aad39SEd Tanous objPath /= ifaceId; 1248d02aad39SEd Tanous setDbusProperty(asyncResp, "xyz.openbmc_project.Network", objPath, 1249d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", "MTU", 1250d02aad39SEd Tanous "MTUSize", mtuSize); 125135fb5311STejas Patil } 125235fb5311STejas Patil 125335fb5311STejas Patil inline void 12544f48d5f6SEd Tanous handleDomainnamePatch(const std::string& ifaceId, 1255bf648f77SEd Tanous const std::string& domainname, 12568d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1257ab6554f1SJoshi-Mansi { 1258ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 1259d02aad39SEd Tanous setDbusProperty( 1260d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1261d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1262d02aad39SEd Tanous ifaceId, 1263d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", "DomainName", "FQDN", 1264d02aad39SEd Tanous vectorDomainname); 1265ab6554f1SJoshi-Mansi } 1266ab6554f1SJoshi-Mansi 12674f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1268bf648f77SEd Tanous { 1269bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 12703544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1271bf648f77SEd Tanous { 1272bf648f77SEd Tanous return false; 1273bf648f77SEd Tanous } 1274bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1275bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1276bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1277bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 12784b242749SEd Tanous const static std::regex pattern( 1279bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1280bf648f77SEd Tanous 1281bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1282bf648f77SEd Tanous } 1283bf648f77SEd Tanous 12844f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1285bf648f77SEd Tanous { 1286bf648f77SEd Tanous // Can have multiple subdomains 1287bf648f77SEd Tanous // Top Level Domain's min length is 2 character 12884b242749SEd Tanous const static std::regex pattern( 12890fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1290bf648f77SEd Tanous 1291bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1292bf648f77SEd Tanous } 1293bf648f77SEd Tanous 12944f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 12958d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1296ab6554f1SJoshi-Mansi { 1297ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1298ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1299ab6554f1SJoshi-Mansi { 1300ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1301ab6554f1SJoshi-Mansi return; 1302ab6554f1SJoshi-Mansi } 1303ab6554f1SJoshi-Mansi 1304ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1305ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1306ab6554f1SJoshi-Mansi { 1307ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1308ab6554f1SJoshi-Mansi return; 1309ab6554f1SJoshi-Mansi } 1310ab6554f1SJoshi-Mansi 1311ab6554f1SJoshi-Mansi std::string hostname; 1312ab6554f1SJoshi-Mansi std::string domainname; 1313ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1314ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1315ab6554f1SJoshi-Mansi 1316ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1317ab6554f1SJoshi-Mansi { 1318ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1319ab6554f1SJoshi-Mansi return; 1320ab6554f1SJoshi-Mansi } 1321ab6554f1SJoshi-Mansi 1322ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1323ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1324ab6554f1SJoshi-Mansi } 1325ab6554f1SJoshi-Mansi 13264f48d5f6SEd Tanous inline void 13274f48d5f6SEd Tanous handleMACAddressPatch(const std::string& ifaceId, 1328bf648f77SEd Tanous const std::string& macAddress, 13298d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1330d577665bSRatan Gupta { 1331d02aad39SEd Tanous setDbusProperty( 1332d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1333d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1334d02aad39SEd Tanous ifaceId, 1335d02aad39SEd Tanous "xyz.openbmc_project.Network.MACAddress", "MACAddress", "MACAddress", 1336d02aad39SEd Tanous macAddress); 1337d577665bSRatan Gupta } 1338286b9118SJohnathan Mantey 13394f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 13404f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 13414f48d5f6SEd Tanous const bool v6Value, 13428d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1343da131a9aSJennifer Lee { 13442c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 1345d02aad39SEd Tanous setDbusProperty( 1346d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1347d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1348d02aad39SEd Tanous ifaceId, 1349d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", propertyName, "DHCPv4", 1350d02aad39SEd Tanous dhcp); 1351eeedda23SJohnathan Mantey } 1352eeedda23SJohnathan Mantey 1353e4588158SJishnu CM enum class NetworkType 1354e4588158SJishnu CM { 1355e4588158SJishnu CM dhcp4, 1356e4588158SJishnu CM dhcp6 1357e4588158SJishnu CM }; 1358e4588158SJishnu CM 1359e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1360e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1361e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1362da131a9aSJennifer Lee { 136362598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 13641847f2a0SAsmitha Karunanithi std::string redfishPropertyName; 1365e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1366e4588158SJishnu CM path /= ethifaceId; 1367e4588158SJishnu CM 1368e4588158SJishnu CM if (type == NetworkType::dhcp4) 1369e4588158SJishnu CM { 1370e4588158SJishnu CM path /= "dhcp4"; 13711847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv4"; 1372e4588158SJishnu CM } 1373e4588158SJishnu CM else 1374e4588158SJishnu CM { 1375e4588158SJishnu CM path /= "dhcp6"; 13761847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv6"; 1377e4588158SJishnu CM } 1378e4588158SJishnu CM 13791847f2a0SAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path, 13801847f2a0SAsmitha Karunanithi "xyz.openbmc_project.Network.DHCPConfiguration", 13811847f2a0SAsmitha Karunanithi propertyName, redfishPropertyName, value); 1382da131a9aSJennifer Lee } 1383d577665bSRatan Gupta 1384b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1385b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1386b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1387b10d8db0SRavi Teja { 1388b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1389b10d8db0SRavi Teja path /= ifaceId; 13901847f2a0SAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path, 13911847f2a0SAsmitha Karunanithi "xyz.openbmc_project.Network.EthernetInterface", 13921847f2a0SAsmitha Karunanithi "IPv6AcceptRA", 13931847f2a0SAsmitha Karunanithi "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 13941847f2a0SAsmitha Karunanithi ipv6AutoConfigEnabled); 1395b10d8db0SRavi Teja } 1396b10d8db0SRavi Teja 13974f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId, 13981f8c7b5dSJohnathan Mantey const EthernetInterfaceData& ethData, 1399f23b7296SEd Tanous const DHCPParameters& v4dhcpParms, 1400f23b7296SEd Tanous const DHCPParameters& v6dhcpParms, 14018d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1402da131a9aSJennifer Lee { 140382695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 140482695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1405da131a9aSJennifer Lee 1406743eb1c0SJohnathan Mantey if (ipv4Active) 1407743eb1c0SJohnathan Mantey { 1408743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1409743eb1c0SJohnathan Mantey } 14101f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 14111f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 14121f8c7b5dSJohnathan Mantey 14131f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 14141f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1415da131a9aSJennifer Lee { 1416b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 14171f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 14181f8c7b5dSJohnathan Mantey { 1419bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1420bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 14211f8c7b5dSJohnathan Mantey "OperatingMode"); 1422da131a9aSJennifer Lee return; 1423da131a9aSJennifer Lee } 1424b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 14251f8c7b5dSJohnathan Mantey } 14261f8c7b5dSJohnathan Mantey else 1427da131a9aSJennifer Lee { 14281f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 14291f8c7b5dSJohnathan Mantey } 14301f8c7b5dSJohnathan Mantey 1431e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1432e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1433e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 14341f8c7b5dSJohnathan Mantey { 1435e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 14361f8c7b5dSJohnathan Mantey } 1437e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 14381f8c7b5dSJohnathan Mantey { 1439e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 14401f8c7b5dSJohnathan Mantey } 14411f8c7b5dSJohnathan Mantey 1442e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1443e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1444e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 14451f8c7b5dSJohnathan Mantey { 1446e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 14471f8c7b5dSJohnathan Mantey } 1448e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 14491f8c7b5dSJohnathan Mantey { 1450e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 14511f8c7b5dSJohnathan Mantey } 14521f8c7b5dSJohnathan Mantey 145391c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 145491c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1455e4588158SJishnu CM if (v4dhcpParms.useDomainName) 14561f8c7b5dSJohnathan Mantey { 1457e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 14581f8c7b5dSJohnathan Mantey } 1459e4588158SJishnu CM if (v6dhcpParms.useDomainName) 14601f8c7b5dSJohnathan Mantey { 1461e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 14621f8c7b5dSJohnathan Mantey } 14631f8c7b5dSJohnathan Mantey 146462598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 14651f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 14661f8c7b5dSJohnathan Mantey asyncResp); 146762598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1468e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1469e4588158SJishnu CM NetworkType::dhcp4); 147062598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1471e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1472e4588158SJishnu CM NetworkType::dhcp4); 147391c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 147491c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1475e4588158SJishnu CM NetworkType::dhcp4); 1476e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1477e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1478e4588158SJishnu CM NetworkType::dhcp6); 1479e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1480e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1481e4588158SJishnu CM NetworkType::dhcp6); 148291c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 148391c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1484e4588158SJishnu CM NetworkType::dhcp6); 1485da131a9aSJennifer Lee } 148601784826SJohnathan Mantey 148777179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 148877179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 148977179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 149001784826SJohnathan Mantey { 149117a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 149217a897dfSManojkiran Eda return value.origin == "Static"; 149317a897dfSManojkiran Eda }); 149401784826SJohnathan Mantey } 149501784826SJohnathan Mantey 149677179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 149777179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 149877179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 149901784826SJohnathan Mantey { 150017a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 150117a897dfSManojkiran Eda return value.origin == "Static"; 150217a897dfSManojkiran Eda }); 150301784826SJohnathan Mantey } 150401784826SJohnathan Mantey 15053dfed536SEd Tanous inline void handleIPv4StaticPatch( 15063dfed536SEd Tanous const std::string& ifaceId, 15073dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1508743eb1c0SJohnathan Mantey const EthernetInterfaceData& ethData, 150977179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 15108d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 15111abe55efSEd Tanous { 1512271584abSEd Tanous unsigned entryIdx = 1; 151301784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 151401784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 151501784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 151601784826SJohnathan Mantey // into the NIC. 151777179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 15182c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 151901784826SJohnathan Mantey 1520743eb1c0SJohnathan Mantey bool gatewayValueAssigned{}; 1521743eb1c0SJohnathan Mantey std::string activePath{}; 1522743eb1c0SJohnathan Mantey std::string activeGateway{}; 1523743eb1c0SJohnathan Mantey if (!ethData.defaultGateway.empty() && ethData.defaultGateway != "0.0.0.0") 1524743eb1c0SJohnathan Mantey { 1525743eb1c0SJohnathan Mantey // The NIC is already configured with a default gateway. Use this if 1526743eb1c0SJohnathan Mantey // the leading entry in the PATCH is '{}', which is preserving an active 1527743eb1c0SJohnathan Mantey // static address. 1528743eb1c0SJohnathan Mantey activeGateway = ethData.defaultGateway; 1529743eb1c0SJohnathan Mantey activePath = "IPv4StaticAddresses/1"; 1530743eb1c0SJohnathan Mantey gatewayValueAssigned = true; 1531743eb1c0SJohnathan Mantey } 1532743eb1c0SJohnathan Mantey 15333dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 15343dfed536SEd Tanous input) 15351abe55efSEd Tanous { 153689492a15SPatrick Williams std::string pathString = "IPv4StaticAddresses/" + 153789492a15SPatrick Williams std::to_string(entryIdx); 15383dfed536SEd Tanous nlohmann::json::object_t* obj = 15393dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 1540743eb1c0SJohnathan Mantey if (obj == nullptr) 1541743eb1c0SJohnathan Mantey { 1542743eb1c0SJohnathan Mantey if (nicIpEntry != ipv4Data.cend()) 1543743eb1c0SJohnathan Mantey { 1544743eb1c0SJohnathan Mantey deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 1545743eb1c0SJohnathan Mantey nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 1546743eb1c0SJohnathan Mantey ipv4Data.cend()); 1547743eb1c0SJohnathan Mantey if (!gatewayValueAssigned && (nicIpEntry == ipv4Data.cend())) 1548743eb1c0SJohnathan Mantey { 1549743eb1c0SJohnathan Mantey // All entries have been processed, and this last has 1550743eb1c0SJohnathan Mantey // requested the IP address be deleted. No prior entry 1551743eb1c0SJohnathan Mantey // performed an action that created or modified a 1552743eb1c0SJohnathan Mantey // gateway. Deleting this IP address means the default 1553743eb1c0SJohnathan Mantey // gateway entry has to be removed as well. 1554743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1555743eb1c0SJohnathan Mantey } 1556743eb1c0SJohnathan Mantey entryIdx++; 1557743eb1c0SJohnathan Mantey continue; 1558743eb1c0SJohnathan Mantey } 1559743eb1c0SJohnathan Mantey // Received a DELETE action on an entry not assigned to the NIC 1560743eb1c0SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 1561743eb1c0SJohnathan Mantey return; 1562743eb1c0SJohnathan Mantey } 1563743eb1c0SJohnathan Mantey 1564743eb1c0SJohnathan Mantey // An Add/Modify action is requested 1565743eb1c0SJohnathan Mantey if (!obj->empty()) 1566f476acbfSRatan Gupta { 1567537174c4SEd Tanous std::optional<std::string> address; 1568537174c4SEd Tanous std::optional<std::string> subnetMask; 1569537174c4SEd Tanous std::optional<std::string> gateway; 1570537174c4SEd Tanous 15713dfed536SEd Tanous if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", 15727e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 15737e27d832SJohnathan Mantey "Gateway", gateway)) 1574537174c4SEd Tanous { 15753dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 157671f52d96SEd Tanous pathString); 1577537174c4SEd Tanous return; 1578179db1d7SKowalski, Kamil } 1579179db1d7SKowalski, Kamil 158001784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 158101784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 158201784826SJohnathan Mantey // current state of the interface. Merge existing state into the 158301784826SJohnathan Mantey // current request. 1584537174c4SEd Tanous if (address) 15851abe55efSEd Tanous { 1586e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 158701784826SJohnathan Mantey { 1588bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1589bf648f77SEd Tanous pathString + "/Address"); 1590e01d0c36SEd Tanous return; 159101784826SJohnathan Mantey } 159201784826SJohnathan Mantey } 159385ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 159401784826SJohnathan Mantey { 1595e01d0c36SEd Tanous address = (nicIpEntry->address); 159601784826SJohnathan Mantey } 159701784826SJohnathan Mantey else 159801784826SJohnathan Mantey { 159901784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 160001784826SJohnathan Mantey pathString + "/Address"); 1601e01d0c36SEd Tanous return; 16024a0cb85cSEd Tanous } 16034a0cb85cSEd Tanous 1604e01d0c36SEd Tanous uint8_t prefixLength = 0; 1605537174c4SEd Tanous if (subnetMask) 16064a0cb85cSEd Tanous { 1607033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1608033f1e4dSEd Tanous &prefixLength)) 16094a0cb85cSEd Tanous { 1610f12894f8SJason M. Bills messages::propertyValueFormatError( 1611537174c4SEd Tanous asyncResp->res, *subnetMask, 16124a0cb85cSEd Tanous pathString + "/SubnetMask"); 1613e01d0c36SEd Tanous return; 16144a0cb85cSEd Tanous } 16154a0cb85cSEd Tanous } 161685ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 16174a0cb85cSEd Tanous { 1618033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 161901784826SJohnathan Mantey &prefixLength)) 16204a0cb85cSEd Tanous { 162101784826SJohnathan Mantey messages::propertyValueFormatError( 162285ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 162301784826SJohnathan Mantey pathString + "/SubnetMask"); 1624e01d0c36SEd Tanous return; 16254a0cb85cSEd Tanous } 16264a0cb85cSEd Tanous } 16271abe55efSEd Tanous else 16281abe55efSEd Tanous { 162901784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 163001784826SJohnathan Mantey pathString + "/SubnetMask"); 1631e01d0c36SEd Tanous return; 163201784826SJohnathan Mantey } 163301784826SJohnathan Mantey 163401784826SJohnathan Mantey if (gateway) 163501784826SJohnathan Mantey { 1636e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 163701784826SJohnathan Mantey { 1638bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1639bf648f77SEd Tanous pathString + "/Gateway"); 1640e01d0c36SEd Tanous return; 164101784826SJohnathan Mantey } 164201784826SJohnathan Mantey } 164385ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 164401784826SJohnathan Mantey { 1645e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 164601784826SJohnathan Mantey } 164701784826SJohnathan Mantey else 16481abe55efSEd Tanous { 1649a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 16504a0cb85cSEd Tanous pathString + "/Gateway"); 165101784826SJohnathan Mantey return; 16524a0cb85cSEd Tanous } 16534a0cb85cSEd Tanous 1654743eb1c0SJohnathan Mantey if (gatewayValueAssigned) 1655743eb1c0SJohnathan Mantey { 1656743eb1c0SJohnathan Mantey if (activeGateway != gateway) 1657743eb1c0SJohnathan Mantey { 1658743eb1c0SJohnathan Mantey // A NIC can only have a single active gateway value. 1659743eb1c0SJohnathan Mantey // If any gateway in the array of static addresses 1660743eb1c0SJohnathan Mantey // mismatch the PATCH is in error. 1661743eb1c0SJohnathan Mantey std::string arg1 = pathString + "/Gateway"; 1662743eb1c0SJohnathan Mantey std::string arg2 = activePath + "/Gateway"; 1663743eb1c0SJohnathan Mantey messages::propertyValueConflict(asyncResp->res, arg1, arg2); 1664743eb1c0SJohnathan Mantey return; 1665743eb1c0SJohnathan Mantey } 1666743eb1c0SJohnathan Mantey } 1667743eb1c0SJohnathan Mantey else 1668743eb1c0SJohnathan Mantey { 1669743eb1c0SJohnathan Mantey // Capture the very first gateway value from the incoming 1670743eb1c0SJohnathan Mantey // JSON record and use it at the default gateway. 1671743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, *gateway, asyncResp); 1672743eb1c0SJohnathan Mantey activeGateway = *gateway; 1673743eb1c0SJohnathan Mantey activePath = pathString; 1674743eb1c0SJohnathan Mantey gatewayValueAssigned = true; 1675743eb1c0SJohnathan Mantey } 1676743eb1c0SJohnathan Mantey 167785ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 16781abe55efSEd Tanous { 16799c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 168077eb0153SEd Tanous nicIpEntry->id, prefixLength, *address, 168177eb0153SEd Tanous *gateway, asyncResp); 168289492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 168389492a15SPatrick Williams ipv4Data.cend()); 1684588c3f0dSKowalski, Kamil } 168501784826SJohnathan Mantey else 168601784826SJohnathan Mantey { 1687cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1688cb13a392SEd Tanous asyncResp); 16894a0cb85cSEd Tanous } 16904a0cb85cSEd Tanous entryIdx++; 16914a0cb85cSEd Tanous } 169201784826SJohnathan Mantey else 169301784826SJohnathan Mantey { 1694743eb1c0SJohnathan Mantey // Received {}, do not modify this address 169585ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 169601784826SJohnathan Mantey { 169789492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 169889492a15SPatrick Williams ipv4Data.cend()); 169901784826SJohnathan Mantey entryIdx++; 170001784826SJohnathan Mantey } 1701743eb1c0SJohnathan Mantey else 1702743eb1c0SJohnathan Mantey { 1703743eb1c0SJohnathan Mantey // Requested a DO NOT MODIFY action on an entry not assigned 1704743eb1c0SJohnathan Mantey // to the NIC 1705743eb1c0SJohnathan Mantey messages::propertyValueFormatError(asyncResp->res, *obj, 1706743eb1c0SJohnathan Mantey pathString); 1707743eb1c0SJohnathan Mantey return; 1708743eb1c0SJohnathan Mantey } 1709743eb1c0SJohnathan Mantey } 171001784826SJohnathan Mantey } 17114a0cb85cSEd Tanous } 17124a0cb85cSEd Tanous 17134f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1714f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1715f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 17168d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1717f85837bfSRAJESWARAN THILLAIGOVINDAN { 17181847f2a0SAsmitha Karunanithi setDbusProperty( 17191847f2a0SAsmitha Karunanithi asyncResp, "xyz.openbmc_project.Network", 17201847f2a0SAsmitha Karunanithi sdbusplus::message::object_path("/xyz/openbmc_project/network") / 17211847f2a0SAsmitha Karunanithi ifaceId, 17229ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 17231847f2a0SAsmitha Karunanithi "StaticNameServers", updatedStaticNameServers); 1724f85837bfSRAJESWARAN THILLAIGOVINDAN } 1725f85837bfSRAJESWARAN THILLAIGOVINDAN 17264f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 17273dfed536SEd Tanous const std::string& ifaceId, 17283dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 172977179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 17308d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1731e48c0fc5SRavi Teja { 1732271584abSEd Tanous size_t entryIdx = 1; 173377179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 17342c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 17353dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 17363dfed536SEd Tanous input) 1737e48c0fc5SRavi Teja { 173889492a15SPatrick Williams std::string pathString = "IPv6StaticAddresses/" + 173989492a15SPatrick Williams std::to_string(entryIdx); 17403dfed536SEd Tanous nlohmann::json::object_t* obj = 17413dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 17423dfed536SEd Tanous if (obj != nullptr && !obj->empty()) 1743e48c0fc5SRavi Teja { 1744e48c0fc5SRavi Teja std::optional<std::string> address; 1745e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 17463dfed536SEd Tanous nlohmann::json::object_t thisJsonCopy = *obj; 17473dfed536SEd Tanous if (!json_util::readJsonObject(thisJsonCopy, asyncResp->res, 17483dfed536SEd Tanous "Address", address, "PrefixLength", 17493dfed536SEd Tanous prefixLength)) 1750e48c0fc5SRavi Teja { 17513dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJsonCopy, 175271f52d96SEd Tanous pathString); 1753e48c0fc5SRavi Teja return; 1754e48c0fc5SRavi Teja } 1755e48c0fc5SRavi Teja 175601784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 175701784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 175801784826SJohnathan Mantey // current state of the interface. Merge existing state into the 175901784826SJohnathan Mantey // current request. 1760d547d8d2SEd Tanous if (!address) 1761e48c0fc5SRavi Teja { 1762d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 176301784826SJohnathan Mantey { 176401784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 176501784826SJohnathan Mantey pathString + "/Address"); 176601784826SJohnathan Mantey return; 1767e48c0fc5SRavi Teja } 1768d547d8d2SEd Tanous address = nicIpEntry->address; 1769d547d8d2SEd Tanous } 1770e48c0fc5SRavi Teja 1771d547d8d2SEd Tanous if (!prefixLength) 1772e48c0fc5SRavi Teja { 1773d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 1774e48c0fc5SRavi Teja { 1775e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1776e48c0fc5SRavi Teja pathString + "/PrefixLength"); 177701784826SJohnathan Mantey return; 1778e48c0fc5SRavi Teja } 1779d547d8d2SEd Tanous prefixLength = nicIpEntry->prefixLength; 1780d547d8d2SEd Tanous } 1781e48c0fc5SRavi Teja 178285ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1783e48c0fc5SRavi Teja { 17849c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 1785d547d8d2SEd Tanous nicIpEntry->id, *prefixLength, 1786d547d8d2SEd Tanous *address, "", asyncResp); 178789492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 178889492a15SPatrick Williams ipv6Data.cend()); 178901784826SJohnathan Mantey } 179001784826SJohnathan Mantey else 179101784826SJohnathan Mantey { 1792d547d8d2SEd Tanous createIPv6(ifaceId, *prefixLength, *address, asyncResp); 1793e48c0fc5SRavi Teja } 1794e48c0fc5SRavi Teja entryIdx++; 1795e48c0fc5SRavi Teja } 179601784826SJohnathan Mantey else 179701784826SJohnathan Mantey { 179885ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 179901784826SJohnathan Mantey { 180001784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 180101784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 180201784826SJohnathan Mantey // in error, so bail out. 18033dfed536SEd Tanous if (obj == nullptr) 180401784826SJohnathan Mantey { 180501784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 180601784826SJohnathan Mantey return; 180701784826SJohnathan Mantey } 18083dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 180971f52d96SEd Tanous pathString); 181001784826SJohnathan Mantey return; 181101784826SJohnathan Mantey } 181201784826SJohnathan Mantey 18133dfed536SEd Tanous if (obj == nullptr) 181401784826SJohnathan Mantey { 18159c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 181601784826SJohnathan Mantey } 181785ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 181801784826SJohnathan Mantey { 181989492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 182089492a15SPatrick Williams ipv6Data.cend()); 182101784826SJohnathan Mantey } 182201784826SJohnathan Mantey entryIdx++; 182301784826SJohnathan Mantey } 182401784826SJohnathan Mantey } 1825e48c0fc5SRavi Teja } 1826e48c0fc5SRavi Teja 18277857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 18287857cb8dSJiaqing Zhao { 18297857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 18307857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 18317857cb8dSJiaqing Zhao } 18327857cb8dSJiaqing Zhao 183377179532SEd Tanous inline void 183477179532SEd Tanous parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 183577179532SEd Tanous const std::string& ifaceId, 183677179532SEd Tanous const EthernetInterfaceData& ethData, 183777179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1838ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 1839ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) 18404a0cb85cSEd Tanous { 18412c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 184281ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1843*253f11b8SEd Tanous jsonResponse["@odata.id"] = 1844*253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 1845*253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId); 18462c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1847eeedda23SJohnathan Mantey 1848eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1849eeedda23SJohnathan Mantey { 18500ef0e289SJohnathan Mantey jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 18512c70f800SEd Tanous jsonResponse["Status"]["State"] = "Enabled"; 1852029573d4SEd Tanous } 1853029573d4SEd Tanous else 1854029573d4SEd Tanous { 18552c70f800SEd Tanous jsonResponse["LinkStatus"] = "NoLink"; 18562c70f800SEd Tanous jsonResponse["Status"]["State"] = "Disabled"; 1857029573d4SEd Tanous } 1858aa05fb27SJohnathan Mantey 18592c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 186035fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 186182695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 18622c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 186382695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1864e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1865e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1866e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled; 18672c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1868b10d8db0SRavi Teja translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled" 18691f8c7b5dSJohnathan Mantey : "Disabled"; 1870e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1871e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1872e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled; 1873b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1874b10d8db0SRavi Teja ethData.ipv6AcceptRa; 18752a133282Smanojkiraneda 187682695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 18774a0cb85cSEd Tanous { 187882695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1879ab6554f1SJoshi-Mansi 1880ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1881ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1882ab6554f1SJoshi-Mansi // FQDN 188382695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1884d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1885d24bfc7aSJennifer Lee { 18862c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1887d24bfc7aSJennifer Lee } 18882c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 18894a0cb85cSEd Tanous } 18904a0cb85cSEd Tanous 18917857cb8dSJiaqing Zhao if (ethData.vlanId) 18927857cb8dSJiaqing Zhao { 18937857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Virtual"; 18947857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 18957857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 18967857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 18977857cb8dSJiaqing Zhao 18987857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 18997857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 19007857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 1901*253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces", 1902*253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, 19037857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 19047857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 19057857cb8dSJiaqing Zhao std::move(relatedInterfaces); 19067857cb8dSJiaqing Zhao } 19077857cb8dSJiaqing Zhao else 19087857cb8dSJiaqing Zhao { 19097857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Physical"; 19107857cb8dSJiaqing Zhao } 19117857cb8dSJiaqing Zhao 19122c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 19132c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 19144a0cb85cSEd Tanous 19152c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 19162c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 19172c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 19182c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 19199eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 19204a0cb85cSEd Tanous { 19212c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1922fa5053a6SGunnar Mills if (gatewayStr.empty()) 1923fa5053a6SGunnar Mills { 1924fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1925fa5053a6SGunnar Mills } 19261476687dSEd Tanous nlohmann::json::object_t ipv4; 19271476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 19281476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 19291476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 19301476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1931fa5053a6SGunnar Mills 19322c70f800SEd Tanous if (ipv4Config.origin == "Static") 1933d1d50814SRavi Teja { 19341476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1935d1d50814SRavi Teja } 19361476687dSEd Tanous 1937b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 193801784826SJohnathan Mantey } 1939d1d50814SRavi Teja 194082695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 19417ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 19427ea79e5eSRavi Teja { 19437ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 19447ea79e5eSRavi Teja } 19457ea79e5eSRavi Teja 19467ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1947e48c0fc5SRavi Teja 1948ce73d5c8SSunitha Harish nlohmann::json::array_t ipv6StaticGatewayArray; 1949ce73d5c8SSunitha Harish for (const auto& ipv6GatewayConfig : ipv6GatewayData) 1950ce73d5c8SSunitha Harish { 1951ce73d5c8SSunitha Harish nlohmann::json::object_t ipv6Gateway; 1952ce73d5c8SSunitha Harish ipv6Gateway["Address"] = ipv6GatewayConfig.gateway; 1953ce73d5c8SSunitha Harish ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength; 1954ce73d5c8SSunitha Harish ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway)); 1955ce73d5c8SSunitha Harish } 1956ce73d5c8SSunitha Harish jsonResponse["IPv6StaticDefaultGateways"] = 1957ce73d5c8SSunitha Harish std::move(ipv6StaticGatewayArray); 1958ce73d5c8SSunitha Harish 19592c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 19602c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 19612c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 19622c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 19637f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 19642c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 19657f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 19669eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1967e48c0fc5SRavi Teja { 19681476687dSEd Tanous nlohmann::json::object_t ipv6; 19691476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 19701476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 19711476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1972f8361275SSunitha Harish 1973b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 19742c70f800SEd Tanous if (ipv6Config.origin == "Static") 1975e48c0fc5SRavi Teja { 19761476687dSEd Tanous nlohmann::json::object_t ipv6Static; 19771476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 19781476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 1979b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 198001784826SJohnathan Mantey } 1981e48c0fc5SRavi Teja } 1982588c3f0dSKowalski, Kamil } 1983588c3f0dSKowalski, Kamil 1984e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1985e7caf250SJiaqing Zhao const std::string& ifaceId, 1986e7caf250SJiaqing Zhao const boost::system::error_code& ec, 1987e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 1988e7caf250SJiaqing Zhao { 1989e7caf250SJiaqing Zhao if (!ec) 1990e7caf250SJiaqing Zhao { 1991e7caf250SJiaqing Zhao return; 1992e7caf250SJiaqing Zhao } 1993e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1994e7caf250SJiaqing Zhao if (dbusError == nullptr) 1995e7caf250SJiaqing Zhao { 1996e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1997e7caf250SJiaqing Zhao return; 1998e7caf250SJiaqing Zhao } 199962598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2000e7caf250SJiaqing Zhao 2001e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 2002e7caf250SJiaqing Zhao dbusError->name) 2003e7caf250SJiaqing Zhao { 2004e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2005e7caf250SJiaqing Zhao ifaceId); 2006e7caf250SJiaqing Zhao return; 2007e7caf250SJiaqing Zhao } 2008e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 2009e7caf250SJiaqing Zhao dbusError->name) 2010e7caf250SJiaqing Zhao { 2011e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 2012e7caf250SJiaqing Zhao return; 2013e7caf250SJiaqing Zhao } 2014e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2015e7caf250SJiaqing Zhao } 2016e7caf250SJiaqing Zhao 2017b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2018b5ca3fdcSJiaqing Zhao const std::string& parentInterfaceUri, 2019b5ca3fdcSJiaqing Zhao const std::string& vlanInterface, 2020b5ca3fdcSJiaqing Zhao const boost::system::error_code& ec, 2021b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m 2022b5ca3fdcSJiaqing Zhao 2023b5ca3fdcSJiaqing Zhao ) 2024b5ca3fdcSJiaqing Zhao { 2025b5ca3fdcSJiaqing Zhao if (ec) 2026b5ca3fdcSJiaqing Zhao { 2027b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2028b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 2029b5ca3fdcSJiaqing Zhao { 2030b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2031b5ca3fdcSJiaqing Zhao return; 2032b5ca3fdcSJiaqing Zhao } 203362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2034b5ca3fdcSJiaqing Zhao 2035b5ca3fdcSJiaqing Zhao if (std::string_view( 2036b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 2037b5ca3fdcSJiaqing Zhao dbusError->name) 2038b5ca3fdcSJiaqing Zhao { 2039b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2040b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2041b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2042b5ca3fdcSJiaqing Zhao return; 2043b5ca3fdcSJiaqing Zhao } 2044b5ca3fdcSJiaqing Zhao if (std::string_view( 2045b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 2046b5ca3fdcSJiaqing Zhao dbusError->name) 2047b5ca3fdcSJiaqing Zhao { 2048b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 2049b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 2050b5ca3fdcSJiaqing Zhao return; 2051b5ca3fdcSJiaqing Zhao } 2052b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2053b5ca3fdcSJiaqing Zhao return; 2054b5ca3fdcSJiaqing Zhao } 2055b5ca3fdcSJiaqing Zhao 2056*253f11b8SEd Tanous const boost::urls::url vlanInterfaceUri = 2057*253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2058*253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface); 2059b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 2060b5ca3fdcSJiaqing Zhao } 2061b5ca3fdcSJiaqing Zhao 2062bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 2063bf648f77SEd Tanous { 2064*253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2065ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 20661476687dSEd Tanous .methods(boost::beast::http::verb::get)( 20671476687dSEd Tanous [&app](const crow::Request& req, 2068*253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2069*253f11b8SEd Tanous const std::string& managerId) { 20703ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 207145ca1b86SEd Tanous { 207245ca1b86SEd Tanous return; 207345ca1b86SEd Tanous } 207445ca1b86SEd Tanous 2075*253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2076*253f11b8SEd Tanous { 2077*253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2078*253f11b8SEd Tanous return; 2079*253f11b8SEd Tanous } 2080*253f11b8SEd Tanous 2081bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2082bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 2083bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2084*253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces", 2085*253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2086bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 2087bf648f77SEd Tanous "Ethernet Network Interface Collection"; 2088bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 2089bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 2090bf648f77SEd Tanous 2091bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 2092bf648f77SEd Tanous // preparation 2093002d39b4SEd Tanous getEthernetIfaceList( 209477179532SEd Tanous [asyncResp](const bool& success, 209577179532SEd Tanous const std::vector<std::string>& ifaceList) { 2096bf648f77SEd Tanous if (!success) 20971abe55efSEd Tanous { 2098f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20999391bb9cSRapkiewicz, Pawel return; 21009391bb9cSRapkiewicz, Pawel } 21019391bb9cSRapkiewicz, Pawel 2102002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 2103bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 2104bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 2105bf648f77SEd Tanous { 21061476687dSEd Tanous nlohmann::json::object_t iface; 2107ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 2108*253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2109*253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem); 21107857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 2111bf648f77SEd Tanous } 2112bf648f77SEd Tanous 2113002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 2114*253f11b8SEd Tanous asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2115*253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces", 2116*253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2117bf648f77SEd Tanous }); 2118bf648f77SEd Tanous }); 2119bf648f77SEd Tanous 2120*253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2121b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 2122b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 2123b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 2124*253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2125*253f11b8SEd Tanous const std::string& managerId) { 2126b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2127b5ca3fdcSJiaqing Zhao { 2128b5ca3fdcSJiaqing Zhao return; 2129b5ca3fdcSJiaqing Zhao } 2130b5ca3fdcSJiaqing Zhao 2131*253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2132*253f11b8SEd Tanous { 2133*253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2134*253f11b8SEd Tanous return; 2135*253f11b8SEd Tanous } 2136*253f11b8SEd Tanous 2137b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 2138b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 21393dfed536SEd Tanous std::vector<nlohmann::json::object_t> relatedInterfaces; 2140b5ca3fdcSJiaqing Zhao 2141b5ca3fdcSJiaqing Zhao if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", 2142b5ca3fdcSJiaqing Zhao vlanEnable, "VLAN/VLANId", vlanId, 2143b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2144b5ca3fdcSJiaqing Zhao relatedInterfaces)) 2145b5ca3fdcSJiaqing Zhao { 2146b5ca3fdcSJiaqing Zhao return; 2147b5ca3fdcSJiaqing Zhao } 2148b5ca3fdcSJiaqing Zhao 2149b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 2150b5ca3fdcSJiaqing Zhao { 2151b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 2152b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2153b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 2154b5ca3fdcSJiaqing Zhao return; 2155b5ca3fdcSJiaqing Zhao } 2156b5ca3fdcSJiaqing Zhao 2157b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 21583dfed536SEd Tanous if (!json_util::readJsonObject(relatedInterfaces[0], asyncResp->res, 2159b5ca3fdcSJiaqing Zhao "@odata.id", parentInterfaceUri)) 2160b5ca3fdcSJiaqing Zhao { 2161b5ca3fdcSJiaqing Zhao messages::propertyMissing(asyncResp->res, 2162b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2163b5ca3fdcSJiaqing Zhao return; 2164b5ca3fdcSJiaqing Zhao } 216562598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 2166b5ca3fdcSJiaqing Zhao 21676fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 2168b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 2169b5ca3fdcSJiaqing Zhao if (!parsedUri) 2170b5ca3fdcSJiaqing Zhao { 2171b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 2172b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2173b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2174b5ca3fdcSJiaqing Zhao return; 2175b5ca3fdcSJiaqing Zhao } 2176b5ca3fdcSJiaqing Zhao 2177b5ca3fdcSJiaqing Zhao std::string parentInterface; 2178b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 2179b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 2180b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 2181b5ca3fdcSJiaqing Zhao { 2182b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2183b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2184b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2185b5ca3fdcSJiaqing Zhao return; 2186b5ca3fdcSJiaqing Zhao } 2187b5ca3fdcSJiaqing Zhao 2188b5ca3fdcSJiaqing Zhao if (!vlanEnable) 2189b5ca3fdcSJiaqing Zhao { 2190b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 2191b5ca3fdcSJiaqing Zhao // create 2192b5ca3fdcSJiaqing Zhao messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", 2193b5ca3fdcSJiaqing Zhao "false"); 2194b5ca3fdcSJiaqing Zhao return; 2195b5ca3fdcSJiaqing Zhao } 2196b5ca3fdcSJiaqing Zhao 2197b5ca3fdcSJiaqing Zhao std::string vlanInterface = parentInterface + "_" + 2198b5ca3fdcSJiaqing Zhao std::to_string(vlanId); 2199b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 2200b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 2201b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 2202b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 2203b5ca3fdcSJiaqing Zhao afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, 2204b5ca3fdcSJiaqing Zhao m); 2205b5ca3fdcSJiaqing Zhao }, 2206b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 2207b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, 2208b5ca3fdcSJiaqing Zhao vlanId); 2209b5ca3fdcSJiaqing Zhao }); 2210b5ca3fdcSJiaqing Zhao 2211*253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2212ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 2213bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 221445ca1b86SEd Tanous [&app](const crow::Request& req, 2215bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2216*253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 22173ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 221845ca1b86SEd Tanous { 221945ca1b86SEd Tanous return; 222045ca1b86SEd Tanous } 2221*253f11b8SEd Tanous 2222*253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2223*253f11b8SEd Tanous { 2224*253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2225*253f11b8SEd Tanous return; 2226*253f11b8SEd Tanous } 2227*253f11b8SEd Tanous 22284a0cb85cSEd Tanous getEthernetIfaceData( 2229bf648f77SEd Tanous ifaceId, 2230ce73d5c8SSunitha Harish [asyncResp, 2231ce73d5c8SSunitha Harish ifaceId](const bool& success, const EthernetInterfaceData& ethData, 223277179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2233ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2234ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 22354a0cb85cSEd Tanous if (!success) 22361abe55efSEd Tanous { 2237bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2238bf648f77SEd Tanous // existing object, and other errors 2239002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2240002d39b4SEd Tanous ifaceId); 22414a0cb85cSEd Tanous return; 22429391bb9cSRapkiewicz, Pawel } 22434c9afe43SEd Tanous 22440f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 224593bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2246002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 22470f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 22480f74e643SEd Tanous "Management Network Interface"; 22490f74e643SEd Tanous 2250ce73d5c8SSunitha Harish parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data, 2251ce73d5c8SSunitha Harish ipv6GatewayData); 22529391bb9cSRapkiewicz, Pawel }); 2253bf648f77SEd Tanous }); 22549391bb9cSRapkiewicz, Pawel 2255*253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2256ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2257bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 225845ca1b86SEd Tanous [&app](const crow::Request& req, 2259bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2260*253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 22613ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 226245ca1b86SEd Tanous { 226345ca1b86SEd Tanous return; 226445ca1b86SEd Tanous } 2265*253f11b8SEd Tanous 2266*253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2267*253f11b8SEd Tanous { 2268*253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2269*253f11b8SEd Tanous return; 2270*253f11b8SEd Tanous } 2271*253f11b8SEd Tanous 2272bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2273ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2274d577665bSRatan Gupta std::optional<std::string> macAddress; 22759a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 22763dfed536SEd Tanous std::optional< 22773dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 22783dfed536SEd Tanous ipv4StaticAddresses; 22793dfed536SEd Tanous std::optional< 22803dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 22813dfed536SEd Tanous ipv6StaticAddresses; 22823dfed536SEd Tanous std::optional< 22833dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 22843dfed536SEd Tanous ipv6StaticDefaultGateways; 2285f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2286b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2287eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 228835fb5311STejas Patil std::optional<size_t> mtuSize; 22891f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 22901f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2291b10d8db0SRavi Teja // clang-format off 22923dfed536SEd Tanous if (!json_util::readJsonPatch(req, asyncResp->res, 22933dfed536SEd Tanous "DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled, 22943dfed536SEd Tanous "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers, 22953dfed536SEd Tanous "DHCPv4/UseDomainName", v4dhcpParms.useDomainName, 22963dfed536SEd Tanous "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers, 22973dfed536SEd Tanous "DHCPv6/OperatingMode", v6dhcpParms.dhcpv6OperatingMode, 22983dfed536SEd Tanous "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers, 22993dfed536SEd Tanous "DHCPv6/UseDomainName", v6dhcpParms.useDomainName, 23003dfed536SEd Tanous "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers, 2301b10d8db0SRavi Teja "FQDN", fqdn, 2302b10d8db0SRavi Teja "HostName", hostname, 2303b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 2304b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 2305b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 2306ce73d5c8SSunitha Harish "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways, 2307b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 2308b10d8db0SRavi Teja "MACAddress", macAddress, 2309b10d8db0SRavi Teja "MTUSize", mtuSize, 2310b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 2311b10d8db0SRavi Teja "StaticNameServers", staticNameServers 2312b10d8db0SRavi Teja ) 2313b10d8db0SRavi Teja ) 23141abe55efSEd Tanous { 2315588c3f0dSKowalski, Kamil return; 2316588c3f0dSKowalski, Kamil } 2317b10d8db0SRavi Teja // clang-format on 2318da131a9aSJennifer Lee 2319bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2320bf648f77SEd Tanous // for JSON preparation 23214a0cb85cSEd Tanous getEthernetIfaceData( 23222c70f800SEd Tanous ifaceId, 2323bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2324ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2325d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 23269a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2327e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 2328ce73d5c8SSunitha Harish ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways), 23293dfed536SEd Tanous staticNameServers = std::move(staticNameServers), mtuSize, 2330b10d8db0SRavi Teja ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms), 2331f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 23323dfed536SEd Tanous const bool success, const EthernetInterfaceData& ethData, 233377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2334ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 23353dfed536SEd Tanous const std::vector<StaticGatewayData>& ipv6GatewayData) mutable { 23361abe55efSEd Tanous if (!success) 23371abe55efSEd Tanous { 2338588c3f0dSKowalski, Kamil // ... otherwise return error 2339bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2340bf648f77SEd Tanous // existing object, and other errors 2341002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2342002d39b4SEd Tanous ifaceId); 2343588c3f0dSKowalski, Kamil return; 2344588c3f0dSKowalski, Kamil } 2345588c3f0dSKowalski, Kamil 2346002d39b4SEd Tanous handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, 2347002d39b4SEd Tanous asyncResp); 23481f8c7b5dSJohnathan Mantey 23490627a2c7SEd Tanous if (hostname) 23501abe55efSEd Tanous { 23510627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 23521abe55efSEd Tanous } 23530627a2c7SEd Tanous 2354b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2355b10d8db0SRavi Teja { 2356b10d8db0SRavi Teja handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled, 2357b10d8db0SRavi Teja asyncResp); 2358b10d8db0SRavi Teja } 2359b10d8db0SRavi Teja 2360ab6554f1SJoshi-Mansi if (fqdn) 2361ab6554f1SJoshi-Mansi { 23622c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2363ab6554f1SJoshi-Mansi } 2364ab6554f1SJoshi-Mansi 2365d577665bSRatan Gupta if (macAddress) 2366d577665bSRatan Gupta { 2367002d39b4SEd Tanous handleMACAddressPatch(ifaceId, *macAddress, asyncResp); 2368d577665bSRatan Gupta } 2369d577665bSRatan Gupta 2370d1d50814SRavi Teja if (ipv4StaticAddresses) 2371d1d50814SRavi Teja { 2372743eb1c0SJohnathan Mantey handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ethData, 2373743eb1c0SJohnathan Mantey ipv4Data, asyncResp); 23741abe55efSEd Tanous } 23750627a2c7SEd Tanous 2376f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2377f85837bfSRAJESWARAN THILLAIGOVINDAN { 2378002d39b4SEd Tanous handleStaticNameServersPatch(ifaceId, *staticNameServers, 2379002d39b4SEd Tanous asyncResp); 2380f85837bfSRAJESWARAN THILLAIGOVINDAN } 23819a6fc6feSRavi Teja 23829a6fc6feSRavi Teja if (ipv6DefaultGateway) 23839a6fc6feSRavi Teja { 23849a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 23859a6fc6feSRavi Teja "IPv6DefaultGateway"); 23869a6fc6feSRavi Teja } 2387e48c0fc5SRavi Teja 2388e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2389e48c0fc5SRavi Teja { 2390ddd70dcaSEd Tanous handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses, 2391ddd70dcaSEd Tanous ipv6Data, asyncResp); 2392e48c0fc5SRavi Teja } 2393eeedda23SJohnathan Mantey 2394ce73d5c8SSunitha Harish if (ipv6StaticDefaultGateway) 2395ce73d5c8SSunitha Harish { 2396ce73d5c8SSunitha Harish handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway, 2397ce73d5c8SSunitha Harish ipv6GatewayData, asyncResp); 2398ce73d5c8SSunitha Harish } 2399ce73d5c8SSunitha Harish 2400eeedda23SJohnathan Mantey if (interfaceEnabled) 2401eeedda23SJohnathan Mantey { 2402d02aad39SEd Tanous setDbusProperty(asyncResp, "xyz.openbmc_project.Network", 2403d02aad39SEd Tanous sdbusplus::message::object_path( 2404d02aad39SEd Tanous "/xyz/openbmc_project/network") / 2405d02aad39SEd Tanous ifaceId, 2406d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", 2407d02aad39SEd Tanous "NICEnabled", "InterfaceEnabled", 2408d02aad39SEd Tanous *interfaceEnabled); 2409eeedda23SJohnathan Mantey } 241035fb5311STejas Patil 241135fb5311STejas Patil if (mtuSize) 241235fb5311STejas Patil { 241335fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 241435fb5311STejas Patil } 2415588c3f0dSKowalski, Kamil }); 2416bf648f77SEd Tanous }); 2417e7caf250SJiaqing Zhao 2418*253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2419e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2420e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2421e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2422e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2423*253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 2424e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2425e7caf250SJiaqing Zhao { 2426e7caf250SJiaqing Zhao return; 2427e7caf250SJiaqing Zhao } 2428e7caf250SJiaqing Zhao 2429*253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2430*253f11b8SEd Tanous { 2431*253f11b8SEd Tanous messages::resourceNotFound(asyncResp->res, "Manager", managerId); 2432*253f11b8SEd Tanous return; 2433*253f11b8SEd Tanous } 2434*253f11b8SEd Tanous 2435e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2436e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2437e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2438e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2439e7caf250SJiaqing Zhao }, 2440e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2441e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2442e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2443e7caf250SJiaqing Zhao }); 24444a0cb85cSEd Tanous } 2445bf648f77SEd Tanous 24469391bb9cSRapkiewicz, Pawel } // namespace redfish 2447