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 1813451e39SWilly Tu #include "bmcweb_config.h" 1913451e39SWilly Tu 203ccb3adbSEd Tanous #include "app.hpp" 213ccb3adbSEd Tanous #include "dbus_singleton.hpp" 227a1dbc48SGeorge Liu #include "dbus_utility.hpp" 233ccb3adbSEd Tanous #include "error_messages.hpp" 243ccb3adbSEd Tanous #include "health.hpp" 252c5875a2SEd Tanous #include "human_sort.hpp" 263ccb3adbSEd Tanous #include "query.hpp" 273ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 28033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 293ccb3adbSEd Tanous #include "utils/json_utils.hpp" 30033f1e4dSEd Tanous 31ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp> 32ef4c65b7SEd Tanous #include <boost/url/format.hpp> 331214b7e7SGunnar Mills 347a1dbc48SGeorge Liu #include <array> 35*3dfed536SEd Tanous #include <cstddef> 36ce73d5c8SSunitha Harish #include <memory> 37a24526dcSEd Tanous #include <optional> 383544d2a7SEd Tanous #include <ranges> 39ab6554f1SJoshi-Mansi #include <regex> 407a1dbc48SGeorge Liu #include <string_view> 41*3dfed536SEd Tanous #include <variant> 4277179532SEd Tanous #include <vector> 439391bb9cSRapkiewicz, Pawel 441abe55efSEd Tanous namespace redfish 451abe55efSEd Tanous { 469391bb9cSRapkiewicz, Pawel 474a0cb85cSEd Tanous enum class LinkType 484a0cb85cSEd Tanous { 494a0cb85cSEd Tanous Local, 504a0cb85cSEd Tanous Global 514a0cb85cSEd Tanous }; 529391bb9cSRapkiewicz, Pawel 539391bb9cSRapkiewicz, Pawel /** 549391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 559391bb9cSRapkiewicz, Pawel */ 561abe55efSEd Tanous struct IPv4AddressData 571abe55efSEd Tanous { 58179db1d7SKowalski, Kamil std::string id; 594a0cb85cSEd Tanous std::string address; 604a0cb85cSEd Tanous std::string domain; 614a0cb85cSEd Tanous std::string gateway; 629391bb9cSRapkiewicz, Pawel std::string netmask; 639391bb9cSRapkiewicz, Pawel std::string origin; 6477179532SEd Tanous LinkType linktype{}; 6577179532SEd Tanous bool isActive{}; 669391bb9cSRapkiewicz, Pawel }; 679391bb9cSRapkiewicz, Pawel 689391bb9cSRapkiewicz, Pawel /** 69e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 70e48c0fc5SRavi Teja */ 71e48c0fc5SRavi Teja struct IPv6AddressData 72e48c0fc5SRavi Teja { 73e48c0fc5SRavi Teja std::string id; 74e48c0fc5SRavi Teja std::string address; 75e48c0fc5SRavi Teja std::string origin; 7677179532SEd Tanous uint8_t prefixLength = 0; 77e48c0fc5SRavi Teja }; 78ce73d5c8SSunitha Harish 79ce73d5c8SSunitha Harish /** 80ce73d5c8SSunitha Harish * Structure for keeping static route data required by Redfish 81ce73d5c8SSunitha Harish */ 82ce73d5c8SSunitha Harish struct StaticGatewayData 83ce73d5c8SSunitha Harish { 84ce73d5c8SSunitha Harish std::string id; 85ce73d5c8SSunitha Harish std::string gateway; 86ce73d5c8SSunitha Harish size_t prefixLength = 0; 87ce73d5c8SSunitha Harish std::string protocol; 88ce73d5c8SSunitha Harish }; 89ce73d5c8SSunitha Harish 90e48c0fc5SRavi Teja /** 919391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 929391bb9cSRapkiewicz, Pawel * available from DBus 939391bb9cSRapkiewicz, Pawel */ 941abe55efSEd Tanous struct EthernetInterfaceData 951abe55efSEd Tanous { 964a0cb85cSEd Tanous uint32_t speed; 9735fb5311STejas Patil size_t mtuSize; 9882695a5bSJiaqing Zhao bool autoNeg; 99e4588158SJishnu CM bool dnsv4Enabled; 100e4588158SJishnu CM bool dnsv6Enabled; 10191c441ecSRavi Teja bool domainv4Enabled; 10291c441ecSRavi Teja bool domainv6Enabled; 103e4588158SJishnu CM bool ntpv4Enabled; 104e4588158SJishnu CM bool ntpv6Enabled; 105e4588158SJishnu CM bool hostNamev4Enabled; 106e4588158SJishnu CM bool hostNamev6Enabled; 107aa05fb27SJohnathan Mantey bool linkUp; 108eeedda23SJohnathan Mantey bool nicEnabled; 109b10d8db0SRavi Teja bool ipv6AcceptRa; 11082695a5bSJiaqing Zhao std::string dhcpEnabled; 1111f8c7b5dSJohnathan Mantey std::string operatingMode; 11282695a5bSJiaqing Zhao std::string hostName; 11382695a5bSJiaqing Zhao std::string defaultGateway; 11482695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 115ce73d5c8SSunitha Harish std::string ipv6StaticDefaultGateway; 11682695a5bSJiaqing Zhao std::string macAddress; 11717e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 1180f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 1190f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 120d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1219391bb9cSRapkiewicz, Pawel }; 1229391bb9cSRapkiewicz, Pawel 1231f8c7b5dSJohnathan Mantey struct DHCPParameters 1241f8c7b5dSJohnathan Mantey { 1251f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 12682695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 12782695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 12882695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1291f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1301f8c7b5dSJohnathan Mantey }; 1311f8c7b5dSJohnathan Mantey 1329391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1339391bb9cSRapkiewicz, Pawel // into full dot notation 1341abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1351abe55efSEd Tanous { 1369391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1379391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1389391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1399391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1409391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1419391bb9cSRapkiewicz, Pawel return netmask; 1429391bb9cSRapkiewicz, Pawel } 1439391bb9cSRapkiewicz, Pawel 14482695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1451f8c7b5dSJohnathan Mantey bool isIPv4) 1461f8c7b5dSJohnathan Mantey { 1471f8c7b5dSJohnathan Mantey if (isIPv4) 1481f8c7b5dSJohnathan Mantey { 1491f8c7b5dSJohnathan Mantey return ( 1501f8c7b5dSJohnathan Mantey (inputDHCP == 1511f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1521f8c7b5dSJohnathan Mantey (inputDHCP == 1531f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1541f8c7b5dSJohnathan Mantey } 1551f8c7b5dSJohnathan Mantey return ((inputDHCP == 1561f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1571f8c7b5dSJohnathan Mantey (inputDHCP == 1581f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1591f8c7b5dSJohnathan Mantey } 1601f8c7b5dSJohnathan Mantey 1612c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1621f8c7b5dSJohnathan Mantey { 1631f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1641f8c7b5dSJohnathan Mantey { 1651f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1661f8c7b5dSJohnathan Mantey } 1673174e4dfSEd Tanous if (isIPv4) 1681f8c7b5dSJohnathan Mantey { 1691f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1701f8c7b5dSJohnathan Mantey } 1713174e4dfSEd Tanous if (isIPv6) 1721f8c7b5dSJohnathan Mantey { 1731f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1741f8c7b5dSJohnathan Mantey } 1751f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1761f8c7b5dSJohnathan Mantey } 1771f8c7b5dSJohnathan Mantey 1784a0cb85cSEd Tanous inline std::string 1794a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string& inputOrigin, 1804a0cb85cSEd Tanous bool isIPv4) 1811abe55efSEd Tanous { 1824a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1831abe55efSEd Tanous { 1844a0cb85cSEd Tanous return "Static"; 1859391bb9cSRapkiewicz, Pawel } 1864a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1871abe55efSEd Tanous { 1884a0cb85cSEd Tanous if (isIPv4) 1891abe55efSEd Tanous { 1904a0cb85cSEd Tanous return "IPv4LinkLocal"; 1911abe55efSEd Tanous } 1924a0cb85cSEd Tanous return "LinkLocal"; 1939391bb9cSRapkiewicz, Pawel } 1944a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1951abe55efSEd Tanous { 1964a0cb85cSEd Tanous if (isIPv4) 1974a0cb85cSEd Tanous { 1984a0cb85cSEd Tanous return "DHCP"; 1994a0cb85cSEd Tanous } 2004a0cb85cSEd Tanous return "DHCPv6"; 2014a0cb85cSEd Tanous } 2024a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 2034a0cb85cSEd Tanous { 2044a0cb85cSEd Tanous return "SLAAC"; 2054a0cb85cSEd Tanous } 2064a0cb85cSEd Tanous return ""; 2074a0cb85cSEd Tanous } 2084a0cb85cSEd Tanous 20902cad96eSEd Tanous inline bool extractEthernetInterfaceData( 21002cad96eSEd Tanous const std::string& ethifaceId, 21102cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 2124a0cb85cSEd Tanous EthernetInterfaceData& ethData) 2134a0cb85cSEd Tanous { 2144c9afe43SEd Tanous bool idFound = false; 21502cad96eSEd Tanous for (const auto& objpath : dbusData) 2164a0cb85cSEd Tanous { 21702cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 2184a0cb85cSEd Tanous { 21981ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 220029573d4SEd Tanous { 2214c9afe43SEd Tanous idFound = true; 2224a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2234a0cb85cSEd Tanous { 2244a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2254a0cb85cSEd Tanous { 2264a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2274a0cb85cSEd Tanous { 2284a0cb85cSEd Tanous const std::string* mac = 229abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2304a0cb85cSEd Tanous if (mac != nullptr) 2314a0cb85cSEd Tanous { 23282695a5bSJiaqing Zhao ethData.macAddress = *mac; 2334a0cb85cSEd Tanous } 2344a0cb85cSEd Tanous } 2354a0cb85cSEd Tanous } 2364a0cb85cSEd Tanous } 2374a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2384a0cb85cSEd Tanous { 2394a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2404a0cb85cSEd Tanous { 2414a0cb85cSEd Tanous if (propertyPair.first == "Id") 2424a0cb85cSEd Tanous { 2431b6b96c5SEd Tanous const uint32_t* id = 244abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2454a0cb85cSEd Tanous if (id != nullptr) 2464a0cb85cSEd Tanous { 24717e22024SJiaqing Zhao ethData.vlanId = *id; 2484a0cb85cSEd Tanous } 2494a0cb85cSEd Tanous } 2504a0cb85cSEd Tanous } 2514a0cb85cSEd Tanous } 2524a0cb85cSEd Tanous else if (ifacePair.first == 2534a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2544a0cb85cSEd Tanous { 2554a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2564a0cb85cSEd Tanous { 2574a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2584a0cb85cSEd Tanous { 2592c70f800SEd Tanous const bool* autoNeg = 260abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2612c70f800SEd Tanous if (autoNeg != nullptr) 2624a0cb85cSEd Tanous { 26382695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2644a0cb85cSEd Tanous } 2654a0cb85cSEd Tanous } 2664a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2674a0cb85cSEd Tanous { 2684a0cb85cSEd Tanous const uint32_t* speed = 269abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2704a0cb85cSEd Tanous if (speed != nullptr) 2714a0cb85cSEd Tanous { 2724a0cb85cSEd Tanous ethData.speed = *speed; 2734a0cb85cSEd Tanous } 2744a0cb85cSEd Tanous } 27535fb5311STejas Patil else if (propertyPair.first == "MTU") 27635fb5311STejas Patil { 2773e7a8da6SAnthony const size_t* mtuSize = 2783e7a8da6SAnthony std::get_if<size_t>(&propertyPair.second); 27935fb5311STejas Patil if (mtuSize != nullptr) 28035fb5311STejas Patil { 28135fb5311STejas Patil ethData.mtuSize = *mtuSize; 28235fb5311STejas Patil } 28335fb5311STejas Patil } 284aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 285aa05fb27SJohnathan Mantey { 286aa05fb27SJohnathan Mantey const bool* linkUp = 287aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 288aa05fb27SJohnathan Mantey if (linkUp != nullptr) 289aa05fb27SJohnathan Mantey { 290aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 291aa05fb27SJohnathan Mantey } 292aa05fb27SJohnathan Mantey } 293eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 294eeedda23SJohnathan Mantey { 295eeedda23SJohnathan Mantey const bool* nicEnabled = 296eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 297eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 298eeedda23SJohnathan Mantey { 299eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 300eeedda23SJohnathan Mantey } 301eeedda23SJohnathan Mantey } 302b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 303b10d8db0SRavi Teja { 304b10d8db0SRavi Teja const bool* ipv6AcceptRa = 305b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 306b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 307b10d8db0SRavi Teja { 308b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 309b10d8db0SRavi Teja } 310b10d8db0SRavi Teja } 311f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 312029573d4SEd Tanous { 313029573d4SEd Tanous const std::vector<std::string>* nameservers = 3148d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 315029573d4SEd Tanous &propertyPair.second); 316029573d4SEd Tanous if (nameservers != nullptr) 317029573d4SEd Tanous { 318f23b7296SEd Tanous ethData.nameServers = *nameservers; 3190f6efdc1Smanojkiran.eda@gmail.com } 3200f6efdc1Smanojkiran.eda@gmail.com } 3210f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3220f6efdc1Smanojkiran.eda@gmail.com { 3230f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3248d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3250f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3260f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3270f6efdc1Smanojkiran.eda@gmail.com { 328f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3294a0cb85cSEd Tanous } 3304a0cb85cSEd Tanous } 3312a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3322a133282Smanojkiraneda { 3332c70f800SEd Tanous const std::string* dhcpEnabled = 3341f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3352c70f800SEd Tanous if (dhcpEnabled != nullptr) 3362a133282Smanojkiraneda { 33782695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3382a133282Smanojkiraneda } 3392a133282Smanojkiraneda } 340d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 341d24bfc7aSJennifer Lee { 342d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3438d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 344d24bfc7aSJennifer Lee &propertyPair.second); 345d24bfc7aSJennifer Lee if (domainNames != nullptr) 346d24bfc7aSJennifer Lee { 347f23b7296SEd Tanous ethData.domainnames = *domainNames; 348d24bfc7aSJennifer Lee } 349d24bfc7aSJennifer Lee } 3509010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3519010ec2eSRavi Teja { 3529010ec2eSRavi Teja const std::string* defaultGateway = 3539010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3549010ec2eSRavi Teja if (defaultGateway != nullptr) 3559010ec2eSRavi Teja { 3569010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3579010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3589010ec2eSRavi Teja { 35982695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3609010ec2eSRavi Teja } 3619010ec2eSRavi Teja else 3629010ec2eSRavi Teja { 36382695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3649010ec2eSRavi Teja } 3659010ec2eSRavi Teja } 3669010ec2eSRavi Teja } 3679010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3689010ec2eSRavi Teja { 3699010ec2eSRavi Teja const std::string* defaultGateway6 = 3709010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3719010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3729010ec2eSRavi Teja { 3739010ec2eSRavi Teja std::string defaultGateway6Str = 3749010ec2eSRavi Teja *defaultGateway6; 3759010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3769010ec2eSRavi Teja { 37782695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3789010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3799010ec2eSRavi Teja } 3809010ec2eSRavi Teja else 3819010ec2eSRavi Teja { 38282695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3839010ec2eSRavi Teja defaultGateway6Str; 3849010ec2eSRavi Teja } 3859010ec2eSRavi Teja } 3869010ec2eSRavi Teja } 387029573d4SEd Tanous } 388029573d4SEd Tanous } 389029573d4SEd Tanous } 3901f8c7b5dSJohnathan Mantey 391e4588158SJishnu CM sdbusplus::message::object_path path( 392e4588158SJishnu CM "/xyz/openbmc_project/network"); 393e4588158SJishnu CM sdbusplus::message::object_path dhcp4Path = path / ethifaceId / 394e4588158SJishnu CM "dhcp4"; 395e4588158SJishnu CM 396e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp4Path) 3971f8c7b5dSJohnathan Mantey { 3981f8c7b5dSJohnathan Mantey if (ifacePair.first == 3991f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 4001f8c7b5dSJohnathan Mantey { 4011f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 4021f8c7b5dSJohnathan Mantey { 4031f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 4041f8c7b5dSJohnathan Mantey { 4052c70f800SEd Tanous const bool* dnsEnabled = 4061f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4072c70f800SEd Tanous if (dnsEnabled != nullptr) 4081f8c7b5dSJohnathan Mantey { 409e4588158SJishnu CM ethData.dnsv4Enabled = *dnsEnabled; 4101f8c7b5dSJohnathan Mantey } 4111f8c7b5dSJohnathan Mantey } 41291c441ecSRavi Teja else if (propertyPair.first == "DomainEnabled") 41391c441ecSRavi Teja { 41491c441ecSRavi Teja const bool* domainEnabled = 41591c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 41691c441ecSRavi Teja if (domainEnabled != nullptr) 41791c441ecSRavi Teja { 41891c441ecSRavi Teja ethData.domainv4Enabled = *domainEnabled; 41991c441ecSRavi Teja } 42091c441ecSRavi Teja } 4211f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 4221f8c7b5dSJohnathan Mantey { 4232c70f800SEd Tanous const bool* ntpEnabled = 4241f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4252c70f800SEd Tanous if (ntpEnabled != nullptr) 4261f8c7b5dSJohnathan Mantey { 427e4588158SJishnu CM ethData.ntpv4Enabled = *ntpEnabled; 4281f8c7b5dSJohnathan Mantey } 4291f8c7b5dSJohnathan Mantey } 4301f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 4311f8c7b5dSJohnathan Mantey { 4322c70f800SEd Tanous const bool* hostNameEnabled = 4331f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4342c70f800SEd Tanous if (hostNameEnabled != nullptr) 4351f8c7b5dSJohnathan Mantey { 436e4588158SJishnu CM ethData.hostNamev4Enabled = *hostNameEnabled; 437e4588158SJishnu CM } 438e4588158SJishnu CM } 439e4588158SJishnu CM } 440e4588158SJishnu CM } 441e4588158SJishnu CM } 442e4588158SJishnu CM 443e4588158SJishnu CM sdbusplus::message::object_path dhcp6Path = path / ethifaceId / 444e4588158SJishnu CM "dhcp6"; 445e4588158SJishnu CM 446e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp6Path) 447e4588158SJishnu CM { 448e4588158SJishnu CM if (ifacePair.first == 449e4588158SJishnu CM "xyz.openbmc_project.Network.DHCPConfiguration") 450e4588158SJishnu CM { 451e4588158SJishnu CM for (const auto& propertyPair : ifacePair.second) 452e4588158SJishnu CM { 453e4588158SJishnu CM if (propertyPair.first == "DNSEnabled") 454e4588158SJishnu CM { 455e4588158SJishnu CM const bool* dnsEnabled = 456e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 457e4588158SJishnu CM if (dnsEnabled != nullptr) 458e4588158SJishnu CM { 459e4588158SJishnu CM ethData.dnsv6Enabled = *dnsEnabled; 460e4588158SJishnu CM } 461e4588158SJishnu CM } 46291c441ecSRavi Teja if (propertyPair.first == "DomainEnabled") 46391c441ecSRavi Teja { 46491c441ecSRavi Teja const bool* domainEnabled = 46591c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 46691c441ecSRavi Teja if (domainEnabled != nullptr) 46791c441ecSRavi Teja { 46891c441ecSRavi Teja ethData.domainv6Enabled = *domainEnabled; 46991c441ecSRavi Teja } 47091c441ecSRavi Teja } 471e4588158SJishnu CM else if (propertyPair.first == "NTPEnabled") 472e4588158SJishnu CM { 473e4588158SJishnu CM const bool* ntpEnabled = 474e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 475e4588158SJishnu CM if (ntpEnabled != nullptr) 476e4588158SJishnu CM { 477e4588158SJishnu CM ethData.ntpv6Enabled = *ntpEnabled; 478e4588158SJishnu CM } 479e4588158SJishnu CM } 480e4588158SJishnu CM else if (propertyPair.first == "HostNameEnabled") 481e4588158SJishnu CM { 482e4588158SJishnu CM const bool* hostNameEnabled = 483e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 484e4588158SJishnu CM if (hostNameEnabled != nullptr) 485e4588158SJishnu CM { 486e4588158SJishnu CM ethData.hostNamev6Enabled = *hostNameEnabled; 4871f8c7b5dSJohnathan Mantey } 4881f8c7b5dSJohnathan Mantey } 4891f8c7b5dSJohnathan Mantey } 4901f8c7b5dSJohnathan Mantey } 4911f8c7b5dSJohnathan Mantey } 492029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 493029573d4SEd Tanous // to check eth number 494029573d4SEd Tanous if (ifacePair.first == 4954a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 4964a0cb85cSEd Tanous { 4974a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 4984a0cb85cSEd Tanous { 4994a0cb85cSEd Tanous if (propertyPair.first == "HostName") 5004a0cb85cSEd Tanous { 5014a0cb85cSEd Tanous const std::string* hostname = 5028d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 5034a0cb85cSEd Tanous if (hostname != nullptr) 5044a0cb85cSEd Tanous { 50582695a5bSJiaqing Zhao ethData.hostName = *hostname; 5064a0cb85cSEd Tanous } 5074a0cb85cSEd Tanous } 5084a0cb85cSEd Tanous } 5094a0cb85cSEd Tanous } 5104a0cb85cSEd Tanous } 5114a0cb85cSEd Tanous } 5124c9afe43SEd Tanous return idFound; 5134a0cb85cSEd Tanous } 5144a0cb85cSEd Tanous 515e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 51677179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 517711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 51877179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 519e48c0fc5SRavi Teja { 52089492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 52189492a15SPatrick Williams ethifaceId; 522e48c0fc5SRavi Teja 523e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 524e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 52581ce609eSEd Tanous for (const auto& objpath : dbusData) 526e48c0fc5SRavi Teja { 527e48c0fc5SRavi Teja // Check if proper pattern for object path appears 528353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 529e48c0fc5SRavi Teja { 5309eb808c1SEd Tanous for (const auto& interface : objpath.second) 531e48c0fc5SRavi Teja { 532e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 533e48c0fc5SRavi Teja { 5343544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 535353163e9STony Lee [](const auto& property) { 536353163e9STony Lee return property.first == "Type"; 537353163e9STony Lee }); 538353163e9STony Lee if (type == interface.second.end()) 539353163e9STony Lee { 540353163e9STony Lee continue; 541353163e9STony Lee } 542353163e9STony Lee 543353163e9STony Lee const std::string* typeStr = 544353163e9STony Lee std::get_if<std::string>(&type->second); 545353163e9STony Lee 546353163e9STony Lee if (typeStr == nullptr || 547353163e9STony Lee (*typeStr != 548353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 549353163e9STony Lee { 550353163e9STony Lee continue; 551353163e9STony Lee } 552353163e9STony Lee 553e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 554e48c0fc5SRavi Teja // appropriate 55577179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 5562c70f800SEd Tanous ipv6Address.id = 557353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5589eb808c1SEd Tanous for (const auto& property : interface.second) 559e48c0fc5SRavi Teja { 560e48c0fc5SRavi Teja if (property.first == "Address") 561e48c0fc5SRavi Teja { 562e48c0fc5SRavi Teja const std::string* address = 563e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 564e48c0fc5SRavi Teja if (address != nullptr) 565e48c0fc5SRavi Teja { 5662c70f800SEd Tanous ipv6Address.address = *address; 567e48c0fc5SRavi Teja } 568e48c0fc5SRavi Teja } 569e48c0fc5SRavi Teja else if (property.first == "Origin") 570e48c0fc5SRavi Teja { 571e48c0fc5SRavi Teja const std::string* origin = 572e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 573e48c0fc5SRavi Teja if (origin != nullptr) 574e48c0fc5SRavi Teja { 5752c70f800SEd Tanous ipv6Address.origin = 576e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 577e48c0fc5SRavi Teja false); 578e48c0fc5SRavi Teja } 579e48c0fc5SRavi Teja } 580e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 581e48c0fc5SRavi Teja { 582e48c0fc5SRavi Teja const uint8_t* prefix = 583e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 584e48c0fc5SRavi Teja if (prefix != nullptr) 585e48c0fc5SRavi Teja { 5862c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 587e48c0fc5SRavi Teja } 588e48c0fc5SRavi Teja } 589889ff694SAsmitha Karunanithi else if (property.first == "Type" || 590889ff694SAsmitha Karunanithi property.first == "Gateway") 591889ff694SAsmitha Karunanithi { 592889ff694SAsmitha Karunanithi // Type & Gateway is not used 593889ff694SAsmitha Karunanithi } 594e48c0fc5SRavi Teja else 595e48c0fc5SRavi Teja { 59662598e31SEd Tanous BMCWEB_LOG_ERROR( 59762598e31SEd Tanous "Got extra property: {} on the {} object", 59862598e31SEd Tanous property.first, objpath.first.str); 599e48c0fc5SRavi Teja } 600e48c0fc5SRavi Teja } 601e48c0fc5SRavi Teja } 602e48c0fc5SRavi Teja } 603e48c0fc5SRavi Teja } 604e48c0fc5SRavi Teja } 605e48c0fc5SRavi Teja } 606e48c0fc5SRavi Teja 6074a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 60877179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 609711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 61077179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 6114a0cb85cSEd Tanous { 61289492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 61389492a15SPatrick Williams ethifaceId; 6144a0cb85cSEd Tanous 6154a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 6164a0cb85cSEd Tanous // single ethernet interface, loop over all of them 61781ce609eSEd Tanous for (const auto& objpath : dbusData) 6184a0cb85cSEd Tanous { 6194a0cb85cSEd Tanous // Check if proper pattern for object path appears 620353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 6214a0cb85cSEd Tanous { 6229eb808c1SEd Tanous for (const auto& interface : objpath.second) 6234a0cb85cSEd Tanous { 6244a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 6254a0cb85cSEd Tanous { 6263544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 627353163e9STony Lee [](const auto& property) { 628353163e9STony Lee return property.first == "Type"; 629353163e9STony Lee }); 630353163e9STony Lee if (type == interface.second.end()) 631353163e9STony Lee { 632353163e9STony Lee continue; 633353163e9STony Lee } 634353163e9STony Lee 635353163e9STony Lee const std::string* typeStr = 636353163e9STony Lee std::get_if<std::string>(&type->second); 637353163e9STony Lee 638353163e9STony Lee if (typeStr == nullptr || 639353163e9STony Lee (*typeStr != 640353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 641353163e9STony Lee { 642353163e9STony Lee continue; 643353163e9STony Lee } 644353163e9STony Lee 6454a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 6464a0cb85cSEd Tanous // appropriate 64777179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 6482c70f800SEd Tanous ipv4Address.id = 649353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 6509eb808c1SEd Tanous for (const auto& property : interface.second) 6514a0cb85cSEd Tanous { 6524a0cb85cSEd Tanous if (property.first == "Address") 6534a0cb85cSEd Tanous { 6544a0cb85cSEd Tanous const std::string* address = 655abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6564a0cb85cSEd Tanous if (address != nullptr) 6574a0cb85cSEd Tanous { 6582c70f800SEd Tanous ipv4Address.address = *address; 6594a0cb85cSEd Tanous } 6604a0cb85cSEd Tanous } 6614a0cb85cSEd Tanous else if (property.first == "Origin") 6624a0cb85cSEd Tanous { 6634a0cb85cSEd Tanous const std::string* origin = 664abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6654a0cb85cSEd Tanous if (origin != nullptr) 6664a0cb85cSEd Tanous { 6672c70f800SEd Tanous ipv4Address.origin = 6684a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 6694a0cb85cSEd Tanous true); 6704a0cb85cSEd Tanous } 6714a0cb85cSEd Tanous } 6724a0cb85cSEd Tanous else if (property.first == "PrefixLength") 6734a0cb85cSEd Tanous { 6744a0cb85cSEd Tanous const uint8_t* mask = 675abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 6764a0cb85cSEd Tanous if (mask != nullptr) 6774a0cb85cSEd Tanous { 6784a0cb85cSEd Tanous // convert it to the string 6792c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 6804a0cb85cSEd Tanous } 6814a0cb85cSEd Tanous } 682889ff694SAsmitha Karunanithi else if (property.first == "Type" || 683889ff694SAsmitha Karunanithi property.first == "Gateway") 684889ff694SAsmitha Karunanithi { 685889ff694SAsmitha Karunanithi // Type & Gateway is not used 686889ff694SAsmitha Karunanithi } 6874a0cb85cSEd Tanous else 6884a0cb85cSEd Tanous { 68962598e31SEd Tanous BMCWEB_LOG_ERROR( 69062598e31SEd Tanous "Got extra property: {} on the {} object", 69162598e31SEd Tanous property.first, objpath.first.str); 6924a0cb85cSEd Tanous } 6934a0cb85cSEd Tanous } 6944a0cb85cSEd Tanous // Check if given address is local, or global 6952c70f800SEd Tanous ipv4Address.linktype = 69611ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 69718659d10SJohnathan Mantey ? LinkType::Local 69818659d10SJohnathan Mantey : LinkType::Global; 6994a0cb85cSEd Tanous } 7004a0cb85cSEd Tanous } 7014a0cb85cSEd Tanous } 7024a0cb85cSEd Tanous } 7034a0cb85cSEd Tanous } 704588c3f0dSKowalski, Kamil 705588c3f0dSKowalski, Kamil /** 70601784826SJohnathan Mantey * @brief Deletes given IPv4 interface 707179db1d7SKowalski, Kamil * 708179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 709179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 710179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 711179db1d7SKowalski, Kamil * 712179db1d7SKowalski, Kamil * @return None 713179db1d7SKowalski, Kamil */ 7149c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 7159c5e585cSRavi Teja const std::string& ipHash, 7168d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7171abe55efSEd Tanous { 71855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7195e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 7201abe55efSEd Tanous if (ec) 7211abe55efSEd Tanous { 722a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7231abe55efSEd Tanous } 724179db1d7SKowalski, Kamil }, 725179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 7269c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 727179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 728179db1d7SKowalski, Kamil } 729179db1d7SKowalski, Kamil 730244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway( 731244b6d5bSGunnar Mills const std::string& ifaceId, const std::string& gateway, 732244b6d5bSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7339010ec2eSRavi Teja { 734d02aad39SEd Tanous setDbusProperty( 735d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 736d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 737d02aad39SEd Tanous ifaceId, 7389ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 739d02aad39SEd Tanous "Gateway", gateway); 7409010ec2eSRavi Teja } 741179db1d7SKowalski, Kamil /** 74201784826SJohnathan Mantey * @brief Creates a static IPv4 entry 743179db1d7SKowalski, Kamil * 74401784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 74501784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 74601784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 74701784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 748179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 749179db1d7SKowalski, Kamil * 750179db1d7SKowalski, Kamil * @return None 751179db1d7SKowalski, Kamil */ 752cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 753cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7548d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7551abe55efSEd Tanous { 7565a39f77aSPatrick Williams auto createIpHandler = [asyncResp, ifaceId, 7575a39f77aSPatrick Williams gateway](const boost::system::error_code& ec) { 7581abe55efSEd Tanous if (ec) 7591abe55efSEd Tanous { 760a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7619010ec2eSRavi Teja return; 762179db1d7SKowalski, Kamil } 7639010ec2eSRavi Teja updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); 7649010ec2eSRavi Teja }; 7659010ec2eSRavi Teja 7669010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 7679010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 768179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 769179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 77001784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 771179db1d7SKowalski, Kamil gateway); 772179db1d7SKowalski, Kamil } 773e48c0fc5SRavi Teja 774e48c0fc5SRavi Teja /** 77501784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 77601784826SJohnathan Mantey * static IPv6 entry 77701784826SJohnathan Mantey * 77801784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 77901784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 78001784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 78101784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 78201784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 78301784826SJohnathan Mantey * 78401784826SJohnathan Mantey * @return None 78501784826SJohnathan Mantey */ 7869c5e585cSRavi Teja 7879c5e585cSRavi Teja enum class IpVersion 7889c5e585cSRavi Teja { 7899c5e585cSRavi Teja IpV4, 7909c5e585cSRavi Teja IpV6 7919c5e585cSRavi Teja }; 7929c5e585cSRavi Teja 7939c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 7949c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 7958d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 7969c5e585cSRavi Teja const std::string& gateway, 7978d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 79801784826SJohnathan Mantey { 79901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8009c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 8019c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 80201784826SJohnathan Mantey if (ec) 80301784826SJohnathan Mantey { 80401784826SJohnathan Mantey messages::internalError(asyncResp->res); 80501784826SJohnathan Mantey } 8069c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 8079c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 80801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8095e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 81023a21a1cSEd Tanous if (ec2) 81101784826SJohnathan Mantey { 81201784826SJohnathan Mantey messages::internalError(asyncResp->res); 81301784826SJohnathan Mantey } 81401784826SJohnathan Mantey }, 81501784826SJohnathan Mantey "xyz.openbmc_project.Network", 81601784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 8179c5e585cSRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address, 8189c5e585cSRavi Teja prefixLength, gateway); 81901784826SJohnathan Mantey }, 82001784826SJohnathan Mantey "xyz.openbmc_project.Network", 8219c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 82201784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 82301784826SJohnathan Mantey } 82401784826SJohnathan Mantey 825ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData( 826ce73d5c8SSunitha Harish const std::string& ethifaceId, 827ce73d5c8SSunitha Harish const dbus::utility::ManagedObjectType& dbusData, 828ce73d5c8SSunitha Harish std::vector<StaticGatewayData>& staticGatewayConfig) 829ce73d5c8SSunitha Harish { 830ce73d5c8SSunitha Harish std::string staticGatewayPathStart("/xyz/openbmc_project/network/"); 831ce73d5c8SSunitha Harish staticGatewayPathStart += ethifaceId; 832ce73d5c8SSunitha Harish 833ce73d5c8SSunitha Harish for (const auto& objpath : dbusData) 834ce73d5c8SSunitha Harish { 835ce73d5c8SSunitha Harish if (!std::string_view(objpath.first.str) 836ce73d5c8SSunitha Harish .starts_with(staticGatewayPathStart)) 837ce73d5c8SSunitha Harish { 838ce73d5c8SSunitha Harish continue; 839ce73d5c8SSunitha Harish } 840ce73d5c8SSunitha Harish for (const auto& interface : objpath.second) 841ce73d5c8SSunitha Harish { 842ce73d5c8SSunitha Harish if (interface.first != "xyz.openbmc_project.Network.StaticGateway") 843ce73d5c8SSunitha Harish { 844ce73d5c8SSunitha Harish continue; 845ce73d5c8SSunitha Harish } 846ce73d5c8SSunitha Harish StaticGatewayData& staticGateway = 847ce73d5c8SSunitha Harish staticGatewayConfig.emplace_back(); 848ce73d5c8SSunitha Harish staticGateway.id = objpath.first.filename(); 849ce73d5c8SSunitha Harish 850ce73d5c8SSunitha Harish bool success = sdbusplus::unpackPropertiesNoThrow( 851ce73d5c8SSunitha Harish redfish::dbus_utils::UnpackErrorPrinter(), interface.second, 852ce73d5c8SSunitha Harish "Gateway", staticGateway.gateway, "PrefixLength", 853ce73d5c8SSunitha Harish staticGateway.prefixLength, "ProtocolType", 854ce73d5c8SSunitha Harish staticGateway.protocol); 855ce73d5c8SSunitha Harish if (!success) 856ce73d5c8SSunitha Harish { 857ce73d5c8SSunitha Harish return false; 858ce73d5c8SSunitha Harish } 859ce73d5c8SSunitha Harish } 860ce73d5c8SSunitha Harish } 861ce73d5c8SSunitha Harish return true; 862ce73d5c8SSunitha Harish } 863ce73d5c8SSunitha Harish 86401784826SJohnathan Mantey /** 865e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 866e48c0fc5SRavi Teja * 867e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 868e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 869e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 870e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 871e48c0fc5SRavi Teja * 872e48c0fc5SRavi Teja * @return None 873e48c0fc5SRavi Teja */ 87401784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 87501784826SJohnathan Mantey const std::string& address, 8768d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 877e48c0fc5SRavi Teja { 878ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 879ce73d5c8SSunitha Harish path /= ifaceId; 880ce73d5c8SSunitha Harish 8815a39f77aSPatrick Williams auto createIpHandler = [asyncResp, 8825a39f77aSPatrick Williams address](const boost::system::error_code& ec) { 883e48c0fc5SRavi Teja if (ec) 884e48c0fc5SRavi Teja { 885fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 886fc23ef8aSNitin Kumar Kotania { 887fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 888fc23ef8aSNitin Kumar Kotania "Address"); 889fc23ef8aSNitin Kumar Kotania } 890fc23ef8aSNitin Kumar Kotania else 891fc23ef8aSNitin Kumar Kotania { 892e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 893e48c0fc5SRavi Teja } 894fc23ef8aSNitin Kumar Kotania } 895e48c0fc5SRavi Teja }; 896ce73d5c8SSunitha Harish // Passing null for gateway, as per redfish spec IPv6StaticAddresses 897ce73d5c8SSunitha Harish // object does not have associated gateway property 898e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 899ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 900e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 901e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 902e48c0fc5SRavi Teja ""); 903e48c0fc5SRavi Teja } 904e48c0fc5SRavi Teja 905179db1d7SKowalski, Kamil /** 906ce73d5c8SSunitha Harish * @brief Deletes given IPv6 Static Gateway 907ce73d5c8SSunitha Harish * 908ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be deleted 909ce73d5c8SSunitha Harish * @param[in] ipHash DBus Hash id of IP that should be deleted 910ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 911ce73d5c8SSunitha Harish * 912ce73d5c8SSunitha Harish * @return None 913ce73d5c8SSunitha Harish */ 914ce73d5c8SSunitha Harish inline void 915ce73d5c8SSunitha Harish deleteIPv6Gateway(std::string_view gatewayId, 916ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 917ce73d5c8SSunitha Harish { 918ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 919ce73d5c8SSunitha Harish path /= gatewayId; 920ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 921ce73d5c8SSunitha Harish [asyncResp](const boost::system::error_code& ec) { 922ce73d5c8SSunitha Harish if (ec) 923ce73d5c8SSunitha Harish { 924ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 925ce73d5c8SSunitha Harish } 926ce73d5c8SSunitha Harish }, 927ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 928ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 929ce73d5c8SSunitha Harish } 930ce73d5c8SSunitha Harish 931ce73d5c8SSunitha Harish /** 932ce73d5c8SSunitha Harish * @brief Creates IPv6 static default gateway with given data 933ce73d5c8SSunitha Harish * 934ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be added 935ce73d5c8SSunitha Harish * @param[in] prefixLength Prefix length that needs to be added 936ce73d5c8SSunitha Harish * @param[in] gateway Gateway address that needs to be added 937ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 938ce73d5c8SSunitha Harish * 939ce73d5c8SSunitha Harish * @return None 940ce73d5c8SSunitha Harish */ 941ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway( 942ce73d5c8SSunitha Harish std::string_view ifaceId, size_t prefixLength, std::string_view gateway, 943ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 944ce73d5c8SSunitha Harish { 945ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 946ce73d5c8SSunitha Harish path /= ifaceId; 947ce73d5c8SSunitha Harish auto createIpHandler = [asyncResp](const boost::system::error_code& ec) { 948ce73d5c8SSunitha Harish if (ec) 949ce73d5c8SSunitha Harish { 950ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 951ce73d5c8SSunitha Harish } 952ce73d5c8SSunitha Harish }; 953ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 954ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 955ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway", 956ce73d5c8SSunitha Harish gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6"); 957ce73d5c8SSunitha Harish } 958ce73d5c8SSunitha Harish 959ce73d5c8SSunitha Harish /** 960ce73d5c8SSunitha Harish * @brief Deletes the IPv6 default gateway entry for this interface and 961ce73d5c8SSunitha Harish * creates a replacement IPv6 default gateway entry 962ce73d5c8SSunitha Harish * 963ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface upon which to create the IPv6 964ce73d5c8SSunitha Harish * entry 965ce73d5c8SSunitha Harish * @param[in] gateway IPv6 gateway to assign to this interface 966ce73d5c8SSunitha Harish * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 967ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 968ce73d5c8SSunitha Harish * 969ce73d5c8SSunitha Harish * @return None 970ce73d5c8SSunitha Harish */ 971ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway( 972ce73d5c8SSunitha Harish std::string_view ifaceId, std::string_view gatewayId, 973ce73d5c8SSunitha Harish std::string_view gateway, size_t prefixLength, 974ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 975ce73d5c8SSunitha Harish { 976ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 977ce73d5c8SSunitha Harish path /= gatewayId; 978ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 979ce73d5c8SSunitha Harish [asyncResp, ifaceId, gateway, 980ce73d5c8SSunitha Harish prefixLength](const boost::system::error_code& ec) { 981ce73d5c8SSunitha Harish if (ec) 982ce73d5c8SSunitha Harish { 983ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 984ce73d5c8SSunitha Harish return; 985ce73d5c8SSunitha Harish } 986ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp); 987ce73d5c8SSunitha Harish }, 988ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 989ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 990ce73d5c8SSunitha Harish } 991ce73d5c8SSunitha Harish 992ce73d5c8SSunitha Harish /** 993ce73d5c8SSunitha Harish * @brief Sets IPv6 default gateway with given data 994ce73d5c8SSunitha Harish * 995ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose gateway should be added 996ce73d5c8SSunitha Harish * @param[in] input Contains address that needs to be added 997ce73d5c8SSunitha Harish * @param[in] staticGatewayData Current static gateways in the system 998ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 999ce73d5c8SSunitha Harish * 1000ce73d5c8SSunitha Harish * @return None 1001ce73d5c8SSunitha Harish */ 1002ce73d5c8SSunitha Harish 1003ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway( 1004*3dfed536SEd Tanous const std::string& ifaceId, 1005*3dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1006ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& staticGatewayData, 1007ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1008ce73d5c8SSunitha Harish { 1009ce73d5c8SSunitha Harish size_t entryIdx = 1; 1010ce73d5c8SSunitha Harish std::vector<StaticGatewayData>::const_iterator staticGatewayEntry = 1011ce73d5c8SSunitha Harish staticGatewayData.begin(); 1012ce73d5c8SSunitha Harish 1013*3dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 1014*3dfed536SEd Tanous input) 1015ce73d5c8SSunitha Harish { 1016ce73d5c8SSunitha Harish // find the next gateway entry 1017ce73d5c8SSunitha Harish while (staticGatewayEntry != staticGatewayData.end()) 1018ce73d5c8SSunitha Harish { 1019ce73d5c8SSunitha Harish if (staticGatewayEntry->protocol == 1020ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.IP.Protocol.IPv6") 1021ce73d5c8SSunitha Harish { 1022ce73d5c8SSunitha Harish break; 1023ce73d5c8SSunitha Harish } 1024ce73d5c8SSunitha Harish staticGatewayEntry++; 1025ce73d5c8SSunitha Harish } 1026ce73d5c8SSunitha Harish std::string pathString = "IPv6StaticDefaultGateways/" + 1027ce73d5c8SSunitha Harish std::to_string(entryIdx); 1028*3dfed536SEd Tanous nlohmann::json::object_t* obj = 1029*3dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 1030*3dfed536SEd Tanous if (obj == nullptr) 1031ce73d5c8SSunitha Harish { 1032ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1033ce73d5c8SSunitha Harish { 1034ce73d5c8SSunitha Harish messages::resourceCannotBeDeleted(asyncResp->res); 1035ce73d5c8SSunitha Harish return; 1036ce73d5c8SSunitha Harish } 1037ce73d5c8SSunitha Harish deleteIPv6Gateway(staticGatewayEntry->id, asyncResp); 1038ce73d5c8SSunitha Harish return; 1039ce73d5c8SSunitha Harish } 1040*3dfed536SEd Tanous if (obj->empty()) 1041ce73d5c8SSunitha Harish { 1042ce73d5c8SSunitha Harish // Do nothing, but make sure the entry exists. 1043ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1044ce73d5c8SSunitha Harish { 1045*3dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 1046ce73d5c8SSunitha Harish pathString); 1047ce73d5c8SSunitha Harish return; 1048ce73d5c8SSunitha Harish } 1049ce73d5c8SSunitha Harish } 1050ce73d5c8SSunitha Harish std::optional<std::string> address; 1051ce73d5c8SSunitha Harish std::optional<size_t> prefixLength; 1052ce73d5c8SSunitha Harish 1053*3dfed536SEd Tanous if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address, 1054*3dfed536SEd Tanous "PrefixLength", prefixLength)) 1055ce73d5c8SSunitha Harish { 1056ce73d5c8SSunitha Harish return; 1057ce73d5c8SSunitha Harish } 1058ce73d5c8SSunitha Harish const std::string* addr = nullptr; 1059ce73d5c8SSunitha Harish size_t prefix = 0; 1060ce73d5c8SSunitha Harish if (address) 1061ce73d5c8SSunitha Harish { 1062ce73d5c8SSunitha Harish addr = &(*address); 1063ce73d5c8SSunitha Harish } 1064ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1065ce73d5c8SSunitha Harish { 1066ce73d5c8SSunitha Harish addr = &(staticGatewayEntry->gateway); 1067ce73d5c8SSunitha Harish } 1068ce73d5c8SSunitha Harish else 1069ce73d5c8SSunitha Harish { 1070ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, pathString + "/Address"); 1071ce73d5c8SSunitha Harish return; 1072ce73d5c8SSunitha Harish } 1073ce73d5c8SSunitha Harish if (prefixLength) 1074ce73d5c8SSunitha Harish { 1075ce73d5c8SSunitha Harish prefix = *prefixLength; 1076ce73d5c8SSunitha Harish } 1077ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1078ce73d5c8SSunitha Harish { 1079ce73d5c8SSunitha Harish prefix = staticGatewayEntry->prefixLength; 1080ce73d5c8SSunitha Harish } 1081ce73d5c8SSunitha Harish else 1082ce73d5c8SSunitha Harish { 1083ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, 1084ce73d5c8SSunitha Harish pathString + "/PrefixLength"); 1085ce73d5c8SSunitha Harish return; 1086ce73d5c8SSunitha Harish } 1087ce73d5c8SSunitha Harish if (staticGatewayEntry != staticGatewayData.end()) 1088ce73d5c8SSunitha Harish { 1089ce73d5c8SSunitha Harish deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id, 1090ce73d5c8SSunitha Harish *addr, prefix, asyncResp); 1091ce73d5c8SSunitha Harish staticGatewayEntry++; 1092ce73d5c8SSunitha Harish } 1093ce73d5c8SSunitha Harish else 1094ce73d5c8SSunitha Harish { 1095ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp); 1096ce73d5c8SSunitha Harish } 1097ce73d5c8SSunitha Harish entryIdx++; 1098ce73d5c8SSunitha Harish } 1099ce73d5c8SSunitha Harish } 1100ce73d5c8SSunitha Harish 1101ce73d5c8SSunitha Harish /** 1102179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 1103179db1d7SKowalski, Kamil * Object 1104179db1d7SKowalski, Kamil * from EntityManager Network Manager 11054a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 1106179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 1107179db1d7SKowalski, Kamil * into JSON 1108179db1d7SKowalski, Kamil */ 1109179db1d7SKowalski, Kamil template <typename CallbackFunc> 111081ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 11111abe55efSEd Tanous CallbackFunc&& callback) 11121abe55efSEd Tanous { 1113f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1114f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1115f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1116f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 1117f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 11188b24275dSEd Tanous const boost::system::error_code& ec, 1119*3dfed536SEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 112055c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 112177179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 112277179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 1123ce73d5c8SSunitha Harish std::vector<StaticGatewayData> ipv6GatewayData; 1124179db1d7SKowalski, Kamil 11258b24275dSEd Tanous if (ec) 11261abe55efSEd Tanous { 1127ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1128179db1d7SKowalski, Kamil return; 1129179db1d7SKowalski, Kamil } 1130179db1d7SKowalski, Kamil 1131002d39b4SEd Tanous bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); 11324c9afe43SEd Tanous if (!found) 11334c9afe43SEd Tanous { 1134ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 11354c9afe43SEd Tanous return; 11364c9afe43SEd Tanous } 11374c9afe43SEd Tanous 11382c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 1139179db1d7SKowalski, Kamil // Fix global GW 11401abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 11411abe55efSEd Tanous { 1142c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 1143c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 11449010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 11451abe55efSEd Tanous { 114682695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 1147179db1d7SKowalski, Kamil } 1148179db1d7SKowalski, Kamil } 1149179db1d7SKowalski, Kamil 11502c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 1151ce73d5c8SSunitha Harish if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData)) 1152ce73d5c8SSunitha Harish { 1153ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1154ce73d5c8SSunitha Harish } 11554e0453b1SGunnar Mills // Finally make a callback with useful data 1156ce73d5c8SSunitha Harish callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1157f5892d0dSGeorge Liu }); 1158271584abSEd Tanous } 1159179db1d7SKowalski, Kamil 1160179db1d7SKowalski, Kamil /** 11619391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 11629391bb9cSRapkiewicz, Pawel * Manager 11631abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 11641abe55efSEd Tanous * into JSON. 11659391bb9cSRapkiewicz, Pawel */ 11669391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 11671abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 11681abe55efSEd Tanous { 1169f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1170f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1171f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1172f94c4ecfSEd Tanous [callback{std::forward<CallbackFunc>(callback)}]( 11738b24275dSEd Tanous const boost::system::error_code& ec, 1174f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 11751abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 11761abe55efSEd Tanous // ethernet interfaces 117777179532SEd Tanous std::vector<std::string> ifaceList; 11782c70f800SEd Tanous ifaceList.reserve(resp.size()); 11798b24275dSEd Tanous if (ec) 11801abe55efSEd Tanous { 11812c70f800SEd Tanous callback(false, ifaceList); 11829391bb9cSRapkiewicz, Pawel return; 11839391bb9cSRapkiewicz, Pawel } 11849391bb9cSRapkiewicz, Pawel 11859391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 11864a0cb85cSEd Tanous for (const auto& objpath : resp) 11871abe55efSEd Tanous { 11889391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 11894a0cb85cSEd Tanous for (const auto& interface : objpath.second) 11901abe55efSEd Tanous { 11911abe55efSEd Tanous // If interface is 11924a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 11934a0cb85cSEd Tanous // what we're looking for. 11949391bb9cSRapkiewicz, Pawel if (interface.first == 11951abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 11961abe55efSEd Tanous { 11972dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 11982dfd18efSEd Tanous if (ifaceId.empty()) 11991abe55efSEd Tanous { 12002dfd18efSEd Tanous continue; 12019391bb9cSRapkiewicz, Pawel } 12022dfd18efSEd Tanous // and put it into output vector. 120377179532SEd Tanous ifaceList.emplace_back(ifaceId); 12049391bb9cSRapkiewicz, Pawel } 12059391bb9cSRapkiewicz, Pawel } 12069391bb9cSRapkiewicz, Pawel } 12072c5875a2SEd Tanous 12083544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 12092c5875a2SEd Tanous 1210a434f2bdSEd Tanous // Finally make a callback with useful data 12112c70f800SEd Tanous callback(true, ifaceList); 1212f5892d0dSGeorge Liu }); 1213271584abSEd Tanous } 12149391bb9cSRapkiewicz, Pawel 12154f48d5f6SEd Tanous inline void 12164f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 12178d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12181abe55efSEd Tanous { 1219ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 1220ab6554f1SJoshi-Mansi if (hostname.length() > 255) 1221ab6554f1SJoshi-Mansi { 1222ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 1223ab6554f1SJoshi-Mansi "HostName"); 1224ab6554f1SJoshi-Mansi return; 1225ab6554f1SJoshi-Mansi } 1226d02aad39SEd Tanous setDbusProperty( 1227d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1228d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network/config"), 1229d02aad39SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1230d02aad39SEd Tanous "HostName", hostname); 1231588c3f0dSKowalski, Kamil } 1232588c3f0dSKowalski, Kamil 12334f48d5f6SEd Tanous inline void 123435fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 123535fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 123635fb5311STejas Patil { 1237d02aad39SEd Tanous sdbusplus::message::object_path objPath("/xyz/openbmc_project/network"); 1238d02aad39SEd Tanous objPath /= ifaceId; 1239d02aad39SEd Tanous setDbusProperty(asyncResp, "xyz.openbmc_project.Network", objPath, 1240d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", "MTU", 1241d02aad39SEd Tanous "MTUSize", mtuSize); 124235fb5311STejas Patil } 124335fb5311STejas Patil 124435fb5311STejas Patil inline void 12454f48d5f6SEd Tanous handleDomainnamePatch(const std::string& ifaceId, 1246bf648f77SEd Tanous const std::string& domainname, 12478d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1248ab6554f1SJoshi-Mansi { 1249ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 1250d02aad39SEd Tanous setDbusProperty( 1251d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1252d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1253d02aad39SEd Tanous ifaceId, 1254d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", "DomainName", "FQDN", 1255d02aad39SEd Tanous vectorDomainname); 1256ab6554f1SJoshi-Mansi } 1257ab6554f1SJoshi-Mansi 12584f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1259bf648f77SEd Tanous { 1260bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 12613544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1262bf648f77SEd Tanous { 1263bf648f77SEd Tanous return false; 1264bf648f77SEd Tanous } 1265bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1266bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1267bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1268bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 12694b242749SEd Tanous const static std::regex pattern( 1270bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1271bf648f77SEd Tanous 1272bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1273bf648f77SEd Tanous } 1274bf648f77SEd Tanous 12754f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1276bf648f77SEd Tanous { 1277bf648f77SEd Tanous // Can have multiple subdomains 1278bf648f77SEd Tanous // Top Level Domain's min length is 2 character 12794b242749SEd Tanous const static std::regex pattern( 12800fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1281bf648f77SEd Tanous 1282bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1283bf648f77SEd Tanous } 1284bf648f77SEd Tanous 12854f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 12868d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1287ab6554f1SJoshi-Mansi { 1288ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1289ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1290ab6554f1SJoshi-Mansi { 1291ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1292ab6554f1SJoshi-Mansi return; 1293ab6554f1SJoshi-Mansi } 1294ab6554f1SJoshi-Mansi 1295ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1296ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1297ab6554f1SJoshi-Mansi { 1298ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1299ab6554f1SJoshi-Mansi return; 1300ab6554f1SJoshi-Mansi } 1301ab6554f1SJoshi-Mansi 1302ab6554f1SJoshi-Mansi std::string hostname; 1303ab6554f1SJoshi-Mansi std::string domainname; 1304ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1305ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1306ab6554f1SJoshi-Mansi 1307ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1308ab6554f1SJoshi-Mansi { 1309ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1310ab6554f1SJoshi-Mansi return; 1311ab6554f1SJoshi-Mansi } 1312ab6554f1SJoshi-Mansi 1313ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1314ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1315ab6554f1SJoshi-Mansi } 1316ab6554f1SJoshi-Mansi 13174f48d5f6SEd Tanous inline void 13184f48d5f6SEd Tanous handleMACAddressPatch(const std::string& ifaceId, 1319bf648f77SEd Tanous const std::string& macAddress, 13208d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1321d577665bSRatan Gupta { 1322d02aad39SEd Tanous setDbusProperty( 1323d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1324d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1325d02aad39SEd Tanous ifaceId, 1326d02aad39SEd Tanous "xyz.openbmc_project.Network.MACAddress", "MACAddress", "MACAddress", 1327d02aad39SEd Tanous macAddress); 1328d577665bSRatan Gupta } 1329286b9118SJohnathan Mantey 13304f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 13314f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 13324f48d5f6SEd Tanous const bool v6Value, 13338d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1334da131a9aSJennifer Lee { 13352c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 1336d02aad39SEd Tanous setDbusProperty( 1337d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1338d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1339d02aad39SEd Tanous ifaceId, 1340d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", propertyName, "DHCPv4", 1341d02aad39SEd Tanous dhcp); 1342eeedda23SJohnathan Mantey } 1343eeedda23SJohnathan Mantey 1344e4588158SJishnu CM enum class NetworkType 1345e4588158SJishnu CM { 1346e4588158SJishnu CM dhcp4, 1347e4588158SJishnu CM dhcp6 1348e4588158SJishnu CM }; 1349e4588158SJishnu CM 1350e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1351e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1352e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1353da131a9aSJennifer Lee { 135462598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 13551847f2a0SAsmitha Karunanithi std::string redfishPropertyName; 1356e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1357e4588158SJishnu CM path /= ethifaceId; 1358e4588158SJishnu CM 1359e4588158SJishnu CM if (type == NetworkType::dhcp4) 1360e4588158SJishnu CM { 1361e4588158SJishnu CM path /= "dhcp4"; 13621847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv4"; 1363e4588158SJishnu CM } 1364e4588158SJishnu CM else 1365e4588158SJishnu CM { 1366e4588158SJishnu CM path /= "dhcp6"; 13671847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv6"; 1368e4588158SJishnu CM } 1369e4588158SJishnu CM 13701847f2a0SAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path, 13711847f2a0SAsmitha Karunanithi "xyz.openbmc_project.Network.DHCPConfiguration", 13721847f2a0SAsmitha Karunanithi propertyName, redfishPropertyName, value); 1373da131a9aSJennifer Lee } 1374d577665bSRatan Gupta 1375b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1376b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1377b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1378b10d8db0SRavi Teja { 1379b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1380b10d8db0SRavi Teja path /= ifaceId; 13811847f2a0SAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path, 13821847f2a0SAsmitha Karunanithi "xyz.openbmc_project.Network.EthernetInterface", 13831847f2a0SAsmitha Karunanithi "IPv6AcceptRA", 13841847f2a0SAsmitha Karunanithi "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 13851847f2a0SAsmitha Karunanithi ipv6AutoConfigEnabled); 1386b10d8db0SRavi Teja } 1387b10d8db0SRavi Teja 13884f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId, 13891f8c7b5dSJohnathan Mantey const EthernetInterfaceData& ethData, 1390f23b7296SEd Tanous const DHCPParameters& v4dhcpParms, 1391f23b7296SEd Tanous const DHCPParameters& v6dhcpParms, 13928d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1393da131a9aSJennifer Lee { 139482695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 139582695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1396da131a9aSJennifer Lee 13971f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 13981f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 13991f8c7b5dSJohnathan Mantey 14001f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 14011f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1402da131a9aSJennifer Lee { 1403b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 14041f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 14051f8c7b5dSJohnathan Mantey { 1406bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1407bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 14081f8c7b5dSJohnathan Mantey "OperatingMode"); 1409da131a9aSJennifer Lee return; 1410da131a9aSJennifer Lee } 1411b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 14121f8c7b5dSJohnathan Mantey } 14131f8c7b5dSJohnathan Mantey else 1414da131a9aSJennifer Lee { 14151f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 14161f8c7b5dSJohnathan Mantey } 14171f8c7b5dSJohnathan Mantey 1418e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1419e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1420e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 14211f8c7b5dSJohnathan Mantey { 1422e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 14231f8c7b5dSJohnathan Mantey } 1424e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 14251f8c7b5dSJohnathan Mantey { 1426e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 14271f8c7b5dSJohnathan Mantey } 14281f8c7b5dSJohnathan Mantey 1429e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1430e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1431e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 14321f8c7b5dSJohnathan Mantey { 1433e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 14341f8c7b5dSJohnathan Mantey } 1435e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 14361f8c7b5dSJohnathan Mantey { 1437e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 14381f8c7b5dSJohnathan Mantey } 14391f8c7b5dSJohnathan Mantey 144091c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 144191c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1442e4588158SJishnu CM if (v4dhcpParms.useDomainName) 14431f8c7b5dSJohnathan Mantey { 1444e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 14451f8c7b5dSJohnathan Mantey } 1446e4588158SJishnu CM if (v6dhcpParms.useDomainName) 14471f8c7b5dSJohnathan Mantey { 1448e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 14491f8c7b5dSJohnathan Mantey } 14501f8c7b5dSJohnathan Mantey 145162598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 14521f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 14531f8c7b5dSJohnathan Mantey asyncResp); 145462598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1455e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1456e4588158SJishnu CM NetworkType::dhcp4); 145762598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1458e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1459e4588158SJishnu CM NetworkType::dhcp4); 146091c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 146191c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1462e4588158SJishnu CM NetworkType::dhcp4); 1463e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1464e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1465e4588158SJishnu CM NetworkType::dhcp6); 1466e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1467e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1468e4588158SJishnu CM NetworkType::dhcp6); 146991c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 147091c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1471e4588158SJishnu CM NetworkType::dhcp6); 1472da131a9aSJennifer Lee } 147301784826SJohnathan Mantey 147477179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 147577179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 147677179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 147701784826SJohnathan Mantey { 147817a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 147917a897dfSManojkiran Eda return value.origin == "Static"; 148017a897dfSManojkiran Eda }); 148101784826SJohnathan Mantey } 148201784826SJohnathan Mantey 148377179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 148477179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 148577179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 148601784826SJohnathan Mantey { 148717a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 148817a897dfSManojkiran Eda return value.origin == "Static"; 148917a897dfSManojkiran Eda }); 149001784826SJohnathan Mantey } 149101784826SJohnathan Mantey 1492*3dfed536SEd Tanous inline void handleIPv4StaticPatch( 1493*3dfed536SEd Tanous const std::string& ifaceId, 1494*3dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 149577179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 14968d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 14971abe55efSEd Tanous { 1498271584abSEd Tanous unsigned entryIdx = 1; 149901784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 150001784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 150101784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 150201784826SJohnathan Mantey // into the NIC. 150377179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 15042c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 150501784826SJohnathan Mantey 1506*3dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 1507*3dfed536SEd Tanous input) 15081abe55efSEd Tanous { 150989492a15SPatrick Williams std::string pathString = "IPv4StaticAddresses/" + 151089492a15SPatrick Williams std::to_string(entryIdx); 1511*3dfed536SEd Tanous nlohmann::json::object_t* obj = 1512*3dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 1513*3dfed536SEd Tanous if (obj != nullptr && !obj->empty()) 1514f476acbfSRatan Gupta { 1515537174c4SEd Tanous std::optional<std::string> address; 1516537174c4SEd Tanous std::optional<std::string> subnetMask; 1517537174c4SEd Tanous std::optional<std::string> gateway; 1518537174c4SEd Tanous 1519*3dfed536SEd Tanous if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", 15207e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 15217e27d832SJohnathan Mantey "Gateway", gateway)) 1522537174c4SEd Tanous { 1523*3dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 152471f52d96SEd Tanous pathString); 1525537174c4SEd Tanous return; 1526179db1d7SKowalski, Kamil } 1527179db1d7SKowalski, Kamil 152801784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 152901784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 153001784826SJohnathan Mantey // current state of the interface. Merge existing state into the 153101784826SJohnathan Mantey // current request. 1532537174c4SEd Tanous if (address) 15331abe55efSEd Tanous { 1534e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 153501784826SJohnathan Mantey { 1536bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1537bf648f77SEd Tanous pathString + "/Address"); 1538e01d0c36SEd Tanous return; 153901784826SJohnathan Mantey } 154001784826SJohnathan Mantey } 154185ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 154201784826SJohnathan Mantey { 1543e01d0c36SEd Tanous address = (nicIpEntry->address); 154401784826SJohnathan Mantey } 154501784826SJohnathan Mantey else 154601784826SJohnathan Mantey { 154701784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 154801784826SJohnathan Mantey pathString + "/Address"); 1549e01d0c36SEd Tanous return; 15504a0cb85cSEd Tanous } 15514a0cb85cSEd Tanous 1552e01d0c36SEd Tanous uint8_t prefixLength = 0; 1553537174c4SEd Tanous if (subnetMask) 15544a0cb85cSEd Tanous { 1555033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1556033f1e4dSEd Tanous &prefixLength)) 15574a0cb85cSEd Tanous { 1558f12894f8SJason M. Bills messages::propertyValueFormatError( 1559537174c4SEd Tanous asyncResp->res, *subnetMask, 15604a0cb85cSEd Tanous pathString + "/SubnetMask"); 1561e01d0c36SEd Tanous return; 15624a0cb85cSEd Tanous } 15634a0cb85cSEd Tanous } 156485ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 15654a0cb85cSEd Tanous { 1566033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 156701784826SJohnathan Mantey &prefixLength)) 15684a0cb85cSEd Tanous { 156901784826SJohnathan Mantey messages::propertyValueFormatError( 157085ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 157101784826SJohnathan Mantey pathString + "/SubnetMask"); 1572e01d0c36SEd Tanous return; 15734a0cb85cSEd Tanous } 15744a0cb85cSEd Tanous } 15751abe55efSEd Tanous else 15761abe55efSEd Tanous { 157701784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 157801784826SJohnathan Mantey pathString + "/SubnetMask"); 1579e01d0c36SEd Tanous return; 158001784826SJohnathan Mantey } 158101784826SJohnathan Mantey 158201784826SJohnathan Mantey if (gateway) 158301784826SJohnathan Mantey { 1584e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 158501784826SJohnathan Mantey { 1586bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1587bf648f77SEd Tanous pathString + "/Gateway"); 1588e01d0c36SEd Tanous return; 158901784826SJohnathan Mantey } 159001784826SJohnathan Mantey } 159185ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 159201784826SJohnathan Mantey { 1593e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 159401784826SJohnathan Mantey } 159501784826SJohnathan Mantey else 15961abe55efSEd Tanous { 1597a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 15984a0cb85cSEd Tanous pathString + "/Gateway"); 159901784826SJohnathan Mantey return; 16004a0cb85cSEd Tanous } 16014a0cb85cSEd Tanous 160285ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 16031abe55efSEd Tanous { 16049c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 160577eb0153SEd Tanous nicIpEntry->id, prefixLength, *address, 160677eb0153SEd Tanous *gateway, asyncResp); 160789492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 160889492a15SPatrick Williams ipv4Data.cend()); 1609588c3f0dSKowalski, Kamil } 161001784826SJohnathan Mantey else 161101784826SJohnathan Mantey { 1612cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1613cb13a392SEd Tanous asyncResp); 16144a0cb85cSEd Tanous } 16154a0cb85cSEd Tanous entryIdx++; 16164a0cb85cSEd Tanous } 161701784826SJohnathan Mantey else 161801784826SJohnathan Mantey { 161985ffe86aSJiaqing Zhao if (nicIpEntry == ipv4Data.cend()) 162001784826SJohnathan Mantey { 162101784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 162201784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 162301784826SJohnathan Mantey // in error, so bail out. 1624*3dfed536SEd Tanous if (obj == nullptr) 162501784826SJohnathan Mantey { 162601784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 162701784826SJohnathan Mantey return; 162801784826SJohnathan Mantey } 1629*3dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 163071f52d96SEd Tanous pathString); 163101784826SJohnathan Mantey return; 163201784826SJohnathan Mantey } 163301784826SJohnathan Mantey 1634*3dfed536SEd Tanous if (obj == nullptr) 163501784826SJohnathan Mantey { 16369c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 163701784826SJohnathan Mantey } 163885ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 163901784826SJohnathan Mantey { 164089492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 164189492a15SPatrick Williams ipv4Data.cend()); 164201784826SJohnathan Mantey } 164301784826SJohnathan Mantey entryIdx++; 164401784826SJohnathan Mantey } 164501784826SJohnathan Mantey } 16464a0cb85cSEd Tanous } 16474a0cb85cSEd Tanous 16484f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1649f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1650f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 16518d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1652f85837bfSRAJESWARAN THILLAIGOVINDAN { 16531847f2a0SAsmitha Karunanithi setDbusProperty( 16541847f2a0SAsmitha Karunanithi asyncResp, "xyz.openbmc_project.Network", 16551847f2a0SAsmitha Karunanithi sdbusplus::message::object_path("/xyz/openbmc_project/network") / 16561847f2a0SAsmitha Karunanithi ifaceId, 16579ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 16581847f2a0SAsmitha Karunanithi "StaticNameServers", updatedStaticNameServers); 1659f85837bfSRAJESWARAN THILLAIGOVINDAN } 1660f85837bfSRAJESWARAN THILLAIGOVINDAN 16614f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 1662*3dfed536SEd Tanous const std::string& ifaceId, 1663*3dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 166477179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 16658d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1666e48c0fc5SRavi Teja { 1667271584abSEd Tanous size_t entryIdx = 1; 166877179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 16692c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1670*3dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 1671*3dfed536SEd Tanous input) 1672e48c0fc5SRavi Teja { 167389492a15SPatrick Williams std::string pathString = "IPv6StaticAddresses/" + 167489492a15SPatrick Williams std::to_string(entryIdx); 1675*3dfed536SEd Tanous nlohmann::json::object_t* obj = 1676*3dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 1677*3dfed536SEd Tanous if (obj != nullptr && !obj->empty()) 1678e48c0fc5SRavi Teja { 1679e48c0fc5SRavi Teja std::optional<std::string> address; 1680e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1681*3dfed536SEd Tanous nlohmann::json::object_t thisJsonCopy = *obj; 1682*3dfed536SEd Tanous if (!json_util::readJsonObject(thisJsonCopy, asyncResp->res, 1683*3dfed536SEd Tanous "Address", address, "PrefixLength", 1684*3dfed536SEd Tanous prefixLength)) 1685e48c0fc5SRavi Teja { 1686*3dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJsonCopy, 168771f52d96SEd Tanous pathString); 1688e48c0fc5SRavi Teja return; 1689e48c0fc5SRavi Teja } 1690e48c0fc5SRavi Teja 169101784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 169201784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 169301784826SJohnathan Mantey // current state of the interface. Merge existing state into the 169401784826SJohnathan Mantey // current request. 1695d547d8d2SEd Tanous if (!address) 1696e48c0fc5SRavi Teja { 1697d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 169801784826SJohnathan Mantey { 169901784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 170001784826SJohnathan Mantey pathString + "/Address"); 170101784826SJohnathan Mantey return; 1702e48c0fc5SRavi Teja } 1703d547d8d2SEd Tanous address = nicIpEntry->address; 1704d547d8d2SEd Tanous } 1705e48c0fc5SRavi Teja 1706d547d8d2SEd Tanous if (!prefixLength) 1707e48c0fc5SRavi Teja { 1708d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 1709e48c0fc5SRavi Teja { 1710e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1711e48c0fc5SRavi Teja pathString + "/PrefixLength"); 171201784826SJohnathan Mantey return; 1713e48c0fc5SRavi Teja } 1714d547d8d2SEd Tanous prefixLength = nicIpEntry->prefixLength; 1715d547d8d2SEd Tanous } 1716e48c0fc5SRavi Teja 171785ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1718e48c0fc5SRavi Teja { 17199c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 1720d547d8d2SEd Tanous nicIpEntry->id, *prefixLength, 1721d547d8d2SEd Tanous *address, "", asyncResp); 172289492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 172389492a15SPatrick Williams ipv6Data.cend()); 172401784826SJohnathan Mantey } 172501784826SJohnathan Mantey else 172601784826SJohnathan Mantey { 1727d547d8d2SEd Tanous createIPv6(ifaceId, *prefixLength, *address, asyncResp); 1728e48c0fc5SRavi Teja } 1729e48c0fc5SRavi Teja entryIdx++; 1730e48c0fc5SRavi Teja } 173101784826SJohnathan Mantey else 173201784826SJohnathan Mantey { 173385ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 173401784826SJohnathan Mantey { 173501784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 173601784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 173701784826SJohnathan Mantey // in error, so bail out. 1738*3dfed536SEd Tanous if (obj == nullptr) 173901784826SJohnathan Mantey { 174001784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 174101784826SJohnathan Mantey return; 174201784826SJohnathan Mantey } 1743*3dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 174471f52d96SEd Tanous pathString); 174501784826SJohnathan Mantey return; 174601784826SJohnathan Mantey } 174701784826SJohnathan Mantey 1748*3dfed536SEd Tanous if (obj == nullptr) 174901784826SJohnathan Mantey { 17509c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 175101784826SJohnathan Mantey } 175285ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 175301784826SJohnathan Mantey { 175489492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 175589492a15SPatrick Williams ipv6Data.cend()); 175601784826SJohnathan Mantey } 175701784826SJohnathan Mantey entryIdx++; 175801784826SJohnathan Mantey } 175901784826SJohnathan Mantey } 1760e48c0fc5SRavi Teja } 1761e48c0fc5SRavi Teja 17627857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 17637857cb8dSJiaqing Zhao { 17647857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 17657857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 17667857cb8dSJiaqing Zhao } 17677857cb8dSJiaqing Zhao 176877179532SEd Tanous inline void 176977179532SEd Tanous parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 177077179532SEd Tanous const std::string& ifaceId, 177177179532SEd Tanous const EthernetInterfaceData& ethData, 177277179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1773ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 1774ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) 17754a0cb85cSEd Tanous { 17762c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 177781ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1778ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 1779ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId); 17802c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1781eeedda23SJohnathan Mantey 178213451e39SWilly Tu if constexpr (bmcwebEnableHealthPopulate) 178313451e39SWilly Tu { 178413451e39SWilly Tu constexpr std::array<std::string_view, 1> inventoryForEthernet = { 178513451e39SWilly Tu "xyz.openbmc_project.Inventory.Item.Ethernet"}; 1786eeedda23SJohnathan Mantey auto health = std::make_shared<HealthPopulate>(asyncResp); 17877a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 17887a1dbc48SGeorge Liu "/", 0, inventoryForEthernet, 17897a1dbc48SGeorge Liu [health](const boost::system::error_code& ec, 1790b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& resp) { 1791eeedda23SJohnathan Mantey if (ec) 1792029573d4SEd Tanous { 1793eeedda23SJohnathan Mantey return; 1794eeedda23SJohnathan Mantey } 1795eeedda23SJohnathan Mantey 1796914e2d5dSEd Tanous health->inventory = resp; 17977a1dbc48SGeorge Liu }); 1798eeedda23SJohnathan Mantey 1799eeedda23SJohnathan Mantey health->populate(); 180013451e39SWilly Tu } 1801eeedda23SJohnathan Mantey 1802eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1803eeedda23SJohnathan Mantey { 18040ef0e289SJohnathan Mantey jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 18052c70f800SEd Tanous jsonResponse["Status"]["State"] = "Enabled"; 1806029573d4SEd Tanous } 1807029573d4SEd Tanous else 1808029573d4SEd Tanous { 18092c70f800SEd Tanous jsonResponse["LinkStatus"] = "NoLink"; 18102c70f800SEd Tanous jsonResponse["Status"]["State"] = "Disabled"; 1811029573d4SEd Tanous } 1812aa05fb27SJohnathan Mantey 18132c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 181435fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 181582695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 18162c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 181782695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1818e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1819e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1820e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled; 18212c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1822b10d8db0SRavi Teja translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled" 18231f8c7b5dSJohnathan Mantey : "Disabled"; 1824e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1825e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1826e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled; 1827b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1828b10d8db0SRavi Teja ethData.ipv6AcceptRa; 18292a133282Smanojkiraneda 183082695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 18314a0cb85cSEd Tanous { 183282695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1833ab6554f1SJoshi-Mansi 1834ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1835ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1836ab6554f1SJoshi-Mansi // FQDN 183782695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1838d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1839d24bfc7aSJennifer Lee { 18402c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1841d24bfc7aSJennifer Lee } 18422c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 18434a0cb85cSEd Tanous } 18444a0cb85cSEd Tanous 18457857cb8dSJiaqing Zhao if (ethData.vlanId) 18467857cb8dSJiaqing Zhao { 18477857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Virtual"; 18487857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 18497857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 18507857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 18517857cb8dSJiaqing Zhao 18527857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 18537857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 18547857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 18557857cb8dSJiaqing Zhao boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces", 18567857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 18577857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 18587857cb8dSJiaqing Zhao std::move(relatedInterfaces); 18597857cb8dSJiaqing Zhao } 18607857cb8dSJiaqing Zhao else 18617857cb8dSJiaqing Zhao { 18627857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Physical"; 18637857cb8dSJiaqing Zhao } 18647857cb8dSJiaqing Zhao 18652c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 18662c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 18674a0cb85cSEd Tanous 18682c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 18692c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 18702c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 18712c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 18729eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 18734a0cb85cSEd Tanous { 18742c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1875fa5053a6SGunnar Mills if (gatewayStr.empty()) 1876fa5053a6SGunnar Mills { 1877fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1878fa5053a6SGunnar Mills } 18791476687dSEd Tanous nlohmann::json::object_t ipv4; 18801476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 18811476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 18821476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 18831476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1884fa5053a6SGunnar Mills 18852c70f800SEd Tanous if (ipv4Config.origin == "Static") 1886d1d50814SRavi Teja { 18871476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1888d1d50814SRavi Teja } 18891476687dSEd Tanous 1890b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 189101784826SJohnathan Mantey } 1892d1d50814SRavi Teja 189382695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 18947ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 18957ea79e5eSRavi Teja { 18967ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 18977ea79e5eSRavi Teja } 18987ea79e5eSRavi Teja 18997ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1900e48c0fc5SRavi Teja 1901ce73d5c8SSunitha Harish nlohmann::json::array_t ipv6StaticGatewayArray; 1902ce73d5c8SSunitha Harish for (const auto& ipv6GatewayConfig : ipv6GatewayData) 1903ce73d5c8SSunitha Harish { 1904ce73d5c8SSunitha Harish nlohmann::json::object_t ipv6Gateway; 1905ce73d5c8SSunitha Harish ipv6Gateway["Address"] = ipv6GatewayConfig.gateway; 1906ce73d5c8SSunitha Harish ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength; 1907ce73d5c8SSunitha Harish ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway)); 1908ce73d5c8SSunitha Harish } 1909ce73d5c8SSunitha Harish jsonResponse["IPv6StaticDefaultGateways"] = 1910ce73d5c8SSunitha Harish std::move(ipv6StaticGatewayArray); 1911ce73d5c8SSunitha Harish 19122c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 19132c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 19142c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 19152c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 19167f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 19172c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 19187f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 19199eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1920e48c0fc5SRavi Teja { 19211476687dSEd Tanous nlohmann::json::object_t ipv6; 19221476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 19231476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 19241476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1925f8361275SSunitha Harish 1926b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 19272c70f800SEd Tanous if (ipv6Config.origin == "Static") 1928e48c0fc5SRavi Teja { 19291476687dSEd Tanous nlohmann::json::object_t ipv6Static; 19301476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 19311476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 1932b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 193301784826SJohnathan Mantey } 1934e48c0fc5SRavi Teja } 1935588c3f0dSKowalski, Kamil } 1936588c3f0dSKowalski, Kamil 1937e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1938e7caf250SJiaqing Zhao const std::string& ifaceId, 1939e7caf250SJiaqing Zhao const boost::system::error_code& ec, 1940e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 1941e7caf250SJiaqing Zhao { 1942e7caf250SJiaqing Zhao if (!ec) 1943e7caf250SJiaqing Zhao { 1944e7caf250SJiaqing Zhao return; 1945e7caf250SJiaqing Zhao } 1946e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1947e7caf250SJiaqing Zhao if (dbusError == nullptr) 1948e7caf250SJiaqing Zhao { 1949e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1950e7caf250SJiaqing Zhao return; 1951e7caf250SJiaqing Zhao } 195262598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1953e7caf250SJiaqing Zhao 1954e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 1955e7caf250SJiaqing Zhao dbusError->name) 1956e7caf250SJiaqing Zhao { 1957e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1958e7caf250SJiaqing Zhao ifaceId); 1959e7caf250SJiaqing Zhao return; 1960e7caf250SJiaqing Zhao } 1961e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 1962e7caf250SJiaqing Zhao dbusError->name) 1963e7caf250SJiaqing Zhao { 1964e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 1965e7caf250SJiaqing Zhao return; 1966e7caf250SJiaqing Zhao } 1967e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1968e7caf250SJiaqing Zhao } 1969e7caf250SJiaqing Zhao 1970b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1971b5ca3fdcSJiaqing Zhao const std::string& parentInterfaceUri, 1972b5ca3fdcSJiaqing Zhao const std::string& vlanInterface, 1973b5ca3fdcSJiaqing Zhao const boost::system::error_code& ec, 1974b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m 1975b5ca3fdcSJiaqing Zhao 1976b5ca3fdcSJiaqing Zhao ) 1977b5ca3fdcSJiaqing Zhao { 1978b5ca3fdcSJiaqing Zhao if (ec) 1979b5ca3fdcSJiaqing Zhao { 1980b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1981b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 1982b5ca3fdcSJiaqing Zhao { 1983b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1984b5ca3fdcSJiaqing Zhao return; 1985b5ca3fdcSJiaqing Zhao } 198662598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1987b5ca3fdcSJiaqing Zhao 1988b5ca3fdcSJiaqing Zhao if (std::string_view( 1989b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 1990b5ca3fdcSJiaqing Zhao dbusError->name) 1991b5ca3fdcSJiaqing Zhao { 1992b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1993b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1994b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1995b5ca3fdcSJiaqing Zhao return; 1996b5ca3fdcSJiaqing Zhao } 1997b5ca3fdcSJiaqing Zhao if (std::string_view( 1998b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 1999b5ca3fdcSJiaqing Zhao dbusError->name) 2000b5ca3fdcSJiaqing Zhao { 2001b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 2002b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 2003b5ca3fdcSJiaqing Zhao return; 2004b5ca3fdcSJiaqing Zhao } 2005b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2006b5ca3fdcSJiaqing Zhao return; 2007b5ca3fdcSJiaqing Zhao } 2008b5ca3fdcSJiaqing Zhao 2009b5ca3fdcSJiaqing Zhao const boost::urls::url vlanInterfaceUri = boost::urls::format( 2010b5ca3fdcSJiaqing Zhao "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface); 2011b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 2012b5ca3fdcSJiaqing Zhao } 2013b5ca3fdcSJiaqing Zhao 2014bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 2015bf648f77SEd Tanous { 2016bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 2017ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 20181476687dSEd Tanous .methods(boost::beast::http::verb::get)( 20191476687dSEd Tanous [&app](const crow::Request& req, 20201476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 20213ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 202245ca1b86SEd Tanous { 202345ca1b86SEd Tanous return; 202445ca1b86SEd Tanous } 202545ca1b86SEd Tanous 2026bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2027bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 2028bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2029bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 2030bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 2031bf648f77SEd Tanous "Ethernet Network Interface Collection"; 2032bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 2033bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 2034bf648f77SEd Tanous 2035bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 2036bf648f77SEd Tanous // preparation 2037002d39b4SEd Tanous getEthernetIfaceList( 203877179532SEd Tanous [asyncResp](const bool& success, 203977179532SEd Tanous const std::vector<std::string>& ifaceList) { 2040bf648f77SEd Tanous if (!success) 20411abe55efSEd Tanous { 2042f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20439391bb9cSRapkiewicz, Pawel return; 20449391bb9cSRapkiewicz, Pawel } 20459391bb9cSRapkiewicz, Pawel 2046002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 2047bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 2048bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 2049bf648f77SEd Tanous { 20501476687dSEd Tanous nlohmann::json::object_t iface; 2051ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 2052ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", 2053ef4c65b7SEd Tanous ifaceItem); 20547857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 2055bf648f77SEd Tanous } 2056bf648f77SEd Tanous 2057002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 2058bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2059bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 2060bf648f77SEd Tanous }); 2061bf648f77SEd Tanous }); 2062bf648f77SEd Tanous 2063b5ca3fdcSJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 2064b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 2065b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 2066b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 2067b5ca3fdcSJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2068b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2069b5ca3fdcSJiaqing Zhao { 2070b5ca3fdcSJiaqing Zhao return; 2071b5ca3fdcSJiaqing Zhao } 2072b5ca3fdcSJiaqing Zhao 2073b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 2074b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 2075*3dfed536SEd Tanous std::vector<nlohmann::json::object_t> relatedInterfaces; 2076b5ca3fdcSJiaqing Zhao 2077b5ca3fdcSJiaqing Zhao if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", 2078b5ca3fdcSJiaqing Zhao vlanEnable, "VLAN/VLANId", vlanId, 2079b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2080b5ca3fdcSJiaqing Zhao relatedInterfaces)) 2081b5ca3fdcSJiaqing Zhao { 2082b5ca3fdcSJiaqing Zhao return; 2083b5ca3fdcSJiaqing Zhao } 2084b5ca3fdcSJiaqing Zhao 2085b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 2086b5ca3fdcSJiaqing Zhao { 2087b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 2088b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2089b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 2090b5ca3fdcSJiaqing Zhao return; 2091b5ca3fdcSJiaqing Zhao } 2092b5ca3fdcSJiaqing Zhao 2093b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 2094*3dfed536SEd Tanous if (!json_util::readJsonObject(relatedInterfaces[0], asyncResp->res, 2095b5ca3fdcSJiaqing Zhao "@odata.id", parentInterfaceUri)) 2096b5ca3fdcSJiaqing Zhao { 2097b5ca3fdcSJiaqing Zhao messages::propertyMissing(asyncResp->res, 2098b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2099b5ca3fdcSJiaqing Zhao return; 2100b5ca3fdcSJiaqing Zhao } 210162598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 2102b5ca3fdcSJiaqing Zhao 21036fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 2104b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 2105b5ca3fdcSJiaqing Zhao if (!parsedUri) 2106b5ca3fdcSJiaqing Zhao { 2107b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 2108b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2109b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2110b5ca3fdcSJiaqing Zhao return; 2111b5ca3fdcSJiaqing Zhao } 2112b5ca3fdcSJiaqing Zhao 2113b5ca3fdcSJiaqing Zhao std::string parentInterface; 2114b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 2115b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 2116b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 2117b5ca3fdcSJiaqing Zhao { 2118b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2119b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2120b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2121b5ca3fdcSJiaqing Zhao return; 2122b5ca3fdcSJiaqing Zhao } 2123b5ca3fdcSJiaqing Zhao 2124b5ca3fdcSJiaqing Zhao if (!vlanEnable) 2125b5ca3fdcSJiaqing Zhao { 2126b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 2127b5ca3fdcSJiaqing Zhao // create 2128b5ca3fdcSJiaqing Zhao messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", 2129b5ca3fdcSJiaqing Zhao "false"); 2130b5ca3fdcSJiaqing Zhao return; 2131b5ca3fdcSJiaqing Zhao } 2132b5ca3fdcSJiaqing Zhao 2133b5ca3fdcSJiaqing Zhao std::string vlanInterface = parentInterface + "_" + 2134b5ca3fdcSJiaqing Zhao std::to_string(vlanId); 2135b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 2136b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 2137b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 2138b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 2139b5ca3fdcSJiaqing Zhao afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, 2140b5ca3fdcSJiaqing Zhao m); 2141b5ca3fdcSJiaqing Zhao }, 2142b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 2143b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, 2144b5ca3fdcSJiaqing Zhao vlanId); 2145b5ca3fdcSJiaqing Zhao }); 2146b5ca3fdcSJiaqing Zhao 2147bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2148ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 2149bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 215045ca1b86SEd Tanous [&app](const crow::Request& req, 2151bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2152bf648f77SEd Tanous const std::string& ifaceId) { 21533ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 215445ca1b86SEd Tanous { 215545ca1b86SEd Tanous return; 215645ca1b86SEd Tanous } 21574a0cb85cSEd Tanous getEthernetIfaceData( 2158bf648f77SEd Tanous ifaceId, 2159ce73d5c8SSunitha Harish [asyncResp, 2160ce73d5c8SSunitha Harish ifaceId](const bool& success, const EthernetInterfaceData& ethData, 216177179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2162ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2163ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 21644a0cb85cSEd Tanous if (!success) 21651abe55efSEd Tanous { 2166bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2167bf648f77SEd Tanous // existing object, and other errors 2168002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2169002d39b4SEd Tanous ifaceId); 21704a0cb85cSEd Tanous return; 21719391bb9cSRapkiewicz, Pawel } 21724c9afe43SEd Tanous 21730f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 217493bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2175002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 21760f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 21770f74e643SEd Tanous "Management Network Interface"; 21780f74e643SEd Tanous 2179ce73d5c8SSunitha Harish parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data, 2180ce73d5c8SSunitha Harish ipv6GatewayData); 21819391bb9cSRapkiewicz, Pawel }); 2182bf648f77SEd Tanous }); 21839391bb9cSRapkiewicz, Pawel 2184bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2185ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2186bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 218745ca1b86SEd Tanous [&app](const crow::Request& req, 2188bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2189bf648f77SEd Tanous const std::string& ifaceId) { 21903ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 219145ca1b86SEd Tanous { 219245ca1b86SEd Tanous return; 219345ca1b86SEd Tanous } 2194bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2195ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2196d577665bSRatan Gupta std::optional<std::string> macAddress; 21979a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2198*3dfed536SEd Tanous std::optional< 2199*3dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 2200*3dfed536SEd Tanous ipv4StaticAddresses; 2201*3dfed536SEd Tanous std::optional< 2202*3dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 2203*3dfed536SEd Tanous ipv6StaticAddresses; 2204*3dfed536SEd Tanous std::optional< 2205*3dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>> 2206*3dfed536SEd Tanous ipv6StaticDefaultGateways; 2207f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2208b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2209eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 221035fb5311STejas Patil std::optional<size_t> mtuSize; 22111f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 22121f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2213b10d8db0SRavi Teja // clang-format off 2214*3dfed536SEd Tanous if (!json_util::readJsonPatch(req, asyncResp->res, 2215*3dfed536SEd Tanous "DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled, 2216*3dfed536SEd Tanous "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers, 2217*3dfed536SEd Tanous "DHCPv4/UseDomainName", v4dhcpParms.useDomainName, 2218*3dfed536SEd Tanous "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers, 2219*3dfed536SEd Tanous "DHCPv6/OperatingMode", v6dhcpParms.dhcpv6OperatingMode, 2220*3dfed536SEd Tanous "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers, 2221*3dfed536SEd Tanous "DHCPv6/UseDomainName", v6dhcpParms.useDomainName, 2222*3dfed536SEd Tanous "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers, 2223b10d8db0SRavi Teja "FQDN", fqdn, 2224b10d8db0SRavi Teja "HostName", hostname, 2225b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 2226b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 2227b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 2228ce73d5c8SSunitha Harish "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways, 2229b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 2230b10d8db0SRavi Teja "MACAddress", macAddress, 2231b10d8db0SRavi Teja "MTUSize", mtuSize, 2232b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 2233b10d8db0SRavi Teja "StaticNameServers", staticNameServers 2234b10d8db0SRavi Teja ) 2235b10d8db0SRavi Teja ) 22361abe55efSEd Tanous { 2237588c3f0dSKowalski, Kamil return; 2238588c3f0dSKowalski, Kamil } 2239b10d8db0SRavi Teja // clang-format on 2240da131a9aSJennifer Lee 2241bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2242bf648f77SEd Tanous // for JSON preparation 22434a0cb85cSEd Tanous getEthernetIfaceData( 22442c70f800SEd Tanous ifaceId, 2245bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2246ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2247d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 22489a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2249e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 2250ce73d5c8SSunitha Harish ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways), 2251*3dfed536SEd Tanous staticNameServers = std::move(staticNameServers), mtuSize, 2252b10d8db0SRavi Teja ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms), 2253f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2254*3dfed536SEd Tanous const bool success, const EthernetInterfaceData& ethData, 225577179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2256ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2257*3dfed536SEd Tanous const std::vector<StaticGatewayData>& ipv6GatewayData) mutable { 22581abe55efSEd Tanous if (!success) 22591abe55efSEd Tanous { 2260588c3f0dSKowalski, Kamil // ... otherwise return error 2261bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2262bf648f77SEd Tanous // existing object, and other errors 2263002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2264002d39b4SEd Tanous ifaceId); 2265588c3f0dSKowalski, Kamil return; 2266588c3f0dSKowalski, Kamil } 2267588c3f0dSKowalski, Kamil 2268002d39b4SEd Tanous handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, 2269002d39b4SEd Tanous asyncResp); 22701f8c7b5dSJohnathan Mantey 22710627a2c7SEd Tanous if (hostname) 22721abe55efSEd Tanous { 22730627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 22741abe55efSEd Tanous } 22750627a2c7SEd Tanous 2276b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2277b10d8db0SRavi Teja { 2278b10d8db0SRavi Teja handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled, 2279b10d8db0SRavi Teja asyncResp); 2280b10d8db0SRavi Teja } 2281b10d8db0SRavi Teja 2282ab6554f1SJoshi-Mansi if (fqdn) 2283ab6554f1SJoshi-Mansi { 22842c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2285ab6554f1SJoshi-Mansi } 2286ab6554f1SJoshi-Mansi 2287d577665bSRatan Gupta if (macAddress) 2288d577665bSRatan Gupta { 2289002d39b4SEd Tanous handleMACAddressPatch(ifaceId, *macAddress, asyncResp); 2290d577665bSRatan Gupta } 2291d577665bSRatan Gupta 2292d1d50814SRavi Teja if (ipv4StaticAddresses) 2293d1d50814SRavi Teja { 2294*3dfed536SEd Tanous handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ipv4Data, 2295*3dfed536SEd Tanous asyncResp); 22961abe55efSEd Tanous } 22970627a2c7SEd Tanous 2298f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2299f85837bfSRAJESWARAN THILLAIGOVINDAN { 2300002d39b4SEd Tanous handleStaticNameServersPatch(ifaceId, *staticNameServers, 2301002d39b4SEd Tanous asyncResp); 2302f85837bfSRAJESWARAN THILLAIGOVINDAN } 23039a6fc6feSRavi Teja 23049a6fc6feSRavi Teja if (ipv6DefaultGateway) 23059a6fc6feSRavi Teja { 23069a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 23079a6fc6feSRavi Teja "IPv6DefaultGateway"); 23089a6fc6feSRavi Teja } 2309e48c0fc5SRavi Teja 2310e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2311e48c0fc5SRavi Teja { 2312ddd70dcaSEd Tanous handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses, 2313ddd70dcaSEd Tanous ipv6Data, asyncResp); 2314e48c0fc5SRavi Teja } 2315eeedda23SJohnathan Mantey 2316ce73d5c8SSunitha Harish if (ipv6StaticDefaultGateway) 2317ce73d5c8SSunitha Harish { 2318ce73d5c8SSunitha Harish handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway, 2319ce73d5c8SSunitha Harish ipv6GatewayData, asyncResp); 2320ce73d5c8SSunitha Harish } 2321ce73d5c8SSunitha Harish 2322eeedda23SJohnathan Mantey if (interfaceEnabled) 2323eeedda23SJohnathan Mantey { 2324d02aad39SEd Tanous setDbusProperty(asyncResp, "xyz.openbmc_project.Network", 2325d02aad39SEd Tanous sdbusplus::message::object_path( 2326d02aad39SEd Tanous "/xyz/openbmc_project/network") / 2327d02aad39SEd Tanous ifaceId, 2328d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", 2329d02aad39SEd Tanous "NICEnabled", "InterfaceEnabled", 2330d02aad39SEd Tanous *interfaceEnabled); 2331eeedda23SJohnathan Mantey } 233235fb5311STejas Patil 233335fb5311STejas Patil if (mtuSize) 233435fb5311STejas Patil { 233535fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 233635fb5311STejas Patil } 2337588c3f0dSKowalski, Kamil }); 2338bf648f77SEd Tanous }); 2339e7caf250SJiaqing Zhao 2340e7caf250SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2341e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2342e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2343e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2344e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2345e7caf250SJiaqing Zhao const std::string& ifaceId) { 2346e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2347e7caf250SJiaqing Zhao { 2348e7caf250SJiaqing Zhao return; 2349e7caf250SJiaqing Zhao } 2350e7caf250SJiaqing Zhao 2351e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2352e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2353e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2354e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2355e7caf250SJiaqing Zhao }, 2356e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2357e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2358e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2359e7caf250SJiaqing Zhao }); 23604a0cb85cSEd Tanous } 2361bf648f77SEd Tanous 23629391bb9cSRapkiewicz, Pawel } // namespace redfish 2363