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 31*ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp> 32ef4c65b7SEd Tanous #include <boost/url/format.hpp> 331214b7e7SGunnar Mills 347a1dbc48SGeorge Liu #include <array> 35*ce73d5c8SSunitha Harish #include <memory> 36a24526dcSEd Tanous #include <optional> 373544d2a7SEd Tanous #include <ranges> 38ab6554f1SJoshi-Mansi #include <regex> 397a1dbc48SGeorge Liu #include <string_view> 4077179532SEd Tanous #include <vector> 419391bb9cSRapkiewicz, Pawel 421abe55efSEd Tanous namespace redfish 431abe55efSEd Tanous { 449391bb9cSRapkiewicz, Pawel 454a0cb85cSEd Tanous enum class LinkType 464a0cb85cSEd Tanous { 474a0cb85cSEd Tanous Local, 484a0cb85cSEd Tanous Global 494a0cb85cSEd Tanous }; 509391bb9cSRapkiewicz, Pawel 519391bb9cSRapkiewicz, Pawel /** 529391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 539391bb9cSRapkiewicz, Pawel */ 541abe55efSEd Tanous struct IPv4AddressData 551abe55efSEd Tanous { 56179db1d7SKowalski, Kamil std::string id; 574a0cb85cSEd Tanous std::string address; 584a0cb85cSEd Tanous std::string domain; 594a0cb85cSEd Tanous std::string gateway; 609391bb9cSRapkiewicz, Pawel std::string netmask; 619391bb9cSRapkiewicz, Pawel std::string origin; 6277179532SEd Tanous LinkType linktype{}; 6377179532SEd Tanous bool isActive{}; 649391bb9cSRapkiewicz, Pawel }; 659391bb9cSRapkiewicz, Pawel 669391bb9cSRapkiewicz, Pawel /** 67e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 68e48c0fc5SRavi Teja */ 69e48c0fc5SRavi Teja struct IPv6AddressData 70e48c0fc5SRavi Teja { 71e48c0fc5SRavi Teja std::string id; 72e48c0fc5SRavi Teja std::string address; 73e48c0fc5SRavi Teja std::string origin; 7477179532SEd Tanous uint8_t prefixLength = 0; 75e48c0fc5SRavi Teja }; 76*ce73d5c8SSunitha Harish 77*ce73d5c8SSunitha Harish /** 78*ce73d5c8SSunitha Harish * Structure for keeping static route data required by Redfish 79*ce73d5c8SSunitha Harish */ 80*ce73d5c8SSunitha Harish struct StaticGatewayData 81*ce73d5c8SSunitha Harish { 82*ce73d5c8SSunitha Harish std::string id; 83*ce73d5c8SSunitha Harish std::string gateway; 84*ce73d5c8SSunitha Harish size_t prefixLength = 0; 85*ce73d5c8SSunitha Harish std::string protocol; 86*ce73d5c8SSunitha Harish }; 87*ce73d5c8SSunitha Harish 88e48c0fc5SRavi Teja /** 899391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 909391bb9cSRapkiewicz, Pawel * available from DBus 919391bb9cSRapkiewicz, Pawel */ 921abe55efSEd Tanous struct EthernetInterfaceData 931abe55efSEd Tanous { 944a0cb85cSEd Tanous uint32_t speed; 9535fb5311STejas Patil size_t mtuSize; 9682695a5bSJiaqing Zhao bool autoNeg; 97e4588158SJishnu CM bool dnsv4Enabled; 98e4588158SJishnu CM bool dnsv6Enabled; 9991c441ecSRavi Teja bool domainv4Enabled; 10091c441ecSRavi Teja bool domainv6Enabled; 101e4588158SJishnu CM bool ntpv4Enabled; 102e4588158SJishnu CM bool ntpv6Enabled; 103e4588158SJishnu CM bool hostNamev4Enabled; 104e4588158SJishnu CM bool hostNamev6Enabled; 105aa05fb27SJohnathan Mantey bool linkUp; 106eeedda23SJohnathan Mantey bool nicEnabled; 107b10d8db0SRavi Teja bool ipv6AcceptRa; 10882695a5bSJiaqing Zhao std::string dhcpEnabled; 1091f8c7b5dSJohnathan Mantey std::string operatingMode; 11082695a5bSJiaqing Zhao std::string hostName; 11182695a5bSJiaqing Zhao std::string defaultGateway; 11282695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 113*ce73d5c8SSunitha Harish std::string ipv6StaticDefaultGateway; 11482695a5bSJiaqing Zhao std::string macAddress; 11517e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 1160f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 1170f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 118d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1199391bb9cSRapkiewicz, Pawel }; 1209391bb9cSRapkiewicz, Pawel 1211f8c7b5dSJohnathan Mantey struct DHCPParameters 1221f8c7b5dSJohnathan Mantey { 1231f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 12482695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 12582695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 12682695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1271f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1281f8c7b5dSJohnathan Mantey }; 1291f8c7b5dSJohnathan Mantey 1309391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1319391bb9cSRapkiewicz, Pawel // into full dot notation 1321abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1331abe55efSEd Tanous { 1349391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1359391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1369391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1379391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1389391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1399391bb9cSRapkiewicz, Pawel return netmask; 1409391bb9cSRapkiewicz, Pawel } 1419391bb9cSRapkiewicz, Pawel 14282695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1431f8c7b5dSJohnathan Mantey bool isIPv4) 1441f8c7b5dSJohnathan Mantey { 1451f8c7b5dSJohnathan Mantey if (isIPv4) 1461f8c7b5dSJohnathan Mantey { 1471f8c7b5dSJohnathan Mantey return ( 1481f8c7b5dSJohnathan Mantey (inputDHCP == 1491f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1501f8c7b5dSJohnathan Mantey (inputDHCP == 1511f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1521f8c7b5dSJohnathan Mantey } 1531f8c7b5dSJohnathan Mantey return ((inputDHCP == 1541f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1551f8c7b5dSJohnathan Mantey (inputDHCP == 1561f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1571f8c7b5dSJohnathan Mantey } 1581f8c7b5dSJohnathan Mantey 1592c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1601f8c7b5dSJohnathan Mantey { 1611f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1621f8c7b5dSJohnathan Mantey { 1631f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1641f8c7b5dSJohnathan Mantey } 1653174e4dfSEd Tanous if (isIPv4) 1661f8c7b5dSJohnathan Mantey { 1671f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1681f8c7b5dSJohnathan Mantey } 1693174e4dfSEd Tanous if (isIPv6) 1701f8c7b5dSJohnathan Mantey { 1711f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1721f8c7b5dSJohnathan Mantey } 1731f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1741f8c7b5dSJohnathan Mantey } 1751f8c7b5dSJohnathan Mantey 1764a0cb85cSEd Tanous inline std::string 1774a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string& inputOrigin, 1784a0cb85cSEd Tanous bool isIPv4) 1791abe55efSEd Tanous { 1804a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1811abe55efSEd Tanous { 1824a0cb85cSEd Tanous return "Static"; 1839391bb9cSRapkiewicz, Pawel } 1844a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1851abe55efSEd Tanous { 1864a0cb85cSEd Tanous if (isIPv4) 1871abe55efSEd Tanous { 1884a0cb85cSEd Tanous return "IPv4LinkLocal"; 1891abe55efSEd Tanous } 1904a0cb85cSEd Tanous return "LinkLocal"; 1919391bb9cSRapkiewicz, Pawel } 1924a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1931abe55efSEd Tanous { 1944a0cb85cSEd Tanous if (isIPv4) 1954a0cb85cSEd Tanous { 1964a0cb85cSEd Tanous return "DHCP"; 1974a0cb85cSEd Tanous } 1984a0cb85cSEd Tanous return "DHCPv6"; 1994a0cb85cSEd Tanous } 2004a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 2014a0cb85cSEd Tanous { 2024a0cb85cSEd Tanous return "SLAAC"; 2034a0cb85cSEd Tanous } 2044a0cb85cSEd Tanous return ""; 2054a0cb85cSEd Tanous } 2064a0cb85cSEd Tanous 20702cad96eSEd Tanous inline bool extractEthernetInterfaceData( 20802cad96eSEd Tanous const std::string& ethifaceId, 20902cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 2104a0cb85cSEd Tanous EthernetInterfaceData& ethData) 2114a0cb85cSEd Tanous { 2124c9afe43SEd Tanous bool idFound = false; 21302cad96eSEd Tanous for (const auto& objpath : dbusData) 2144a0cb85cSEd Tanous { 21502cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 2164a0cb85cSEd Tanous { 21781ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 218029573d4SEd Tanous { 2194c9afe43SEd Tanous idFound = true; 2204a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2214a0cb85cSEd Tanous { 2224a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2234a0cb85cSEd Tanous { 2244a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2254a0cb85cSEd Tanous { 2264a0cb85cSEd Tanous const std::string* mac = 227abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2284a0cb85cSEd Tanous if (mac != nullptr) 2294a0cb85cSEd Tanous { 23082695a5bSJiaqing Zhao ethData.macAddress = *mac; 2314a0cb85cSEd Tanous } 2324a0cb85cSEd Tanous } 2334a0cb85cSEd Tanous } 2344a0cb85cSEd Tanous } 2354a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2364a0cb85cSEd Tanous { 2374a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2384a0cb85cSEd Tanous { 2394a0cb85cSEd Tanous if (propertyPair.first == "Id") 2404a0cb85cSEd Tanous { 2411b6b96c5SEd Tanous const uint32_t* id = 242abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2434a0cb85cSEd Tanous if (id != nullptr) 2444a0cb85cSEd Tanous { 24517e22024SJiaqing Zhao ethData.vlanId = *id; 2464a0cb85cSEd Tanous } 2474a0cb85cSEd Tanous } 2484a0cb85cSEd Tanous } 2494a0cb85cSEd Tanous } 2504a0cb85cSEd Tanous else if (ifacePair.first == 2514a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2524a0cb85cSEd Tanous { 2534a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2544a0cb85cSEd Tanous { 2554a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2564a0cb85cSEd Tanous { 2572c70f800SEd Tanous const bool* autoNeg = 258abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2592c70f800SEd Tanous if (autoNeg != nullptr) 2604a0cb85cSEd Tanous { 26182695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2624a0cb85cSEd Tanous } 2634a0cb85cSEd Tanous } 2644a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2654a0cb85cSEd Tanous { 2664a0cb85cSEd Tanous const uint32_t* speed = 267abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2684a0cb85cSEd Tanous if (speed != nullptr) 2694a0cb85cSEd Tanous { 2704a0cb85cSEd Tanous ethData.speed = *speed; 2714a0cb85cSEd Tanous } 2724a0cb85cSEd Tanous } 27335fb5311STejas Patil else if (propertyPair.first == "MTU") 27435fb5311STejas Patil { 2753e7a8da6SAnthony const size_t* mtuSize = 2763e7a8da6SAnthony std::get_if<size_t>(&propertyPair.second); 27735fb5311STejas Patil if (mtuSize != nullptr) 27835fb5311STejas Patil { 27935fb5311STejas Patil ethData.mtuSize = *mtuSize; 28035fb5311STejas Patil } 28135fb5311STejas Patil } 282aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 283aa05fb27SJohnathan Mantey { 284aa05fb27SJohnathan Mantey const bool* linkUp = 285aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 286aa05fb27SJohnathan Mantey if (linkUp != nullptr) 287aa05fb27SJohnathan Mantey { 288aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 289aa05fb27SJohnathan Mantey } 290aa05fb27SJohnathan Mantey } 291eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 292eeedda23SJohnathan Mantey { 293eeedda23SJohnathan Mantey const bool* nicEnabled = 294eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 295eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 296eeedda23SJohnathan Mantey { 297eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 298eeedda23SJohnathan Mantey } 299eeedda23SJohnathan Mantey } 300b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 301b10d8db0SRavi Teja { 302b10d8db0SRavi Teja const bool* ipv6AcceptRa = 303b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 304b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 305b10d8db0SRavi Teja { 306b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 307b10d8db0SRavi Teja } 308b10d8db0SRavi Teja } 309f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 310029573d4SEd Tanous { 311029573d4SEd Tanous const std::vector<std::string>* nameservers = 3128d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 313029573d4SEd Tanous &propertyPair.second); 314029573d4SEd Tanous if (nameservers != nullptr) 315029573d4SEd Tanous { 316f23b7296SEd Tanous ethData.nameServers = *nameservers; 3170f6efdc1Smanojkiran.eda@gmail.com } 3180f6efdc1Smanojkiran.eda@gmail.com } 3190f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3200f6efdc1Smanojkiran.eda@gmail.com { 3210f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3228d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3230f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3240f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3250f6efdc1Smanojkiran.eda@gmail.com { 326f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3274a0cb85cSEd Tanous } 3284a0cb85cSEd Tanous } 3292a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3302a133282Smanojkiraneda { 3312c70f800SEd Tanous const std::string* dhcpEnabled = 3321f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3332c70f800SEd Tanous if (dhcpEnabled != nullptr) 3342a133282Smanojkiraneda { 33582695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3362a133282Smanojkiraneda } 3372a133282Smanojkiraneda } 338d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 339d24bfc7aSJennifer Lee { 340d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3418d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 342d24bfc7aSJennifer Lee &propertyPair.second); 343d24bfc7aSJennifer Lee if (domainNames != nullptr) 344d24bfc7aSJennifer Lee { 345f23b7296SEd Tanous ethData.domainnames = *domainNames; 346d24bfc7aSJennifer Lee } 347d24bfc7aSJennifer Lee } 3489010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3499010ec2eSRavi Teja { 3509010ec2eSRavi Teja const std::string* defaultGateway = 3519010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3529010ec2eSRavi Teja if (defaultGateway != nullptr) 3539010ec2eSRavi Teja { 3549010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3559010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3569010ec2eSRavi Teja { 35782695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3589010ec2eSRavi Teja } 3599010ec2eSRavi Teja else 3609010ec2eSRavi Teja { 36182695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3629010ec2eSRavi Teja } 3639010ec2eSRavi Teja } 3649010ec2eSRavi Teja } 3659010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3669010ec2eSRavi Teja { 3679010ec2eSRavi Teja const std::string* defaultGateway6 = 3689010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3699010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3709010ec2eSRavi Teja { 3719010ec2eSRavi Teja std::string defaultGateway6Str = 3729010ec2eSRavi Teja *defaultGateway6; 3739010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3749010ec2eSRavi Teja { 37582695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3769010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3779010ec2eSRavi Teja } 3789010ec2eSRavi Teja else 3799010ec2eSRavi Teja { 38082695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3819010ec2eSRavi Teja defaultGateway6Str; 3829010ec2eSRavi Teja } 3839010ec2eSRavi Teja } 3849010ec2eSRavi Teja } 385029573d4SEd Tanous } 386029573d4SEd Tanous } 387029573d4SEd Tanous } 3881f8c7b5dSJohnathan Mantey 389e4588158SJishnu CM sdbusplus::message::object_path path( 390e4588158SJishnu CM "/xyz/openbmc_project/network"); 391e4588158SJishnu CM sdbusplus::message::object_path dhcp4Path = path / ethifaceId / 392e4588158SJishnu CM "dhcp4"; 393e4588158SJishnu CM 394e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp4Path) 3951f8c7b5dSJohnathan Mantey { 3961f8c7b5dSJohnathan Mantey if (ifacePair.first == 3971f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 3981f8c7b5dSJohnathan Mantey { 3991f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 4001f8c7b5dSJohnathan Mantey { 4011f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 4021f8c7b5dSJohnathan Mantey { 4032c70f800SEd Tanous const bool* dnsEnabled = 4041f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4052c70f800SEd Tanous if (dnsEnabled != nullptr) 4061f8c7b5dSJohnathan Mantey { 407e4588158SJishnu CM ethData.dnsv4Enabled = *dnsEnabled; 4081f8c7b5dSJohnathan Mantey } 4091f8c7b5dSJohnathan Mantey } 41091c441ecSRavi Teja else if (propertyPair.first == "DomainEnabled") 41191c441ecSRavi Teja { 41291c441ecSRavi Teja const bool* domainEnabled = 41391c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 41491c441ecSRavi Teja if (domainEnabled != nullptr) 41591c441ecSRavi Teja { 41691c441ecSRavi Teja ethData.domainv4Enabled = *domainEnabled; 41791c441ecSRavi Teja } 41891c441ecSRavi Teja } 4191f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 4201f8c7b5dSJohnathan Mantey { 4212c70f800SEd Tanous const bool* ntpEnabled = 4221f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4232c70f800SEd Tanous if (ntpEnabled != nullptr) 4241f8c7b5dSJohnathan Mantey { 425e4588158SJishnu CM ethData.ntpv4Enabled = *ntpEnabled; 4261f8c7b5dSJohnathan Mantey } 4271f8c7b5dSJohnathan Mantey } 4281f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 4291f8c7b5dSJohnathan Mantey { 4302c70f800SEd Tanous const bool* hostNameEnabled = 4311f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4322c70f800SEd Tanous if (hostNameEnabled != nullptr) 4331f8c7b5dSJohnathan Mantey { 434e4588158SJishnu CM ethData.hostNamev4Enabled = *hostNameEnabled; 435e4588158SJishnu CM } 436e4588158SJishnu CM } 437e4588158SJishnu CM } 438e4588158SJishnu CM } 439e4588158SJishnu CM } 440e4588158SJishnu CM 441e4588158SJishnu CM sdbusplus::message::object_path dhcp6Path = path / ethifaceId / 442e4588158SJishnu CM "dhcp6"; 443e4588158SJishnu CM 444e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp6Path) 445e4588158SJishnu CM { 446e4588158SJishnu CM if (ifacePair.first == 447e4588158SJishnu CM "xyz.openbmc_project.Network.DHCPConfiguration") 448e4588158SJishnu CM { 449e4588158SJishnu CM for (const auto& propertyPair : ifacePair.second) 450e4588158SJishnu CM { 451e4588158SJishnu CM if (propertyPair.first == "DNSEnabled") 452e4588158SJishnu CM { 453e4588158SJishnu CM const bool* dnsEnabled = 454e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 455e4588158SJishnu CM if (dnsEnabled != nullptr) 456e4588158SJishnu CM { 457e4588158SJishnu CM ethData.dnsv6Enabled = *dnsEnabled; 458e4588158SJishnu CM } 459e4588158SJishnu CM } 46091c441ecSRavi Teja if (propertyPair.first == "DomainEnabled") 46191c441ecSRavi Teja { 46291c441ecSRavi Teja const bool* domainEnabled = 46391c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 46491c441ecSRavi Teja if (domainEnabled != nullptr) 46591c441ecSRavi Teja { 46691c441ecSRavi Teja ethData.domainv6Enabled = *domainEnabled; 46791c441ecSRavi Teja } 46891c441ecSRavi Teja } 469e4588158SJishnu CM else if (propertyPair.first == "NTPEnabled") 470e4588158SJishnu CM { 471e4588158SJishnu CM const bool* ntpEnabled = 472e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 473e4588158SJishnu CM if (ntpEnabled != nullptr) 474e4588158SJishnu CM { 475e4588158SJishnu CM ethData.ntpv6Enabled = *ntpEnabled; 476e4588158SJishnu CM } 477e4588158SJishnu CM } 478e4588158SJishnu CM else if (propertyPair.first == "HostNameEnabled") 479e4588158SJishnu CM { 480e4588158SJishnu CM const bool* hostNameEnabled = 481e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 482e4588158SJishnu CM if (hostNameEnabled != nullptr) 483e4588158SJishnu CM { 484e4588158SJishnu CM ethData.hostNamev6Enabled = *hostNameEnabled; 4851f8c7b5dSJohnathan Mantey } 4861f8c7b5dSJohnathan Mantey } 4871f8c7b5dSJohnathan Mantey } 4881f8c7b5dSJohnathan Mantey } 4891f8c7b5dSJohnathan Mantey } 490029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 491029573d4SEd Tanous // to check eth number 492029573d4SEd Tanous if (ifacePair.first == 4934a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 4944a0cb85cSEd Tanous { 4954a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 4964a0cb85cSEd Tanous { 4974a0cb85cSEd Tanous if (propertyPair.first == "HostName") 4984a0cb85cSEd Tanous { 4994a0cb85cSEd Tanous const std::string* hostname = 5008d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 5014a0cb85cSEd Tanous if (hostname != nullptr) 5024a0cb85cSEd Tanous { 50382695a5bSJiaqing Zhao ethData.hostName = *hostname; 5044a0cb85cSEd Tanous } 5054a0cb85cSEd Tanous } 5064a0cb85cSEd Tanous } 5074a0cb85cSEd Tanous } 5084a0cb85cSEd Tanous } 5094a0cb85cSEd Tanous } 5104c9afe43SEd Tanous return idFound; 5114a0cb85cSEd Tanous } 5124a0cb85cSEd Tanous 513e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 51477179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 515711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 51677179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 517e48c0fc5SRavi Teja { 51889492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 51989492a15SPatrick Williams ethifaceId; 520e48c0fc5SRavi Teja 521e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 522e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 52381ce609eSEd Tanous for (const auto& objpath : dbusData) 524e48c0fc5SRavi Teja { 525e48c0fc5SRavi Teja // Check if proper pattern for object path appears 526353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 527e48c0fc5SRavi Teja { 5289eb808c1SEd Tanous for (const auto& interface : objpath.second) 529e48c0fc5SRavi Teja { 530e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 531e48c0fc5SRavi Teja { 5323544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 533353163e9STony Lee [](const auto& property) { 534353163e9STony Lee return property.first == "Type"; 535353163e9STony Lee }); 536353163e9STony Lee if (type == interface.second.end()) 537353163e9STony Lee { 538353163e9STony Lee continue; 539353163e9STony Lee } 540353163e9STony Lee 541353163e9STony Lee const std::string* typeStr = 542353163e9STony Lee std::get_if<std::string>(&type->second); 543353163e9STony Lee 544353163e9STony Lee if (typeStr == nullptr || 545353163e9STony Lee (*typeStr != 546353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 547353163e9STony Lee { 548353163e9STony Lee continue; 549353163e9STony Lee } 550353163e9STony Lee 551e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 552e48c0fc5SRavi Teja // appropriate 55377179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 5542c70f800SEd Tanous ipv6Address.id = 555353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5569eb808c1SEd Tanous for (const auto& property : interface.second) 557e48c0fc5SRavi Teja { 558e48c0fc5SRavi Teja if (property.first == "Address") 559e48c0fc5SRavi Teja { 560e48c0fc5SRavi Teja const std::string* address = 561e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 562e48c0fc5SRavi Teja if (address != nullptr) 563e48c0fc5SRavi Teja { 5642c70f800SEd Tanous ipv6Address.address = *address; 565e48c0fc5SRavi Teja } 566e48c0fc5SRavi Teja } 567e48c0fc5SRavi Teja else if (property.first == "Origin") 568e48c0fc5SRavi Teja { 569e48c0fc5SRavi Teja const std::string* origin = 570e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 571e48c0fc5SRavi Teja if (origin != nullptr) 572e48c0fc5SRavi Teja { 5732c70f800SEd Tanous ipv6Address.origin = 574e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 575e48c0fc5SRavi Teja false); 576e48c0fc5SRavi Teja } 577e48c0fc5SRavi Teja } 578e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 579e48c0fc5SRavi Teja { 580e48c0fc5SRavi Teja const uint8_t* prefix = 581e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 582e48c0fc5SRavi Teja if (prefix != nullptr) 583e48c0fc5SRavi Teja { 5842c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 585e48c0fc5SRavi Teja } 586e48c0fc5SRavi Teja } 587889ff694SAsmitha Karunanithi else if (property.first == "Type" || 588889ff694SAsmitha Karunanithi property.first == "Gateway") 589889ff694SAsmitha Karunanithi { 590889ff694SAsmitha Karunanithi // Type & Gateway is not used 591889ff694SAsmitha Karunanithi } 592e48c0fc5SRavi Teja else 593e48c0fc5SRavi Teja { 59462598e31SEd Tanous BMCWEB_LOG_ERROR( 59562598e31SEd Tanous "Got extra property: {} on the {} object", 59662598e31SEd Tanous property.first, objpath.first.str); 597e48c0fc5SRavi Teja } 598e48c0fc5SRavi Teja } 599e48c0fc5SRavi Teja } 600e48c0fc5SRavi Teja } 601e48c0fc5SRavi Teja } 602e48c0fc5SRavi Teja } 603e48c0fc5SRavi Teja } 604e48c0fc5SRavi Teja 6054a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 60677179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 607711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 60877179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 6094a0cb85cSEd Tanous { 61089492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 61189492a15SPatrick Williams ethifaceId; 6124a0cb85cSEd Tanous 6134a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 6144a0cb85cSEd Tanous // single ethernet interface, loop over all of them 61581ce609eSEd Tanous for (const auto& objpath : dbusData) 6164a0cb85cSEd Tanous { 6174a0cb85cSEd Tanous // Check if proper pattern for object path appears 618353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 6194a0cb85cSEd Tanous { 6209eb808c1SEd Tanous for (const auto& interface : objpath.second) 6214a0cb85cSEd Tanous { 6224a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 6234a0cb85cSEd Tanous { 6243544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 625353163e9STony Lee [](const auto& property) { 626353163e9STony Lee return property.first == "Type"; 627353163e9STony Lee }); 628353163e9STony Lee if (type == interface.second.end()) 629353163e9STony Lee { 630353163e9STony Lee continue; 631353163e9STony Lee } 632353163e9STony Lee 633353163e9STony Lee const std::string* typeStr = 634353163e9STony Lee std::get_if<std::string>(&type->second); 635353163e9STony Lee 636353163e9STony Lee if (typeStr == nullptr || 637353163e9STony Lee (*typeStr != 638353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 639353163e9STony Lee { 640353163e9STony Lee continue; 641353163e9STony Lee } 642353163e9STony Lee 6434a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 6444a0cb85cSEd Tanous // appropriate 64577179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 6462c70f800SEd Tanous ipv4Address.id = 647353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 6489eb808c1SEd Tanous for (const auto& property : interface.second) 6494a0cb85cSEd Tanous { 6504a0cb85cSEd Tanous if (property.first == "Address") 6514a0cb85cSEd Tanous { 6524a0cb85cSEd Tanous const std::string* address = 653abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6544a0cb85cSEd Tanous if (address != nullptr) 6554a0cb85cSEd Tanous { 6562c70f800SEd Tanous ipv4Address.address = *address; 6574a0cb85cSEd Tanous } 6584a0cb85cSEd Tanous } 6594a0cb85cSEd Tanous else if (property.first == "Origin") 6604a0cb85cSEd Tanous { 6614a0cb85cSEd Tanous const std::string* origin = 662abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6634a0cb85cSEd Tanous if (origin != nullptr) 6644a0cb85cSEd Tanous { 6652c70f800SEd Tanous ipv4Address.origin = 6664a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 6674a0cb85cSEd Tanous true); 6684a0cb85cSEd Tanous } 6694a0cb85cSEd Tanous } 6704a0cb85cSEd Tanous else if (property.first == "PrefixLength") 6714a0cb85cSEd Tanous { 6724a0cb85cSEd Tanous const uint8_t* mask = 673abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 6744a0cb85cSEd Tanous if (mask != nullptr) 6754a0cb85cSEd Tanous { 6764a0cb85cSEd Tanous // convert it to the string 6772c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 6784a0cb85cSEd Tanous } 6794a0cb85cSEd Tanous } 680889ff694SAsmitha Karunanithi else if (property.first == "Type" || 681889ff694SAsmitha Karunanithi property.first == "Gateway") 682889ff694SAsmitha Karunanithi { 683889ff694SAsmitha Karunanithi // Type & Gateway is not used 684889ff694SAsmitha Karunanithi } 6854a0cb85cSEd Tanous else 6864a0cb85cSEd Tanous { 68762598e31SEd Tanous BMCWEB_LOG_ERROR( 68862598e31SEd Tanous "Got extra property: {} on the {} object", 68962598e31SEd Tanous property.first, objpath.first.str); 6904a0cb85cSEd Tanous } 6914a0cb85cSEd Tanous } 6924a0cb85cSEd Tanous // Check if given address is local, or global 6932c70f800SEd Tanous ipv4Address.linktype = 69411ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 69518659d10SJohnathan Mantey ? LinkType::Local 69618659d10SJohnathan Mantey : LinkType::Global; 6974a0cb85cSEd Tanous } 6984a0cb85cSEd Tanous } 6994a0cb85cSEd Tanous } 7004a0cb85cSEd Tanous } 7014a0cb85cSEd Tanous } 702588c3f0dSKowalski, Kamil 703588c3f0dSKowalski, Kamil /** 70401784826SJohnathan Mantey * @brief Deletes given IPv4 interface 705179db1d7SKowalski, Kamil * 706179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 707179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 708179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 709179db1d7SKowalski, Kamil * 710179db1d7SKowalski, Kamil * @return None 711179db1d7SKowalski, Kamil */ 7129c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 7139c5e585cSRavi Teja const std::string& ipHash, 7148d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7151abe55efSEd Tanous { 71655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7175e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 7181abe55efSEd Tanous if (ec) 7191abe55efSEd Tanous { 720a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7211abe55efSEd Tanous } 722179db1d7SKowalski, Kamil }, 723179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 7249c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 725179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 726179db1d7SKowalski, Kamil } 727179db1d7SKowalski, Kamil 728244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway( 729244b6d5bSGunnar Mills const std::string& ifaceId, const std::string& gateway, 730244b6d5bSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7319010ec2eSRavi Teja { 7329ae226faSGeorge Liu sdbusplus::asio::setProperty( 7339ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 7349ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 7359ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 7369ae226faSGeorge Liu gateway, [asyncResp](const boost::system::error_code& ec) { 7379010ec2eSRavi Teja if (ec) 7389010ec2eSRavi Teja { 7399010ec2eSRavi Teja messages::internalError(asyncResp->res); 7409010ec2eSRavi Teja return; 7419010ec2eSRavi Teja } 7429010ec2eSRavi Teja asyncResp->res.result(boost::beast::http::status::no_content); 7439ae226faSGeorge Liu }); 7449010ec2eSRavi Teja } 745179db1d7SKowalski, Kamil /** 74601784826SJohnathan Mantey * @brief Creates a static IPv4 entry 747179db1d7SKowalski, Kamil * 74801784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 74901784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 75001784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 75101784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 752179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 753179db1d7SKowalski, Kamil * 754179db1d7SKowalski, Kamil * @return None 755179db1d7SKowalski, Kamil */ 756cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 757cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7588d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7591abe55efSEd Tanous { 7605a39f77aSPatrick Williams auto createIpHandler = [asyncResp, ifaceId, 7615a39f77aSPatrick Williams gateway](const boost::system::error_code& ec) { 7621abe55efSEd Tanous if (ec) 7631abe55efSEd Tanous { 764a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7659010ec2eSRavi Teja return; 766179db1d7SKowalski, Kamil } 7679010ec2eSRavi Teja updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); 7689010ec2eSRavi Teja }; 7699010ec2eSRavi Teja 7709010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 7719010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 772179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 773179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 77401784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 775179db1d7SKowalski, Kamil gateway); 776179db1d7SKowalski, Kamil } 777e48c0fc5SRavi Teja 778e48c0fc5SRavi Teja /** 77901784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 78001784826SJohnathan Mantey * static IPv6 entry 78101784826SJohnathan Mantey * 78201784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 78301784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 78401784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 78501784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 78601784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 78701784826SJohnathan Mantey * 78801784826SJohnathan Mantey * @return None 78901784826SJohnathan Mantey */ 7909c5e585cSRavi Teja 7919c5e585cSRavi Teja enum class IpVersion 7929c5e585cSRavi Teja { 7939c5e585cSRavi Teja IpV4, 7949c5e585cSRavi Teja IpV6 7959c5e585cSRavi Teja }; 7969c5e585cSRavi Teja 7979c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 7989c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 7998d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 8009c5e585cSRavi Teja const std::string& gateway, 8018d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 80201784826SJohnathan Mantey { 80301784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8049c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 8059c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 80601784826SJohnathan Mantey if (ec) 80701784826SJohnathan Mantey { 80801784826SJohnathan Mantey messages::internalError(asyncResp->res); 80901784826SJohnathan Mantey } 8109c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 8119c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 81201784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8135e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 81423a21a1cSEd Tanous if (ec2) 81501784826SJohnathan Mantey { 81601784826SJohnathan Mantey messages::internalError(asyncResp->res); 81701784826SJohnathan Mantey } 81801784826SJohnathan Mantey }, 81901784826SJohnathan Mantey "xyz.openbmc_project.Network", 82001784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 8219c5e585cSRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address, 8229c5e585cSRavi Teja prefixLength, gateway); 82301784826SJohnathan Mantey }, 82401784826SJohnathan Mantey "xyz.openbmc_project.Network", 8259c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 82601784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 82701784826SJohnathan Mantey } 82801784826SJohnathan Mantey 829*ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData( 830*ce73d5c8SSunitha Harish const std::string& ethifaceId, 831*ce73d5c8SSunitha Harish const dbus::utility::ManagedObjectType& dbusData, 832*ce73d5c8SSunitha Harish std::vector<StaticGatewayData>& staticGatewayConfig) 833*ce73d5c8SSunitha Harish { 834*ce73d5c8SSunitha Harish std::string staticGatewayPathStart("/xyz/openbmc_project/network/"); 835*ce73d5c8SSunitha Harish staticGatewayPathStart += ethifaceId; 836*ce73d5c8SSunitha Harish 837*ce73d5c8SSunitha Harish for (const auto& objpath : dbusData) 838*ce73d5c8SSunitha Harish { 839*ce73d5c8SSunitha Harish if (!std::string_view(objpath.first.str) 840*ce73d5c8SSunitha Harish .starts_with(staticGatewayPathStart)) 841*ce73d5c8SSunitha Harish { 842*ce73d5c8SSunitha Harish continue; 843*ce73d5c8SSunitha Harish } 844*ce73d5c8SSunitha Harish for (const auto& interface : objpath.second) 845*ce73d5c8SSunitha Harish { 846*ce73d5c8SSunitha Harish if (interface.first != "xyz.openbmc_project.Network.StaticGateway") 847*ce73d5c8SSunitha Harish { 848*ce73d5c8SSunitha Harish continue; 849*ce73d5c8SSunitha Harish } 850*ce73d5c8SSunitha Harish StaticGatewayData& staticGateway = 851*ce73d5c8SSunitha Harish staticGatewayConfig.emplace_back(); 852*ce73d5c8SSunitha Harish staticGateway.id = objpath.first.filename(); 853*ce73d5c8SSunitha Harish 854*ce73d5c8SSunitha Harish bool success = sdbusplus::unpackPropertiesNoThrow( 855*ce73d5c8SSunitha Harish redfish::dbus_utils::UnpackErrorPrinter(), interface.second, 856*ce73d5c8SSunitha Harish "Gateway", staticGateway.gateway, "PrefixLength", 857*ce73d5c8SSunitha Harish staticGateway.prefixLength, "ProtocolType", 858*ce73d5c8SSunitha Harish staticGateway.protocol); 859*ce73d5c8SSunitha Harish if (!success) 860*ce73d5c8SSunitha Harish { 861*ce73d5c8SSunitha Harish return false; 862*ce73d5c8SSunitha Harish } 863*ce73d5c8SSunitha Harish } 864*ce73d5c8SSunitha Harish } 865*ce73d5c8SSunitha Harish return true; 866*ce73d5c8SSunitha Harish } 867*ce73d5c8SSunitha Harish 86801784826SJohnathan Mantey /** 869e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 870e48c0fc5SRavi Teja * 871e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 872e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 873e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 874e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 875e48c0fc5SRavi Teja * 876e48c0fc5SRavi Teja * @return None 877e48c0fc5SRavi Teja */ 87801784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 87901784826SJohnathan Mantey const std::string& address, 8808d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 881e48c0fc5SRavi Teja { 882*ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 883*ce73d5c8SSunitha Harish path /= ifaceId; 884*ce73d5c8SSunitha Harish 8855a39f77aSPatrick Williams auto createIpHandler = [asyncResp, 8865a39f77aSPatrick Williams address](const boost::system::error_code& ec) { 887e48c0fc5SRavi Teja if (ec) 888e48c0fc5SRavi Teja { 889fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 890fc23ef8aSNitin Kumar Kotania { 891fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 892fc23ef8aSNitin Kumar Kotania "Address"); 893fc23ef8aSNitin Kumar Kotania } 894fc23ef8aSNitin Kumar Kotania else 895fc23ef8aSNitin Kumar Kotania { 896e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 897e48c0fc5SRavi Teja } 898fc23ef8aSNitin Kumar Kotania } 899e48c0fc5SRavi Teja }; 900*ce73d5c8SSunitha Harish // Passing null for gateway, as per redfish spec IPv6StaticAddresses 901*ce73d5c8SSunitha Harish // object does not have associated gateway property 902e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 903*ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 904e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 905e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 906e48c0fc5SRavi Teja ""); 907e48c0fc5SRavi Teja } 908e48c0fc5SRavi Teja 909179db1d7SKowalski, Kamil /** 910*ce73d5c8SSunitha Harish * @brief Deletes given IPv6 Static Gateway 911*ce73d5c8SSunitha Harish * 912*ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be deleted 913*ce73d5c8SSunitha Harish * @param[in] ipHash DBus Hash id of IP that should be deleted 914*ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 915*ce73d5c8SSunitha Harish * 916*ce73d5c8SSunitha Harish * @return None 917*ce73d5c8SSunitha Harish */ 918*ce73d5c8SSunitha Harish inline void 919*ce73d5c8SSunitha Harish deleteIPv6Gateway(std::string_view gatewayId, 920*ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 921*ce73d5c8SSunitha Harish { 922*ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 923*ce73d5c8SSunitha Harish path /= gatewayId; 924*ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 925*ce73d5c8SSunitha Harish [asyncResp](const boost::system::error_code& ec) { 926*ce73d5c8SSunitha Harish if (ec) 927*ce73d5c8SSunitha Harish { 928*ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 929*ce73d5c8SSunitha Harish } 930*ce73d5c8SSunitha Harish }, 931*ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 932*ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 933*ce73d5c8SSunitha Harish } 934*ce73d5c8SSunitha Harish 935*ce73d5c8SSunitha Harish /** 936*ce73d5c8SSunitha Harish * @brief Creates IPv6 static default gateway with given data 937*ce73d5c8SSunitha Harish * 938*ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be added 939*ce73d5c8SSunitha Harish * @param[in] prefixLength Prefix length that needs to be added 940*ce73d5c8SSunitha Harish * @param[in] gateway Gateway address that needs to be added 941*ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 942*ce73d5c8SSunitha Harish * 943*ce73d5c8SSunitha Harish * @return None 944*ce73d5c8SSunitha Harish */ 945*ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway( 946*ce73d5c8SSunitha Harish std::string_view ifaceId, size_t prefixLength, std::string_view gateway, 947*ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 948*ce73d5c8SSunitha Harish { 949*ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 950*ce73d5c8SSunitha Harish path /= ifaceId; 951*ce73d5c8SSunitha Harish auto createIpHandler = [asyncResp](const boost::system::error_code& ec) { 952*ce73d5c8SSunitha Harish if (ec) 953*ce73d5c8SSunitha Harish { 954*ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 955*ce73d5c8SSunitha Harish } 956*ce73d5c8SSunitha Harish }; 957*ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 958*ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 959*ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway", 960*ce73d5c8SSunitha Harish gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6"); 961*ce73d5c8SSunitha Harish } 962*ce73d5c8SSunitha Harish 963*ce73d5c8SSunitha Harish /** 964*ce73d5c8SSunitha Harish * @brief Deletes the IPv6 default gateway entry for this interface and 965*ce73d5c8SSunitha Harish * creates a replacement IPv6 default gateway entry 966*ce73d5c8SSunitha Harish * 967*ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface upon which to create the IPv6 968*ce73d5c8SSunitha Harish * entry 969*ce73d5c8SSunitha Harish * @param[in] gateway IPv6 gateway to assign to this interface 970*ce73d5c8SSunitha Harish * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 971*ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 972*ce73d5c8SSunitha Harish * 973*ce73d5c8SSunitha Harish * @return None 974*ce73d5c8SSunitha Harish */ 975*ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway( 976*ce73d5c8SSunitha Harish std::string_view ifaceId, std::string_view gatewayId, 977*ce73d5c8SSunitha Harish std::string_view gateway, size_t prefixLength, 978*ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 979*ce73d5c8SSunitha Harish { 980*ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 981*ce73d5c8SSunitha Harish path /= gatewayId; 982*ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 983*ce73d5c8SSunitha Harish [asyncResp, ifaceId, gateway, 984*ce73d5c8SSunitha Harish prefixLength](const boost::system::error_code& ec) { 985*ce73d5c8SSunitha Harish if (ec) 986*ce73d5c8SSunitha Harish { 987*ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 988*ce73d5c8SSunitha Harish return; 989*ce73d5c8SSunitha Harish } 990*ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp); 991*ce73d5c8SSunitha Harish }, 992*ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 993*ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 994*ce73d5c8SSunitha Harish } 995*ce73d5c8SSunitha Harish 996*ce73d5c8SSunitha Harish /** 997*ce73d5c8SSunitha Harish * @brief Sets IPv6 default gateway with given data 998*ce73d5c8SSunitha Harish * 999*ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose gateway should be added 1000*ce73d5c8SSunitha Harish * @param[in] input Contains address that needs to be added 1001*ce73d5c8SSunitha Harish * @param[in] staticGatewayData Current static gateways in the system 1002*ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 1003*ce73d5c8SSunitha Harish * 1004*ce73d5c8SSunitha Harish * @return None 1005*ce73d5c8SSunitha Harish */ 1006*ce73d5c8SSunitha Harish 1007*ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway( 1008*ce73d5c8SSunitha Harish const std::string& ifaceId, const nlohmann::json::array_t& input, 1009*ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& staticGatewayData, 1010*ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1011*ce73d5c8SSunitha Harish { 1012*ce73d5c8SSunitha Harish size_t entryIdx = 1; 1013*ce73d5c8SSunitha Harish std::vector<StaticGatewayData>::const_iterator staticGatewayEntry = 1014*ce73d5c8SSunitha Harish staticGatewayData.begin(); 1015*ce73d5c8SSunitha Harish 1016*ce73d5c8SSunitha Harish for (const nlohmann::json& thisJson : input) 1017*ce73d5c8SSunitha Harish { 1018*ce73d5c8SSunitha Harish // find the next gateway entry 1019*ce73d5c8SSunitha Harish while (staticGatewayEntry != staticGatewayData.end()) 1020*ce73d5c8SSunitha Harish { 1021*ce73d5c8SSunitha Harish if (staticGatewayEntry->protocol == 1022*ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.IP.Protocol.IPv6") 1023*ce73d5c8SSunitha Harish { 1024*ce73d5c8SSunitha Harish break; 1025*ce73d5c8SSunitha Harish } 1026*ce73d5c8SSunitha Harish staticGatewayEntry++; 1027*ce73d5c8SSunitha Harish } 1028*ce73d5c8SSunitha Harish std::string pathString = "IPv6StaticDefaultGateways/" + 1029*ce73d5c8SSunitha Harish std::to_string(entryIdx); 1030*ce73d5c8SSunitha Harish if (thisJson.is_null()) 1031*ce73d5c8SSunitha Harish { 1032*ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1033*ce73d5c8SSunitha Harish { 1034*ce73d5c8SSunitha Harish messages::resourceCannotBeDeleted(asyncResp->res); 1035*ce73d5c8SSunitha Harish return; 1036*ce73d5c8SSunitha Harish } 1037*ce73d5c8SSunitha Harish deleteIPv6Gateway(staticGatewayEntry->id, asyncResp); 1038*ce73d5c8SSunitha Harish return; 1039*ce73d5c8SSunitha Harish } 1040*ce73d5c8SSunitha Harish if (thisJson.is_object() && thisJson.empty()) 1041*ce73d5c8SSunitha Harish { 1042*ce73d5c8SSunitha Harish // Do nothing, but make sure the entry exists. 1043*ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1044*ce73d5c8SSunitha Harish { 1045*ce73d5c8SSunitha Harish messages::propertyValueFormatError(asyncResp->res, thisJson, 1046*ce73d5c8SSunitha Harish pathString); 1047*ce73d5c8SSunitha Harish return; 1048*ce73d5c8SSunitha Harish } 1049*ce73d5c8SSunitha Harish } 1050*ce73d5c8SSunitha Harish std::optional<std::string> address; 1051*ce73d5c8SSunitha Harish std::optional<size_t> prefixLength; 1052*ce73d5c8SSunitha Harish 1053*ce73d5c8SSunitha Harish nlohmann::json thisJsonCopy = thisJson; 1054*ce73d5c8SSunitha Harish if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 1055*ce73d5c8SSunitha Harish address, "PrefixLength", prefixLength)) 1056*ce73d5c8SSunitha Harish { 1057*ce73d5c8SSunitha Harish return; 1058*ce73d5c8SSunitha Harish } 1059*ce73d5c8SSunitha Harish const std::string* addr = nullptr; 1060*ce73d5c8SSunitha Harish size_t prefix = 0; 1061*ce73d5c8SSunitha Harish if (address) 1062*ce73d5c8SSunitha Harish { 1063*ce73d5c8SSunitha Harish addr = &(*address); 1064*ce73d5c8SSunitha Harish } 1065*ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1066*ce73d5c8SSunitha Harish { 1067*ce73d5c8SSunitha Harish addr = &(staticGatewayEntry->gateway); 1068*ce73d5c8SSunitha Harish } 1069*ce73d5c8SSunitha Harish else 1070*ce73d5c8SSunitha Harish { 1071*ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, pathString + "/Address"); 1072*ce73d5c8SSunitha Harish return; 1073*ce73d5c8SSunitha Harish } 1074*ce73d5c8SSunitha Harish if (prefixLength) 1075*ce73d5c8SSunitha Harish { 1076*ce73d5c8SSunitha Harish prefix = *prefixLength; 1077*ce73d5c8SSunitha Harish } 1078*ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1079*ce73d5c8SSunitha Harish { 1080*ce73d5c8SSunitha Harish prefix = staticGatewayEntry->prefixLength; 1081*ce73d5c8SSunitha Harish } 1082*ce73d5c8SSunitha Harish else 1083*ce73d5c8SSunitha Harish { 1084*ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, 1085*ce73d5c8SSunitha Harish pathString + "/PrefixLength"); 1086*ce73d5c8SSunitha Harish return; 1087*ce73d5c8SSunitha Harish } 1088*ce73d5c8SSunitha Harish if (staticGatewayEntry != staticGatewayData.end()) 1089*ce73d5c8SSunitha Harish { 1090*ce73d5c8SSunitha Harish deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id, 1091*ce73d5c8SSunitha Harish *addr, prefix, asyncResp); 1092*ce73d5c8SSunitha Harish staticGatewayEntry++; 1093*ce73d5c8SSunitha Harish } 1094*ce73d5c8SSunitha Harish else 1095*ce73d5c8SSunitha Harish { 1096*ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp); 1097*ce73d5c8SSunitha Harish } 1098*ce73d5c8SSunitha Harish entryIdx++; 1099*ce73d5c8SSunitha Harish } 1100*ce73d5c8SSunitha Harish } 1101*ce73d5c8SSunitha Harish 1102*ce73d5c8SSunitha Harish /** 1103179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 1104179db1d7SKowalski, Kamil * Object 1105179db1d7SKowalski, Kamil * from EntityManager Network Manager 11064a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 1107179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 1108179db1d7SKowalski, Kamil * into JSON 1109179db1d7SKowalski, Kamil */ 1110179db1d7SKowalski, Kamil template <typename CallbackFunc> 111181ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 11121abe55efSEd Tanous CallbackFunc&& callback) 11131abe55efSEd Tanous { 1114f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1115f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1116f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1117f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 1118f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 11198b24275dSEd Tanous const boost::system::error_code& ec, 112002cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 112155c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 112277179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 112377179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 1124*ce73d5c8SSunitha Harish std::vector<StaticGatewayData> ipv6GatewayData; 1125179db1d7SKowalski, Kamil 11268b24275dSEd Tanous if (ec) 11271abe55efSEd Tanous { 1128*ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1129179db1d7SKowalski, Kamil return; 1130179db1d7SKowalski, Kamil } 1131179db1d7SKowalski, Kamil 1132002d39b4SEd Tanous bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); 11334c9afe43SEd Tanous if (!found) 11344c9afe43SEd Tanous { 1135*ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 11364c9afe43SEd Tanous return; 11374c9afe43SEd Tanous } 11384c9afe43SEd Tanous 11392c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 1140179db1d7SKowalski, Kamil // Fix global GW 11411abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 11421abe55efSEd Tanous { 1143c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 1144c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 11459010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 11461abe55efSEd Tanous { 114782695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 1148179db1d7SKowalski, Kamil } 1149179db1d7SKowalski, Kamil } 1150179db1d7SKowalski, Kamil 11512c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 1152*ce73d5c8SSunitha Harish if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData)) 1153*ce73d5c8SSunitha Harish { 1154*ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1155*ce73d5c8SSunitha Harish } 11564e0453b1SGunnar Mills // Finally make a callback with useful data 1157*ce73d5c8SSunitha Harish callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1158f5892d0dSGeorge Liu }); 1159271584abSEd Tanous } 1160179db1d7SKowalski, Kamil 1161179db1d7SKowalski, Kamil /** 11629391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 11639391bb9cSRapkiewicz, Pawel * Manager 11641abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 11651abe55efSEd Tanous * into JSON. 11669391bb9cSRapkiewicz, Pawel */ 11679391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 11681abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 11691abe55efSEd Tanous { 1170f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1171f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1172f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1173f94c4ecfSEd Tanous [callback{std::forward<CallbackFunc>(callback)}]( 11748b24275dSEd Tanous const boost::system::error_code& ec, 1175f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 11761abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 11771abe55efSEd Tanous // ethernet interfaces 117877179532SEd Tanous std::vector<std::string> ifaceList; 11792c70f800SEd Tanous ifaceList.reserve(resp.size()); 11808b24275dSEd Tanous if (ec) 11811abe55efSEd Tanous { 11822c70f800SEd Tanous callback(false, ifaceList); 11839391bb9cSRapkiewicz, Pawel return; 11849391bb9cSRapkiewicz, Pawel } 11859391bb9cSRapkiewicz, Pawel 11869391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 11874a0cb85cSEd Tanous for (const auto& objpath : resp) 11881abe55efSEd Tanous { 11899391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 11904a0cb85cSEd Tanous for (const auto& interface : objpath.second) 11911abe55efSEd Tanous { 11921abe55efSEd Tanous // If interface is 11934a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 11944a0cb85cSEd Tanous // what we're looking for. 11959391bb9cSRapkiewicz, Pawel if (interface.first == 11961abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 11971abe55efSEd Tanous { 11982dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 11992dfd18efSEd Tanous if (ifaceId.empty()) 12001abe55efSEd Tanous { 12012dfd18efSEd Tanous continue; 12029391bb9cSRapkiewicz, Pawel } 12032dfd18efSEd Tanous // and put it into output vector. 120477179532SEd Tanous ifaceList.emplace_back(ifaceId); 12059391bb9cSRapkiewicz, Pawel } 12069391bb9cSRapkiewicz, Pawel } 12079391bb9cSRapkiewicz, Pawel } 12082c5875a2SEd Tanous 12093544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 12102c5875a2SEd Tanous 1211a434f2bdSEd Tanous // Finally make a callback with useful data 12122c70f800SEd Tanous callback(true, ifaceList); 1213f5892d0dSGeorge Liu }); 1214271584abSEd Tanous } 12159391bb9cSRapkiewicz, Pawel 12164f48d5f6SEd Tanous inline void 12174f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 12188d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12191abe55efSEd Tanous { 1220ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 1221ab6554f1SJoshi-Mansi if (hostname.length() > 255) 1222ab6554f1SJoshi-Mansi { 1223ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 1224ab6554f1SJoshi-Mansi "HostName"); 1225ab6554f1SJoshi-Mansi return; 1226ab6554f1SJoshi-Mansi } 12279ae226faSGeorge Liu sdbusplus::asio::setProperty( 12289ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 12299ae226faSGeorge Liu "/xyz/openbmc_project/network/config", 12309ae226faSGeorge Liu "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname, 12315e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 12324a0cb85cSEd Tanous if (ec) 12334a0cb85cSEd Tanous { 1234a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12351abe55efSEd Tanous } 12369ae226faSGeorge Liu }); 1237588c3f0dSKowalski, Kamil } 1238588c3f0dSKowalski, Kamil 12394f48d5f6SEd Tanous inline void 124035fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 124135fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 124235fb5311STejas Patil { 124389492a15SPatrick Williams sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" + 124489492a15SPatrick Williams ifaceId; 12459ae226faSGeorge Liu sdbusplus::asio::setProperty( 12469ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath, 12479ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize, 12485e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 124935fb5311STejas Patil if (ec) 125035fb5311STejas Patil { 125135fb5311STejas Patil messages::internalError(asyncResp->res); 125235fb5311STejas Patil } 12539ae226faSGeorge Liu }); 125435fb5311STejas Patil } 125535fb5311STejas Patil 125635fb5311STejas Patil inline void 12574f48d5f6SEd Tanous handleDomainnamePatch(const std::string& ifaceId, 1258bf648f77SEd Tanous const std::string& domainname, 12598d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1260ab6554f1SJoshi-Mansi { 1261ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 12629ae226faSGeorge Liu sdbusplus::asio::setProperty( 12639ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 12649ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 12659ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 12669ae226faSGeorge Liu vectorDomainname, [asyncResp](const boost::system::error_code& ec) { 1267ab6554f1SJoshi-Mansi if (ec) 1268ab6554f1SJoshi-Mansi { 1269ab6554f1SJoshi-Mansi messages::internalError(asyncResp->res); 1270ab6554f1SJoshi-Mansi } 12719ae226faSGeorge Liu }); 1272ab6554f1SJoshi-Mansi } 1273ab6554f1SJoshi-Mansi 12744f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1275bf648f77SEd Tanous { 1276bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 12773544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1278bf648f77SEd Tanous { 1279bf648f77SEd Tanous return false; 1280bf648f77SEd Tanous } 1281bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1282bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1283bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1284bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 12854b242749SEd Tanous const static std::regex pattern( 1286bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1287bf648f77SEd Tanous 1288bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1289bf648f77SEd Tanous } 1290bf648f77SEd Tanous 12914f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1292bf648f77SEd Tanous { 1293bf648f77SEd Tanous // Can have multiple subdomains 1294bf648f77SEd Tanous // Top Level Domain's min length is 2 character 12954b242749SEd Tanous const static std::regex pattern( 12960fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1297bf648f77SEd Tanous 1298bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1299bf648f77SEd Tanous } 1300bf648f77SEd Tanous 13014f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 13028d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1303ab6554f1SJoshi-Mansi { 1304ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1305ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1306ab6554f1SJoshi-Mansi { 1307ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1308ab6554f1SJoshi-Mansi return; 1309ab6554f1SJoshi-Mansi } 1310ab6554f1SJoshi-Mansi 1311ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1312ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1313ab6554f1SJoshi-Mansi { 1314ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1315ab6554f1SJoshi-Mansi return; 1316ab6554f1SJoshi-Mansi } 1317ab6554f1SJoshi-Mansi 1318ab6554f1SJoshi-Mansi std::string hostname; 1319ab6554f1SJoshi-Mansi std::string domainname; 1320ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1321ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1322ab6554f1SJoshi-Mansi 1323ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1324ab6554f1SJoshi-Mansi { 1325ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1326ab6554f1SJoshi-Mansi return; 1327ab6554f1SJoshi-Mansi } 1328ab6554f1SJoshi-Mansi 1329ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1330ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1331ab6554f1SJoshi-Mansi } 1332ab6554f1SJoshi-Mansi 13334f48d5f6SEd Tanous inline void 13344f48d5f6SEd Tanous handleMACAddressPatch(const std::string& ifaceId, 1335bf648f77SEd Tanous const std::string& macAddress, 13368d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1337d577665bSRatan Gupta { 133858283f41SJohnathan Mantey static constexpr std::string_view dbusNotAllowedError = 133958283f41SJohnathan Mantey "xyz.openbmc_project.Common.Error.NotAllowed"; 134058283f41SJohnathan Mantey 13419ae226faSGeorge Liu sdbusplus::asio::setProperty( 13429ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 13439ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 13449ae226faSGeorge Liu "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress, 13459ae226faSGeorge Liu [asyncResp](const boost::system::error_code& ec, 13465b378546SPatrick Williams const sdbusplus::message_t& msg) { 1347d577665bSRatan Gupta if (ec) 1348d577665bSRatan Gupta { 134958283f41SJohnathan Mantey const sd_bus_error* err = msg.get_error(); 135058283f41SJohnathan Mantey if (err == nullptr) 135158283f41SJohnathan Mantey { 135258283f41SJohnathan Mantey messages::internalError(asyncResp->res); 135358283f41SJohnathan Mantey return; 135458283f41SJohnathan Mantey } 135558283f41SJohnathan Mantey if (err->name == dbusNotAllowedError) 135658283f41SJohnathan Mantey { 135758283f41SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "MACAddress"); 135858283f41SJohnathan Mantey return; 135958283f41SJohnathan Mantey } 1360d577665bSRatan Gupta messages::internalError(asyncResp->res); 1361d577665bSRatan Gupta return; 1362d577665bSRatan Gupta } 13639ae226faSGeorge Liu }); 1364d577665bSRatan Gupta } 1365286b9118SJohnathan Mantey 13664f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 13674f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 13684f48d5f6SEd Tanous const bool v6Value, 13698d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1370da131a9aSJennifer Lee { 13712c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 13729ae226faSGeorge Liu sdbusplus::asio::setProperty( 13739ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 13749ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 13759ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp, 13765e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1377da131a9aSJennifer Lee if (ec) 1378da131a9aSJennifer Lee { 137962598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1380da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1381da131a9aSJennifer Lee return; 1382da131a9aSJennifer Lee } 13838f7e9c19SJayaprakash Mutyala messages::success(asyncResp->res); 13849ae226faSGeorge Liu }); 1385da131a9aSJennifer Lee } 13861f8c7b5dSJohnathan Mantey 13874f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty( 1388eeedda23SJohnathan Mantey const std::string& ifaceId, const std::string& propertyName, 13898d1b46d7Szhanghch05 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1390eeedda23SJohnathan Mantey { 13919ae226faSGeorge Liu sdbusplus::asio::setProperty( 13929ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 13939ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 13949ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, value, 13955e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1396eeedda23SJohnathan Mantey if (ec) 1397eeedda23SJohnathan Mantey { 139862598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1399eeedda23SJohnathan Mantey messages::internalError(asyncResp->res); 1400eeedda23SJohnathan Mantey return; 1401eeedda23SJohnathan Mantey } 14029ae226faSGeorge Liu }); 1403eeedda23SJohnathan Mantey } 1404eeedda23SJohnathan Mantey 1405e4588158SJishnu CM enum class NetworkType 1406e4588158SJishnu CM { 1407e4588158SJishnu CM dhcp4, 1408e4588158SJishnu CM dhcp6 1409e4588158SJishnu CM }; 1410e4588158SJishnu CM 1411e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1412e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1413e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1414da131a9aSJennifer Lee { 141562598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 1416e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1417e4588158SJishnu CM path /= ethifaceId; 1418e4588158SJishnu CM 1419e4588158SJishnu CM if (type == NetworkType::dhcp4) 1420e4588158SJishnu CM { 1421e4588158SJishnu CM path /= "dhcp4"; 1422e4588158SJishnu CM } 1423e4588158SJishnu CM else 1424e4588158SJishnu CM { 1425e4588158SJishnu CM path /= "dhcp6"; 1426e4588158SJishnu CM } 1427e4588158SJishnu CM 14289ae226faSGeorge Liu sdbusplus::asio::setProperty( 1429e4588158SJishnu CM *crow::connections::systemBus, "xyz.openbmc_project.Network", path, 14309ae226faSGeorge Liu "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value, 14315e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1432da131a9aSJennifer Lee if (ec) 1433da131a9aSJennifer Lee { 143462598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1435da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1436da131a9aSJennifer Lee return; 1437da131a9aSJennifer Lee } 14389ae226faSGeorge Liu }); 1439da131a9aSJennifer Lee } 1440d577665bSRatan Gupta 1441b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1442b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1443b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1444b10d8db0SRavi Teja { 1445b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1446b10d8db0SRavi Teja path /= ifaceId; 1447b10d8db0SRavi Teja sdbusplus::asio::setProperty( 1448b10d8db0SRavi Teja *crow::connections::systemBus, "xyz.openbmc_project.Network", path, 1449b10d8db0SRavi Teja "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA", 1450b10d8db0SRavi Teja ipv6AutoConfigEnabled, 1451b10d8db0SRavi Teja [asyncResp](const boost::system::error_code& ec) { 1452b10d8db0SRavi Teja if (ec) 1453b10d8db0SRavi Teja { 1454b10d8db0SRavi Teja BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1455b10d8db0SRavi Teja messages::internalError(asyncResp->res); 1456b10d8db0SRavi Teja return; 1457b10d8db0SRavi Teja } 1458b10d8db0SRavi Teja messages::success(asyncResp->res); 1459b10d8db0SRavi Teja }); 1460b10d8db0SRavi Teja } 1461b10d8db0SRavi Teja 14624f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId, 14631f8c7b5dSJohnathan Mantey const EthernetInterfaceData& ethData, 1464f23b7296SEd Tanous const DHCPParameters& v4dhcpParms, 1465f23b7296SEd Tanous const DHCPParameters& v6dhcpParms, 14668d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1467da131a9aSJennifer Lee { 146882695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 146982695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1470da131a9aSJennifer Lee 14711f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 14721f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 14731f8c7b5dSJohnathan Mantey 14741f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 14751f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1476da131a9aSJennifer Lee { 1477b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 14781f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 14791f8c7b5dSJohnathan Mantey { 1480bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1481bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 14821f8c7b5dSJohnathan Mantey "OperatingMode"); 1483da131a9aSJennifer Lee return; 1484da131a9aSJennifer Lee } 1485b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 14861f8c7b5dSJohnathan Mantey } 14871f8c7b5dSJohnathan Mantey else 1488da131a9aSJennifer Lee { 14891f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 14901f8c7b5dSJohnathan Mantey } 14911f8c7b5dSJohnathan Mantey 1492e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1493e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1494e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 14951f8c7b5dSJohnathan Mantey { 1496e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 14971f8c7b5dSJohnathan Mantey } 1498e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 14991f8c7b5dSJohnathan Mantey { 1500e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 15011f8c7b5dSJohnathan Mantey } 15021f8c7b5dSJohnathan Mantey 1503e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1504e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1505e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 15061f8c7b5dSJohnathan Mantey { 1507e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 15081f8c7b5dSJohnathan Mantey } 1509e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 15101f8c7b5dSJohnathan Mantey { 1511e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 15121f8c7b5dSJohnathan Mantey } 15131f8c7b5dSJohnathan Mantey 151491c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 151591c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1516e4588158SJishnu CM if (v4dhcpParms.useDomainName) 15171f8c7b5dSJohnathan Mantey { 1518e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 15191f8c7b5dSJohnathan Mantey } 1520e4588158SJishnu CM if (v6dhcpParms.useDomainName) 15211f8c7b5dSJohnathan Mantey { 1522e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 15231f8c7b5dSJohnathan Mantey } 15241f8c7b5dSJohnathan Mantey 152562598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 15261f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 15271f8c7b5dSJohnathan Mantey asyncResp); 152862598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1529e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1530e4588158SJishnu CM NetworkType::dhcp4); 153162598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1532e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1533e4588158SJishnu CM NetworkType::dhcp4); 153491c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 153591c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1536e4588158SJishnu CM NetworkType::dhcp4); 1537e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1538e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1539e4588158SJishnu CM NetworkType::dhcp6); 1540e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1541e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1542e4588158SJishnu CM NetworkType::dhcp6); 154391c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 154491c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1545e4588158SJishnu CM NetworkType::dhcp6); 1546da131a9aSJennifer Lee } 154701784826SJohnathan Mantey 154877179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 154977179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 155077179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 155101784826SJohnathan Mantey { 155217a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 155317a897dfSManojkiran Eda return value.origin == "Static"; 155417a897dfSManojkiran Eda }); 155501784826SJohnathan Mantey } 155601784826SJohnathan Mantey 155777179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 155877179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 155977179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 156001784826SJohnathan Mantey { 156117a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 156217a897dfSManojkiran Eda return value.origin == "Static"; 156317a897dfSManojkiran Eda }); 156401784826SJohnathan Mantey } 156501784826SJohnathan Mantey 156677179532SEd Tanous inline void 1567ddd70dcaSEd Tanous handleIPv4StaticPatch(const std::string& ifaceId, 1568ddd70dcaSEd Tanous nlohmann::json::array_t& input, 156977179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 15708d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 15711abe55efSEd Tanous { 1572ddd70dcaSEd Tanous if (input.empty()) 1573f476acbfSRatan Gupta { 15742e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1575d1d50814SRavi Teja "IPv4StaticAddresses"); 1576f476acbfSRatan Gupta return; 1577f476acbfSRatan Gupta } 1578f476acbfSRatan Gupta 1579271584abSEd Tanous unsigned entryIdx = 1; 158001784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 158101784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 158201784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 158301784826SJohnathan Mantey // into the NIC. 158477179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 15852c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 158601784826SJohnathan Mantey 1587537174c4SEd Tanous for (nlohmann::json& thisJson : input) 15881abe55efSEd Tanous { 158989492a15SPatrick Williams std::string pathString = "IPv4StaticAddresses/" + 159089492a15SPatrick Williams std::to_string(entryIdx); 1591179db1d7SKowalski, Kamil 159201784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1593f476acbfSRatan Gupta { 1594537174c4SEd Tanous std::optional<std::string> address; 1595537174c4SEd Tanous std::optional<std::string> subnetMask; 1596537174c4SEd Tanous std::optional<std::string> gateway; 1597537174c4SEd Tanous 1598537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 15997e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 16007e27d832SJohnathan Mantey "Gateway", gateway)) 1601537174c4SEd Tanous { 1602f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 160371f52d96SEd Tanous pathString); 1604537174c4SEd Tanous return; 1605179db1d7SKowalski, Kamil } 1606179db1d7SKowalski, Kamil 160701784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 160801784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 160901784826SJohnathan Mantey // current state of the interface. Merge existing state into the 161001784826SJohnathan Mantey // current request. 1611537174c4SEd Tanous if (address) 16121abe55efSEd Tanous { 1613e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 161401784826SJohnathan Mantey { 1615bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1616bf648f77SEd Tanous pathString + "/Address"); 1617e01d0c36SEd Tanous return; 161801784826SJohnathan Mantey } 161901784826SJohnathan Mantey } 162085ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 162101784826SJohnathan Mantey { 1622e01d0c36SEd Tanous address = (nicIpEntry->address); 162301784826SJohnathan Mantey } 162401784826SJohnathan Mantey else 162501784826SJohnathan Mantey { 162601784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 162701784826SJohnathan Mantey pathString + "/Address"); 1628e01d0c36SEd Tanous return; 16294a0cb85cSEd Tanous } 16304a0cb85cSEd Tanous 1631e01d0c36SEd Tanous uint8_t prefixLength = 0; 1632537174c4SEd Tanous if (subnetMask) 16334a0cb85cSEd Tanous { 1634033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1635033f1e4dSEd Tanous &prefixLength)) 16364a0cb85cSEd Tanous { 1637f12894f8SJason M. Bills messages::propertyValueFormatError( 1638537174c4SEd Tanous asyncResp->res, *subnetMask, 16394a0cb85cSEd Tanous pathString + "/SubnetMask"); 1640e01d0c36SEd Tanous return; 16414a0cb85cSEd Tanous } 16424a0cb85cSEd Tanous } 164385ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 16444a0cb85cSEd Tanous { 1645033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 164601784826SJohnathan Mantey &prefixLength)) 16474a0cb85cSEd Tanous { 164801784826SJohnathan Mantey messages::propertyValueFormatError( 164985ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 165001784826SJohnathan Mantey pathString + "/SubnetMask"); 1651e01d0c36SEd Tanous return; 16524a0cb85cSEd Tanous } 16534a0cb85cSEd Tanous } 16541abe55efSEd Tanous else 16551abe55efSEd Tanous { 165601784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 165701784826SJohnathan Mantey pathString + "/SubnetMask"); 1658e01d0c36SEd Tanous return; 165901784826SJohnathan Mantey } 166001784826SJohnathan Mantey 166101784826SJohnathan Mantey if (gateway) 166201784826SJohnathan Mantey { 1663e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 166401784826SJohnathan Mantey { 1665bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1666bf648f77SEd Tanous pathString + "/Gateway"); 1667e01d0c36SEd Tanous return; 166801784826SJohnathan Mantey } 166901784826SJohnathan Mantey } 167085ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 167101784826SJohnathan Mantey { 1672e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 167301784826SJohnathan Mantey } 167401784826SJohnathan Mantey else 16751abe55efSEd Tanous { 1676a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 16774a0cb85cSEd Tanous pathString + "/Gateway"); 167801784826SJohnathan Mantey return; 16794a0cb85cSEd Tanous } 16804a0cb85cSEd Tanous 168185ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 16821abe55efSEd Tanous { 16839c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 168477eb0153SEd Tanous nicIpEntry->id, prefixLength, *address, 168577eb0153SEd Tanous *gateway, asyncResp); 168689492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 168789492a15SPatrick Williams ipv4Data.cend()); 1688588c3f0dSKowalski, Kamil } 168901784826SJohnathan Mantey else 169001784826SJohnathan Mantey { 1691cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1692cb13a392SEd Tanous asyncResp); 16934a0cb85cSEd Tanous } 16944a0cb85cSEd Tanous entryIdx++; 16954a0cb85cSEd Tanous } 169601784826SJohnathan Mantey else 169701784826SJohnathan Mantey { 169885ffe86aSJiaqing Zhao if (nicIpEntry == ipv4Data.cend()) 169901784826SJohnathan Mantey { 170001784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 170101784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 170201784826SJohnathan Mantey // in error, so bail out. 170301784826SJohnathan Mantey if (thisJson.is_null()) 170401784826SJohnathan Mantey { 170501784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 170601784826SJohnathan Mantey return; 170701784826SJohnathan Mantey } 1708f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 170971f52d96SEd Tanous pathString); 171001784826SJohnathan Mantey return; 171101784826SJohnathan Mantey } 171201784826SJohnathan Mantey 171301784826SJohnathan Mantey if (thisJson.is_null()) 171401784826SJohnathan Mantey { 17159c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 171601784826SJohnathan Mantey } 171785ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 171801784826SJohnathan Mantey { 171989492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 172089492a15SPatrick Williams ipv4Data.cend()); 172101784826SJohnathan Mantey } 172201784826SJohnathan Mantey entryIdx++; 172301784826SJohnathan Mantey } 172401784826SJohnathan Mantey } 17254a0cb85cSEd Tanous } 17264a0cb85cSEd Tanous 17274f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1728f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1729f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 17308d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1731f85837bfSRAJESWARAN THILLAIGOVINDAN { 17329ae226faSGeorge Liu sdbusplus::asio::setProperty( 17339ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 17349ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 17359ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 17369ae226faSGeorge Liu updatedStaticNameServers, 17375e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1738f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1739f85837bfSRAJESWARAN THILLAIGOVINDAN { 1740f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1741f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1742f85837bfSRAJESWARAN THILLAIGOVINDAN } 17439ae226faSGeorge Liu }); 1744f85837bfSRAJESWARAN THILLAIGOVINDAN } 1745f85837bfSRAJESWARAN THILLAIGOVINDAN 17464f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 1747ddd70dcaSEd Tanous const std::string& ifaceId, const nlohmann::json::array_t& input, 174877179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 17498d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1750e48c0fc5SRavi Teja { 1751ddd70dcaSEd Tanous if (input.empty()) 1752e48c0fc5SRavi Teja { 17532e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1754e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1755e48c0fc5SRavi Teja return; 1756e48c0fc5SRavi Teja } 1757271584abSEd Tanous size_t entryIdx = 1; 175877179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 17592c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1760f23b7296SEd Tanous for (const nlohmann::json& thisJson : input) 1761e48c0fc5SRavi Teja { 176289492a15SPatrick Williams std::string pathString = "IPv6StaticAddresses/" + 176389492a15SPatrick Williams std::to_string(entryIdx); 1764e48c0fc5SRavi Teja 176501784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1766e48c0fc5SRavi Teja { 1767e48c0fc5SRavi Teja std::optional<std::string> address; 1768e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1769f23b7296SEd Tanous nlohmann::json thisJsonCopy = thisJson; 1770bf648f77SEd Tanous if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 1771bf648f77SEd Tanous address, "PrefixLength", prefixLength)) 1772e48c0fc5SRavi Teja { 1773f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 177471f52d96SEd Tanous pathString); 1775e48c0fc5SRavi Teja return; 1776e48c0fc5SRavi Teja } 1777e48c0fc5SRavi Teja 1778543f4400SEd Tanous const std::string* addr = nullptr; 1779543f4400SEd Tanous uint8_t prefix = 0; 178001784826SJohnathan Mantey 178101784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 178201784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 178301784826SJohnathan Mantey // current state of the interface. Merge existing state into the 178401784826SJohnathan Mantey // current request. 1785e48c0fc5SRavi Teja if (address) 1786e48c0fc5SRavi Teja { 178701784826SJohnathan Mantey addr = &(*address); 1788e48c0fc5SRavi Teja } 178985ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 179001784826SJohnathan Mantey { 179185ffe86aSJiaqing Zhao addr = &(nicIpEntry->address); 179201784826SJohnathan Mantey } 179301784826SJohnathan Mantey else 179401784826SJohnathan Mantey { 179501784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 179601784826SJohnathan Mantey pathString + "/Address"); 179701784826SJohnathan Mantey return; 1798e48c0fc5SRavi Teja } 1799e48c0fc5SRavi Teja 1800e48c0fc5SRavi Teja if (prefixLength) 1801e48c0fc5SRavi Teja { 180201784826SJohnathan Mantey prefix = *prefixLength; 180301784826SJohnathan Mantey } 180485ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 1805e48c0fc5SRavi Teja { 180685ffe86aSJiaqing Zhao prefix = nicIpEntry->prefixLength; 1807e48c0fc5SRavi Teja } 1808e48c0fc5SRavi Teja else 1809e48c0fc5SRavi Teja { 1810e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1811e48c0fc5SRavi Teja pathString + "/PrefixLength"); 181201784826SJohnathan Mantey return; 1813e48c0fc5SRavi Teja } 1814e48c0fc5SRavi Teja 181585ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1816e48c0fc5SRavi Teja { 18179c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 181877eb0153SEd Tanous nicIpEntry->id, prefix, *addr, "", 1819e48c0fc5SRavi Teja asyncResp); 182089492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 182189492a15SPatrick Williams ipv6Data.cend()); 182201784826SJohnathan Mantey } 182301784826SJohnathan Mantey else 182401784826SJohnathan Mantey { 182501784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1826e48c0fc5SRavi Teja } 1827e48c0fc5SRavi Teja entryIdx++; 1828e48c0fc5SRavi Teja } 182901784826SJohnathan Mantey else 183001784826SJohnathan Mantey { 183185ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 183201784826SJohnathan Mantey { 183301784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 183401784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 183501784826SJohnathan Mantey // in error, so bail out. 183601784826SJohnathan Mantey if (thisJson.is_null()) 183701784826SJohnathan Mantey { 183801784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 183901784826SJohnathan Mantey return; 184001784826SJohnathan Mantey } 1841f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 184271f52d96SEd Tanous pathString); 184301784826SJohnathan Mantey return; 184401784826SJohnathan Mantey } 184501784826SJohnathan Mantey 184601784826SJohnathan Mantey if (thisJson.is_null()) 184701784826SJohnathan Mantey { 18489c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 184901784826SJohnathan Mantey } 185085ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 185101784826SJohnathan Mantey { 185289492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 185389492a15SPatrick Williams ipv6Data.cend()); 185401784826SJohnathan Mantey } 185501784826SJohnathan Mantey entryIdx++; 185601784826SJohnathan Mantey } 185701784826SJohnathan Mantey } 1858e48c0fc5SRavi Teja } 1859e48c0fc5SRavi Teja 18607857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 18617857cb8dSJiaqing Zhao { 18627857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 18637857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 18647857cb8dSJiaqing Zhao } 18657857cb8dSJiaqing Zhao 186677179532SEd Tanous inline void 186777179532SEd Tanous parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 186877179532SEd Tanous const std::string& ifaceId, 186977179532SEd Tanous const EthernetInterfaceData& ethData, 187077179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1871*ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 1872*ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) 18734a0cb85cSEd Tanous { 18742c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 187581ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1876ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 1877ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId); 18782c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1879eeedda23SJohnathan Mantey 188013451e39SWilly Tu if constexpr (bmcwebEnableHealthPopulate) 188113451e39SWilly Tu { 188213451e39SWilly Tu constexpr std::array<std::string_view, 1> inventoryForEthernet = { 188313451e39SWilly Tu "xyz.openbmc_project.Inventory.Item.Ethernet"}; 1884eeedda23SJohnathan Mantey auto health = std::make_shared<HealthPopulate>(asyncResp); 18857a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 18867a1dbc48SGeorge Liu "/", 0, inventoryForEthernet, 18877a1dbc48SGeorge Liu [health](const boost::system::error_code& ec, 1888b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& resp) { 1889eeedda23SJohnathan Mantey if (ec) 1890029573d4SEd Tanous { 1891eeedda23SJohnathan Mantey return; 1892eeedda23SJohnathan Mantey } 1893eeedda23SJohnathan Mantey 1894914e2d5dSEd Tanous health->inventory = resp; 18957a1dbc48SGeorge Liu }); 1896eeedda23SJohnathan Mantey 1897eeedda23SJohnathan Mantey health->populate(); 189813451e39SWilly Tu } 1899eeedda23SJohnathan Mantey 1900eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1901eeedda23SJohnathan Mantey { 19020ef0e289SJohnathan Mantey jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 19032c70f800SEd Tanous jsonResponse["Status"]["State"] = "Enabled"; 1904029573d4SEd Tanous } 1905029573d4SEd Tanous else 1906029573d4SEd Tanous { 19072c70f800SEd Tanous jsonResponse["LinkStatus"] = "NoLink"; 19082c70f800SEd Tanous jsonResponse["Status"]["State"] = "Disabled"; 1909029573d4SEd Tanous } 1910aa05fb27SJohnathan Mantey 19112c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 191235fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 191382695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 19142c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 191582695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1916e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1917e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1918e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled; 19192c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1920b10d8db0SRavi Teja translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled" 19211f8c7b5dSJohnathan Mantey : "Disabled"; 1922e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1923e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1924e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled; 1925b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1926b10d8db0SRavi Teja ethData.ipv6AcceptRa; 19272a133282Smanojkiraneda 192882695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 19294a0cb85cSEd Tanous { 193082695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1931ab6554f1SJoshi-Mansi 1932ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1933ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1934ab6554f1SJoshi-Mansi // FQDN 193582695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1936d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1937d24bfc7aSJennifer Lee { 19382c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1939d24bfc7aSJennifer Lee } 19402c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 19414a0cb85cSEd Tanous } 19424a0cb85cSEd Tanous 19437857cb8dSJiaqing Zhao if (ethData.vlanId) 19447857cb8dSJiaqing Zhao { 19457857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Virtual"; 19467857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 19477857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 19487857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 19497857cb8dSJiaqing Zhao 19507857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 19517857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 19527857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 19537857cb8dSJiaqing Zhao boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces", 19547857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 19557857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 19567857cb8dSJiaqing Zhao std::move(relatedInterfaces); 19577857cb8dSJiaqing Zhao } 19587857cb8dSJiaqing Zhao else 19597857cb8dSJiaqing Zhao { 19607857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Physical"; 19617857cb8dSJiaqing Zhao } 19627857cb8dSJiaqing Zhao 19632c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 19642c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 19654a0cb85cSEd Tanous 19662c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 19672c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 19682c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 19692c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 19709eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 19714a0cb85cSEd Tanous { 19722c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1973fa5053a6SGunnar Mills if (gatewayStr.empty()) 1974fa5053a6SGunnar Mills { 1975fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1976fa5053a6SGunnar Mills } 19771476687dSEd Tanous nlohmann::json::object_t ipv4; 19781476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 19791476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 19801476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 19811476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1982fa5053a6SGunnar Mills 19832c70f800SEd Tanous if (ipv4Config.origin == "Static") 1984d1d50814SRavi Teja { 19851476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1986d1d50814SRavi Teja } 19871476687dSEd Tanous 1988b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 198901784826SJohnathan Mantey } 1990d1d50814SRavi Teja 199182695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 19927ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 19937ea79e5eSRavi Teja { 19947ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 19957ea79e5eSRavi Teja } 19967ea79e5eSRavi Teja 19977ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1998e48c0fc5SRavi Teja 1999*ce73d5c8SSunitha Harish nlohmann::json::array_t ipv6StaticGatewayArray; 2000*ce73d5c8SSunitha Harish for (const auto& ipv6GatewayConfig : ipv6GatewayData) 2001*ce73d5c8SSunitha Harish { 2002*ce73d5c8SSunitha Harish nlohmann::json::object_t ipv6Gateway; 2003*ce73d5c8SSunitha Harish ipv6Gateway["Address"] = ipv6GatewayConfig.gateway; 2004*ce73d5c8SSunitha Harish ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength; 2005*ce73d5c8SSunitha Harish ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway)); 2006*ce73d5c8SSunitha Harish } 2007*ce73d5c8SSunitha Harish jsonResponse["IPv6StaticDefaultGateways"] = 2008*ce73d5c8SSunitha Harish std::move(ipv6StaticGatewayArray); 2009*ce73d5c8SSunitha Harish 20102c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 20112c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 20122c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 20132c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 20147f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 20152c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 20167f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 20179eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 2018e48c0fc5SRavi Teja { 20191476687dSEd Tanous nlohmann::json::object_t ipv6; 20201476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 20211476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 20221476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 2023f8361275SSunitha Harish 2024b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 20252c70f800SEd Tanous if (ipv6Config.origin == "Static") 2026e48c0fc5SRavi Teja { 20271476687dSEd Tanous nlohmann::json::object_t ipv6Static; 20281476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 20291476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 2030b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 203101784826SJohnathan Mantey } 2032e48c0fc5SRavi Teja } 2033588c3f0dSKowalski, Kamil } 2034588c3f0dSKowalski, Kamil 2035e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2036e7caf250SJiaqing Zhao const std::string& ifaceId, 2037e7caf250SJiaqing Zhao const boost::system::error_code& ec, 2038e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 2039e7caf250SJiaqing Zhao { 2040e7caf250SJiaqing Zhao if (!ec) 2041e7caf250SJiaqing Zhao { 2042e7caf250SJiaqing Zhao return; 2043e7caf250SJiaqing Zhao } 2044e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2045e7caf250SJiaqing Zhao if (dbusError == nullptr) 2046e7caf250SJiaqing Zhao { 2047e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2048e7caf250SJiaqing Zhao return; 2049e7caf250SJiaqing Zhao } 205062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2051e7caf250SJiaqing Zhao 2052e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 2053e7caf250SJiaqing Zhao dbusError->name) 2054e7caf250SJiaqing Zhao { 2055e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2056e7caf250SJiaqing Zhao ifaceId); 2057e7caf250SJiaqing Zhao return; 2058e7caf250SJiaqing Zhao } 2059e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 2060e7caf250SJiaqing Zhao dbusError->name) 2061e7caf250SJiaqing Zhao { 2062e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 2063e7caf250SJiaqing Zhao return; 2064e7caf250SJiaqing Zhao } 2065e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2066e7caf250SJiaqing Zhao } 2067e7caf250SJiaqing Zhao 2068b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2069b5ca3fdcSJiaqing Zhao const std::string& parentInterfaceUri, 2070b5ca3fdcSJiaqing Zhao const std::string& vlanInterface, 2071b5ca3fdcSJiaqing Zhao const boost::system::error_code& ec, 2072b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m 2073b5ca3fdcSJiaqing Zhao 2074b5ca3fdcSJiaqing Zhao ) 2075b5ca3fdcSJiaqing Zhao { 2076b5ca3fdcSJiaqing Zhao if (ec) 2077b5ca3fdcSJiaqing Zhao { 2078b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2079b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 2080b5ca3fdcSJiaqing Zhao { 2081b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2082b5ca3fdcSJiaqing Zhao return; 2083b5ca3fdcSJiaqing Zhao } 208462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2085b5ca3fdcSJiaqing Zhao 2086b5ca3fdcSJiaqing Zhao if (std::string_view( 2087b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 2088b5ca3fdcSJiaqing Zhao dbusError->name) 2089b5ca3fdcSJiaqing Zhao { 2090b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2091b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2092b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2093b5ca3fdcSJiaqing Zhao return; 2094b5ca3fdcSJiaqing Zhao } 2095b5ca3fdcSJiaqing Zhao if (std::string_view( 2096b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 2097b5ca3fdcSJiaqing Zhao dbusError->name) 2098b5ca3fdcSJiaqing Zhao { 2099b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 2100b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 2101b5ca3fdcSJiaqing Zhao return; 2102b5ca3fdcSJiaqing Zhao } 2103b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2104b5ca3fdcSJiaqing Zhao return; 2105b5ca3fdcSJiaqing Zhao } 2106b5ca3fdcSJiaqing Zhao 2107b5ca3fdcSJiaqing Zhao const boost::urls::url vlanInterfaceUri = boost::urls::format( 2108b5ca3fdcSJiaqing Zhao "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface); 2109b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 2110b5ca3fdcSJiaqing Zhao } 2111b5ca3fdcSJiaqing Zhao 2112bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 2113bf648f77SEd Tanous { 2114bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 2115ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 21161476687dSEd Tanous .methods(boost::beast::http::verb::get)( 21171476687dSEd Tanous [&app](const crow::Request& req, 21181476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 21193ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 212045ca1b86SEd Tanous { 212145ca1b86SEd Tanous return; 212245ca1b86SEd Tanous } 212345ca1b86SEd Tanous 2124bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2125bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 2126bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2127bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 2128bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 2129bf648f77SEd Tanous "Ethernet Network Interface Collection"; 2130bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 2131bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 2132bf648f77SEd Tanous 2133bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 2134bf648f77SEd Tanous // preparation 2135002d39b4SEd Tanous getEthernetIfaceList( 213677179532SEd Tanous [asyncResp](const bool& success, 213777179532SEd Tanous const std::vector<std::string>& ifaceList) { 2138bf648f77SEd Tanous if (!success) 21391abe55efSEd Tanous { 2140f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21419391bb9cSRapkiewicz, Pawel return; 21429391bb9cSRapkiewicz, Pawel } 21439391bb9cSRapkiewicz, Pawel 2144002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 2145bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 2146bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 2147bf648f77SEd Tanous { 21481476687dSEd Tanous nlohmann::json::object_t iface; 2149ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 2150ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", 2151ef4c65b7SEd Tanous ifaceItem); 21527857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 2153bf648f77SEd Tanous } 2154bf648f77SEd Tanous 2155002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 2156bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2157bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 2158bf648f77SEd Tanous }); 2159bf648f77SEd Tanous }); 2160bf648f77SEd Tanous 2161b5ca3fdcSJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 2162b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 2163b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 2164b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 2165b5ca3fdcSJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2166b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2167b5ca3fdcSJiaqing Zhao { 2168b5ca3fdcSJiaqing Zhao return; 2169b5ca3fdcSJiaqing Zhao } 2170b5ca3fdcSJiaqing Zhao 2171b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 2172b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 2173b5ca3fdcSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 2174b5ca3fdcSJiaqing Zhao 2175b5ca3fdcSJiaqing Zhao if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", 2176b5ca3fdcSJiaqing Zhao vlanEnable, "VLAN/VLANId", vlanId, 2177b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2178b5ca3fdcSJiaqing Zhao relatedInterfaces)) 2179b5ca3fdcSJiaqing Zhao { 2180b5ca3fdcSJiaqing Zhao return; 2181b5ca3fdcSJiaqing Zhao } 2182b5ca3fdcSJiaqing Zhao 2183b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 2184b5ca3fdcSJiaqing Zhao { 2185b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 2186b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2187b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 2188b5ca3fdcSJiaqing Zhao return; 2189b5ca3fdcSJiaqing Zhao } 2190b5ca3fdcSJiaqing Zhao 2191b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 2192b5ca3fdcSJiaqing Zhao if (!json_util::readJson(relatedInterfaces[0], asyncResp->res, 2193b5ca3fdcSJiaqing Zhao "@odata.id", parentInterfaceUri)) 2194b5ca3fdcSJiaqing Zhao { 2195b5ca3fdcSJiaqing Zhao messages::propertyMissing(asyncResp->res, 2196b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2197b5ca3fdcSJiaqing Zhao return; 2198b5ca3fdcSJiaqing Zhao } 219962598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 2200b5ca3fdcSJiaqing Zhao 22016fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 2202b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 2203b5ca3fdcSJiaqing Zhao if (!parsedUri) 2204b5ca3fdcSJiaqing Zhao { 2205b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 2206b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2207b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2208b5ca3fdcSJiaqing Zhao return; 2209b5ca3fdcSJiaqing Zhao } 2210b5ca3fdcSJiaqing Zhao 2211b5ca3fdcSJiaqing Zhao std::string parentInterface; 2212b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 2213b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 2214b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 2215b5ca3fdcSJiaqing Zhao { 2216b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2217b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2218b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2219b5ca3fdcSJiaqing Zhao return; 2220b5ca3fdcSJiaqing Zhao } 2221b5ca3fdcSJiaqing Zhao 2222b5ca3fdcSJiaqing Zhao if (!vlanEnable) 2223b5ca3fdcSJiaqing Zhao { 2224b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 2225b5ca3fdcSJiaqing Zhao // create 2226b5ca3fdcSJiaqing Zhao messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", 2227b5ca3fdcSJiaqing Zhao "false"); 2228b5ca3fdcSJiaqing Zhao return; 2229b5ca3fdcSJiaqing Zhao } 2230b5ca3fdcSJiaqing Zhao 2231b5ca3fdcSJiaqing Zhao std::string vlanInterface = parentInterface + "_" + 2232b5ca3fdcSJiaqing Zhao std::to_string(vlanId); 2233b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 2234b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 2235b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 2236b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 2237b5ca3fdcSJiaqing Zhao afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, 2238b5ca3fdcSJiaqing Zhao m); 2239b5ca3fdcSJiaqing Zhao }, 2240b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 2241b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, 2242b5ca3fdcSJiaqing Zhao vlanId); 2243b5ca3fdcSJiaqing Zhao }); 2244b5ca3fdcSJiaqing Zhao 2245bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2246ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 2247bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 224845ca1b86SEd Tanous [&app](const crow::Request& req, 2249bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2250bf648f77SEd Tanous const std::string& ifaceId) { 22513ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 225245ca1b86SEd Tanous { 225345ca1b86SEd Tanous return; 225445ca1b86SEd Tanous } 22554a0cb85cSEd Tanous getEthernetIfaceData( 2256bf648f77SEd Tanous ifaceId, 2257*ce73d5c8SSunitha Harish [asyncResp, 2258*ce73d5c8SSunitha Harish ifaceId](const bool& success, const EthernetInterfaceData& ethData, 225977179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2260*ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2261*ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 22624a0cb85cSEd Tanous if (!success) 22631abe55efSEd Tanous { 2264bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2265bf648f77SEd Tanous // existing object, and other errors 2266002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2267002d39b4SEd Tanous ifaceId); 22684a0cb85cSEd Tanous return; 22699391bb9cSRapkiewicz, Pawel } 22704c9afe43SEd Tanous 22710f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 227293bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2273002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 22740f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 22750f74e643SEd Tanous "Management Network Interface"; 22760f74e643SEd Tanous 2277*ce73d5c8SSunitha Harish parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data, 2278*ce73d5c8SSunitha Harish ipv6GatewayData); 22799391bb9cSRapkiewicz, Pawel }); 2280bf648f77SEd Tanous }); 22819391bb9cSRapkiewicz, Pawel 2282bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2283ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2284bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 228545ca1b86SEd Tanous [&app](const crow::Request& req, 2286bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2287bf648f77SEd Tanous const std::string& ifaceId) { 22883ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 228945ca1b86SEd Tanous { 229045ca1b86SEd Tanous return; 229145ca1b86SEd Tanous } 2292bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2293ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2294d577665bSRatan Gupta std::optional<std::string> macAddress; 22959a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2296ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv4StaticAddresses; 2297ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv6StaticAddresses; 2298*ce73d5c8SSunitha Harish std::optional<nlohmann::json::array_t> ipv6StaticDefaultGateways; 2299f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2300da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 23011f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 2302b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2303eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 230435fb5311STejas Patil std::optional<size_t> mtuSize; 23051f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 23061f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2307b10d8db0SRavi Teja // clang-format off 230815ed6780SWilly Tu if (!json_util::readJsonPatch( 2309b10d8db0SRavi Teja req, asyncResp->res, 2310b10d8db0SRavi Teja "DHCPv4", dhcpv4, 2311b10d8db0SRavi Teja "DHCPv6", dhcpv6, 2312b10d8db0SRavi Teja "FQDN", fqdn, 2313b10d8db0SRavi Teja "HostName", hostname, 2314b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 2315b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 2316b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 2317*ce73d5c8SSunitha Harish "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways, 2318b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 2319b10d8db0SRavi Teja "MACAddress", macAddress, 2320b10d8db0SRavi Teja "MTUSize", mtuSize, 2321b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 2322b10d8db0SRavi Teja "StaticNameServers", staticNameServers 2323b10d8db0SRavi Teja ) 2324b10d8db0SRavi Teja ) 23251abe55efSEd Tanous { 2326588c3f0dSKowalski, Kamil return; 2327588c3f0dSKowalski, Kamil } 2328b10d8db0SRavi Teja //clang-format on 2329da131a9aSJennifer Lee if (dhcpv4) 2330da131a9aSJennifer Lee { 2331002d39b4SEd Tanous if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 23321f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 233382695a5bSJiaqing Zhao v4dhcpParms.useDnsServers, "UseNTPServers", 233482695a5bSJiaqing Zhao v4dhcpParms.useNtpServers, "UseDomainName", 233582695a5bSJiaqing Zhao v4dhcpParms.useDomainName)) 23361f8c7b5dSJohnathan Mantey { 23371f8c7b5dSJohnathan Mantey return; 23381f8c7b5dSJohnathan Mantey } 23391f8c7b5dSJohnathan Mantey } 23401f8c7b5dSJohnathan Mantey 23411f8c7b5dSJohnathan Mantey if (dhcpv6) 23421f8c7b5dSJohnathan Mantey { 2343002d39b4SEd Tanous if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode", 2344002d39b4SEd Tanous v6dhcpParms.dhcpv6OperatingMode, 2345002d39b4SEd Tanous "UseDNSServers", v6dhcpParms.useDnsServers, 2346002d39b4SEd Tanous "UseNTPServers", v6dhcpParms.useNtpServers, 2347002d39b4SEd Tanous "UseDomainName", 234882695a5bSJiaqing Zhao v6dhcpParms.useDomainName)) 23491f8c7b5dSJohnathan Mantey { 23501f8c7b5dSJohnathan Mantey return; 23511f8c7b5dSJohnathan Mantey } 2352da131a9aSJennifer Lee } 2353da131a9aSJennifer Lee 2354bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2355bf648f77SEd Tanous // for JSON preparation 23564a0cb85cSEd Tanous getEthernetIfaceData( 23572c70f800SEd Tanous ifaceId, 2358bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2359ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2360d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 23619a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2362e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 2363*ce73d5c8SSunitha Harish ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways), 23641f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 2365bc20089aSEd Tanous dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize, 2366b10d8db0SRavi Teja ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms), 2367f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2368002d39b4SEd Tanous const bool& success, const EthernetInterfaceData& ethData, 236977179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2370*ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2371*ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 23721abe55efSEd Tanous if (!success) 23731abe55efSEd Tanous { 2374588c3f0dSKowalski, Kamil // ... otherwise return error 2375bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2376bf648f77SEd Tanous // existing object, and other errors 2377002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2378002d39b4SEd Tanous ifaceId); 2379588c3f0dSKowalski, Kamil return; 2380588c3f0dSKowalski, Kamil } 2381588c3f0dSKowalski, Kamil 23821f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 23831f8c7b5dSJohnathan Mantey { 2384002d39b4SEd Tanous handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, 2385002d39b4SEd Tanous asyncResp); 23861f8c7b5dSJohnathan Mantey } 23871f8c7b5dSJohnathan Mantey 23880627a2c7SEd Tanous if (hostname) 23891abe55efSEd Tanous { 23900627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 23911abe55efSEd Tanous } 23920627a2c7SEd Tanous 2393b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2394b10d8db0SRavi Teja { 2395b10d8db0SRavi Teja handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled, 2396b10d8db0SRavi Teja asyncResp); 2397b10d8db0SRavi Teja } 2398b10d8db0SRavi Teja 2399ab6554f1SJoshi-Mansi if (fqdn) 2400ab6554f1SJoshi-Mansi { 24012c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2402ab6554f1SJoshi-Mansi } 2403ab6554f1SJoshi-Mansi 2404d577665bSRatan Gupta if (macAddress) 2405d577665bSRatan Gupta { 2406002d39b4SEd Tanous handleMACAddressPatch(ifaceId, *macAddress, asyncResp); 2407d577665bSRatan Gupta } 2408d577665bSRatan Gupta 2409d1d50814SRavi Teja if (ipv4StaticAddresses) 2410d1d50814SRavi Teja { 2411bf648f77SEd Tanous // TODO(ed) for some reason the capture of 2412bf648f77SEd Tanous // ipv4Addresses above is returning a const value, 2413bf648f77SEd Tanous // not a non-const value. This doesn't really work 2414bf648f77SEd Tanous // for us, as we need to be able to efficiently move 2415bf648f77SEd Tanous // out the intermedia nlohmann::json objects. This 2416bf648f77SEd Tanous // makes a copy of the structure, and operates on 2417bf648f77SEd Tanous // that, but could be done more efficiently 2418ddd70dcaSEd Tanous nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses; 2419002d39b4SEd Tanous handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp); 24201abe55efSEd Tanous } 24210627a2c7SEd Tanous 2422f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2423f85837bfSRAJESWARAN THILLAIGOVINDAN { 2424002d39b4SEd Tanous handleStaticNameServersPatch(ifaceId, *staticNameServers, 2425002d39b4SEd Tanous asyncResp); 2426f85837bfSRAJESWARAN THILLAIGOVINDAN } 24279a6fc6feSRavi Teja 24289a6fc6feSRavi Teja if (ipv6DefaultGateway) 24299a6fc6feSRavi Teja { 24309a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 24319a6fc6feSRavi Teja "IPv6DefaultGateway"); 24329a6fc6feSRavi Teja } 2433e48c0fc5SRavi Teja 2434e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2435e48c0fc5SRavi Teja { 2436ddd70dcaSEd Tanous handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses, 2437ddd70dcaSEd Tanous ipv6Data, asyncResp); 2438e48c0fc5SRavi Teja } 2439eeedda23SJohnathan Mantey 2440*ce73d5c8SSunitha Harish if (ipv6StaticDefaultGateway) 2441*ce73d5c8SSunitha Harish { 2442*ce73d5c8SSunitha Harish handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway, 2443*ce73d5c8SSunitha Harish ipv6GatewayData, asyncResp); 2444*ce73d5c8SSunitha Harish } 2445*ce73d5c8SSunitha Harish 2446eeedda23SJohnathan Mantey if (interfaceEnabled) 2447eeedda23SJohnathan Mantey { 2448002d39b4SEd Tanous setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled", 2449002d39b4SEd Tanous *interfaceEnabled, asyncResp); 2450eeedda23SJohnathan Mantey } 245135fb5311STejas Patil 245235fb5311STejas Patil if (mtuSize) 245335fb5311STejas Patil { 245435fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 245535fb5311STejas Patil } 2456588c3f0dSKowalski, Kamil }); 2457bf648f77SEd Tanous }); 2458e7caf250SJiaqing Zhao 2459e7caf250SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2460e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2461e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2462e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2463e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2464e7caf250SJiaqing Zhao const std::string& ifaceId) { 2465e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2466e7caf250SJiaqing Zhao { 2467e7caf250SJiaqing Zhao return; 2468e7caf250SJiaqing Zhao } 2469e7caf250SJiaqing Zhao 2470e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2471e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2472e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2473e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2474e7caf250SJiaqing Zhao }, 2475e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2476e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2477e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2478e7caf250SJiaqing Zhao }); 24794a0cb85cSEd Tanous } 2480bf648f77SEd Tanous 24819391bb9cSRapkiewicz, Pawel } // namespace redfish 2482