19391bb9cSRapkiewicz, Pawel /* 29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 39391bb9cSRapkiewicz, Pawel // 49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License. 69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at 79391bb9cSRapkiewicz, Pawel // 89391bb9cSRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 99391bb9cSRapkiewicz, Pawel // 109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and 149391bb9cSRapkiewicz, Pawel // limitations under the License. 159391bb9cSRapkiewicz, Pawel */ 169391bb9cSRapkiewicz, Pawel #pragma once 179391bb9cSRapkiewicz, Pawel 1813451e39SWilly Tu #include "bmcweb_config.h" 1913451e39SWilly Tu 203ccb3adbSEd Tanous #include "app.hpp" 213ccb3adbSEd Tanous #include "dbus_singleton.hpp" 227a1dbc48SGeorge Liu #include "dbus_utility.hpp" 233ccb3adbSEd Tanous #include "error_messages.hpp" 243ccb3adbSEd Tanous #include "health.hpp" 252c5875a2SEd Tanous #include "human_sort.hpp" 263ccb3adbSEd Tanous #include "query.hpp" 273ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 28033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 293ccb3adbSEd Tanous #include "utils/json_utils.hpp" 30033f1e4dSEd Tanous 31ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp> 32ef4c65b7SEd Tanous #include <boost/url/format.hpp> 331214b7e7SGunnar Mills 347a1dbc48SGeorge Liu #include <array> 35ce73d5c8SSunitha 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 }; 76ce73d5c8SSunitha Harish 77ce73d5c8SSunitha Harish /** 78ce73d5c8SSunitha Harish * Structure for keeping static route data required by Redfish 79ce73d5c8SSunitha Harish */ 80ce73d5c8SSunitha Harish struct StaticGatewayData 81ce73d5c8SSunitha Harish { 82ce73d5c8SSunitha Harish std::string id; 83ce73d5c8SSunitha Harish std::string gateway; 84ce73d5c8SSunitha Harish size_t prefixLength = 0; 85ce73d5c8SSunitha Harish std::string protocol; 86ce73d5c8SSunitha Harish }; 87ce73d5c8SSunitha 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; 113ce73d5c8SSunitha 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 { 732d02aad39SEd Tanous setDbusProperty( 733d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 734d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 735d02aad39SEd Tanous ifaceId, 7369ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 737d02aad39SEd Tanous "Gateway", gateway); 7389010ec2eSRavi Teja } 739179db1d7SKowalski, Kamil /** 74001784826SJohnathan Mantey * @brief Creates a static IPv4 entry 741179db1d7SKowalski, Kamil * 74201784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 74301784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 74401784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 74501784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 746179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 747179db1d7SKowalski, Kamil * 748179db1d7SKowalski, Kamil * @return None 749179db1d7SKowalski, Kamil */ 750cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 751cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7528d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7531abe55efSEd Tanous { 7545a39f77aSPatrick Williams auto createIpHandler = [asyncResp, ifaceId, 7555a39f77aSPatrick Williams gateway](const boost::system::error_code& ec) { 7561abe55efSEd Tanous if (ec) 7571abe55efSEd Tanous { 758a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7599010ec2eSRavi Teja return; 760179db1d7SKowalski, Kamil } 7619010ec2eSRavi Teja updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); 7629010ec2eSRavi Teja }; 7639010ec2eSRavi Teja 7649010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 7659010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 766179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 767179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 76801784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 769179db1d7SKowalski, Kamil gateway); 770179db1d7SKowalski, Kamil } 771e48c0fc5SRavi Teja 772e48c0fc5SRavi Teja /** 77301784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 77401784826SJohnathan Mantey * static IPv6 entry 77501784826SJohnathan Mantey * 77601784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 77701784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 77801784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 77901784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 78001784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 78101784826SJohnathan Mantey * 78201784826SJohnathan Mantey * @return None 78301784826SJohnathan Mantey */ 7849c5e585cSRavi Teja 7859c5e585cSRavi Teja enum class IpVersion 7869c5e585cSRavi Teja { 7879c5e585cSRavi Teja IpV4, 7889c5e585cSRavi Teja IpV6 7899c5e585cSRavi Teja }; 7909c5e585cSRavi Teja 7919c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 7929c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 7938d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 7949c5e585cSRavi Teja const std::string& gateway, 7958d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 79601784826SJohnathan Mantey { 79701784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7989c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 7999c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 80001784826SJohnathan Mantey if (ec) 80101784826SJohnathan Mantey { 80201784826SJohnathan Mantey messages::internalError(asyncResp->res); 80301784826SJohnathan Mantey } 8049c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 8059c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 80601784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8075e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 80823a21a1cSEd Tanous if (ec2) 80901784826SJohnathan Mantey { 81001784826SJohnathan Mantey messages::internalError(asyncResp->res); 81101784826SJohnathan Mantey } 81201784826SJohnathan Mantey }, 81301784826SJohnathan Mantey "xyz.openbmc_project.Network", 81401784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 8159c5e585cSRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address, 8169c5e585cSRavi Teja prefixLength, gateway); 81701784826SJohnathan Mantey }, 81801784826SJohnathan Mantey "xyz.openbmc_project.Network", 8199c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 82001784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 82101784826SJohnathan Mantey } 82201784826SJohnathan Mantey 823ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData( 824ce73d5c8SSunitha Harish const std::string& ethifaceId, 825ce73d5c8SSunitha Harish const dbus::utility::ManagedObjectType& dbusData, 826ce73d5c8SSunitha Harish std::vector<StaticGatewayData>& staticGatewayConfig) 827ce73d5c8SSunitha Harish { 828ce73d5c8SSunitha Harish std::string staticGatewayPathStart("/xyz/openbmc_project/network/"); 829ce73d5c8SSunitha Harish staticGatewayPathStart += ethifaceId; 830ce73d5c8SSunitha Harish 831ce73d5c8SSunitha Harish for (const auto& objpath : dbusData) 832ce73d5c8SSunitha Harish { 833ce73d5c8SSunitha Harish if (!std::string_view(objpath.first.str) 834ce73d5c8SSunitha Harish .starts_with(staticGatewayPathStart)) 835ce73d5c8SSunitha Harish { 836ce73d5c8SSunitha Harish continue; 837ce73d5c8SSunitha Harish } 838ce73d5c8SSunitha Harish for (const auto& interface : objpath.second) 839ce73d5c8SSunitha Harish { 840ce73d5c8SSunitha Harish if (interface.first != "xyz.openbmc_project.Network.StaticGateway") 841ce73d5c8SSunitha Harish { 842ce73d5c8SSunitha Harish continue; 843ce73d5c8SSunitha Harish } 844ce73d5c8SSunitha Harish StaticGatewayData& staticGateway = 845ce73d5c8SSunitha Harish staticGatewayConfig.emplace_back(); 846ce73d5c8SSunitha Harish staticGateway.id = objpath.first.filename(); 847ce73d5c8SSunitha Harish 848ce73d5c8SSunitha Harish bool success = sdbusplus::unpackPropertiesNoThrow( 849ce73d5c8SSunitha Harish redfish::dbus_utils::UnpackErrorPrinter(), interface.second, 850ce73d5c8SSunitha Harish "Gateway", staticGateway.gateway, "PrefixLength", 851ce73d5c8SSunitha Harish staticGateway.prefixLength, "ProtocolType", 852ce73d5c8SSunitha Harish staticGateway.protocol); 853ce73d5c8SSunitha Harish if (!success) 854ce73d5c8SSunitha Harish { 855ce73d5c8SSunitha Harish return false; 856ce73d5c8SSunitha Harish } 857ce73d5c8SSunitha Harish } 858ce73d5c8SSunitha Harish } 859ce73d5c8SSunitha Harish return true; 860ce73d5c8SSunitha Harish } 861ce73d5c8SSunitha Harish 86201784826SJohnathan Mantey /** 863e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 864e48c0fc5SRavi Teja * 865e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 866e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 867e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 868e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 869e48c0fc5SRavi Teja * 870e48c0fc5SRavi Teja * @return None 871e48c0fc5SRavi Teja */ 87201784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 87301784826SJohnathan Mantey const std::string& address, 8748d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 875e48c0fc5SRavi Teja { 876ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 877ce73d5c8SSunitha Harish path /= ifaceId; 878ce73d5c8SSunitha Harish 8795a39f77aSPatrick Williams auto createIpHandler = [asyncResp, 8805a39f77aSPatrick Williams address](const boost::system::error_code& ec) { 881e48c0fc5SRavi Teja if (ec) 882e48c0fc5SRavi Teja { 883fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 884fc23ef8aSNitin Kumar Kotania { 885fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 886fc23ef8aSNitin Kumar Kotania "Address"); 887fc23ef8aSNitin Kumar Kotania } 888fc23ef8aSNitin Kumar Kotania else 889fc23ef8aSNitin Kumar Kotania { 890e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 891e48c0fc5SRavi Teja } 892fc23ef8aSNitin Kumar Kotania } 893e48c0fc5SRavi Teja }; 894ce73d5c8SSunitha Harish // Passing null for gateway, as per redfish spec IPv6StaticAddresses 895ce73d5c8SSunitha Harish // object does not have associated gateway property 896e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 897ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 898e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 899e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 900e48c0fc5SRavi Teja ""); 901e48c0fc5SRavi Teja } 902e48c0fc5SRavi Teja 903179db1d7SKowalski, Kamil /** 904ce73d5c8SSunitha Harish * @brief Deletes given IPv6 Static Gateway 905ce73d5c8SSunitha Harish * 906ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be deleted 907ce73d5c8SSunitha Harish * @param[in] ipHash DBus Hash id of IP that should be deleted 908ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 909ce73d5c8SSunitha Harish * 910ce73d5c8SSunitha Harish * @return None 911ce73d5c8SSunitha Harish */ 912ce73d5c8SSunitha Harish inline void 913ce73d5c8SSunitha Harish deleteIPv6Gateway(std::string_view gatewayId, 914ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 915ce73d5c8SSunitha Harish { 916ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 917ce73d5c8SSunitha Harish path /= gatewayId; 918ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 919ce73d5c8SSunitha Harish [asyncResp](const boost::system::error_code& ec) { 920ce73d5c8SSunitha Harish if (ec) 921ce73d5c8SSunitha Harish { 922ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 923ce73d5c8SSunitha Harish } 924ce73d5c8SSunitha Harish }, 925ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 926ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 927ce73d5c8SSunitha Harish } 928ce73d5c8SSunitha Harish 929ce73d5c8SSunitha Harish /** 930ce73d5c8SSunitha Harish * @brief Creates IPv6 static default gateway with given data 931ce73d5c8SSunitha Harish * 932ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be added 933ce73d5c8SSunitha Harish * @param[in] prefixLength Prefix length that needs to be added 934ce73d5c8SSunitha Harish * @param[in] gateway Gateway address that needs to be added 935ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 936ce73d5c8SSunitha Harish * 937ce73d5c8SSunitha Harish * @return None 938ce73d5c8SSunitha Harish */ 939ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway( 940ce73d5c8SSunitha Harish std::string_view ifaceId, size_t prefixLength, std::string_view gateway, 941ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 942ce73d5c8SSunitha Harish { 943ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 944ce73d5c8SSunitha Harish path /= ifaceId; 945ce73d5c8SSunitha Harish auto createIpHandler = [asyncResp](const boost::system::error_code& ec) { 946ce73d5c8SSunitha Harish if (ec) 947ce73d5c8SSunitha Harish { 948ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 949ce73d5c8SSunitha Harish } 950ce73d5c8SSunitha Harish }; 951ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 952ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 953ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway", 954ce73d5c8SSunitha Harish gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6"); 955ce73d5c8SSunitha Harish } 956ce73d5c8SSunitha Harish 957ce73d5c8SSunitha Harish /** 958ce73d5c8SSunitha Harish * @brief Deletes the IPv6 default gateway entry for this interface and 959ce73d5c8SSunitha Harish * creates a replacement IPv6 default gateway entry 960ce73d5c8SSunitha Harish * 961ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface upon which to create the IPv6 962ce73d5c8SSunitha Harish * entry 963ce73d5c8SSunitha Harish * @param[in] gateway IPv6 gateway to assign to this interface 964ce73d5c8SSunitha Harish * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 965ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 966ce73d5c8SSunitha Harish * 967ce73d5c8SSunitha Harish * @return None 968ce73d5c8SSunitha Harish */ 969ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway( 970ce73d5c8SSunitha Harish std::string_view ifaceId, std::string_view gatewayId, 971ce73d5c8SSunitha Harish std::string_view gateway, size_t prefixLength, 972ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 973ce73d5c8SSunitha Harish { 974ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 975ce73d5c8SSunitha Harish path /= gatewayId; 976ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 977ce73d5c8SSunitha Harish [asyncResp, ifaceId, gateway, 978ce73d5c8SSunitha Harish prefixLength](const boost::system::error_code& ec) { 979ce73d5c8SSunitha Harish if (ec) 980ce73d5c8SSunitha Harish { 981ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 982ce73d5c8SSunitha Harish return; 983ce73d5c8SSunitha Harish } 984ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp); 985ce73d5c8SSunitha Harish }, 986ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 987ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 988ce73d5c8SSunitha Harish } 989ce73d5c8SSunitha Harish 990ce73d5c8SSunitha Harish /** 991ce73d5c8SSunitha Harish * @brief Sets IPv6 default gateway with given data 992ce73d5c8SSunitha Harish * 993ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose gateway should be added 994ce73d5c8SSunitha Harish * @param[in] input Contains address that needs to be added 995ce73d5c8SSunitha Harish * @param[in] staticGatewayData Current static gateways in the system 996ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 997ce73d5c8SSunitha Harish * 998ce73d5c8SSunitha Harish * @return None 999ce73d5c8SSunitha Harish */ 1000ce73d5c8SSunitha Harish 1001ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway( 1002ce73d5c8SSunitha Harish const std::string& ifaceId, const nlohmann::json::array_t& input, 1003ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& staticGatewayData, 1004ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1005ce73d5c8SSunitha Harish { 1006ce73d5c8SSunitha Harish size_t entryIdx = 1; 1007ce73d5c8SSunitha Harish std::vector<StaticGatewayData>::const_iterator staticGatewayEntry = 1008ce73d5c8SSunitha Harish staticGatewayData.begin(); 1009ce73d5c8SSunitha Harish 1010ce73d5c8SSunitha Harish for (const nlohmann::json& thisJson : input) 1011ce73d5c8SSunitha Harish { 1012ce73d5c8SSunitha Harish // find the next gateway entry 1013ce73d5c8SSunitha Harish while (staticGatewayEntry != staticGatewayData.end()) 1014ce73d5c8SSunitha Harish { 1015ce73d5c8SSunitha Harish if (staticGatewayEntry->protocol == 1016ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.IP.Protocol.IPv6") 1017ce73d5c8SSunitha Harish { 1018ce73d5c8SSunitha Harish break; 1019ce73d5c8SSunitha Harish } 1020ce73d5c8SSunitha Harish staticGatewayEntry++; 1021ce73d5c8SSunitha Harish } 1022ce73d5c8SSunitha Harish std::string pathString = "IPv6StaticDefaultGateways/" + 1023ce73d5c8SSunitha Harish std::to_string(entryIdx); 1024ce73d5c8SSunitha Harish if (thisJson.is_null()) 1025ce73d5c8SSunitha Harish { 1026ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1027ce73d5c8SSunitha Harish { 1028ce73d5c8SSunitha Harish messages::resourceCannotBeDeleted(asyncResp->res); 1029ce73d5c8SSunitha Harish return; 1030ce73d5c8SSunitha Harish } 1031ce73d5c8SSunitha Harish deleteIPv6Gateway(staticGatewayEntry->id, asyncResp); 1032ce73d5c8SSunitha Harish return; 1033ce73d5c8SSunitha Harish } 1034ce73d5c8SSunitha Harish if (thisJson.is_object() && thisJson.empty()) 1035ce73d5c8SSunitha Harish { 1036ce73d5c8SSunitha Harish // Do nothing, but make sure the entry exists. 1037ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1038ce73d5c8SSunitha Harish { 1039ce73d5c8SSunitha Harish messages::propertyValueFormatError(asyncResp->res, thisJson, 1040ce73d5c8SSunitha Harish pathString); 1041ce73d5c8SSunitha Harish return; 1042ce73d5c8SSunitha Harish } 1043ce73d5c8SSunitha Harish } 1044ce73d5c8SSunitha Harish std::optional<std::string> address; 1045ce73d5c8SSunitha Harish std::optional<size_t> prefixLength; 1046ce73d5c8SSunitha Harish 1047ce73d5c8SSunitha Harish nlohmann::json thisJsonCopy = thisJson; 1048ce73d5c8SSunitha Harish if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 1049ce73d5c8SSunitha Harish address, "PrefixLength", prefixLength)) 1050ce73d5c8SSunitha Harish { 1051ce73d5c8SSunitha Harish return; 1052ce73d5c8SSunitha Harish } 1053ce73d5c8SSunitha Harish const std::string* addr = nullptr; 1054ce73d5c8SSunitha Harish size_t prefix = 0; 1055ce73d5c8SSunitha Harish if (address) 1056ce73d5c8SSunitha Harish { 1057ce73d5c8SSunitha Harish addr = &(*address); 1058ce73d5c8SSunitha Harish } 1059ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1060ce73d5c8SSunitha Harish { 1061ce73d5c8SSunitha Harish addr = &(staticGatewayEntry->gateway); 1062ce73d5c8SSunitha Harish } 1063ce73d5c8SSunitha Harish else 1064ce73d5c8SSunitha Harish { 1065ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, pathString + "/Address"); 1066ce73d5c8SSunitha Harish return; 1067ce73d5c8SSunitha Harish } 1068ce73d5c8SSunitha Harish if (prefixLength) 1069ce73d5c8SSunitha Harish { 1070ce73d5c8SSunitha Harish prefix = *prefixLength; 1071ce73d5c8SSunitha Harish } 1072ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1073ce73d5c8SSunitha Harish { 1074ce73d5c8SSunitha Harish prefix = staticGatewayEntry->prefixLength; 1075ce73d5c8SSunitha Harish } 1076ce73d5c8SSunitha Harish else 1077ce73d5c8SSunitha Harish { 1078ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, 1079ce73d5c8SSunitha Harish pathString + "/PrefixLength"); 1080ce73d5c8SSunitha Harish return; 1081ce73d5c8SSunitha Harish } 1082ce73d5c8SSunitha Harish if (staticGatewayEntry != staticGatewayData.end()) 1083ce73d5c8SSunitha Harish { 1084ce73d5c8SSunitha Harish deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id, 1085ce73d5c8SSunitha Harish *addr, prefix, asyncResp); 1086ce73d5c8SSunitha Harish staticGatewayEntry++; 1087ce73d5c8SSunitha Harish } 1088ce73d5c8SSunitha Harish else 1089ce73d5c8SSunitha Harish { 1090ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp); 1091ce73d5c8SSunitha Harish } 1092ce73d5c8SSunitha Harish entryIdx++; 1093ce73d5c8SSunitha Harish } 1094ce73d5c8SSunitha Harish } 1095ce73d5c8SSunitha Harish 1096ce73d5c8SSunitha Harish /** 1097179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 1098179db1d7SKowalski, Kamil * Object 1099179db1d7SKowalski, Kamil * from EntityManager Network Manager 11004a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 1101179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 1102179db1d7SKowalski, Kamil * into JSON 1103179db1d7SKowalski, Kamil */ 1104179db1d7SKowalski, Kamil template <typename CallbackFunc> 110581ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 11061abe55efSEd Tanous CallbackFunc&& callback) 11071abe55efSEd Tanous { 1108f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1109f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1110f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1111f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 1112f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 11138b24275dSEd Tanous const boost::system::error_code& ec, 111402cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 111555c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 111677179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 111777179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 1118ce73d5c8SSunitha Harish std::vector<StaticGatewayData> ipv6GatewayData; 1119179db1d7SKowalski, Kamil 11208b24275dSEd Tanous if (ec) 11211abe55efSEd Tanous { 1122ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1123179db1d7SKowalski, Kamil return; 1124179db1d7SKowalski, Kamil } 1125179db1d7SKowalski, Kamil 1126002d39b4SEd Tanous bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); 11274c9afe43SEd Tanous if (!found) 11284c9afe43SEd Tanous { 1129ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 11304c9afe43SEd Tanous return; 11314c9afe43SEd Tanous } 11324c9afe43SEd Tanous 11332c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 1134179db1d7SKowalski, Kamil // Fix global GW 11351abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 11361abe55efSEd Tanous { 1137c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 1138c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 11399010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 11401abe55efSEd Tanous { 114182695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 1142179db1d7SKowalski, Kamil } 1143179db1d7SKowalski, Kamil } 1144179db1d7SKowalski, Kamil 11452c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 1146ce73d5c8SSunitha Harish if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData)) 1147ce73d5c8SSunitha Harish { 1148ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1149ce73d5c8SSunitha Harish } 11504e0453b1SGunnar Mills // Finally make a callback with useful data 1151ce73d5c8SSunitha Harish callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1152f5892d0dSGeorge Liu }); 1153271584abSEd Tanous } 1154179db1d7SKowalski, Kamil 1155179db1d7SKowalski, Kamil /** 11569391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 11579391bb9cSRapkiewicz, Pawel * Manager 11581abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 11591abe55efSEd Tanous * into JSON. 11609391bb9cSRapkiewicz, Pawel */ 11619391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 11621abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 11631abe55efSEd Tanous { 1164f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1165f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1166f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1167f94c4ecfSEd Tanous [callback{std::forward<CallbackFunc>(callback)}]( 11688b24275dSEd Tanous const boost::system::error_code& ec, 1169f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 11701abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 11711abe55efSEd Tanous // ethernet interfaces 117277179532SEd Tanous std::vector<std::string> ifaceList; 11732c70f800SEd Tanous ifaceList.reserve(resp.size()); 11748b24275dSEd Tanous if (ec) 11751abe55efSEd Tanous { 11762c70f800SEd Tanous callback(false, ifaceList); 11779391bb9cSRapkiewicz, Pawel return; 11789391bb9cSRapkiewicz, Pawel } 11799391bb9cSRapkiewicz, Pawel 11809391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 11814a0cb85cSEd Tanous for (const auto& objpath : resp) 11821abe55efSEd Tanous { 11839391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 11844a0cb85cSEd Tanous for (const auto& interface : objpath.second) 11851abe55efSEd Tanous { 11861abe55efSEd Tanous // If interface is 11874a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 11884a0cb85cSEd Tanous // what we're looking for. 11899391bb9cSRapkiewicz, Pawel if (interface.first == 11901abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 11911abe55efSEd Tanous { 11922dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 11932dfd18efSEd Tanous if (ifaceId.empty()) 11941abe55efSEd Tanous { 11952dfd18efSEd Tanous continue; 11969391bb9cSRapkiewicz, Pawel } 11972dfd18efSEd Tanous // and put it into output vector. 119877179532SEd Tanous ifaceList.emplace_back(ifaceId); 11999391bb9cSRapkiewicz, Pawel } 12009391bb9cSRapkiewicz, Pawel } 12019391bb9cSRapkiewicz, Pawel } 12022c5875a2SEd Tanous 12033544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 12042c5875a2SEd Tanous 1205a434f2bdSEd Tanous // Finally make a callback with useful data 12062c70f800SEd Tanous callback(true, ifaceList); 1207f5892d0dSGeorge Liu }); 1208271584abSEd Tanous } 12099391bb9cSRapkiewicz, Pawel 12104f48d5f6SEd Tanous inline void 12114f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 12128d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12131abe55efSEd Tanous { 1214ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 1215ab6554f1SJoshi-Mansi if (hostname.length() > 255) 1216ab6554f1SJoshi-Mansi { 1217ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 1218ab6554f1SJoshi-Mansi "HostName"); 1219ab6554f1SJoshi-Mansi return; 1220ab6554f1SJoshi-Mansi } 1221d02aad39SEd Tanous setDbusProperty( 1222d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1223d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network/config"), 1224d02aad39SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1225d02aad39SEd Tanous "HostName", hostname); 1226588c3f0dSKowalski, Kamil } 1227588c3f0dSKowalski, Kamil 12284f48d5f6SEd Tanous inline void 122935fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 123035fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 123135fb5311STejas Patil { 1232d02aad39SEd Tanous sdbusplus::message::object_path objPath("/xyz/openbmc_project/network"); 1233d02aad39SEd Tanous objPath /= ifaceId; 1234d02aad39SEd Tanous setDbusProperty(asyncResp, "xyz.openbmc_project.Network", objPath, 1235d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", "MTU", 1236d02aad39SEd Tanous "MTUSize", mtuSize); 123735fb5311STejas Patil } 123835fb5311STejas Patil 123935fb5311STejas Patil inline void 12404f48d5f6SEd Tanous handleDomainnamePatch(const std::string& ifaceId, 1241bf648f77SEd Tanous const std::string& domainname, 12428d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1243ab6554f1SJoshi-Mansi { 1244ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 1245d02aad39SEd Tanous setDbusProperty( 1246d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1247d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1248d02aad39SEd Tanous ifaceId, 1249d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", "DomainName", "FQDN", 1250d02aad39SEd Tanous vectorDomainname); 1251ab6554f1SJoshi-Mansi } 1252ab6554f1SJoshi-Mansi 12534f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1254bf648f77SEd Tanous { 1255bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 12563544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1257bf648f77SEd Tanous { 1258bf648f77SEd Tanous return false; 1259bf648f77SEd Tanous } 1260bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1261bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1262bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1263bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 12644b242749SEd Tanous const static std::regex pattern( 1265bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1266bf648f77SEd Tanous 1267bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1268bf648f77SEd Tanous } 1269bf648f77SEd Tanous 12704f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1271bf648f77SEd Tanous { 1272bf648f77SEd Tanous // Can have multiple subdomains 1273bf648f77SEd Tanous // Top Level Domain's min length is 2 character 12744b242749SEd Tanous const static std::regex pattern( 12750fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1276bf648f77SEd Tanous 1277bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1278bf648f77SEd Tanous } 1279bf648f77SEd Tanous 12804f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 12818d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1282ab6554f1SJoshi-Mansi { 1283ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1284ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1285ab6554f1SJoshi-Mansi { 1286ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1287ab6554f1SJoshi-Mansi return; 1288ab6554f1SJoshi-Mansi } 1289ab6554f1SJoshi-Mansi 1290ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1291ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1292ab6554f1SJoshi-Mansi { 1293ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1294ab6554f1SJoshi-Mansi return; 1295ab6554f1SJoshi-Mansi } 1296ab6554f1SJoshi-Mansi 1297ab6554f1SJoshi-Mansi std::string hostname; 1298ab6554f1SJoshi-Mansi std::string domainname; 1299ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1300ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1301ab6554f1SJoshi-Mansi 1302ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1303ab6554f1SJoshi-Mansi { 1304ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1305ab6554f1SJoshi-Mansi return; 1306ab6554f1SJoshi-Mansi } 1307ab6554f1SJoshi-Mansi 1308ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1309ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1310ab6554f1SJoshi-Mansi } 1311ab6554f1SJoshi-Mansi 13124f48d5f6SEd Tanous inline void 13134f48d5f6SEd Tanous handleMACAddressPatch(const std::string& ifaceId, 1314bf648f77SEd Tanous const std::string& macAddress, 13158d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1316d577665bSRatan Gupta { 1317d02aad39SEd Tanous setDbusProperty( 1318d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1319d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1320d02aad39SEd Tanous ifaceId, 1321d02aad39SEd Tanous "xyz.openbmc_project.Network.MACAddress", "MACAddress", "MACAddress", 1322d02aad39SEd Tanous macAddress); 1323d577665bSRatan Gupta } 1324286b9118SJohnathan Mantey 13254f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 13264f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 13274f48d5f6SEd Tanous const bool v6Value, 13288d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1329da131a9aSJennifer Lee { 13302c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 1331d02aad39SEd Tanous setDbusProperty( 1332d02aad39SEd Tanous asyncResp, "xyz.openbmc_project.Network", 1333d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1334d02aad39SEd Tanous ifaceId, 1335d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", propertyName, "DHCPv4", 1336d02aad39SEd Tanous dhcp); 1337eeedda23SJohnathan Mantey } 1338eeedda23SJohnathan Mantey 1339e4588158SJishnu CM enum class NetworkType 1340e4588158SJishnu CM { 1341e4588158SJishnu CM dhcp4, 1342e4588158SJishnu CM dhcp6 1343e4588158SJishnu CM }; 1344e4588158SJishnu CM 1345e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1346e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1347e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1348da131a9aSJennifer Lee { 134962598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 1350*1847f2a0SAsmitha Karunanithi std::string redfishPropertyName; 1351e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1352e4588158SJishnu CM path /= ethifaceId; 1353e4588158SJishnu CM 1354e4588158SJishnu CM if (type == NetworkType::dhcp4) 1355e4588158SJishnu CM { 1356e4588158SJishnu CM path /= "dhcp4"; 1357*1847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv4"; 1358e4588158SJishnu CM } 1359e4588158SJishnu CM else 1360e4588158SJishnu CM { 1361e4588158SJishnu CM path /= "dhcp6"; 1362*1847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv6"; 1363e4588158SJishnu CM } 1364e4588158SJishnu CM 1365*1847f2a0SAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path, 1366*1847f2a0SAsmitha Karunanithi "xyz.openbmc_project.Network.DHCPConfiguration", 1367*1847f2a0SAsmitha Karunanithi propertyName, redfishPropertyName, value); 1368da131a9aSJennifer Lee } 1369d577665bSRatan Gupta 1370b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1371b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1372b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1373b10d8db0SRavi Teja { 1374b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1375b10d8db0SRavi Teja path /= ifaceId; 1376*1847f2a0SAsmitha Karunanithi setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path, 1377*1847f2a0SAsmitha Karunanithi "xyz.openbmc_project.Network.EthernetInterface", 1378*1847f2a0SAsmitha Karunanithi "IPv6AcceptRA", 1379*1847f2a0SAsmitha Karunanithi "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 1380*1847f2a0SAsmitha Karunanithi ipv6AutoConfigEnabled); 1381b10d8db0SRavi Teja } 1382b10d8db0SRavi Teja 13834f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId, 13841f8c7b5dSJohnathan Mantey const EthernetInterfaceData& ethData, 1385f23b7296SEd Tanous const DHCPParameters& v4dhcpParms, 1386f23b7296SEd Tanous const DHCPParameters& v6dhcpParms, 13878d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1388da131a9aSJennifer Lee { 138982695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 139082695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1391da131a9aSJennifer Lee 13921f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 13931f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 13941f8c7b5dSJohnathan Mantey 13951f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 13961f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1397da131a9aSJennifer Lee { 1398b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 13991f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 14001f8c7b5dSJohnathan Mantey { 1401bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1402bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 14031f8c7b5dSJohnathan Mantey "OperatingMode"); 1404da131a9aSJennifer Lee return; 1405da131a9aSJennifer Lee } 1406b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 14071f8c7b5dSJohnathan Mantey } 14081f8c7b5dSJohnathan Mantey else 1409da131a9aSJennifer Lee { 14101f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 14111f8c7b5dSJohnathan Mantey } 14121f8c7b5dSJohnathan Mantey 1413e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1414e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1415e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 14161f8c7b5dSJohnathan Mantey { 1417e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 14181f8c7b5dSJohnathan Mantey } 1419e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 14201f8c7b5dSJohnathan Mantey { 1421e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 14221f8c7b5dSJohnathan Mantey } 14231f8c7b5dSJohnathan Mantey 1424e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1425e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1426e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 14271f8c7b5dSJohnathan Mantey { 1428e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 14291f8c7b5dSJohnathan Mantey } 1430e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 14311f8c7b5dSJohnathan Mantey { 1432e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 14331f8c7b5dSJohnathan Mantey } 14341f8c7b5dSJohnathan Mantey 143591c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 143691c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1437e4588158SJishnu CM if (v4dhcpParms.useDomainName) 14381f8c7b5dSJohnathan Mantey { 1439e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 14401f8c7b5dSJohnathan Mantey } 1441e4588158SJishnu CM if (v6dhcpParms.useDomainName) 14421f8c7b5dSJohnathan Mantey { 1443e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 14441f8c7b5dSJohnathan Mantey } 14451f8c7b5dSJohnathan Mantey 144662598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 14471f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 14481f8c7b5dSJohnathan Mantey asyncResp); 144962598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1450e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1451e4588158SJishnu CM NetworkType::dhcp4); 145262598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1453e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1454e4588158SJishnu CM NetworkType::dhcp4); 145591c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 145691c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1457e4588158SJishnu CM NetworkType::dhcp4); 1458e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1459e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1460e4588158SJishnu CM NetworkType::dhcp6); 1461e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1462e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1463e4588158SJishnu CM NetworkType::dhcp6); 146491c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 146591c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1466e4588158SJishnu CM NetworkType::dhcp6); 1467da131a9aSJennifer Lee } 146801784826SJohnathan Mantey 146977179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 147077179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 147177179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 147201784826SJohnathan Mantey { 147317a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 147417a897dfSManojkiran Eda return value.origin == "Static"; 147517a897dfSManojkiran Eda }); 147601784826SJohnathan Mantey } 147701784826SJohnathan Mantey 147877179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 147977179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 148077179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 148101784826SJohnathan Mantey { 148217a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 148317a897dfSManojkiran Eda return value.origin == "Static"; 148417a897dfSManojkiran Eda }); 148501784826SJohnathan Mantey } 148601784826SJohnathan Mantey 148777179532SEd Tanous inline void 1488ddd70dcaSEd Tanous handleIPv4StaticPatch(const std::string& ifaceId, 1489ddd70dcaSEd Tanous nlohmann::json::array_t& input, 149077179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 14918d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 14921abe55efSEd Tanous { 1493ddd70dcaSEd Tanous if (input.empty()) 1494f476acbfSRatan Gupta { 14952e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1496d1d50814SRavi Teja "IPv4StaticAddresses"); 1497f476acbfSRatan Gupta return; 1498f476acbfSRatan Gupta } 1499f476acbfSRatan Gupta 1500271584abSEd Tanous unsigned entryIdx = 1; 150101784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 150201784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 150301784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 150401784826SJohnathan Mantey // into the NIC. 150577179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 15062c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 150701784826SJohnathan Mantey 1508537174c4SEd Tanous for (nlohmann::json& thisJson : input) 15091abe55efSEd Tanous { 151089492a15SPatrick Williams std::string pathString = "IPv4StaticAddresses/" + 151189492a15SPatrick Williams std::to_string(entryIdx); 1512179db1d7SKowalski, Kamil 151301784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1514f476acbfSRatan Gupta { 1515537174c4SEd Tanous std::optional<std::string> address; 1516537174c4SEd Tanous std::optional<std::string> subnetMask; 1517537174c4SEd Tanous std::optional<std::string> gateway; 1518537174c4SEd Tanous 1519537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 15207e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 15217e27d832SJohnathan Mantey "Gateway", gateway)) 1522537174c4SEd Tanous { 1523f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 152471f52d96SEd Tanous pathString); 1525537174c4SEd Tanous return; 1526179db1d7SKowalski, Kamil } 1527179db1d7SKowalski, Kamil 152801784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 152901784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 153001784826SJohnathan Mantey // current state of the interface. Merge existing state into the 153101784826SJohnathan Mantey // current request. 1532537174c4SEd Tanous if (address) 15331abe55efSEd Tanous { 1534e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 153501784826SJohnathan Mantey { 1536bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1537bf648f77SEd Tanous pathString + "/Address"); 1538e01d0c36SEd Tanous return; 153901784826SJohnathan Mantey } 154001784826SJohnathan Mantey } 154185ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 154201784826SJohnathan Mantey { 1543e01d0c36SEd Tanous address = (nicIpEntry->address); 154401784826SJohnathan Mantey } 154501784826SJohnathan Mantey else 154601784826SJohnathan Mantey { 154701784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 154801784826SJohnathan Mantey pathString + "/Address"); 1549e01d0c36SEd Tanous return; 15504a0cb85cSEd Tanous } 15514a0cb85cSEd Tanous 1552e01d0c36SEd Tanous uint8_t prefixLength = 0; 1553537174c4SEd Tanous if (subnetMask) 15544a0cb85cSEd Tanous { 1555033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1556033f1e4dSEd Tanous &prefixLength)) 15574a0cb85cSEd Tanous { 1558f12894f8SJason M. Bills messages::propertyValueFormatError( 1559537174c4SEd Tanous asyncResp->res, *subnetMask, 15604a0cb85cSEd Tanous pathString + "/SubnetMask"); 1561e01d0c36SEd Tanous return; 15624a0cb85cSEd Tanous } 15634a0cb85cSEd Tanous } 156485ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 15654a0cb85cSEd Tanous { 1566033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 156701784826SJohnathan Mantey &prefixLength)) 15684a0cb85cSEd Tanous { 156901784826SJohnathan Mantey messages::propertyValueFormatError( 157085ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 157101784826SJohnathan Mantey pathString + "/SubnetMask"); 1572e01d0c36SEd Tanous return; 15734a0cb85cSEd Tanous } 15744a0cb85cSEd Tanous } 15751abe55efSEd Tanous else 15761abe55efSEd Tanous { 157701784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 157801784826SJohnathan Mantey pathString + "/SubnetMask"); 1579e01d0c36SEd Tanous return; 158001784826SJohnathan Mantey } 158101784826SJohnathan Mantey 158201784826SJohnathan Mantey if (gateway) 158301784826SJohnathan Mantey { 1584e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 158501784826SJohnathan Mantey { 1586bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1587bf648f77SEd Tanous pathString + "/Gateway"); 1588e01d0c36SEd Tanous return; 158901784826SJohnathan Mantey } 159001784826SJohnathan Mantey } 159185ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 159201784826SJohnathan Mantey { 1593e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 159401784826SJohnathan Mantey } 159501784826SJohnathan Mantey else 15961abe55efSEd Tanous { 1597a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 15984a0cb85cSEd Tanous pathString + "/Gateway"); 159901784826SJohnathan Mantey return; 16004a0cb85cSEd Tanous } 16014a0cb85cSEd Tanous 160285ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 16031abe55efSEd Tanous { 16049c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 160577eb0153SEd Tanous nicIpEntry->id, prefixLength, *address, 160677eb0153SEd Tanous *gateway, asyncResp); 160789492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 160889492a15SPatrick Williams ipv4Data.cend()); 1609588c3f0dSKowalski, Kamil } 161001784826SJohnathan Mantey else 161101784826SJohnathan Mantey { 1612cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1613cb13a392SEd Tanous asyncResp); 16144a0cb85cSEd Tanous } 16154a0cb85cSEd Tanous entryIdx++; 16164a0cb85cSEd Tanous } 161701784826SJohnathan Mantey else 161801784826SJohnathan Mantey { 161985ffe86aSJiaqing Zhao if (nicIpEntry == ipv4Data.cend()) 162001784826SJohnathan Mantey { 162101784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 162201784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 162301784826SJohnathan Mantey // in error, so bail out. 162401784826SJohnathan Mantey if (thisJson.is_null()) 162501784826SJohnathan Mantey { 162601784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 162701784826SJohnathan Mantey return; 162801784826SJohnathan Mantey } 1629f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 163071f52d96SEd Tanous pathString); 163101784826SJohnathan Mantey return; 163201784826SJohnathan Mantey } 163301784826SJohnathan Mantey 163401784826SJohnathan Mantey if (thisJson.is_null()) 163501784826SJohnathan Mantey { 16369c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 163701784826SJohnathan Mantey } 163885ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 163901784826SJohnathan Mantey { 164089492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 164189492a15SPatrick Williams ipv4Data.cend()); 164201784826SJohnathan Mantey } 164301784826SJohnathan Mantey entryIdx++; 164401784826SJohnathan Mantey } 164501784826SJohnathan Mantey } 16464a0cb85cSEd Tanous } 16474a0cb85cSEd Tanous 16484f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1649f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1650f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 16518d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1652f85837bfSRAJESWARAN THILLAIGOVINDAN { 1653*1847f2a0SAsmitha Karunanithi setDbusProperty( 1654*1847f2a0SAsmitha Karunanithi asyncResp, "xyz.openbmc_project.Network", 1655*1847f2a0SAsmitha Karunanithi sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1656*1847f2a0SAsmitha Karunanithi ifaceId, 16579ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 1658*1847f2a0SAsmitha Karunanithi "StaticNameServers", updatedStaticNameServers); 1659f85837bfSRAJESWARAN THILLAIGOVINDAN } 1660f85837bfSRAJESWARAN THILLAIGOVINDAN 16614f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 1662ddd70dcaSEd Tanous const std::string& ifaceId, const nlohmann::json::array_t& input, 166377179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 16648d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1665e48c0fc5SRavi Teja { 1666ddd70dcaSEd Tanous if (input.empty()) 1667e48c0fc5SRavi Teja { 16682e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1669e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1670e48c0fc5SRavi Teja return; 1671e48c0fc5SRavi Teja } 1672271584abSEd Tanous size_t entryIdx = 1; 167377179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 16742c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1675f23b7296SEd Tanous for (const nlohmann::json& thisJson : input) 1676e48c0fc5SRavi Teja { 167789492a15SPatrick Williams std::string pathString = "IPv6StaticAddresses/" + 167889492a15SPatrick Williams std::to_string(entryIdx); 1679e48c0fc5SRavi Teja 168001784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1681e48c0fc5SRavi Teja { 1682e48c0fc5SRavi Teja std::optional<std::string> address; 1683e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1684f23b7296SEd Tanous nlohmann::json thisJsonCopy = thisJson; 1685bf648f77SEd Tanous if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 1686bf648f77SEd Tanous address, "PrefixLength", prefixLength)) 1687e48c0fc5SRavi Teja { 1688f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 168971f52d96SEd Tanous pathString); 1690e48c0fc5SRavi Teja return; 1691e48c0fc5SRavi Teja } 1692e48c0fc5SRavi Teja 169301784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 169401784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 169501784826SJohnathan Mantey // current state of the interface. Merge existing state into the 169601784826SJohnathan Mantey // current request. 1697d547d8d2SEd Tanous if (!address) 1698e48c0fc5SRavi Teja { 1699d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 170001784826SJohnathan Mantey { 170101784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 170201784826SJohnathan Mantey pathString + "/Address"); 170301784826SJohnathan Mantey return; 1704e48c0fc5SRavi Teja } 1705d547d8d2SEd Tanous address = nicIpEntry->address; 1706d547d8d2SEd Tanous } 1707e48c0fc5SRavi Teja 1708d547d8d2SEd Tanous if (!prefixLength) 1709e48c0fc5SRavi Teja { 1710d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 1711e48c0fc5SRavi Teja { 1712e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1713e48c0fc5SRavi Teja pathString + "/PrefixLength"); 171401784826SJohnathan Mantey return; 1715e48c0fc5SRavi Teja } 1716d547d8d2SEd Tanous prefixLength = nicIpEntry->prefixLength; 1717d547d8d2SEd Tanous } 1718e48c0fc5SRavi Teja 171985ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1720e48c0fc5SRavi Teja { 17219c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 1722d547d8d2SEd Tanous nicIpEntry->id, *prefixLength, 1723d547d8d2SEd Tanous *address, "", asyncResp); 172489492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 172589492a15SPatrick Williams ipv6Data.cend()); 172601784826SJohnathan Mantey } 172701784826SJohnathan Mantey else 172801784826SJohnathan Mantey { 1729d547d8d2SEd Tanous createIPv6(ifaceId, *prefixLength, *address, asyncResp); 1730e48c0fc5SRavi Teja } 1731e48c0fc5SRavi Teja entryIdx++; 1732e48c0fc5SRavi Teja } 173301784826SJohnathan Mantey else 173401784826SJohnathan Mantey { 173585ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 173601784826SJohnathan Mantey { 173701784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 173801784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 173901784826SJohnathan Mantey // in error, so bail out. 174001784826SJohnathan Mantey if (thisJson.is_null()) 174101784826SJohnathan Mantey { 174201784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 174301784826SJohnathan Mantey return; 174401784826SJohnathan Mantey } 1745f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 174671f52d96SEd Tanous pathString); 174701784826SJohnathan Mantey return; 174801784826SJohnathan Mantey } 174901784826SJohnathan Mantey 175001784826SJohnathan Mantey if (thisJson.is_null()) 175101784826SJohnathan Mantey { 17529c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 175301784826SJohnathan Mantey } 175485ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 175501784826SJohnathan Mantey { 175689492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 175789492a15SPatrick Williams ipv6Data.cend()); 175801784826SJohnathan Mantey } 175901784826SJohnathan Mantey entryIdx++; 176001784826SJohnathan Mantey } 176101784826SJohnathan Mantey } 1762e48c0fc5SRavi Teja } 1763e48c0fc5SRavi Teja 17647857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 17657857cb8dSJiaqing Zhao { 17667857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 17677857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 17687857cb8dSJiaqing Zhao } 17697857cb8dSJiaqing Zhao 177077179532SEd Tanous inline void 177177179532SEd Tanous parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 177277179532SEd Tanous const std::string& ifaceId, 177377179532SEd Tanous const EthernetInterfaceData& ethData, 177477179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1775ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 1776ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) 17774a0cb85cSEd Tanous { 17782c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 177981ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1780ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 1781ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId); 17822c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1783eeedda23SJohnathan Mantey 178413451e39SWilly Tu if constexpr (bmcwebEnableHealthPopulate) 178513451e39SWilly Tu { 178613451e39SWilly Tu constexpr std::array<std::string_view, 1> inventoryForEthernet = { 178713451e39SWilly Tu "xyz.openbmc_project.Inventory.Item.Ethernet"}; 1788eeedda23SJohnathan Mantey auto health = std::make_shared<HealthPopulate>(asyncResp); 17897a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 17907a1dbc48SGeorge Liu "/", 0, inventoryForEthernet, 17917a1dbc48SGeorge Liu [health](const boost::system::error_code& ec, 1792b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& resp) { 1793eeedda23SJohnathan Mantey if (ec) 1794029573d4SEd Tanous { 1795eeedda23SJohnathan Mantey return; 1796eeedda23SJohnathan Mantey } 1797eeedda23SJohnathan Mantey 1798914e2d5dSEd Tanous health->inventory = resp; 17997a1dbc48SGeorge Liu }); 1800eeedda23SJohnathan Mantey 1801eeedda23SJohnathan Mantey health->populate(); 180213451e39SWilly Tu } 1803eeedda23SJohnathan Mantey 1804eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1805eeedda23SJohnathan Mantey { 18060ef0e289SJohnathan Mantey jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 18072c70f800SEd Tanous jsonResponse["Status"]["State"] = "Enabled"; 1808029573d4SEd Tanous } 1809029573d4SEd Tanous else 1810029573d4SEd Tanous { 18112c70f800SEd Tanous jsonResponse["LinkStatus"] = "NoLink"; 18122c70f800SEd Tanous jsonResponse["Status"]["State"] = "Disabled"; 1813029573d4SEd Tanous } 1814aa05fb27SJohnathan Mantey 18152c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 181635fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 181782695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 18182c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 181982695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1820e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1821e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1822e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled; 18232c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1824b10d8db0SRavi Teja translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled" 18251f8c7b5dSJohnathan Mantey : "Disabled"; 1826e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1827e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1828e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled; 1829b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1830b10d8db0SRavi Teja ethData.ipv6AcceptRa; 18312a133282Smanojkiraneda 183282695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 18334a0cb85cSEd Tanous { 183482695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1835ab6554f1SJoshi-Mansi 1836ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1837ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1838ab6554f1SJoshi-Mansi // FQDN 183982695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1840d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1841d24bfc7aSJennifer Lee { 18422c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1843d24bfc7aSJennifer Lee } 18442c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 18454a0cb85cSEd Tanous } 18464a0cb85cSEd Tanous 18477857cb8dSJiaqing Zhao if (ethData.vlanId) 18487857cb8dSJiaqing Zhao { 18497857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Virtual"; 18507857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 18517857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 18527857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 18537857cb8dSJiaqing Zhao 18547857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 18557857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 18567857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 18577857cb8dSJiaqing Zhao boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces", 18587857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 18597857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 18607857cb8dSJiaqing Zhao std::move(relatedInterfaces); 18617857cb8dSJiaqing Zhao } 18627857cb8dSJiaqing Zhao else 18637857cb8dSJiaqing Zhao { 18647857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Physical"; 18657857cb8dSJiaqing Zhao } 18667857cb8dSJiaqing Zhao 18672c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 18682c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 18694a0cb85cSEd Tanous 18702c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 18712c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 18722c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 18732c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 18749eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 18754a0cb85cSEd Tanous { 18762c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1877fa5053a6SGunnar Mills if (gatewayStr.empty()) 1878fa5053a6SGunnar Mills { 1879fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1880fa5053a6SGunnar Mills } 18811476687dSEd Tanous nlohmann::json::object_t ipv4; 18821476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 18831476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 18841476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 18851476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1886fa5053a6SGunnar Mills 18872c70f800SEd Tanous if (ipv4Config.origin == "Static") 1888d1d50814SRavi Teja { 18891476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1890d1d50814SRavi Teja } 18911476687dSEd Tanous 1892b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 189301784826SJohnathan Mantey } 1894d1d50814SRavi Teja 189582695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 18967ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 18977ea79e5eSRavi Teja { 18987ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 18997ea79e5eSRavi Teja } 19007ea79e5eSRavi Teja 19017ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1902e48c0fc5SRavi Teja 1903ce73d5c8SSunitha Harish nlohmann::json::array_t ipv6StaticGatewayArray; 1904ce73d5c8SSunitha Harish for (const auto& ipv6GatewayConfig : ipv6GatewayData) 1905ce73d5c8SSunitha Harish { 1906ce73d5c8SSunitha Harish nlohmann::json::object_t ipv6Gateway; 1907ce73d5c8SSunitha Harish ipv6Gateway["Address"] = ipv6GatewayConfig.gateway; 1908ce73d5c8SSunitha Harish ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength; 1909ce73d5c8SSunitha Harish ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway)); 1910ce73d5c8SSunitha Harish } 1911ce73d5c8SSunitha Harish jsonResponse["IPv6StaticDefaultGateways"] = 1912ce73d5c8SSunitha Harish std::move(ipv6StaticGatewayArray); 1913ce73d5c8SSunitha Harish 19142c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 19152c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 19162c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 19172c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 19187f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 19192c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 19207f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 19219eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1922e48c0fc5SRavi Teja { 19231476687dSEd Tanous nlohmann::json::object_t ipv6; 19241476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 19251476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 19261476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1927f8361275SSunitha Harish 1928b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 19292c70f800SEd Tanous if (ipv6Config.origin == "Static") 1930e48c0fc5SRavi Teja { 19311476687dSEd Tanous nlohmann::json::object_t ipv6Static; 19321476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 19331476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 1934b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 193501784826SJohnathan Mantey } 1936e48c0fc5SRavi Teja } 1937588c3f0dSKowalski, Kamil } 1938588c3f0dSKowalski, Kamil 1939e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1940e7caf250SJiaqing Zhao const std::string& ifaceId, 1941e7caf250SJiaqing Zhao const boost::system::error_code& ec, 1942e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 1943e7caf250SJiaqing Zhao { 1944e7caf250SJiaqing Zhao if (!ec) 1945e7caf250SJiaqing Zhao { 1946e7caf250SJiaqing Zhao return; 1947e7caf250SJiaqing Zhao } 1948e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1949e7caf250SJiaqing Zhao if (dbusError == nullptr) 1950e7caf250SJiaqing Zhao { 1951e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1952e7caf250SJiaqing Zhao return; 1953e7caf250SJiaqing Zhao } 195462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1955e7caf250SJiaqing Zhao 1956e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 1957e7caf250SJiaqing Zhao dbusError->name) 1958e7caf250SJiaqing Zhao { 1959e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1960e7caf250SJiaqing Zhao ifaceId); 1961e7caf250SJiaqing Zhao return; 1962e7caf250SJiaqing Zhao } 1963e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 1964e7caf250SJiaqing Zhao dbusError->name) 1965e7caf250SJiaqing Zhao { 1966e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 1967e7caf250SJiaqing Zhao return; 1968e7caf250SJiaqing Zhao } 1969e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1970e7caf250SJiaqing Zhao } 1971e7caf250SJiaqing Zhao 1972b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1973b5ca3fdcSJiaqing Zhao const std::string& parentInterfaceUri, 1974b5ca3fdcSJiaqing Zhao const std::string& vlanInterface, 1975b5ca3fdcSJiaqing Zhao const boost::system::error_code& ec, 1976b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m 1977b5ca3fdcSJiaqing Zhao 1978b5ca3fdcSJiaqing Zhao ) 1979b5ca3fdcSJiaqing Zhao { 1980b5ca3fdcSJiaqing Zhao if (ec) 1981b5ca3fdcSJiaqing Zhao { 1982b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1983b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 1984b5ca3fdcSJiaqing Zhao { 1985b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1986b5ca3fdcSJiaqing Zhao return; 1987b5ca3fdcSJiaqing Zhao } 198862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1989b5ca3fdcSJiaqing Zhao 1990b5ca3fdcSJiaqing Zhao if (std::string_view( 1991b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 1992b5ca3fdcSJiaqing Zhao dbusError->name) 1993b5ca3fdcSJiaqing Zhao { 1994b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1995b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1996b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1997b5ca3fdcSJiaqing Zhao return; 1998b5ca3fdcSJiaqing Zhao } 1999b5ca3fdcSJiaqing Zhao if (std::string_view( 2000b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 2001b5ca3fdcSJiaqing Zhao dbusError->name) 2002b5ca3fdcSJiaqing Zhao { 2003b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 2004b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 2005b5ca3fdcSJiaqing Zhao return; 2006b5ca3fdcSJiaqing Zhao } 2007b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2008b5ca3fdcSJiaqing Zhao return; 2009b5ca3fdcSJiaqing Zhao } 2010b5ca3fdcSJiaqing Zhao 2011b5ca3fdcSJiaqing Zhao const boost::urls::url vlanInterfaceUri = boost::urls::format( 2012b5ca3fdcSJiaqing Zhao "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface); 2013b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 2014b5ca3fdcSJiaqing Zhao } 2015b5ca3fdcSJiaqing Zhao 2016bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 2017bf648f77SEd Tanous { 2018bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 2019ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 20201476687dSEd Tanous .methods(boost::beast::http::verb::get)( 20211476687dSEd Tanous [&app](const crow::Request& req, 20221476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 20233ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 202445ca1b86SEd Tanous { 202545ca1b86SEd Tanous return; 202645ca1b86SEd Tanous } 202745ca1b86SEd Tanous 2028bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2029bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 2030bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2031bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 2032bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 2033bf648f77SEd Tanous "Ethernet Network Interface Collection"; 2034bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 2035bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 2036bf648f77SEd Tanous 2037bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 2038bf648f77SEd Tanous // preparation 2039002d39b4SEd Tanous getEthernetIfaceList( 204077179532SEd Tanous [asyncResp](const bool& success, 204177179532SEd Tanous const std::vector<std::string>& ifaceList) { 2042bf648f77SEd Tanous if (!success) 20431abe55efSEd Tanous { 2044f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20459391bb9cSRapkiewicz, Pawel return; 20469391bb9cSRapkiewicz, Pawel } 20479391bb9cSRapkiewicz, Pawel 2048002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 2049bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 2050bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 2051bf648f77SEd Tanous { 20521476687dSEd Tanous nlohmann::json::object_t iface; 2053ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 2054ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", 2055ef4c65b7SEd Tanous ifaceItem); 20567857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 2057bf648f77SEd Tanous } 2058bf648f77SEd Tanous 2059002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 2060bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 2061bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 2062bf648f77SEd Tanous }); 2063bf648f77SEd Tanous }); 2064bf648f77SEd Tanous 2065b5ca3fdcSJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 2066b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 2067b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 2068b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 2069b5ca3fdcSJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2070b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2071b5ca3fdcSJiaqing Zhao { 2072b5ca3fdcSJiaqing Zhao return; 2073b5ca3fdcSJiaqing Zhao } 2074b5ca3fdcSJiaqing Zhao 2075b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 2076b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 2077b5ca3fdcSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 2078b5ca3fdcSJiaqing Zhao 2079b5ca3fdcSJiaqing Zhao if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", 2080b5ca3fdcSJiaqing Zhao vlanEnable, "VLAN/VLANId", vlanId, 2081b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2082b5ca3fdcSJiaqing Zhao relatedInterfaces)) 2083b5ca3fdcSJiaqing Zhao { 2084b5ca3fdcSJiaqing Zhao return; 2085b5ca3fdcSJiaqing Zhao } 2086b5ca3fdcSJiaqing Zhao 2087b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 2088b5ca3fdcSJiaqing Zhao { 2089b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 2090b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2091b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 2092b5ca3fdcSJiaqing Zhao return; 2093b5ca3fdcSJiaqing Zhao } 2094b5ca3fdcSJiaqing Zhao 2095b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 2096b5ca3fdcSJiaqing Zhao if (!json_util::readJson(relatedInterfaces[0], asyncResp->res, 2097b5ca3fdcSJiaqing Zhao "@odata.id", parentInterfaceUri)) 2098b5ca3fdcSJiaqing Zhao { 2099b5ca3fdcSJiaqing Zhao messages::propertyMissing(asyncResp->res, 2100b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2101b5ca3fdcSJiaqing Zhao return; 2102b5ca3fdcSJiaqing Zhao } 210362598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 2104b5ca3fdcSJiaqing Zhao 21056fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 2106b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 2107b5ca3fdcSJiaqing Zhao if (!parsedUri) 2108b5ca3fdcSJiaqing Zhao { 2109b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 2110b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2111b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2112b5ca3fdcSJiaqing Zhao return; 2113b5ca3fdcSJiaqing Zhao } 2114b5ca3fdcSJiaqing Zhao 2115b5ca3fdcSJiaqing Zhao std::string parentInterface; 2116b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 2117b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 2118b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 2119b5ca3fdcSJiaqing Zhao { 2120b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2121b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2122b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2123b5ca3fdcSJiaqing Zhao return; 2124b5ca3fdcSJiaqing Zhao } 2125b5ca3fdcSJiaqing Zhao 2126b5ca3fdcSJiaqing Zhao if (!vlanEnable) 2127b5ca3fdcSJiaqing Zhao { 2128b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 2129b5ca3fdcSJiaqing Zhao // create 2130b5ca3fdcSJiaqing Zhao messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", 2131b5ca3fdcSJiaqing Zhao "false"); 2132b5ca3fdcSJiaqing Zhao return; 2133b5ca3fdcSJiaqing Zhao } 2134b5ca3fdcSJiaqing Zhao 2135b5ca3fdcSJiaqing Zhao std::string vlanInterface = parentInterface + "_" + 2136b5ca3fdcSJiaqing Zhao std::to_string(vlanId); 2137b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 2138b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 2139b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 2140b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 2141b5ca3fdcSJiaqing Zhao afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, 2142b5ca3fdcSJiaqing Zhao m); 2143b5ca3fdcSJiaqing Zhao }, 2144b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 2145b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, 2146b5ca3fdcSJiaqing Zhao vlanId); 2147b5ca3fdcSJiaqing Zhao }); 2148b5ca3fdcSJiaqing Zhao 2149bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2150ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 2151bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 215245ca1b86SEd Tanous [&app](const crow::Request& req, 2153bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2154bf648f77SEd Tanous const std::string& ifaceId) { 21553ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 215645ca1b86SEd Tanous { 215745ca1b86SEd Tanous return; 215845ca1b86SEd Tanous } 21594a0cb85cSEd Tanous getEthernetIfaceData( 2160bf648f77SEd Tanous ifaceId, 2161ce73d5c8SSunitha Harish [asyncResp, 2162ce73d5c8SSunitha Harish ifaceId](const bool& success, const EthernetInterfaceData& ethData, 216377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2164ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2165ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 21664a0cb85cSEd Tanous if (!success) 21671abe55efSEd Tanous { 2168bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2169bf648f77SEd Tanous // existing object, and other errors 2170002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2171002d39b4SEd Tanous ifaceId); 21724a0cb85cSEd Tanous return; 21739391bb9cSRapkiewicz, Pawel } 21744c9afe43SEd Tanous 21750f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 217693bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2177002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 21780f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 21790f74e643SEd Tanous "Management Network Interface"; 21800f74e643SEd Tanous 2181ce73d5c8SSunitha Harish parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data, 2182ce73d5c8SSunitha Harish ipv6GatewayData); 21839391bb9cSRapkiewicz, Pawel }); 2184bf648f77SEd Tanous }); 21859391bb9cSRapkiewicz, Pawel 2186bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2187ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2188bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 218945ca1b86SEd Tanous [&app](const crow::Request& req, 2190bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2191bf648f77SEd Tanous const std::string& ifaceId) { 21923ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 219345ca1b86SEd Tanous { 219445ca1b86SEd Tanous return; 219545ca1b86SEd Tanous } 2196bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2197ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2198d577665bSRatan Gupta std::optional<std::string> macAddress; 21999a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2200ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv4StaticAddresses; 2201ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv6StaticAddresses; 2202ce73d5c8SSunitha Harish std::optional<nlohmann::json::array_t> ipv6StaticDefaultGateways; 2203f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2204da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 22051f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 2206b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2207eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 220835fb5311STejas Patil std::optional<size_t> mtuSize; 22091f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 22101f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2211b10d8db0SRavi Teja // clang-format off 221215ed6780SWilly Tu if (!json_util::readJsonPatch( 2213b10d8db0SRavi Teja req, asyncResp->res, 2214b10d8db0SRavi Teja "DHCPv4", dhcpv4, 2215b10d8db0SRavi Teja "DHCPv6", dhcpv6, 2216b10d8db0SRavi Teja "FQDN", fqdn, 2217b10d8db0SRavi Teja "HostName", hostname, 2218b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 2219b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 2220b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 2221ce73d5c8SSunitha Harish "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways, 2222b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 2223b10d8db0SRavi Teja "MACAddress", macAddress, 2224b10d8db0SRavi Teja "MTUSize", mtuSize, 2225b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 2226b10d8db0SRavi Teja "StaticNameServers", staticNameServers 2227b10d8db0SRavi Teja ) 2228b10d8db0SRavi Teja ) 22291abe55efSEd Tanous { 2230588c3f0dSKowalski, Kamil return; 2231588c3f0dSKowalski, Kamil } 2232b10d8db0SRavi Teja // clang-format on 2233da131a9aSJennifer Lee if (dhcpv4) 2234da131a9aSJennifer Lee { 2235002d39b4SEd Tanous if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 22361f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 223782695a5bSJiaqing Zhao v4dhcpParms.useDnsServers, "UseNTPServers", 223882695a5bSJiaqing Zhao v4dhcpParms.useNtpServers, "UseDomainName", 223982695a5bSJiaqing Zhao v4dhcpParms.useDomainName)) 22401f8c7b5dSJohnathan Mantey { 22411f8c7b5dSJohnathan Mantey return; 22421f8c7b5dSJohnathan Mantey } 22431f8c7b5dSJohnathan Mantey } 22441f8c7b5dSJohnathan Mantey 22451f8c7b5dSJohnathan Mantey if (dhcpv6) 22461f8c7b5dSJohnathan Mantey { 2247002d39b4SEd Tanous if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode", 2248002d39b4SEd Tanous v6dhcpParms.dhcpv6OperatingMode, 2249002d39b4SEd Tanous "UseDNSServers", v6dhcpParms.useDnsServers, 2250002d39b4SEd Tanous "UseNTPServers", v6dhcpParms.useNtpServers, 2251002d39b4SEd Tanous "UseDomainName", 225282695a5bSJiaqing Zhao v6dhcpParms.useDomainName)) 22531f8c7b5dSJohnathan Mantey { 22541f8c7b5dSJohnathan Mantey return; 22551f8c7b5dSJohnathan Mantey } 2256da131a9aSJennifer Lee } 2257da131a9aSJennifer Lee 2258bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2259bf648f77SEd Tanous // for JSON preparation 22604a0cb85cSEd Tanous getEthernetIfaceData( 22612c70f800SEd Tanous ifaceId, 2262bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2263ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2264d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 22659a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2266e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 2267ce73d5c8SSunitha Harish ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways), 22681f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 2269bc20089aSEd Tanous dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize, 2270b10d8db0SRavi Teja ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms), 2271f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2272002d39b4SEd Tanous const bool& success, const EthernetInterfaceData& ethData, 227377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2274ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2275ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 22761abe55efSEd Tanous if (!success) 22771abe55efSEd Tanous { 2278588c3f0dSKowalski, Kamil // ... otherwise return error 2279bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2280bf648f77SEd Tanous // existing object, and other errors 2281002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2282002d39b4SEd Tanous ifaceId); 2283588c3f0dSKowalski, Kamil return; 2284588c3f0dSKowalski, Kamil } 2285588c3f0dSKowalski, Kamil 22861f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 22871f8c7b5dSJohnathan Mantey { 2288002d39b4SEd Tanous handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, 2289002d39b4SEd Tanous asyncResp); 22901f8c7b5dSJohnathan Mantey } 22911f8c7b5dSJohnathan Mantey 22920627a2c7SEd Tanous if (hostname) 22931abe55efSEd Tanous { 22940627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 22951abe55efSEd Tanous } 22960627a2c7SEd Tanous 2297b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2298b10d8db0SRavi Teja { 2299b10d8db0SRavi Teja handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled, 2300b10d8db0SRavi Teja asyncResp); 2301b10d8db0SRavi Teja } 2302b10d8db0SRavi Teja 2303ab6554f1SJoshi-Mansi if (fqdn) 2304ab6554f1SJoshi-Mansi { 23052c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2306ab6554f1SJoshi-Mansi } 2307ab6554f1SJoshi-Mansi 2308d577665bSRatan Gupta if (macAddress) 2309d577665bSRatan Gupta { 2310002d39b4SEd Tanous handleMACAddressPatch(ifaceId, *macAddress, asyncResp); 2311d577665bSRatan Gupta } 2312d577665bSRatan Gupta 2313d1d50814SRavi Teja if (ipv4StaticAddresses) 2314d1d50814SRavi Teja { 2315bf648f77SEd Tanous // TODO(ed) for some reason the capture of 2316bf648f77SEd Tanous // ipv4Addresses above is returning a const value, 2317bf648f77SEd Tanous // not a non-const value. This doesn't really work 2318bf648f77SEd Tanous // for us, as we need to be able to efficiently move 2319bf648f77SEd Tanous // out the intermedia nlohmann::json objects. This 2320bf648f77SEd Tanous // makes a copy of the structure, and operates on 2321bf648f77SEd Tanous // that, but could be done more efficiently 2322ddd70dcaSEd Tanous nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses; 2323002d39b4SEd Tanous handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp); 23241abe55efSEd Tanous } 23250627a2c7SEd Tanous 2326f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2327f85837bfSRAJESWARAN THILLAIGOVINDAN { 2328002d39b4SEd Tanous handleStaticNameServersPatch(ifaceId, *staticNameServers, 2329002d39b4SEd Tanous asyncResp); 2330f85837bfSRAJESWARAN THILLAIGOVINDAN } 23319a6fc6feSRavi Teja 23329a6fc6feSRavi Teja if (ipv6DefaultGateway) 23339a6fc6feSRavi Teja { 23349a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 23359a6fc6feSRavi Teja "IPv6DefaultGateway"); 23369a6fc6feSRavi Teja } 2337e48c0fc5SRavi Teja 2338e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2339e48c0fc5SRavi Teja { 2340ddd70dcaSEd Tanous handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses, 2341ddd70dcaSEd Tanous ipv6Data, asyncResp); 2342e48c0fc5SRavi Teja } 2343eeedda23SJohnathan Mantey 2344ce73d5c8SSunitha Harish if (ipv6StaticDefaultGateway) 2345ce73d5c8SSunitha Harish { 2346ce73d5c8SSunitha Harish handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway, 2347ce73d5c8SSunitha Harish ipv6GatewayData, asyncResp); 2348ce73d5c8SSunitha Harish } 2349ce73d5c8SSunitha Harish 2350eeedda23SJohnathan Mantey if (interfaceEnabled) 2351eeedda23SJohnathan Mantey { 2352d02aad39SEd Tanous setDbusProperty(asyncResp, "xyz.openbmc_project.Network", 2353d02aad39SEd Tanous sdbusplus::message::object_path( 2354d02aad39SEd Tanous "/xyz/openbmc_project/network") / 2355d02aad39SEd Tanous ifaceId, 2356d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", 2357d02aad39SEd Tanous "NICEnabled", "InterfaceEnabled", 2358d02aad39SEd Tanous *interfaceEnabled); 2359eeedda23SJohnathan Mantey } 236035fb5311STejas Patil 236135fb5311STejas Patil if (mtuSize) 236235fb5311STejas Patil { 236335fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 236435fb5311STejas Patil } 2365588c3f0dSKowalski, Kamil }); 2366bf648f77SEd Tanous }); 2367e7caf250SJiaqing Zhao 2368e7caf250SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2369e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2370e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2371e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2372e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2373e7caf250SJiaqing Zhao const std::string& ifaceId) { 2374e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2375e7caf250SJiaqing Zhao { 2376e7caf250SJiaqing Zhao return; 2377e7caf250SJiaqing Zhao } 2378e7caf250SJiaqing Zhao 2379e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2380e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2381e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2382e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2383e7caf250SJiaqing Zhao }, 2384e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2385e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2386e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2387e7caf250SJiaqing Zhao }); 23884a0cb85cSEd Tanous } 2389bf648f77SEd Tanous 23909391bb9cSRapkiewicz, Pawel } // namespace redfish 2391