19391bb9cSRapkiewicz, Pawel /* 29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 39391bb9cSRapkiewicz, Pawel // 49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License. 69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at 79391bb9cSRapkiewicz, Pawel // 89391bb9cSRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 99391bb9cSRapkiewicz, Pawel // 109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and 149391bb9cSRapkiewicz, Pawel // limitations under the License. 159391bb9cSRapkiewicz, Pawel */ 169391bb9cSRapkiewicz, Pawel #pragma once 179391bb9cSRapkiewicz, Pawel 183ccb3adbSEd Tanous #include "app.hpp" 193ccb3adbSEd Tanous #include "dbus_singleton.hpp" 207a1dbc48SGeorge Liu #include "dbus_utility.hpp" 213ccb3adbSEd Tanous #include "error_messages.hpp" 22539d8c6bSEd Tanous #include "generated/enums/ethernet_interface.hpp" 23539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 242c5875a2SEd Tanous #include "human_sort.hpp" 253ccb3adbSEd Tanous #include "query.hpp" 263ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 27033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 283ccb3adbSEd Tanous #include "utils/json_utils.hpp" 29033f1e4dSEd Tanous 30ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp> 31ef4c65b7SEd Tanous #include <boost/url/format.hpp> 321214b7e7SGunnar Mills 337a1dbc48SGeorge Liu #include <array> 343dfed536SEd Tanous #include <cstddef> 35ce73d5c8SSunitha Harish #include <memory> 36a24526dcSEd Tanous #include <optional> 373544d2a7SEd Tanous #include <ranges> 38ab6554f1SJoshi-Mansi #include <regex> 397a1dbc48SGeorge Liu #include <string_view> 403dfed536SEd Tanous #include <variant> 4177179532SEd Tanous #include <vector> 429391bb9cSRapkiewicz, Pawel 431abe55efSEd Tanous namespace redfish 441abe55efSEd Tanous { 459391bb9cSRapkiewicz, Pawel 464a0cb85cSEd Tanous enum class LinkType 474a0cb85cSEd Tanous { 484a0cb85cSEd Tanous Local, 494a0cb85cSEd Tanous Global 504a0cb85cSEd Tanous }; 519391bb9cSRapkiewicz, Pawel 52743eb1c0SJohnathan Mantey enum class IpVersion 53743eb1c0SJohnathan Mantey { 54743eb1c0SJohnathan Mantey IpV4, 55743eb1c0SJohnathan Mantey IpV6 56743eb1c0SJohnathan Mantey }; 57743eb1c0SJohnathan Mantey 589391bb9cSRapkiewicz, Pawel /** 599391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 609391bb9cSRapkiewicz, Pawel */ 611abe55efSEd Tanous struct IPv4AddressData 621abe55efSEd Tanous { 63179db1d7SKowalski, Kamil std::string id; 644a0cb85cSEd Tanous std::string address; 654a0cb85cSEd Tanous std::string domain; 664a0cb85cSEd Tanous std::string gateway; 679391bb9cSRapkiewicz, Pawel std::string netmask; 689391bb9cSRapkiewicz, Pawel std::string origin; 6977179532SEd Tanous LinkType linktype{}; 7077179532SEd Tanous bool isActive{}; 719391bb9cSRapkiewicz, Pawel }; 729391bb9cSRapkiewicz, Pawel 739391bb9cSRapkiewicz, Pawel /** 74e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 75e48c0fc5SRavi Teja */ 76e48c0fc5SRavi Teja struct IPv6AddressData 77e48c0fc5SRavi Teja { 78e48c0fc5SRavi Teja std::string id; 79e48c0fc5SRavi Teja std::string address; 80e48c0fc5SRavi Teja std::string origin; 8177179532SEd Tanous uint8_t prefixLength = 0; 82e48c0fc5SRavi Teja }; 83ce73d5c8SSunitha Harish 84ce73d5c8SSunitha Harish /** 85ce73d5c8SSunitha Harish * Structure for keeping static route data required by Redfish 86ce73d5c8SSunitha Harish */ 87ce73d5c8SSunitha Harish struct StaticGatewayData 88ce73d5c8SSunitha Harish { 89ce73d5c8SSunitha Harish std::string id; 90ce73d5c8SSunitha Harish std::string gateway; 91ce73d5c8SSunitha Harish size_t prefixLength = 0; 92ce73d5c8SSunitha Harish std::string protocol; 93ce73d5c8SSunitha Harish }; 94ce73d5c8SSunitha Harish 95e48c0fc5SRavi Teja /** 969391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 979391bb9cSRapkiewicz, Pawel * available from DBus 989391bb9cSRapkiewicz, Pawel */ 991abe55efSEd Tanous struct EthernetInterfaceData 1001abe55efSEd Tanous { 1014a0cb85cSEd Tanous uint32_t speed; 10235fb5311STejas Patil size_t mtuSize; 10382695a5bSJiaqing Zhao bool autoNeg; 104e4588158SJishnu CM bool dnsv4Enabled; 105e4588158SJishnu CM bool dnsv6Enabled; 10691c441ecSRavi Teja bool domainv4Enabled; 10791c441ecSRavi Teja bool domainv6Enabled; 108e4588158SJishnu CM bool ntpv4Enabled; 109e4588158SJishnu CM bool ntpv6Enabled; 110e4588158SJishnu CM bool hostNamev4Enabled; 111e4588158SJishnu CM bool hostNamev6Enabled; 112aa05fb27SJohnathan Mantey bool linkUp; 113eeedda23SJohnathan Mantey bool nicEnabled; 114b10d8db0SRavi Teja bool ipv6AcceptRa; 11582695a5bSJiaqing Zhao std::string dhcpEnabled; 1161f8c7b5dSJohnathan Mantey std::string operatingMode; 11782695a5bSJiaqing Zhao std::string hostName; 11882695a5bSJiaqing Zhao std::string defaultGateway; 11982695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 120ce73d5c8SSunitha Harish std::string ipv6StaticDefaultGateway; 121*4652c640SAsmitha Karunanithi std::optional<std::string> macAddress; 12217e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 1230f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 1240f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 125d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1269391bb9cSRapkiewicz, Pawel }; 1279391bb9cSRapkiewicz, Pawel 1281f8c7b5dSJohnathan Mantey struct DHCPParameters 1291f8c7b5dSJohnathan Mantey { 1301f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 13182695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 13282695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 13382695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1341f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1351f8c7b5dSJohnathan Mantey }; 1361f8c7b5dSJohnathan Mantey 1379391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1389391bb9cSRapkiewicz, Pawel // into full dot notation 1391abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1401abe55efSEd Tanous { 1419391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1429391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1439391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1449391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1459391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1469391bb9cSRapkiewicz, Pawel return netmask; 1479391bb9cSRapkiewicz, Pawel } 1489391bb9cSRapkiewicz, Pawel 14982695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1501f8c7b5dSJohnathan Mantey bool isIPv4) 1511f8c7b5dSJohnathan Mantey { 1521f8c7b5dSJohnathan Mantey if (isIPv4) 1531f8c7b5dSJohnathan Mantey { 1541f8c7b5dSJohnathan Mantey return ( 1551f8c7b5dSJohnathan Mantey (inputDHCP == 1561f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1571f8c7b5dSJohnathan Mantey (inputDHCP == 1581f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1591f8c7b5dSJohnathan Mantey } 1601f8c7b5dSJohnathan Mantey return ((inputDHCP == 1611f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1621f8c7b5dSJohnathan Mantey (inputDHCP == 1631f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1641f8c7b5dSJohnathan Mantey } 1651f8c7b5dSJohnathan Mantey 1662c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1671f8c7b5dSJohnathan Mantey { 1681f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1691f8c7b5dSJohnathan Mantey { 1701f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1711f8c7b5dSJohnathan Mantey } 1723174e4dfSEd Tanous if (isIPv4) 1731f8c7b5dSJohnathan Mantey { 1741f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1751f8c7b5dSJohnathan Mantey } 1763174e4dfSEd Tanous if (isIPv6) 1771f8c7b5dSJohnathan Mantey { 1781f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1791f8c7b5dSJohnathan Mantey } 1801f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1811f8c7b5dSJohnathan Mantey } 1821f8c7b5dSJohnathan Mantey 183bd79bce8SPatrick Williams inline std::string translateAddressOriginDbusToRedfish( 184bd79bce8SPatrick Williams const std::string& inputOrigin, bool isIPv4) 1851abe55efSEd Tanous { 1864a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1871abe55efSEd Tanous { 1884a0cb85cSEd Tanous return "Static"; 1899391bb9cSRapkiewicz, Pawel } 1904a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1911abe55efSEd Tanous { 1924a0cb85cSEd Tanous if (isIPv4) 1931abe55efSEd Tanous { 1944a0cb85cSEd Tanous return "IPv4LinkLocal"; 1951abe55efSEd Tanous } 1964a0cb85cSEd Tanous return "LinkLocal"; 1979391bb9cSRapkiewicz, Pawel } 1984a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1991abe55efSEd Tanous { 2004a0cb85cSEd Tanous if (isIPv4) 2014a0cb85cSEd Tanous { 2024a0cb85cSEd Tanous return "DHCP"; 2034a0cb85cSEd Tanous } 2044a0cb85cSEd Tanous return "DHCPv6"; 2054a0cb85cSEd Tanous } 2064a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 2074a0cb85cSEd Tanous { 2084a0cb85cSEd Tanous return "SLAAC"; 2094a0cb85cSEd Tanous } 2104a0cb85cSEd Tanous return ""; 2114a0cb85cSEd Tanous } 2124a0cb85cSEd Tanous 21302cad96eSEd Tanous inline bool extractEthernetInterfaceData( 21402cad96eSEd Tanous const std::string& ethifaceId, 21502cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 2164a0cb85cSEd Tanous EthernetInterfaceData& ethData) 2174a0cb85cSEd Tanous { 2184c9afe43SEd Tanous bool idFound = false; 21902cad96eSEd Tanous for (const auto& objpath : dbusData) 2204a0cb85cSEd Tanous { 22102cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 2224a0cb85cSEd Tanous { 22381ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 224029573d4SEd Tanous { 2254c9afe43SEd Tanous idFound = true; 2264a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2274a0cb85cSEd Tanous { 2284a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2294a0cb85cSEd Tanous { 2304a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2314a0cb85cSEd Tanous { 2324a0cb85cSEd Tanous const std::string* mac = 233abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2344a0cb85cSEd Tanous if (mac != nullptr) 2354a0cb85cSEd Tanous { 23682695a5bSJiaqing Zhao ethData.macAddress = *mac; 2374a0cb85cSEd Tanous } 2384a0cb85cSEd Tanous } 2394a0cb85cSEd Tanous } 2404a0cb85cSEd Tanous } 2414a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2424a0cb85cSEd Tanous { 2434a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2444a0cb85cSEd Tanous { 2454a0cb85cSEd Tanous if (propertyPair.first == "Id") 2464a0cb85cSEd Tanous { 2471b6b96c5SEd Tanous const uint32_t* id = 248abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2494a0cb85cSEd Tanous if (id != nullptr) 2504a0cb85cSEd Tanous { 25117e22024SJiaqing Zhao ethData.vlanId = *id; 2524a0cb85cSEd Tanous } 2534a0cb85cSEd Tanous } 2544a0cb85cSEd Tanous } 2554a0cb85cSEd Tanous } 2564a0cb85cSEd Tanous else if (ifacePair.first == 2574a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2584a0cb85cSEd Tanous { 2594a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2604a0cb85cSEd Tanous { 2614a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2624a0cb85cSEd Tanous { 2632c70f800SEd Tanous const bool* autoNeg = 264abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2652c70f800SEd Tanous if (autoNeg != nullptr) 2664a0cb85cSEd Tanous { 26782695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2684a0cb85cSEd Tanous } 2694a0cb85cSEd Tanous } 2704a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2714a0cb85cSEd Tanous { 2724a0cb85cSEd Tanous const uint32_t* speed = 273abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2744a0cb85cSEd Tanous if (speed != nullptr) 2754a0cb85cSEd Tanous { 2764a0cb85cSEd Tanous ethData.speed = *speed; 2774a0cb85cSEd Tanous } 2784a0cb85cSEd Tanous } 27935fb5311STejas Patil else if (propertyPair.first == "MTU") 28035fb5311STejas Patil { 2813e7a8da6SAnthony const size_t* mtuSize = 2823e7a8da6SAnthony std::get_if<size_t>(&propertyPair.second); 28335fb5311STejas Patil if (mtuSize != nullptr) 28435fb5311STejas Patil { 28535fb5311STejas Patil ethData.mtuSize = *mtuSize; 28635fb5311STejas Patil } 28735fb5311STejas Patil } 288aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 289aa05fb27SJohnathan Mantey { 290aa05fb27SJohnathan Mantey const bool* linkUp = 291aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 292aa05fb27SJohnathan Mantey if (linkUp != nullptr) 293aa05fb27SJohnathan Mantey { 294aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 295aa05fb27SJohnathan Mantey } 296aa05fb27SJohnathan Mantey } 297eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 298eeedda23SJohnathan Mantey { 299eeedda23SJohnathan Mantey const bool* nicEnabled = 300eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 301eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 302eeedda23SJohnathan Mantey { 303eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 304eeedda23SJohnathan Mantey } 305eeedda23SJohnathan Mantey } 306b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 307b10d8db0SRavi Teja { 308b10d8db0SRavi Teja const bool* ipv6AcceptRa = 309b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 310b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 311b10d8db0SRavi Teja { 312b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 313b10d8db0SRavi Teja } 314b10d8db0SRavi Teja } 315f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 316029573d4SEd Tanous { 317029573d4SEd Tanous const std::vector<std::string>* nameservers = 3188d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 319029573d4SEd Tanous &propertyPair.second); 320029573d4SEd Tanous if (nameservers != nullptr) 321029573d4SEd Tanous { 322f23b7296SEd Tanous ethData.nameServers = *nameservers; 3230f6efdc1Smanojkiran.eda@gmail.com } 3240f6efdc1Smanojkiran.eda@gmail.com } 3250f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3260f6efdc1Smanojkiran.eda@gmail.com { 3270f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3288d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3290f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3300f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3310f6efdc1Smanojkiran.eda@gmail.com { 332f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3334a0cb85cSEd Tanous } 3344a0cb85cSEd Tanous } 3352a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3362a133282Smanojkiraneda { 3372c70f800SEd Tanous const std::string* dhcpEnabled = 3381f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3392c70f800SEd Tanous if (dhcpEnabled != nullptr) 3402a133282Smanojkiraneda { 34182695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3422a133282Smanojkiraneda } 3432a133282Smanojkiraneda } 344d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 345d24bfc7aSJennifer Lee { 346d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3478d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 348d24bfc7aSJennifer Lee &propertyPair.second); 349d24bfc7aSJennifer Lee if (domainNames != nullptr) 350d24bfc7aSJennifer Lee { 351f23b7296SEd Tanous ethData.domainnames = *domainNames; 352d24bfc7aSJennifer Lee } 353d24bfc7aSJennifer Lee } 3549010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3559010ec2eSRavi Teja { 3569010ec2eSRavi Teja const std::string* defaultGateway = 3579010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3589010ec2eSRavi Teja if (defaultGateway != nullptr) 3599010ec2eSRavi Teja { 3609010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3619010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3629010ec2eSRavi Teja { 36382695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3649010ec2eSRavi Teja } 3659010ec2eSRavi Teja else 3669010ec2eSRavi Teja { 36782695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3689010ec2eSRavi Teja } 3699010ec2eSRavi Teja } 3709010ec2eSRavi Teja } 3719010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3729010ec2eSRavi Teja { 3739010ec2eSRavi Teja const std::string* defaultGateway6 = 3749010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3759010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3769010ec2eSRavi Teja { 3779010ec2eSRavi Teja std::string defaultGateway6Str = 3789010ec2eSRavi Teja *defaultGateway6; 3799010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3809010ec2eSRavi Teja { 38182695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3829010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3839010ec2eSRavi Teja } 3849010ec2eSRavi Teja else 3859010ec2eSRavi Teja { 38682695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3879010ec2eSRavi Teja defaultGateway6Str; 3889010ec2eSRavi Teja } 3899010ec2eSRavi Teja } 3909010ec2eSRavi Teja } 391029573d4SEd Tanous } 392029573d4SEd Tanous } 393029573d4SEd Tanous } 3941f8c7b5dSJohnathan Mantey 395e4588158SJishnu CM sdbusplus::message::object_path path( 396e4588158SJishnu CM "/xyz/openbmc_project/network"); 397bd79bce8SPatrick Williams sdbusplus::message::object_path dhcp4Path = 398bd79bce8SPatrick Williams path / ethifaceId / "dhcp4"; 399e4588158SJishnu CM 400e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp4Path) 4011f8c7b5dSJohnathan Mantey { 4021f8c7b5dSJohnathan Mantey if (ifacePair.first == 4031f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 4041f8c7b5dSJohnathan Mantey { 4051f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 4061f8c7b5dSJohnathan Mantey { 4071f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 4081f8c7b5dSJohnathan Mantey { 4092c70f800SEd Tanous const bool* dnsEnabled = 4101f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4112c70f800SEd Tanous if (dnsEnabled != nullptr) 4121f8c7b5dSJohnathan Mantey { 413e4588158SJishnu CM ethData.dnsv4Enabled = *dnsEnabled; 4141f8c7b5dSJohnathan Mantey } 4151f8c7b5dSJohnathan Mantey } 41691c441ecSRavi Teja else if (propertyPair.first == "DomainEnabled") 41791c441ecSRavi Teja { 41891c441ecSRavi Teja const bool* domainEnabled = 41991c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 42091c441ecSRavi Teja if (domainEnabled != nullptr) 42191c441ecSRavi Teja { 42291c441ecSRavi Teja ethData.domainv4Enabled = *domainEnabled; 42391c441ecSRavi Teja } 42491c441ecSRavi Teja } 4251f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 4261f8c7b5dSJohnathan Mantey { 4272c70f800SEd Tanous const bool* ntpEnabled = 4281f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4292c70f800SEd Tanous if (ntpEnabled != nullptr) 4301f8c7b5dSJohnathan Mantey { 431e4588158SJishnu CM ethData.ntpv4Enabled = *ntpEnabled; 4321f8c7b5dSJohnathan Mantey } 4331f8c7b5dSJohnathan Mantey } 4341f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 4351f8c7b5dSJohnathan Mantey { 4362c70f800SEd Tanous const bool* hostNameEnabled = 4371f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4382c70f800SEd Tanous if (hostNameEnabled != nullptr) 4391f8c7b5dSJohnathan Mantey { 440e4588158SJishnu CM ethData.hostNamev4Enabled = *hostNameEnabled; 441e4588158SJishnu CM } 442e4588158SJishnu CM } 443e4588158SJishnu CM } 444e4588158SJishnu CM } 445e4588158SJishnu CM } 446e4588158SJishnu CM 447bd79bce8SPatrick Williams sdbusplus::message::object_path dhcp6Path = 448bd79bce8SPatrick Williams path / ethifaceId / "dhcp6"; 449e4588158SJishnu CM 450e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp6Path) 451e4588158SJishnu CM { 452e4588158SJishnu CM if (ifacePair.first == 453e4588158SJishnu CM "xyz.openbmc_project.Network.DHCPConfiguration") 454e4588158SJishnu CM { 455e4588158SJishnu CM for (const auto& propertyPair : ifacePair.second) 456e4588158SJishnu CM { 457e4588158SJishnu CM if (propertyPair.first == "DNSEnabled") 458e4588158SJishnu CM { 459e4588158SJishnu CM const bool* dnsEnabled = 460e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 461e4588158SJishnu CM if (dnsEnabled != nullptr) 462e4588158SJishnu CM { 463e4588158SJishnu CM ethData.dnsv6Enabled = *dnsEnabled; 464e4588158SJishnu CM } 465e4588158SJishnu CM } 46691c441ecSRavi Teja if (propertyPair.first == "DomainEnabled") 46791c441ecSRavi Teja { 46891c441ecSRavi Teja const bool* domainEnabled = 46991c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 47091c441ecSRavi Teja if (domainEnabled != nullptr) 47191c441ecSRavi Teja { 47291c441ecSRavi Teja ethData.domainv6Enabled = *domainEnabled; 47391c441ecSRavi Teja } 47491c441ecSRavi Teja } 475e4588158SJishnu CM else if (propertyPair.first == "NTPEnabled") 476e4588158SJishnu CM { 477e4588158SJishnu CM const bool* ntpEnabled = 478e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 479e4588158SJishnu CM if (ntpEnabled != nullptr) 480e4588158SJishnu CM { 481e4588158SJishnu CM ethData.ntpv6Enabled = *ntpEnabled; 482e4588158SJishnu CM } 483e4588158SJishnu CM } 484e4588158SJishnu CM else if (propertyPair.first == "HostNameEnabled") 485e4588158SJishnu CM { 486e4588158SJishnu CM const bool* hostNameEnabled = 487e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 488e4588158SJishnu CM if (hostNameEnabled != nullptr) 489e4588158SJishnu CM { 490e4588158SJishnu CM ethData.hostNamev6Enabled = *hostNameEnabled; 4911f8c7b5dSJohnathan Mantey } 4921f8c7b5dSJohnathan Mantey } 4931f8c7b5dSJohnathan Mantey } 4941f8c7b5dSJohnathan Mantey } 4951f8c7b5dSJohnathan Mantey } 496029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 497029573d4SEd Tanous // to check eth number 498029573d4SEd Tanous if (ifacePair.first == 4994a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 5004a0cb85cSEd Tanous { 5014a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 5024a0cb85cSEd Tanous { 5034a0cb85cSEd Tanous if (propertyPair.first == "HostName") 5044a0cb85cSEd Tanous { 5054a0cb85cSEd Tanous const std::string* hostname = 5068d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 5074a0cb85cSEd Tanous if (hostname != nullptr) 5084a0cb85cSEd Tanous { 50982695a5bSJiaqing Zhao ethData.hostName = *hostname; 5104a0cb85cSEd Tanous } 5114a0cb85cSEd Tanous } 5124a0cb85cSEd Tanous } 5134a0cb85cSEd Tanous } 5144a0cb85cSEd Tanous } 5154a0cb85cSEd Tanous } 5164c9afe43SEd Tanous return idFound; 5174a0cb85cSEd Tanous } 5184a0cb85cSEd Tanous 519e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 52077179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 521711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 52277179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 523e48c0fc5SRavi Teja { 524bd79bce8SPatrick Williams const std::string ipPathStart = 525bd79bce8SPatrick Williams "/xyz/openbmc_project/network/" + ethifaceId; 526e48c0fc5SRavi Teja 527e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 528e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 52981ce609eSEd Tanous for (const auto& objpath : dbusData) 530e48c0fc5SRavi Teja { 531e48c0fc5SRavi Teja // Check if proper pattern for object path appears 532353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 533e48c0fc5SRavi Teja { 5349eb808c1SEd Tanous for (const auto& interface : objpath.second) 535e48c0fc5SRavi Teja { 536e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 537e48c0fc5SRavi Teja { 538bd79bce8SPatrick Williams auto type = std::ranges::find_if( 539bd79bce8SPatrick Williams interface.second, [](const auto& property) { 540353163e9STony Lee return property.first == "Type"; 541353163e9STony Lee }); 542353163e9STony Lee if (type == interface.second.end()) 543353163e9STony Lee { 544353163e9STony Lee continue; 545353163e9STony Lee } 546353163e9STony Lee 547353163e9STony Lee const std::string* typeStr = 548353163e9STony Lee std::get_if<std::string>(&type->second); 549353163e9STony Lee 550353163e9STony Lee if (typeStr == nullptr || 551353163e9STony Lee (*typeStr != 552353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 553353163e9STony Lee { 554353163e9STony Lee continue; 555353163e9STony Lee } 556353163e9STony Lee 557e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 558e48c0fc5SRavi Teja // appropriate 55977179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 5602c70f800SEd Tanous ipv6Address.id = 561353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5629eb808c1SEd Tanous for (const auto& property : interface.second) 563e48c0fc5SRavi Teja { 564e48c0fc5SRavi Teja if (property.first == "Address") 565e48c0fc5SRavi Teja { 566e48c0fc5SRavi Teja const std::string* address = 567e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 568e48c0fc5SRavi Teja if (address != nullptr) 569e48c0fc5SRavi Teja { 5702c70f800SEd Tanous ipv6Address.address = *address; 571e48c0fc5SRavi Teja } 572e48c0fc5SRavi Teja } 573e48c0fc5SRavi Teja else if (property.first == "Origin") 574e48c0fc5SRavi Teja { 575e48c0fc5SRavi Teja const std::string* origin = 576e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 577e48c0fc5SRavi Teja if (origin != nullptr) 578e48c0fc5SRavi Teja { 5792c70f800SEd Tanous ipv6Address.origin = 580e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 581e48c0fc5SRavi Teja false); 582e48c0fc5SRavi Teja } 583e48c0fc5SRavi Teja } 584e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 585e48c0fc5SRavi Teja { 586e48c0fc5SRavi Teja const uint8_t* prefix = 587e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 588e48c0fc5SRavi Teja if (prefix != nullptr) 589e48c0fc5SRavi Teja { 5902c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 591e48c0fc5SRavi Teja } 592e48c0fc5SRavi Teja } 593889ff694SAsmitha Karunanithi else if (property.first == "Type" || 594889ff694SAsmitha Karunanithi property.first == "Gateway") 595889ff694SAsmitha Karunanithi { 596889ff694SAsmitha Karunanithi // Type & Gateway is not used 597889ff694SAsmitha Karunanithi } 598e48c0fc5SRavi Teja else 599e48c0fc5SRavi Teja { 60062598e31SEd Tanous BMCWEB_LOG_ERROR( 60162598e31SEd Tanous "Got extra property: {} on the {} object", 60262598e31SEd Tanous property.first, objpath.first.str); 603e48c0fc5SRavi Teja } 604e48c0fc5SRavi Teja } 605e48c0fc5SRavi Teja } 606e48c0fc5SRavi Teja } 607e48c0fc5SRavi Teja } 608e48c0fc5SRavi Teja } 609e48c0fc5SRavi Teja } 610e48c0fc5SRavi Teja 6114a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 61277179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 613711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 61477179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 6154a0cb85cSEd Tanous { 616bd79bce8SPatrick Williams const std::string ipPathStart = 617bd79bce8SPatrick Williams "/xyz/openbmc_project/network/" + ethifaceId; 6184a0cb85cSEd Tanous 6194a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 6204a0cb85cSEd Tanous // single ethernet interface, loop over all of them 62181ce609eSEd Tanous for (const auto& objpath : dbusData) 6224a0cb85cSEd Tanous { 6234a0cb85cSEd Tanous // Check if proper pattern for object path appears 624353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 6254a0cb85cSEd Tanous { 6269eb808c1SEd Tanous for (const auto& interface : objpath.second) 6274a0cb85cSEd Tanous { 6284a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 6294a0cb85cSEd Tanous { 630bd79bce8SPatrick Williams auto type = std::ranges::find_if( 631bd79bce8SPatrick Williams interface.second, [](const auto& property) { 632353163e9STony Lee return property.first == "Type"; 633353163e9STony Lee }); 634353163e9STony Lee if (type == interface.second.end()) 635353163e9STony Lee { 636353163e9STony Lee continue; 637353163e9STony Lee } 638353163e9STony Lee 639353163e9STony Lee const std::string* typeStr = 640353163e9STony Lee std::get_if<std::string>(&type->second); 641353163e9STony Lee 642353163e9STony Lee if (typeStr == nullptr || 643353163e9STony Lee (*typeStr != 644353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 645353163e9STony Lee { 646353163e9STony Lee continue; 647353163e9STony Lee } 648353163e9STony Lee 6494a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 6504a0cb85cSEd Tanous // appropriate 65177179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 6522c70f800SEd Tanous ipv4Address.id = 653353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 6549eb808c1SEd Tanous for (const auto& property : interface.second) 6554a0cb85cSEd Tanous { 6564a0cb85cSEd Tanous if (property.first == "Address") 6574a0cb85cSEd Tanous { 6584a0cb85cSEd Tanous const std::string* address = 659abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6604a0cb85cSEd Tanous if (address != nullptr) 6614a0cb85cSEd Tanous { 6622c70f800SEd Tanous ipv4Address.address = *address; 6634a0cb85cSEd Tanous } 6644a0cb85cSEd Tanous } 6654a0cb85cSEd Tanous else if (property.first == "Origin") 6664a0cb85cSEd Tanous { 6674a0cb85cSEd Tanous const std::string* origin = 668abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6694a0cb85cSEd Tanous if (origin != nullptr) 6704a0cb85cSEd Tanous { 6712c70f800SEd Tanous ipv4Address.origin = 6724a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 6734a0cb85cSEd Tanous true); 6744a0cb85cSEd Tanous } 6754a0cb85cSEd Tanous } 6764a0cb85cSEd Tanous else if (property.first == "PrefixLength") 6774a0cb85cSEd Tanous { 6784a0cb85cSEd Tanous const uint8_t* mask = 679abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 6804a0cb85cSEd Tanous if (mask != nullptr) 6814a0cb85cSEd Tanous { 6824a0cb85cSEd Tanous // convert it to the string 6832c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 6844a0cb85cSEd Tanous } 6854a0cb85cSEd Tanous } 686889ff694SAsmitha Karunanithi else if (property.first == "Type" || 687889ff694SAsmitha Karunanithi property.first == "Gateway") 688889ff694SAsmitha Karunanithi { 689889ff694SAsmitha Karunanithi // Type & Gateway is not used 690889ff694SAsmitha Karunanithi } 6914a0cb85cSEd Tanous else 6924a0cb85cSEd Tanous { 69362598e31SEd Tanous BMCWEB_LOG_ERROR( 69462598e31SEd Tanous "Got extra property: {} on the {} object", 69562598e31SEd Tanous property.first, objpath.first.str); 6964a0cb85cSEd Tanous } 6974a0cb85cSEd Tanous } 6984a0cb85cSEd Tanous // Check if given address is local, or global 6992c70f800SEd Tanous ipv4Address.linktype = 70011ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 70118659d10SJohnathan Mantey ? LinkType::Local 70218659d10SJohnathan Mantey : LinkType::Global; 7034a0cb85cSEd Tanous } 7044a0cb85cSEd Tanous } 7054a0cb85cSEd Tanous } 7064a0cb85cSEd Tanous } 7074a0cb85cSEd Tanous } 708588c3f0dSKowalski, Kamil 709588c3f0dSKowalski, Kamil /** 710743eb1c0SJohnathan Mantey * @brief Modifies the default gateway assigned to the NIC 711743eb1c0SJohnathan Mantey * 712743eb1c0SJohnathan Mantey * @param[in] ifaceId Id of network interface whose default gateway is to be 713743eb1c0SJohnathan Mantey * changed 714743eb1c0SJohnathan Mantey * @param[in] gateway The new gateway value. Assigning an empty string 715743eb1c0SJohnathan Mantey * causes the gateway to be deleted 716743eb1c0SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 717743eb1c0SJohnathan Mantey * 718743eb1c0SJohnathan Mantey * @return None 719743eb1c0SJohnathan Mantey */ 720743eb1c0SJohnathan Mantey inline void updateIPv4DefaultGateway( 721743eb1c0SJohnathan Mantey const std::string& ifaceId, const std::string& gateway, 722743eb1c0SJohnathan Mantey const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 723743eb1c0SJohnathan Mantey { 724743eb1c0SJohnathan Mantey setDbusProperty( 725e93abac6SGinu George asyncResp, "Gateway", "xyz.openbmc_project.Network", 726743eb1c0SJohnathan Mantey sdbusplus::message::object_path("/xyz/openbmc_project/network") / 727743eb1c0SJohnathan Mantey ifaceId, 728743eb1c0SJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 729e93abac6SGinu George gateway); 730743eb1c0SJohnathan Mantey } 731743eb1c0SJohnathan Mantey 732743eb1c0SJohnathan Mantey /** 733743eb1c0SJohnathan Mantey * @brief Deletes given static IP address for the interface 734179db1d7SKowalski, Kamil * 735179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 736179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 737179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 738179db1d7SKowalski, Kamil * 739179db1d7SKowalski, Kamil * @return None 740179db1d7SKowalski, Kamil */ 7419c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 7429c5e585cSRavi Teja const std::string& ipHash, 7438d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7441abe55efSEd Tanous { 74555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7465e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 7471abe55efSEd Tanous if (ec) 7481abe55efSEd Tanous { 749a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7501abe55efSEd Tanous } 751179db1d7SKowalski, Kamil }, 752179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 7539c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 754179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 755179db1d7SKowalski, Kamil } 756179db1d7SKowalski, Kamil 757179db1d7SKowalski, Kamil /** 75801784826SJohnathan Mantey * @brief Creates a static IPv4 entry 759179db1d7SKowalski, Kamil * 76001784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 76101784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 76201784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 76301784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 764179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 765179db1d7SKowalski, Kamil * 766179db1d7SKowalski, Kamil * @return None 767179db1d7SKowalski, Kamil */ 768cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 769cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7708d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7711abe55efSEd Tanous { 772bd79bce8SPatrick Williams auto createIpHandler = 773bd79bce8SPatrick Williams [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) { 7741abe55efSEd Tanous if (ec) 7751abe55efSEd Tanous { 776a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7779010ec2eSRavi Teja return; 778179db1d7SKowalski, Kamil } 7799010ec2eSRavi Teja }; 7809010ec2eSRavi Teja 7819010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 7829010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 783179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 784179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 78501784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 786179db1d7SKowalski, Kamil gateway); 787179db1d7SKowalski, Kamil } 788e48c0fc5SRavi Teja 789e48c0fc5SRavi Teja /** 790743eb1c0SJohnathan Mantey * @brief Deletes the IP entry for this interface and creates a replacement 791743eb1c0SJohnathan Mantey * static entry 79201784826SJohnathan Mantey * 79301784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 79401784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 795743eb1c0SJohnathan Mantey * @param[in] prefixLength Prefix syntax for the subnet mask 796743eb1c0SJohnathan Mantey * @param[in] address Address to assign to this interface 797743eb1c0SJohnathan Mantey * @param[in] numStaticAddrs Count of IPv4 static addresses 79801784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 79901784826SJohnathan Mantey * 80001784826SJohnathan Mantey * @return None 80101784826SJohnathan Mantey */ 8029c5e585cSRavi Teja 8039c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 8049c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 8058d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 8069c5e585cSRavi Teja const std::string& gateway, 8078d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 80801784826SJohnathan Mantey { 80901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8109c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 8119c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 81201784826SJohnathan Mantey if (ec) 81301784826SJohnathan Mantey { 81401784826SJohnathan Mantey messages::internalError(asyncResp->res); 81501784826SJohnathan Mantey } 8169c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 8179c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 81801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8195e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 82023a21a1cSEd Tanous if (ec2) 82101784826SJohnathan Mantey { 82201784826SJohnathan Mantey messages::internalError(asyncResp->res); 82301784826SJohnathan Mantey } 82401784826SJohnathan Mantey }, 82501784826SJohnathan Mantey "xyz.openbmc_project.Network", 82601784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 827bd79bce8SPatrick Williams "xyz.openbmc_project.Network.IP.Create", "IP", protocol, 828bd79bce8SPatrick Williams address, prefixLength, gateway); 82901784826SJohnathan Mantey }, 83001784826SJohnathan Mantey "xyz.openbmc_project.Network", 8319c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 83201784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 83301784826SJohnathan Mantey } 83401784826SJohnathan Mantey 835ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData( 836ce73d5c8SSunitha Harish const std::string& ethifaceId, 837ce73d5c8SSunitha Harish const dbus::utility::ManagedObjectType& dbusData, 838ce73d5c8SSunitha Harish std::vector<StaticGatewayData>& staticGatewayConfig) 839ce73d5c8SSunitha Harish { 840ce73d5c8SSunitha Harish std::string staticGatewayPathStart("/xyz/openbmc_project/network/"); 841ce73d5c8SSunitha Harish staticGatewayPathStart += ethifaceId; 842ce73d5c8SSunitha Harish 843ce73d5c8SSunitha Harish for (const auto& objpath : dbusData) 844ce73d5c8SSunitha Harish { 845ce73d5c8SSunitha Harish if (!std::string_view(objpath.first.str) 846ce73d5c8SSunitha Harish .starts_with(staticGatewayPathStart)) 847ce73d5c8SSunitha Harish { 848ce73d5c8SSunitha Harish continue; 849ce73d5c8SSunitha Harish } 850ce73d5c8SSunitha Harish for (const auto& interface : objpath.second) 851ce73d5c8SSunitha Harish { 852ce73d5c8SSunitha Harish if (interface.first != "xyz.openbmc_project.Network.StaticGateway") 853ce73d5c8SSunitha Harish { 854ce73d5c8SSunitha Harish continue; 855ce73d5c8SSunitha Harish } 856ce73d5c8SSunitha Harish StaticGatewayData& staticGateway = 857ce73d5c8SSunitha Harish staticGatewayConfig.emplace_back(); 858ce73d5c8SSunitha Harish staticGateway.id = objpath.first.filename(); 859ce73d5c8SSunitha Harish 860ce73d5c8SSunitha Harish bool success = sdbusplus::unpackPropertiesNoThrow( 861ce73d5c8SSunitha Harish redfish::dbus_utils::UnpackErrorPrinter(), interface.second, 862ce73d5c8SSunitha Harish "Gateway", staticGateway.gateway, "PrefixLength", 863ce73d5c8SSunitha Harish staticGateway.prefixLength, "ProtocolType", 864ce73d5c8SSunitha Harish staticGateway.protocol); 865ce73d5c8SSunitha Harish if (!success) 866ce73d5c8SSunitha Harish { 867ce73d5c8SSunitha Harish return false; 868ce73d5c8SSunitha Harish } 869ce73d5c8SSunitha Harish } 870ce73d5c8SSunitha Harish } 871ce73d5c8SSunitha Harish return true; 872ce73d5c8SSunitha Harish } 873ce73d5c8SSunitha Harish 87401784826SJohnathan Mantey /** 875e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 876e48c0fc5SRavi Teja * 877e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 878e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 879e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 880e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 881e48c0fc5SRavi Teja * 882e48c0fc5SRavi Teja * @return None 883e48c0fc5SRavi Teja */ 88401784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 88501784826SJohnathan Mantey const std::string& address, 8868d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 887e48c0fc5SRavi Teja { 888ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 889ce73d5c8SSunitha Harish path /= ifaceId; 890ce73d5c8SSunitha Harish 891bd79bce8SPatrick Williams auto createIpHandler = 892bd79bce8SPatrick Williams [asyncResp, address](const boost::system::error_code& ec) { 893e48c0fc5SRavi Teja if (ec) 894e48c0fc5SRavi Teja { 895fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 896fc23ef8aSNitin Kumar Kotania { 897fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 898fc23ef8aSNitin Kumar Kotania "Address"); 899fc23ef8aSNitin Kumar Kotania } 900fc23ef8aSNitin Kumar Kotania else 901fc23ef8aSNitin Kumar Kotania { 902e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 903e48c0fc5SRavi Teja } 904fc23ef8aSNitin Kumar Kotania } 905e48c0fc5SRavi Teja }; 906ce73d5c8SSunitha Harish // Passing null for gateway, as per redfish spec IPv6StaticAddresses 907ce73d5c8SSunitha Harish // object does not have associated gateway property 908e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 909ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 910e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 911e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 912e48c0fc5SRavi Teja ""); 913e48c0fc5SRavi Teja } 914e48c0fc5SRavi Teja 915179db1d7SKowalski, Kamil /** 916ce73d5c8SSunitha Harish * @brief Deletes given IPv6 Static Gateway 917ce73d5c8SSunitha Harish * 918ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be deleted 919ce73d5c8SSunitha Harish * @param[in] ipHash DBus Hash id of IP that should be deleted 920ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 921ce73d5c8SSunitha Harish * 922ce73d5c8SSunitha Harish * @return None 923ce73d5c8SSunitha Harish */ 924ce73d5c8SSunitha Harish inline void 925739b27b2SRavi Teja deleteIPv6Gateway(std::string_view ifaceId, std::string_view gatewayId, 926ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 927ce73d5c8SSunitha Harish { 928ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 929739b27b2SRavi Teja path /= ifaceId; 930ce73d5c8SSunitha Harish path /= gatewayId; 931ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 932ce73d5c8SSunitha Harish [asyncResp](const boost::system::error_code& ec) { 933ce73d5c8SSunitha Harish if (ec) 934ce73d5c8SSunitha Harish { 935ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 936ce73d5c8SSunitha Harish } 937ce73d5c8SSunitha Harish }, 938ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 939ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 940ce73d5c8SSunitha Harish } 941ce73d5c8SSunitha Harish 942ce73d5c8SSunitha Harish /** 943ce73d5c8SSunitha Harish * @brief Creates IPv6 static default gateway with given data 944ce73d5c8SSunitha Harish * 945ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be added 946ce73d5c8SSunitha Harish * @param[in] prefixLength Prefix length that needs to be added 947ce73d5c8SSunitha Harish * @param[in] gateway Gateway address that needs to be added 948ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 949ce73d5c8SSunitha Harish * 950ce73d5c8SSunitha Harish * @return None 951ce73d5c8SSunitha Harish */ 952ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway( 953ce73d5c8SSunitha Harish std::string_view ifaceId, size_t prefixLength, std::string_view gateway, 954ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 955ce73d5c8SSunitha Harish { 956ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 957ce73d5c8SSunitha Harish path /= ifaceId; 958ce73d5c8SSunitha Harish auto createIpHandler = [asyncResp](const boost::system::error_code& ec) { 959ce73d5c8SSunitha Harish if (ec) 960ce73d5c8SSunitha Harish { 961ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 962ce73d5c8SSunitha Harish } 963ce73d5c8SSunitha Harish }; 964ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 965ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 966ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway", 967ce73d5c8SSunitha Harish gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6"); 968ce73d5c8SSunitha Harish } 969ce73d5c8SSunitha Harish 970ce73d5c8SSunitha Harish /** 971ce73d5c8SSunitha Harish * @brief Deletes the IPv6 default gateway entry for this interface and 972ce73d5c8SSunitha Harish * creates a replacement IPv6 default gateway entry 973ce73d5c8SSunitha Harish * 974ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface upon which to create the IPv6 975ce73d5c8SSunitha Harish * entry 976ce73d5c8SSunitha Harish * @param[in] gateway IPv6 gateway to assign to this interface 977ce73d5c8SSunitha Harish * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 978ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 979ce73d5c8SSunitha Harish * 980ce73d5c8SSunitha Harish * @return None 981ce73d5c8SSunitha Harish */ 982ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway( 983ce73d5c8SSunitha Harish std::string_view ifaceId, std::string_view gatewayId, 984ce73d5c8SSunitha Harish std::string_view gateway, size_t prefixLength, 985ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 986ce73d5c8SSunitha Harish { 987ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 988739b27b2SRavi Teja path /= ifaceId; 989ce73d5c8SSunitha Harish path /= gatewayId; 990ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 991ce73d5c8SSunitha Harish [asyncResp, ifaceId, gateway, 992ce73d5c8SSunitha Harish prefixLength](const boost::system::error_code& ec) { 993ce73d5c8SSunitha Harish if (ec) 994ce73d5c8SSunitha Harish { 995ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 996ce73d5c8SSunitha Harish return; 997ce73d5c8SSunitha Harish } 998ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp); 999ce73d5c8SSunitha Harish }, 1000ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 1001ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 1002ce73d5c8SSunitha Harish } 1003ce73d5c8SSunitha Harish 1004ce73d5c8SSunitha Harish /** 1005ce73d5c8SSunitha Harish * @brief Sets IPv6 default gateway with given data 1006ce73d5c8SSunitha Harish * 1007ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose gateway should be added 1008ce73d5c8SSunitha Harish * @param[in] input Contains address that needs to be added 1009ce73d5c8SSunitha Harish * @param[in] staticGatewayData Current static gateways in the system 1010ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 1011ce73d5c8SSunitha Harish * 1012ce73d5c8SSunitha Harish * @return None 1013ce73d5c8SSunitha Harish */ 1014ce73d5c8SSunitha Harish 1015ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway( 10163dfed536SEd Tanous const std::string& ifaceId, 10173dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1018ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& staticGatewayData, 1019ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1020ce73d5c8SSunitha Harish { 1021ce73d5c8SSunitha Harish size_t entryIdx = 1; 1022ce73d5c8SSunitha Harish std::vector<StaticGatewayData>::const_iterator staticGatewayEntry = 1023ce73d5c8SSunitha Harish staticGatewayData.begin(); 1024ce73d5c8SSunitha Harish 10253dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 10263dfed536SEd Tanous input) 1027ce73d5c8SSunitha Harish { 1028ce73d5c8SSunitha Harish // find the next gateway entry 1029ce73d5c8SSunitha Harish while (staticGatewayEntry != staticGatewayData.end()) 1030ce73d5c8SSunitha Harish { 1031ce73d5c8SSunitha Harish if (staticGatewayEntry->protocol == 1032ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.IP.Protocol.IPv6") 1033ce73d5c8SSunitha Harish { 1034ce73d5c8SSunitha Harish break; 1035ce73d5c8SSunitha Harish } 1036ce73d5c8SSunitha Harish staticGatewayEntry++; 1037ce73d5c8SSunitha Harish } 1038bd79bce8SPatrick Williams std::string pathString = 1039bd79bce8SPatrick Williams "IPv6StaticDefaultGateways/" + std::to_string(entryIdx); 10403dfed536SEd Tanous nlohmann::json::object_t* obj = 10413dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 10423dfed536SEd Tanous if (obj == nullptr) 1043ce73d5c8SSunitha Harish { 1044ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1045ce73d5c8SSunitha Harish { 1046ce73d5c8SSunitha Harish messages::resourceCannotBeDeleted(asyncResp->res); 1047ce73d5c8SSunitha Harish return; 1048ce73d5c8SSunitha Harish } 1049739b27b2SRavi Teja deleteIPv6Gateway(ifaceId, staticGatewayEntry->id, asyncResp); 1050ce73d5c8SSunitha Harish return; 1051ce73d5c8SSunitha Harish } 10523dfed536SEd Tanous if (obj->empty()) 1053ce73d5c8SSunitha Harish { 1054ce73d5c8SSunitha Harish // Do nothing, but make sure the entry exists. 1055ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1056ce73d5c8SSunitha Harish { 10573dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 1058ce73d5c8SSunitha Harish pathString); 1059ce73d5c8SSunitha Harish return; 1060ce73d5c8SSunitha Harish } 1061ce73d5c8SSunitha Harish } 1062ce73d5c8SSunitha Harish std::optional<std::string> address; 1063ce73d5c8SSunitha Harish std::optional<size_t> prefixLength; 1064ce73d5c8SSunitha Harish 10653dfed536SEd Tanous if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address, 10663dfed536SEd Tanous "PrefixLength", prefixLength)) 1067ce73d5c8SSunitha Harish { 1068ce73d5c8SSunitha Harish return; 1069ce73d5c8SSunitha Harish } 1070ce73d5c8SSunitha Harish const std::string* addr = nullptr; 1071ce73d5c8SSunitha Harish size_t prefix = 0; 1072ce73d5c8SSunitha Harish if (address) 1073ce73d5c8SSunitha Harish { 1074ce73d5c8SSunitha Harish addr = &(*address); 1075ce73d5c8SSunitha Harish } 1076ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1077ce73d5c8SSunitha Harish { 1078ce73d5c8SSunitha Harish addr = &(staticGatewayEntry->gateway); 1079ce73d5c8SSunitha Harish } 1080ce73d5c8SSunitha Harish else 1081ce73d5c8SSunitha Harish { 1082ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, pathString + "/Address"); 1083ce73d5c8SSunitha Harish return; 1084ce73d5c8SSunitha Harish } 1085ce73d5c8SSunitha Harish if (prefixLength) 1086ce73d5c8SSunitha Harish { 1087ce73d5c8SSunitha Harish prefix = *prefixLength; 1088ce73d5c8SSunitha Harish } 1089ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1090ce73d5c8SSunitha Harish { 1091ce73d5c8SSunitha Harish prefix = staticGatewayEntry->prefixLength; 1092ce73d5c8SSunitha Harish } 1093ce73d5c8SSunitha Harish else 1094ce73d5c8SSunitha Harish { 1095ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, 1096ce73d5c8SSunitha Harish pathString + "/PrefixLength"); 1097ce73d5c8SSunitha Harish return; 1098ce73d5c8SSunitha Harish } 1099ce73d5c8SSunitha Harish if (staticGatewayEntry != staticGatewayData.end()) 1100ce73d5c8SSunitha Harish { 1101ce73d5c8SSunitha Harish deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id, 1102ce73d5c8SSunitha Harish *addr, prefix, asyncResp); 1103ce73d5c8SSunitha Harish staticGatewayEntry++; 1104ce73d5c8SSunitha Harish } 1105ce73d5c8SSunitha Harish else 1106ce73d5c8SSunitha Harish { 1107ce73d5c8SSunitha Harish createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp); 1108ce73d5c8SSunitha Harish } 1109ce73d5c8SSunitha Harish entryIdx++; 1110ce73d5c8SSunitha Harish } 1111ce73d5c8SSunitha Harish } 1112ce73d5c8SSunitha Harish 1113ce73d5c8SSunitha Harish /** 1114179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 1115179db1d7SKowalski, Kamil * Object 1116179db1d7SKowalski, Kamil * from EntityManager Network Manager 11174a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 1118179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 1119179db1d7SKowalski, Kamil * into JSON 1120179db1d7SKowalski, Kamil */ 1121179db1d7SKowalski, Kamil template <typename CallbackFunc> 112281ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 11231abe55efSEd Tanous CallbackFunc&& callback) 11241abe55efSEd Tanous { 1125f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1126f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1127f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1128f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 11298cb2c024SEd Tanous callback = std::forward<CallbackFunc>(callback)]( 11308b24275dSEd Tanous const boost::system::error_code& ec, 11313dfed536SEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 113255c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 113377179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 113477179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 1135ce73d5c8SSunitha Harish std::vector<StaticGatewayData> ipv6GatewayData; 1136179db1d7SKowalski, Kamil 11378b24275dSEd Tanous if (ec) 11381abe55efSEd Tanous { 1139ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1140179db1d7SKowalski, Kamil return; 1141179db1d7SKowalski, Kamil } 1142179db1d7SKowalski, Kamil 1143bd79bce8SPatrick Williams bool found = 1144bd79bce8SPatrick Williams extractEthernetInterfaceData(ethifaceId, resp, ethData); 11454c9afe43SEd Tanous if (!found) 11464c9afe43SEd Tanous { 1147ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 11484c9afe43SEd Tanous return; 11494c9afe43SEd Tanous } 11504c9afe43SEd Tanous 11512c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 1152179db1d7SKowalski, Kamil // Fix global GW 11531abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 11541abe55efSEd Tanous { 1155c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 1156c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 11579010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 11581abe55efSEd Tanous { 115982695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 1160179db1d7SKowalski, Kamil } 1161179db1d7SKowalski, Kamil } 1162179db1d7SKowalski, Kamil 11632c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 1164bd79bce8SPatrick Williams if (!extractIPv6DefaultGatewayData(ethifaceId, resp, 1165bd79bce8SPatrick Williams ipv6GatewayData)) 1166ce73d5c8SSunitha Harish { 1167ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1168ce73d5c8SSunitha Harish } 11694e0453b1SGunnar Mills // Finally make a callback with useful data 1170ce73d5c8SSunitha Harish callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1171f5892d0dSGeorge Liu }); 1172271584abSEd Tanous } 1173179db1d7SKowalski, Kamil 1174179db1d7SKowalski, Kamil /** 11759391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 11769391bb9cSRapkiewicz, Pawel * Manager 11771abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 11781abe55efSEd Tanous * into JSON. 11799391bb9cSRapkiewicz, Pawel */ 11809391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 11811abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 11821abe55efSEd Tanous { 1183f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1184f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1185f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 11868cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 11878b24275dSEd Tanous const boost::system::error_code& ec, 1188f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 11891abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 11901abe55efSEd Tanous // ethernet interfaces 119177179532SEd Tanous std::vector<std::string> ifaceList; 11922c70f800SEd Tanous ifaceList.reserve(resp.size()); 11938b24275dSEd Tanous if (ec) 11941abe55efSEd Tanous { 11952c70f800SEd Tanous callback(false, ifaceList); 11969391bb9cSRapkiewicz, Pawel return; 11979391bb9cSRapkiewicz, Pawel } 11989391bb9cSRapkiewicz, Pawel 11999391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 12004a0cb85cSEd Tanous for (const auto& objpath : resp) 12011abe55efSEd Tanous { 12029391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 12034a0cb85cSEd Tanous for (const auto& interface : objpath.second) 12041abe55efSEd Tanous { 12051abe55efSEd Tanous // If interface is 12064a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 12074a0cb85cSEd Tanous // what we're looking for. 12089391bb9cSRapkiewicz, Pawel if (interface.first == 12091abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 12101abe55efSEd Tanous { 12112dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 12122dfd18efSEd Tanous if (ifaceId.empty()) 12131abe55efSEd Tanous { 12142dfd18efSEd Tanous continue; 12159391bb9cSRapkiewicz, Pawel } 12162dfd18efSEd Tanous // and put it into output vector. 121777179532SEd Tanous ifaceList.emplace_back(ifaceId); 12189391bb9cSRapkiewicz, Pawel } 12199391bb9cSRapkiewicz, Pawel } 12209391bb9cSRapkiewicz, Pawel } 12212c5875a2SEd Tanous 12223544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 12232c5875a2SEd Tanous 1224a434f2bdSEd Tanous // Finally make a callback with useful data 12252c70f800SEd Tanous callback(true, ifaceList); 1226f5892d0dSGeorge Liu }); 1227271584abSEd Tanous } 12289391bb9cSRapkiewicz, Pawel 12294f48d5f6SEd Tanous inline void 12304f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 12318d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12321abe55efSEd Tanous { 1233ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 1234ab6554f1SJoshi-Mansi if (hostname.length() > 255) 1235ab6554f1SJoshi-Mansi { 1236ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 1237ab6554f1SJoshi-Mansi "HostName"); 1238ab6554f1SJoshi-Mansi return; 1239ab6554f1SJoshi-Mansi } 1240d02aad39SEd Tanous setDbusProperty( 1241e93abac6SGinu George asyncResp, "HostName", "xyz.openbmc_project.Network", 1242d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network/config"), 1243d02aad39SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1244e93abac6SGinu George hostname); 1245588c3f0dSKowalski, Kamil } 1246588c3f0dSKowalski, Kamil 12474f48d5f6SEd Tanous inline void 124835fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 124935fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 125035fb5311STejas Patil { 1251d02aad39SEd Tanous sdbusplus::message::object_path objPath("/xyz/openbmc_project/network"); 1252d02aad39SEd Tanous objPath /= ifaceId; 1253e93abac6SGinu George setDbusProperty(asyncResp, "MTUSize", "xyz.openbmc_project.Network", 1254e93abac6SGinu George objPath, "xyz.openbmc_project.Network.EthernetInterface", 1255e93abac6SGinu George "MTU", mtuSize); 125635fb5311STejas Patil } 125735fb5311STejas Patil 1258bd79bce8SPatrick Williams inline void handleDomainnamePatch( 1259bd79bce8SPatrick Williams const std::string& ifaceId, const std::string& domainname, 12608d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1261ab6554f1SJoshi-Mansi { 1262ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 1263d02aad39SEd Tanous setDbusProperty( 1264e93abac6SGinu George asyncResp, "FQDN", "xyz.openbmc_project.Network", 1265d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1266d02aad39SEd Tanous ifaceId, 1267e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 1268d02aad39SEd Tanous vectorDomainname); 1269ab6554f1SJoshi-Mansi } 1270ab6554f1SJoshi-Mansi 12714f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1272bf648f77SEd Tanous { 1273bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 12743544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1275bf648f77SEd Tanous { 1276bf648f77SEd Tanous return false; 1277bf648f77SEd Tanous } 1278bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1279bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1280bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1281bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 12824b242749SEd Tanous const static std::regex pattern( 1283bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1284bf648f77SEd Tanous 1285bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1286bf648f77SEd Tanous } 1287bf648f77SEd Tanous 12884f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1289bf648f77SEd Tanous { 1290bf648f77SEd Tanous // Can have multiple subdomains 1291bf648f77SEd Tanous // Top Level Domain's min length is 2 character 12924b242749SEd Tanous const static std::regex pattern( 12930fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1294bf648f77SEd Tanous 1295bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1296bf648f77SEd Tanous } 1297bf648f77SEd Tanous 12984f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 12998d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1300ab6554f1SJoshi-Mansi { 1301ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1302ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1303ab6554f1SJoshi-Mansi { 1304ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1305ab6554f1SJoshi-Mansi return; 1306ab6554f1SJoshi-Mansi } 1307ab6554f1SJoshi-Mansi 1308ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1309ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1310ab6554f1SJoshi-Mansi { 1311ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1312ab6554f1SJoshi-Mansi return; 1313ab6554f1SJoshi-Mansi } 1314ab6554f1SJoshi-Mansi 1315ab6554f1SJoshi-Mansi std::string hostname; 1316ab6554f1SJoshi-Mansi std::string domainname; 1317ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1318ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1319ab6554f1SJoshi-Mansi 1320ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1321ab6554f1SJoshi-Mansi { 1322ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1323ab6554f1SJoshi-Mansi return; 1324ab6554f1SJoshi-Mansi } 1325ab6554f1SJoshi-Mansi 1326ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1327ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1328ab6554f1SJoshi-Mansi } 1329ab6554f1SJoshi-Mansi 1330bd79bce8SPatrick Williams inline void handleMACAddressPatch( 1331bd79bce8SPatrick Williams const std::string& ifaceId, const std::string& macAddress, 13328d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1333d577665bSRatan Gupta { 1334d02aad39SEd Tanous setDbusProperty( 1335e93abac6SGinu George asyncResp, "MACAddress", "xyz.openbmc_project.Network", 1336d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1337d02aad39SEd Tanous ifaceId, 1338e93abac6SGinu George "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress); 1339d577665bSRatan Gupta } 1340286b9118SJohnathan Mantey 13414f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 13424f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 13434f48d5f6SEd Tanous const bool v6Value, 13448d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1345da131a9aSJennifer Lee { 13462c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 1347d02aad39SEd Tanous setDbusProperty( 1348e93abac6SGinu George asyncResp, "DHCPv4", "xyz.openbmc_project.Network", 1349d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1350d02aad39SEd Tanous ifaceId, 1351e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp); 1352eeedda23SJohnathan Mantey } 1353eeedda23SJohnathan Mantey 1354e4588158SJishnu CM enum class NetworkType 1355e4588158SJishnu CM { 1356e4588158SJishnu CM dhcp4, 1357e4588158SJishnu CM dhcp6 1358e4588158SJishnu CM }; 1359e4588158SJishnu CM 1360e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1361e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1362e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1363da131a9aSJennifer Lee { 136462598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 13651847f2a0SAsmitha Karunanithi std::string redfishPropertyName; 1366e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1367e4588158SJishnu CM path /= ethifaceId; 1368e4588158SJishnu CM 1369e4588158SJishnu CM if (type == NetworkType::dhcp4) 1370e4588158SJishnu CM { 1371e4588158SJishnu CM path /= "dhcp4"; 13721847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv4"; 1373e4588158SJishnu CM } 1374e4588158SJishnu CM else 1375e4588158SJishnu CM { 1376e4588158SJishnu CM path /= "dhcp6"; 13771847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv6"; 1378e4588158SJishnu CM } 1379e4588158SJishnu CM 1380e93abac6SGinu George setDbusProperty( 1381e93abac6SGinu George asyncResp, redfishPropertyName, "xyz.openbmc_project.Network", path, 1382e93abac6SGinu George "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value); 1383da131a9aSJennifer Lee } 1384d577665bSRatan Gupta 1385b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1386b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1387b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1388b10d8db0SRavi Teja { 1389b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1390b10d8db0SRavi Teja path /= ifaceId; 1391e93abac6SGinu George setDbusProperty(asyncResp, 13921847f2a0SAsmitha Karunanithi "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 1393e93abac6SGinu George "xyz.openbmc_project.Network", path, 1394e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", 1395e93abac6SGinu George "IPv6AcceptRA", ipv6AutoConfigEnabled); 1396b10d8db0SRavi Teja } 1397b10d8db0SRavi Teja 1398bd79bce8SPatrick Williams inline void handleDHCPPatch( 1399bd79bce8SPatrick Williams const std::string& ifaceId, const EthernetInterfaceData& ethData, 1400bd79bce8SPatrick Williams const DHCPParameters& v4dhcpParms, const DHCPParameters& v6dhcpParms, 14018d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1402da131a9aSJennifer Lee { 140382695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 140482695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1405da131a9aSJennifer Lee 1406743eb1c0SJohnathan Mantey if (ipv4Active) 1407743eb1c0SJohnathan Mantey { 1408743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1409743eb1c0SJohnathan Mantey } 14101f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 14111f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 14121f8c7b5dSJohnathan Mantey 14131f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 14141f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1415da131a9aSJennifer Lee { 1416b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 14171f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 14181f8c7b5dSJohnathan Mantey { 1419bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1420bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 14211f8c7b5dSJohnathan Mantey "OperatingMode"); 1422da131a9aSJennifer Lee return; 1423da131a9aSJennifer Lee } 1424b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 14251f8c7b5dSJohnathan Mantey } 14261f8c7b5dSJohnathan Mantey else 1427da131a9aSJennifer Lee { 14281f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 14291f8c7b5dSJohnathan Mantey } 14301f8c7b5dSJohnathan Mantey 1431e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1432e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1433e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 14341f8c7b5dSJohnathan Mantey { 1435e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 14361f8c7b5dSJohnathan Mantey } 1437e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 14381f8c7b5dSJohnathan Mantey { 1439e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 14401f8c7b5dSJohnathan Mantey } 14411f8c7b5dSJohnathan Mantey 1442e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1443e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1444e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 14451f8c7b5dSJohnathan Mantey { 1446e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 14471f8c7b5dSJohnathan Mantey } 1448e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 14491f8c7b5dSJohnathan Mantey { 1450e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 14511f8c7b5dSJohnathan Mantey } 14521f8c7b5dSJohnathan Mantey 145391c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 145491c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1455e4588158SJishnu CM if (v4dhcpParms.useDomainName) 14561f8c7b5dSJohnathan Mantey { 1457e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 14581f8c7b5dSJohnathan Mantey } 1459e4588158SJishnu CM if (v6dhcpParms.useDomainName) 14601f8c7b5dSJohnathan Mantey { 1461e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 14621f8c7b5dSJohnathan Mantey } 14631f8c7b5dSJohnathan Mantey 146462598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 14651f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 14661f8c7b5dSJohnathan Mantey asyncResp); 146762598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1468e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1469e4588158SJishnu CM NetworkType::dhcp4); 147062598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1471e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1472e4588158SJishnu CM NetworkType::dhcp4); 147391c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 147491c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1475e4588158SJishnu CM NetworkType::dhcp4); 1476e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1477e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1478e4588158SJishnu CM NetworkType::dhcp6); 1479e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1480e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1481e4588158SJishnu CM NetworkType::dhcp6); 148291c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 148391c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1484e4588158SJishnu CM NetworkType::dhcp6); 1485da131a9aSJennifer Lee } 148601784826SJohnathan Mantey 148777179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 148877179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 148977179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 149001784826SJohnathan Mantey { 149117a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 149217a897dfSManojkiran Eda return value.origin == "Static"; 149317a897dfSManojkiran Eda }); 149401784826SJohnathan Mantey } 149501784826SJohnathan Mantey 149677179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 149777179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 149877179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 149901784826SJohnathan Mantey { 150017a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 150117a897dfSManojkiran Eda return value.origin == "Static"; 150217a897dfSManojkiran Eda }); 150301784826SJohnathan Mantey } 150401784826SJohnathan Mantey 15053dfed536SEd Tanous inline void handleIPv4StaticPatch( 15063dfed536SEd Tanous const std::string& ifaceId, 15073dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1508743eb1c0SJohnathan Mantey const EthernetInterfaceData& ethData, 150977179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 15108d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 15111abe55efSEd Tanous { 1512271584abSEd Tanous unsigned entryIdx = 1; 151301784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 151401784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 151501784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 151601784826SJohnathan Mantey // into the NIC. 151777179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 15182c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 151901784826SJohnathan Mantey 1520743eb1c0SJohnathan Mantey bool gatewayValueAssigned{}; 15214a8f5d43SJohnathan Mantey bool preserveGateway{}; 1522743eb1c0SJohnathan Mantey std::string activePath{}; 1523743eb1c0SJohnathan Mantey std::string activeGateway{}; 1524743eb1c0SJohnathan Mantey if (!ethData.defaultGateway.empty() && ethData.defaultGateway != "0.0.0.0") 1525743eb1c0SJohnathan Mantey { 1526743eb1c0SJohnathan Mantey // The NIC is already configured with a default gateway. Use this if 1527743eb1c0SJohnathan Mantey // the leading entry in the PATCH is '{}', which is preserving an active 1528743eb1c0SJohnathan Mantey // static address. 1529743eb1c0SJohnathan Mantey activeGateway = ethData.defaultGateway; 1530743eb1c0SJohnathan Mantey activePath = "IPv4StaticAddresses/1"; 1531743eb1c0SJohnathan Mantey gatewayValueAssigned = true; 1532743eb1c0SJohnathan Mantey } 1533743eb1c0SJohnathan Mantey 15343dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 15353dfed536SEd Tanous input) 15361abe55efSEd Tanous { 1537bd79bce8SPatrick Williams std::string pathString = 1538bd79bce8SPatrick Williams "IPv4StaticAddresses/" + std::to_string(entryIdx); 15393dfed536SEd Tanous nlohmann::json::object_t* obj = 15403dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 1541743eb1c0SJohnathan Mantey if (obj == nullptr) 1542743eb1c0SJohnathan Mantey { 1543743eb1c0SJohnathan Mantey if (nicIpEntry != ipv4Data.cend()) 1544743eb1c0SJohnathan Mantey { 1545743eb1c0SJohnathan Mantey deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 1546bd79bce8SPatrick Williams nicIpEntry = 1547bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv4Data.cend()); 15484a8f5d43SJohnathan Mantey if (!preserveGateway && (nicIpEntry == ipv4Data.cend())) 1549743eb1c0SJohnathan Mantey { 1550743eb1c0SJohnathan Mantey // All entries have been processed, and this last has 1551743eb1c0SJohnathan Mantey // requested the IP address be deleted. No prior entry 1552743eb1c0SJohnathan Mantey // performed an action that created or modified a 1553743eb1c0SJohnathan Mantey // gateway. Deleting this IP address means the default 1554743eb1c0SJohnathan Mantey // gateway entry has to be removed as well. 1555743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1556743eb1c0SJohnathan Mantey } 1557743eb1c0SJohnathan Mantey entryIdx++; 1558743eb1c0SJohnathan Mantey continue; 1559743eb1c0SJohnathan Mantey } 1560743eb1c0SJohnathan Mantey // Received a DELETE action on an entry not assigned to the NIC 1561743eb1c0SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 1562743eb1c0SJohnathan Mantey return; 1563743eb1c0SJohnathan Mantey } 1564743eb1c0SJohnathan Mantey 1565743eb1c0SJohnathan Mantey // An Add/Modify action is requested 1566743eb1c0SJohnathan Mantey if (!obj->empty()) 1567f476acbfSRatan Gupta { 1568537174c4SEd Tanous std::optional<std::string> address; 1569537174c4SEd Tanous std::optional<std::string> subnetMask; 1570537174c4SEd Tanous std::optional<std::string> gateway; 1571537174c4SEd Tanous 15723dfed536SEd Tanous if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", 15737e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 15747e27d832SJohnathan Mantey "Gateway", gateway)) 1575537174c4SEd Tanous { 15763dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 157771f52d96SEd Tanous pathString); 1578537174c4SEd Tanous return; 1579179db1d7SKowalski, Kamil } 1580179db1d7SKowalski, Kamil 158101784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 158201784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 158301784826SJohnathan Mantey // current state of the interface. Merge existing state into the 158401784826SJohnathan Mantey // current request. 1585537174c4SEd Tanous if (address) 15861abe55efSEd Tanous { 1587e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 158801784826SJohnathan Mantey { 1589bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1590bf648f77SEd Tanous pathString + "/Address"); 1591e01d0c36SEd Tanous return; 159201784826SJohnathan Mantey } 159301784826SJohnathan Mantey } 159485ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 159501784826SJohnathan Mantey { 1596e01d0c36SEd Tanous address = (nicIpEntry->address); 159701784826SJohnathan Mantey } 159801784826SJohnathan Mantey else 159901784826SJohnathan Mantey { 160001784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 160101784826SJohnathan Mantey pathString + "/Address"); 1602e01d0c36SEd Tanous return; 16034a0cb85cSEd Tanous } 16044a0cb85cSEd Tanous 1605e01d0c36SEd Tanous uint8_t prefixLength = 0; 1606537174c4SEd Tanous if (subnetMask) 16074a0cb85cSEd Tanous { 1608033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1609033f1e4dSEd Tanous &prefixLength)) 16104a0cb85cSEd Tanous { 1611f12894f8SJason M. Bills messages::propertyValueFormatError( 1612537174c4SEd Tanous asyncResp->res, *subnetMask, 16134a0cb85cSEd Tanous pathString + "/SubnetMask"); 1614e01d0c36SEd Tanous return; 16154a0cb85cSEd Tanous } 16164a0cb85cSEd Tanous } 161785ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 16184a0cb85cSEd Tanous { 1619033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 162001784826SJohnathan Mantey &prefixLength)) 16214a0cb85cSEd Tanous { 162201784826SJohnathan Mantey messages::propertyValueFormatError( 162385ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 162401784826SJohnathan Mantey pathString + "/SubnetMask"); 1625e01d0c36SEd Tanous return; 16264a0cb85cSEd Tanous } 16274a0cb85cSEd Tanous } 16281abe55efSEd Tanous else 16291abe55efSEd Tanous { 163001784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 163101784826SJohnathan Mantey pathString + "/SubnetMask"); 1632e01d0c36SEd Tanous return; 163301784826SJohnathan Mantey } 163401784826SJohnathan Mantey 163501784826SJohnathan Mantey if (gateway) 163601784826SJohnathan Mantey { 1637e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 163801784826SJohnathan Mantey { 1639bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1640bf648f77SEd Tanous pathString + "/Gateway"); 1641e01d0c36SEd Tanous return; 164201784826SJohnathan Mantey } 164301784826SJohnathan Mantey } 164485ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 164501784826SJohnathan Mantey { 1646e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 164701784826SJohnathan Mantey } 164801784826SJohnathan Mantey else 16491abe55efSEd Tanous { 1650a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 16514a0cb85cSEd Tanous pathString + "/Gateway"); 165201784826SJohnathan Mantey return; 16534a0cb85cSEd Tanous } 16544a0cb85cSEd Tanous 1655743eb1c0SJohnathan Mantey if (gatewayValueAssigned) 1656743eb1c0SJohnathan Mantey { 1657743eb1c0SJohnathan Mantey if (activeGateway != gateway) 1658743eb1c0SJohnathan Mantey { 1659743eb1c0SJohnathan Mantey // A NIC can only have a single active gateway value. 1660743eb1c0SJohnathan Mantey // If any gateway in the array of static addresses 1661743eb1c0SJohnathan Mantey // mismatch the PATCH is in error. 1662743eb1c0SJohnathan Mantey std::string arg1 = pathString + "/Gateway"; 1663743eb1c0SJohnathan Mantey std::string arg2 = activePath + "/Gateway"; 1664743eb1c0SJohnathan Mantey messages::propertyValueConflict(asyncResp->res, arg1, arg2); 1665743eb1c0SJohnathan Mantey return; 1666743eb1c0SJohnathan Mantey } 1667743eb1c0SJohnathan Mantey } 1668743eb1c0SJohnathan Mantey else 1669743eb1c0SJohnathan Mantey { 1670743eb1c0SJohnathan Mantey // Capture the very first gateway value from the incoming 1671743eb1c0SJohnathan Mantey // JSON record and use it at the default gateway. 1672743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, *gateway, asyncResp); 1673743eb1c0SJohnathan Mantey activeGateway = *gateway; 1674743eb1c0SJohnathan Mantey activePath = pathString; 1675743eb1c0SJohnathan Mantey gatewayValueAssigned = true; 1676743eb1c0SJohnathan Mantey } 1677743eb1c0SJohnathan Mantey 167885ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 16791abe55efSEd Tanous { 16809c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 168177eb0153SEd Tanous nicIpEntry->id, prefixLength, *address, 168277eb0153SEd Tanous *gateway, asyncResp); 1683bd79bce8SPatrick Williams nicIpEntry = 1684bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv4Data.cend()); 16854a8f5d43SJohnathan Mantey preserveGateway = true; 1686588c3f0dSKowalski, Kamil } 168701784826SJohnathan Mantey else 168801784826SJohnathan Mantey { 1689cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1690cb13a392SEd Tanous asyncResp); 16914a8f5d43SJohnathan Mantey preserveGateway = true; 16924a0cb85cSEd Tanous } 16934a0cb85cSEd Tanous entryIdx++; 16944a0cb85cSEd Tanous } 169501784826SJohnathan Mantey else 169601784826SJohnathan Mantey { 1697743eb1c0SJohnathan Mantey // Received {}, do not modify this address 169885ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 169901784826SJohnathan Mantey { 1700bd79bce8SPatrick Williams nicIpEntry = 1701bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv4Data.cend()); 17024a8f5d43SJohnathan Mantey preserveGateway = true; 170301784826SJohnathan Mantey entryIdx++; 170401784826SJohnathan Mantey } 1705743eb1c0SJohnathan Mantey else 1706743eb1c0SJohnathan Mantey { 1707743eb1c0SJohnathan Mantey // Requested a DO NOT MODIFY action on an entry not assigned 1708743eb1c0SJohnathan Mantey // to the NIC 1709743eb1c0SJohnathan Mantey messages::propertyValueFormatError(asyncResp->res, *obj, 1710743eb1c0SJohnathan Mantey pathString); 1711743eb1c0SJohnathan Mantey return; 1712743eb1c0SJohnathan Mantey } 1713743eb1c0SJohnathan Mantey } 171401784826SJohnathan Mantey } 17154a0cb85cSEd Tanous } 17164a0cb85cSEd Tanous 17174f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1718f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1719f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 17208d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1721f85837bfSRAJESWARAN THILLAIGOVINDAN { 17221847f2a0SAsmitha Karunanithi setDbusProperty( 1723e93abac6SGinu George asyncResp, "StaticNameServers", "xyz.openbmc_project.Network", 17241847f2a0SAsmitha Karunanithi sdbusplus::message::object_path("/xyz/openbmc_project/network") / 17251847f2a0SAsmitha Karunanithi ifaceId, 17269ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 1727e93abac6SGinu George updatedStaticNameServers); 1728f85837bfSRAJESWARAN THILLAIGOVINDAN } 1729f85837bfSRAJESWARAN THILLAIGOVINDAN 17304f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 17313dfed536SEd Tanous const std::string& ifaceId, 17323dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 173377179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 17348d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1735e48c0fc5SRavi Teja { 1736271584abSEd Tanous size_t entryIdx = 1; 173777179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 17382c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 17393dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 17403dfed536SEd Tanous input) 1741e48c0fc5SRavi Teja { 1742bd79bce8SPatrick Williams std::string pathString = 1743bd79bce8SPatrick Williams "IPv6StaticAddresses/" + std::to_string(entryIdx); 17443dfed536SEd Tanous nlohmann::json::object_t* obj = 17453dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 17463dfed536SEd Tanous if (obj != nullptr && !obj->empty()) 1747e48c0fc5SRavi Teja { 1748e48c0fc5SRavi Teja std::optional<std::string> address; 1749e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 17503dfed536SEd Tanous nlohmann::json::object_t thisJsonCopy = *obj; 17513dfed536SEd Tanous if (!json_util::readJsonObject(thisJsonCopy, asyncResp->res, 17523dfed536SEd Tanous "Address", address, "PrefixLength", 17533dfed536SEd Tanous prefixLength)) 1754e48c0fc5SRavi Teja { 17553dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJsonCopy, 175671f52d96SEd Tanous pathString); 1757e48c0fc5SRavi Teja return; 1758e48c0fc5SRavi Teja } 1759e48c0fc5SRavi Teja 176001784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 176101784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 176201784826SJohnathan Mantey // current state of the interface. Merge existing state into the 176301784826SJohnathan Mantey // current request. 1764d547d8d2SEd Tanous if (!address) 1765e48c0fc5SRavi Teja { 1766d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 176701784826SJohnathan Mantey { 176801784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 176901784826SJohnathan Mantey pathString + "/Address"); 177001784826SJohnathan Mantey return; 1771e48c0fc5SRavi Teja } 1772d547d8d2SEd Tanous address = nicIpEntry->address; 1773d547d8d2SEd Tanous } 1774e48c0fc5SRavi Teja 1775d547d8d2SEd Tanous if (!prefixLength) 1776e48c0fc5SRavi Teja { 1777d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 1778e48c0fc5SRavi Teja { 1779e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1780e48c0fc5SRavi Teja pathString + "/PrefixLength"); 178101784826SJohnathan Mantey return; 1782e48c0fc5SRavi Teja } 1783d547d8d2SEd Tanous prefixLength = nicIpEntry->prefixLength; 1784d547d8d2SEd Tanous } 1785e48c0fc5SRavi Teja 178685ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1787e48c0fc5SRavi Teja { 17889c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 1789d547d8d2SEd Tanous nicIpEntry->id, *prefixLength, 1790d547d8d2SEd Tanous *address, "", asyncResp); 1791bd79bce8SPatrick Williams nicIpEntry = 1792bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend()); 179301784826SJohnathan Mantey } 179401784826SJohnathan Mantey else 179501784826SJohnathan Mantey { 1796d547d8d2SEd Tanous createIPv6(ifaceId, *prefixLength, *address, asyncResp); 1797e48c0fc5SRavi Teja } 1798e48c0fc5SRavi Teja entryIdx++; 1799e48c0fc5SRavi Teja } 180001784826SJohnathan Mantey else 180101784826SJohnathan Mantey { 180285ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 180301784826SJohnathan Mantey { 180401784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 180501784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 180601784826SJohnathan Mantey // in error, so bail out. 18073dfed536SEd Tanous if (obj == nullptr) 180801784826SJohnathan Mantey { 180901784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 181001784826SJohnathan Mantey return; 181101784826SJohnathan Mantey } 18123dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 181371f52d96SEd Tanous pathString); 181401784826SJohnathan Mantey return; 181501784826SJohnathan Mantey } 181601784826SJohnathan Mantey 18173dfed536SEd Tanous if (obj == nullptr) 181801784826SJohnathan Mantey { 18199c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 182001784826SJohnathan Mantey } 182185ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 182201784826SJohnathan Mantey { 1823bd79bce8SPatrick Williams nicIpEntry = 1824bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend()); 182501784826SJohnathan Mantey } 182601784826SJohnathan Mantey entryIdx++; 182701784826SJohnathan Mantey } 182801784826SJohnathan Mantey } 1829e48c0fc5SRavi Teja } 1830e48c0fc5SRavi Teja 18317857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 18327857cb8dSJiaqing Zhao { 18337857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 18347857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 18357857cb8dSJiaqing Zhao } 18367857cb8dSJiaqing Zhao 1837bd79bce8SPatrick Williams inline void parseInterfaceData( 1838bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1839bd79bce8SPatrick Williams const std::string& ifaceId, const EthernetInterfaceData& ethData, 184077179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1841ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 1842ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) 18434a0cb85cSEd Tanous { 18442c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 184581ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1846253f11b8SEd Tanous jsonResponse["@odata.id"] = 1847253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 1848253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId); 18492c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1850eeedda23SJohnathan Mantey 1851eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1852eeedda23SJohnathan Mantey { 1853539d8c6bSEd Tanous jsonResponse["LinkStatus"] = 1854539d8c6bSEd Tanous ethData.linkUp ? ethernet_interface::LinkStatus::LinkUp 1855539d8c6bSEd Tanous : ethernet_interface::LinkStatus::LinkDown; 1856539d8c6bSEd Tanous jsonResponse["Status"]["State"] = resource::State::Enabled; 1857029573d4SEd Tanous } 1858029573d4SEd Tanous else 1859029573d4SEd Tanous { 1860539d8c6bSEd Tanous jsonResponse["LinkStatus"] = ethernet_interface::LinkStatus::NoLink; 1861539d8c6bSEd Tanous jsonResponse["Status"]["State"] = resource::State::Disabled; 1862029573d4SEd Tanous } 1863aa05fb27SJohnathan Mantey 18642c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 186535fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 1866*4652c640SAsmitha Karunanithi if (ethData.macAddress) 1867*4652c640SAsmitha Karunanithi { 1868*4652c640SAsmitha Karunanithi jsonResponse["MACAddress"] = *ethData.macAddress; 1869*4652c640SAsmitha Karunanithi } 18702c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 187182695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1872e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1873e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1874de9ad764SRavi Teja jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled; 18752c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1876bd79bce8SPatrick Williams translateDhcpEnabledToBool(ethData.dhcpEnabled, false) 1877bd79bce8SPatrick Williams ? "Enabled" 18781f8c7b5dSJohnathan Mantey : "Disabled"; 1879e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1880e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1881de9ad764SRavi Teja jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled; 1882b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1883b10d8db0SRavi Teja ethData.ipv6AcceptRa; 18842a133282Smanojkiraneda 188582695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 18864a0cb85cSEd Tanous { 188782695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1888ab6554f1SJoshi-Mansi 1889ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1890ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1891ab6554f1SJoshi-Mansi // FQDN 189282695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1893d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1894d24bfc7aSJennifer Lee { 18952c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1896d24bfc7aSJennifer Lee } 18972c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 18984a0cb85cSEd Tanous } 18994a0cb85cSEd Tanous 19007857cb8dSJiaqing Zhao if (ethData.vlanId) 19017857cb8dSJiaqing Zhao { 1902539d8c6bSEd Tanous jsonResponse["EthernetInterfaceType"] = 1903539d8c6bSEd Tanous ethernet_interface::EthernetDeviceType::Virtual; 19047857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 19057857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 19067857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 19077857cb8dSJiaqing Zhao 19087857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 19097857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 19107857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 1911253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces", 1912253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, 19137857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 19147857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 19157857cb8dSJiaqing Zhao std::move(relatedInterfaces); 19167857cb8dSJiaqing Zhao } 19177857cb8dSJiaqing Zhao else 19187857cb8dSJiaqing Zhao { 1919539d8c6bSEd Tanous jsonResponse["EthernetInterfaceType"] = 1920539d8c6bSEd Tanous ethernet_interface::EthernetDeviceType::Physical; 19217857cb8dSJiaqing Zhao } 19227857cb8dSJiaqing Zhao 19232c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 19242c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 19254a0cb85cSEd Tanous 19262c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 19272c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 19282c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 19292c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 19309eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 19314a0cb85cSEd Tanous { 19322c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1933fa5053a6SGunnar Mills if (gatewayStr.empty()) 1934fa5053a6SGunnar Mills { 1935fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1936fa5053a6SGunnar Mills } 19371476687dSEd Tanous nlohmann::json::object_t ipv4; 19381476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 19391476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 19401476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 19411476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1942fa5053a6SGunnar Mills 19432c70f800SEd Tanous if (ipv4Config.origin == "Static") 1944d1d50814SRavi Teja { 19451476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1946d1d50814SRavi Teja } 19471476687dSEd Tanous 1948b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 194901784826SJohnathan Mantey } 1950d1d50814SRavi Teja 195182695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 19527ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 19537ea79e5eSRavi Teja { 19547ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 19557ea79e5eSRavi Teja } 19567ea79e5eSRavi Teja 19577ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1958e48c0fc5SRavi Teja 1959ce73d5c8SSunitha Harish nlohmann::json::array_t ipv6StaticGatewayArray; 1960ce73d5c8SSunitha Harish for (const auto& ipv6GatewayConfig : ipv6GatewayData) 1961ce73d5c8SSunitha Harish { 1962ce73d5c8SSunitha Harish nlohmann::json::object_t ipv6Gateway; 1963ce73d5c8SSunitha Harish ipv6Gateway["Address"] = ipv6GatewayConfig.gateway; 1964ce73d5c8SSunitha Harish ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength; 1965ce73d5c8SSunitha Harish ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway)); 1966ce73d5c8SSunitha Harish } 1967ce73d5c8SSunitha Harish jsonResponse["IPv6StaticDefaultGateways"] = 1968ce73d5c8SSunitha Harish std::move(ipv6StaticGatewayArray); 1969ce73d5c8SSunitha Harish 19702c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 19712c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 19722c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 19732c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 19747f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 19752c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 19767f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 19779eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1978e48c0fc5SRavi Teja { 19791476687dSEd Tanous nlohmann::json::object_t ipv6; 19801476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 19811476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 19821476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1983f8361275SSunitha Harish 1984b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 19852c70f800SEd Tanous if (ipv6Config.origin == "Static") 1986e48c0fc5SRavi Teja { 19871476687dSEd Tanous nlohmann::json::object_t ipv6Static; 19881476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 19891476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 1990b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 199101784826SJohnathan Mantey } 1992e48c0fc5SRavi Teja } 1993588c3f0dSKowalski, Kamil } 1994588c3f0dSKowalski, Kamil 1995e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1996e7caf250SJiaqing Zhao const std::string& ifaceId, 1997e7caf250SJiaqing Zhao const boost::system::error_code& ec, 1998e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 1999e7caf250SJiaqing Zhao { 2000e7caf250SJiaqing Zhao if (!ec) 2001e7caf250SJiaqing Zhao { 2002e7caf250SJiaqing Zhao return; 2003e7caf250SJiaqing Zhao } 2004e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2005e7caf250SJiaqing Zhao if (dbusError == nullptr) 2006e7caf250SJiaqing Zhao { 2007e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2008e7caf250SJiaqing Zhao return; 2009e7caf250SJiaqing Zhao } 201062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2011e7caf250SJiaqing Zhao 2012e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 2013e7caf250SJiaqing Zhao dbusError->name) 2014e7caf250SJiaqing Zhao { 2015e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2016e7caf250SJiaqing Zhao ifaceId); 2017e7caf250SJiaqing Zhao return; 2018e7caf250SJiaqing Zhao } 2019e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 2020e7caf250SJiaqing Zhao dbusError->name) 2021e7caf250SJiaqing Zhao { 2022e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 2023e7caf250SJiaqing Zhao return; 2024e7caf250SJiaqing Zhao } 2025e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2026e7caf250SJiaqing Zhao } 2027e7caf250SJiaqing Zhao 2028bd79bce8SPatrick Williams inline void afterVlanCreate( 2029bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2030bd79bce8SPatrick Williams const std::string& parentInterfaceUri, const std::string& vlanInterface, 2031bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& m 2032b5ca3fdcSJiaqing Zhao 2033b5ca3fdcSJiaqing Zhao ) 2034b5ca3fdcSJiaqing Zhao { 2035b5ca3fdcSJiaqing Zhao if (ec) 2036b5ca3fdcSJiaqing Zhao { 2037b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2038b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 2039b5ca3fdcSJiaqing Zhao { 2040b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2041b5ca3fdcSJiaqing Zhao return; 2042b5ca3fdcSJiaqing Zhao } 204362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2044b5ca3fdcSJiaqing Zhao 2045b5ca3fdcSJiaqing Zhao if (std::string_view( 2046b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 2047b5ca3fdcSJiaqing Zhao dbusError->name) 2048b5ca3fdcSJiaqing Zhao { 2049b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2050b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2051b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2052b5ca3fdcSJiaqing Zhao return; 2053b5ca3fdcSJiaqing Zhao } 2054b5ca3fdcSJiaqing Zhao if (std::string_view( 2055b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 2056b5ca3fdcSJiaqing Zhao dbusError->name) 2057b5ca3fdcSJiaqing Zhao { 2058b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 2059b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 2060b5ca3fdcSJiaqing Zhao return; 2061b5ca3fdcSJiaqing Zhao } 2062b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2063b5ca3fdcSJiaqing Zhao return; 2064b5ca3fdcSJiaqing Zhao } 2065b5ca3fdcSJiaqing Zhao 2066253f11b8SEd Tanous const boost::urls::url vlanInterfaceUri = 2067253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2068253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface); 2069b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 2070b5ca3fdcSJiaqing Zhao } 2071b5ca3fdcSJiaqing Zhao 2072bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 2073bf648f77SEd Tanous { 2074253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2075ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 20761476687dSEd Tanous .methods(boost::beast::http::verb::get)( 20771476687dSEd Tanous [&app](const crow::Request& req, 2078253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2079253f11b8SEd Tanous const std::string& managerId) { 20803ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 208145ca1b86SEd Tanous { 208245ca1b86SEd Tanous return; 208345ca1b86SEd Tanous } 208445ca1b86SEd Tanous 2085253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2086253f11b8SEd Tanous { 2087bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2088bd79bce8SPatrick Williams managerId); 2089253f11b8SEd Tanous return; 2090253f11b8SEd Tanous } 2091253f11b8SEd Tanous 2092bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2093bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 2094bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2095bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/EthernetInterfaces", 2096253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2097bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 2098bf648f77SEd Tanous "Ethernet Network Interface Collection"; 2099bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 2100bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 2101bf648f77SEd Tanous 2102bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 2103bf648f77SEd Tanous // preparation 2104002d39b4SEd Tanous getEthernetIfaceList( 210577179532SEd Tanous [asyncResp](const bool& success, 210677179532SEd Tanous const std::vector<std::string>& ifaceList) { 2107bf648f77SEd Tanous if (!success) 21081abe55efSEd Tanous { 2109f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21109391bb9cSRapkiewicz, Pawel return; 21119391bb9cSRapkiewicz, Pawel } 21129391bb9cSRapkiewicz, Pawel 2113bd79bce8SPatrick Williams nlohmann::json& ifaceArray = 2114bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 2115bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 2116bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 2117bf648f77SEd Tanous { 21181476687dSEd Tanous nlohmann::json::object_t iface; 2119ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 2120253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2121253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem); 21227857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 2123bf648f77SEd Tanous } 2124bf648f77SEd Tanous 2125bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 2126bd79bce8SPatrick Williams ifaceArray.size(); 2127bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = 2128bd79bce8SPatrick Williams boost::urls::format( 2129253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces", 2130253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2131bf648f77SEd Tanous }); 2132bf648f77SEd Tanous }); 2133bf648f77SEd Tanous 2134253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2135b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 2136b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 2137b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 2138253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2139253f11b8SEd Tanous const std::string& managerId) { 2140b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2141b5ca3fdcSJiaqing Zhao { 2142b5ca3fdcSJiaqing Zhao return; 2143b5ca3fdcSJiaqing Zhao } 2144b5ca3fdcSJiaqing Zhao 2145253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2146253f11b8SEd Tanous { 2147bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2148bd79bce8SPatrick Williams managerId); 2149253f11b8SEd Tanous return; 2150253f11b8SEd Tanous } 2151253f11b8SEd Tanous 2152b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 2153b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 21543dfed536SEd Tanous std::vector<nlohmann::json::object_t> relatedInterfaces; 2155b5ca3fdcSJiaqing Zhao 2156bd79bce8SPatrick Williams if (!json_util::readJsonPatch( 2157bd79bce8SPatrick Williams req, asyncResp->res, "VLAN/VLANEnable", vlanEnable, 2158bd79bce8SPatrick Williams "VLAN/VLANId", vlanId, "Links/RelatedInterfaces", 2159b5ca3fdcSJiaqing Zhao relatedInterfaces)) 2160b5ca3fdcSJiaqing Zhao { 2161b5ca3fdcSJiaqing Zhao return; 2162b5ca3fdcSJiaqing Zhao } 2163b5ca3fdcSJiaqing Zhao 2164b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 2165b5ca3fdcSJiaqing Zhao { 2166b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 2167b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2168b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 2169b5ca3fdcSJiaqing Zhao return; 2170b5ca3fdcSJiaqing Zhao } 2171b5ca3fdcSJiaqing Zhao 2172b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 2173bd79bce8SPatrick Williams if (!json_util::readJsonObject(relatedInterfaces[0], 2174bd79bce8SPatrick Williams asyncResp->res, "@odata.id", 2175bd79bce8SPatrick Williams parentInterfaceUri)) 2176b5ca3fdcSJiaqing Zhao { 2177bd79bce8SPatrick Williams messages::propertyMissing( 2178bd79bce8SPatrick Williams asyncResp->res, "Links/RelatedInterfaces/0/@odata.id"); 2179b5ca3fdcSJiaqing Zhao return; 2180b5ca3fdcSJiaqing Zhao } 218162598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 2182b5ca3fdcSJiaqing Zhao 21836fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 2184b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 2185b5ca3fdcSJiaqing Zhao if (!parsedUri) 2186b5ca3fdcSJiaqing Zhao { 2187b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 2188b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2189b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2190b5ca3fdcSJiaqing Zhao return; 2191b5ca3fdcSJiaqing Zhao } 2192b5ca3fdcSJiaqing Zhao 2193b5ca3fdcSJiaqing Zhao std::string parentInterface; 2194b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 2195b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 2196b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 2197b5ca3fdcSJiaqing Zhao { 2198b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2199b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2200b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2201b5ca3fdcSJiaqing Zhao return; 2202b5ca3fdcSJiaqing Zhao } 2203b5ca3fdcSJiaqing Zhao 2204b5ca3fdcSJiaqing Zhao if (!vlanEnable) 2205b5ca3fdcSJiaqing Zhao { 2206b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 2207b5ca3fdcSJiaqing Zhao // create 2208bd79bce8SPatrick Williams messages::propertyValueIncorrect( 2209bd79bce8SPatrick Williams asyncResp->res, "VLAN/VLANEnable", "false"); 2210b5ca3fdcSJiaqing Zhao return; 2211b5ca3fdcSJiaqing Zhao } 2212b5ca3fdcSJiaqing Zhao 2213bd79bce8SPatrick Williams std::string vlanInterface = 2214bd79bce8SPatrick Williams parentInterface + "_" + std::to_string(vlanId); 2215b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 2216b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 2217b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 2218b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 2219bd79bce8SPatrick Williams afterVlanCreate(asyncResp, parentInterfaceUri, 2220bd79bce8SPatrick Williams vlanInterface, ec, m); 2221b5ca3fdcSJiaqing Zhao }, 2222bd79bce8SPatrick Williams "xyz.openbmc_project.Network", 2223bd79bce8SPatrick Williams "/xyz/openbmc_project/network", 2224bd79bce8SPatrick Williams "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 2225bd79bce8SPatrick Williams parentInterface, vlanId); 2226b5ca3fdcSJiaqing Zhao }); 2227b5ca3fdcSJiaqing Zhao 2228253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2229ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 2230bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 223145ca1b86SEd Tanous [&app](const crow::Request& req, 2232bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2233253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 22343ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 223545ca1b86SEd Tanous { 223645ca1b86SEd Tanous return; 223745ca1b86SEd Tanous } 2238253f11b8SEd Tanous 2239253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2240253f11b8SEd Tanous { 2241bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2242bd79bce8SPatrick Williams managerId); 2243253f11b8SEd Tanous return; 2244253f11b8SEd Tanous } 2245253f11b8SEd Tanous 22464a0cb85cSEd Tanous getEthernetIfaceData( 2247bf648f77SEd Tanous ifaceId, 2248bd79bce8SPatrick Williams [asyncResp, ifaceId]( 2249bd79bce8SPatrick Williams const bool& success, 2250bd79bce8SPatrick Williams const EthernetInterfaceData& ethData, 225177179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2252ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2253ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 22544a0cb85cSEd Tanous if (!success) 22551abe55efSEd Tanous { 2256bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2257bf648f77SEd Tanous // existing object, and other errors 2258bd79bce8SPatrick Williams messages::resourceNotFound( 2259bd79bce8SPatrick Williams asyncResp->res, "EthernetInterface", ifaceId); 22604a0cb85cSEd Tanous return; 22619391bb9cSRapkiewicz, Pawel } 22624c9afe43SEd Tanous 22630f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 226493bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2265bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2266bd79bce8SPatrick Williams "Manager Ethernet Interface"; 22670f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 22680f74e643SEd Tanous "Management Network Interface"; 22690f74e643SEd Tanous 2270bd79bce8SPatrick Williams parseInterfaceData(asyncResp, ifaceId, ethData, 2271bd79bce8SPatrick Williams ipv4Data, ipv6Data, ipv6GatewayData); 22729391bb9cSRapkiewicz, Pawel }); 2273bf648f77SEd Tanous }); 22749391bb9cSRapkiewicz, Pawel 2275253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2276ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2277bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 227845ca1b86SEd Tanous [&app](const crow::Request& req, 2279bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2280253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 22813ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 228245ca1b86SEd Tanous { 228345ca1b86SEd Tanous return; 228445ca1b86SEd Tanous } 2285253f11b8SEd Tanous 2286253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2287253f11b8SEd Tanous { 2288bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2289bd79bce8SPatrick Williams managerId); 2290253f11b8SEd Tanous return; 2291253f11b8SEd Tanous } 2292253f11b8SEd Tanous 2293bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2294ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2295d577665bSRatan Gupta std::optional<std::string> macAddress; 22969a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2297bd79bce8SPatrick Williams std::optional<std::vector< 2298bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 22993dfed536SEd Tanous ipv4StaticAddresses; 2300bd79bce8SPatrick Williams std::optional<std::vector< 2301bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23023dfed536SEd Tanous ipv6StaticAddresses; 2303bd79bce8SPatrick Williams std::optional<std::vector< 2304bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23053dfed536SEd Tanous ipv6StaticDefaultGateways; 2306f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2307b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2308eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 230935fb5311STejas Patil std::optional<size_t> mtuSize; 23101f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 23111f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2312b10d8db0SRavi Teja // clang-format off 23133dfed536SEd Tanous if (!json_util::readJsonPatch(req, asyncResp->res, 23143dfed536SEd Tanous "DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled, 23153dfed536SEd Tanous "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers, 23163dfed536SEd Tanous "DHCPv4/UseDomainName", v4dhcpParms.useDomainName, 23173dfed536SEd Tanous "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers, 23183dfed536SEd Tanous "DHCPv6/OperatingMode", v6dhcpParms.dhcpv6OperatingMode, 23193dfed536SEd Tanous "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers, 23203dfed536SEd Tanous "DHCPv6/UseDomainName", v6dhcpParms.useDomainName, 23213dfed536SEd Tanous "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers, 2322b10d8db0SRavi Teja "FQDN", fqdn, 2323b10d8db0SRavi Teja "HostName", hostname, 2324b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 2325b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 2326b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 2327ce73d5c8SSunitha Harish "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways, 2328b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 2329b10d8db0SRavi Teja "MACAddress", macAddress, 2330b10d8db0SRavi Teja "MTUSize", mtuSize, 2331b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 2332b10d8db0SRavi Teja "StaticNameServers", staticNameServers 2333b10d8db0SRavi Teja ) 2334b10d8db0SRavi Teja ) 23351abe55efSEd Tanous { 2336588c3f0dSKowalski, Kamil return; 2337588c3f0dSKowalski, Kamil } 2338b10d8db0SRavi Teja // clang-format on 2339da131a9aSJennifer Lee 2340bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2341bf648f77SEd Tanous // for JSON preparation 23424a0cb85cSEd Tanous getEthernetIfaceData( 23432c70f800SEd Tanous ifaceId, 2344bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2345ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2346d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 23479a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2348e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 2349bd79bce8SPatrick Williams ipv6StaticDefaultGateway = 2350bd79bce8SPatrick Williams std::move(ipv6StaticDefaultGateways), 23513dfed536SEd Tanous staticNameServers = std::move(staticNameServers), mtuSize, 2352bd79bce8SPatrick Williams ipv6AutoConfigEnabled, 2353bd79bce8SPatrick Williams v4dhcpParms = std::move(v4dhcpParms), 2354f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2355bd79bce8SPatrick Williams const bool success, 2356bd79bce8SPatrick Williams const EthernetInterfaceData& ethData, 235777179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2358ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2359bd79bce8SPatrick Williams const std::vector<StaticGatewayData>& 2360bd79bce8SPatrick Williams ipv6GatewayData) mutable { 23611abe55efSEd Tanous if (!success) 23621abe55efSEd Tanous { 2363588c3f0dSKowalski, Kamil // ... otherwise return error 2364bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2365bf648f77SEd Tanous // existing object, and other errors 2366bd79bce8SPatrick Williams messages::resourceNotFound( 2367bd79bce8SPatrick Williams asyncResp->res, "EthernetInterface", ifaceId); 2368588c3f0dSKowalski, Kamil return; 2369588c3f0dSKowalski, Kamil } 2370588c3f0dSKowalski, Kamil 2371bd79bce8SPatrick Williams handleDHCPPatch(ifaceId, ethData, v4dhcpParms, 2372bd79bce8SPatrick Williams v6dhcpParms, asyncResp); 23731f8c7b5dSJohnathan Mantey 23740627a2c7SEd Tanous if (hostname) 23751abe55efSEd Tanous { 23760627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 23771abe55efSEd Tanous } 23780627a2c7SEd Tanous 2379b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2380b10d8db0SRavi Teja { 2381bd79bce8SPatrick Williams handleSLAACAutoConfigPatch( 2382bd79bce8SPatrick Williams ifaceId, *ipv6AutoConfigEnabled, asyncResp); 2383b10d8db0SRavi Teja } 2384b10d8db0SRavi Teja 2385ab6554f1SJoshi-Mansi if (fqdn) 2386ab6554f1SJoshi-Mansi { 23872c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2388ab6554f1SJoshi-Mansi } 2389ab6554f1SJoshi-Mansi 2390d577665bSRatan Gupta if (macAddress) 2391d577665bSRatan Gupta { 2392bd79bce8SPatrick Williams handleMACAddressPatch(ifaceId, *macAddress, 2393bd79bce8SPatrick Williams asyncResp); 2394d577665bSRatan Gupta } 2395d577665bSRatan Gupta 2396d1d50814SRavi Teja if (ipv4StaticAddresses) 2397d1d50814SRavi Teja { 2398bd79bce8SPatrick Williams handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, 2399bd79bce8SPatrick Williams ethData, ipv4Data, asyncResp); 24001abe55efSEd Tanous } 24010627a2c7SEd Tanous 2402f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2403f85837bfSRAJESWARAN THILLAIGOVINDAN { 2404bd79bce8SPatrick Williams handleStaticNameServersPatch( 2405bd79bce8SPatrick Williams ifaceId, *staticNameServers, asyncResp); 2406f85837bfSRAJESWARAN THILLAIGOVINDAN } 24079a6fc6feSRavi Teja 24089a6fc6feSRavi Teja if (ipv6DefaultGateway) 24099a6fc6feSRavi Teja { 24109a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 24119a6fc6feSRavi Teja "IPv6DefaultGateway"); 24129a6fc6feSRavi Teja } 2413e48c0fc5SRavi Teja 2414e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2415e48c0fc5SRavi Teja { 2416bd79bce8SPatrick Williams handleIPv6StaticAddressesPatch(ifaceId, 2417bd79bce8SPatrick Williams *ipv6StaticAddresses, 2418ddd70dcaSEd Tanous ipv6Data, asyncResp); 2419e48c0fc5SRavi Teja } 2420eeedda23SJohnathan Mantey 2421ce73d5c8SSunitha Harish if (ipv6StaticDefaultGateway) 2422ce73d5c8SSunitha Harish { 2423bd79bce8SPatrick Williams handleIPv6DefaultGateway( 2424bd79bce8SPatrick Williams ifaceId, *ipv6StaticDefaultGateway, 2425ce73d5c8SSunitha Harish ipv6GatewayData, asyncResp); 2426ce73d5c8SSunitha Harish } 2427ce73d5c8SSunitha Harish 2428eeedda23SJohnathan Mantey if (interfaceEnabled) 2429eeedda23SJohnathan Mantey { 2430bd79bce8SPatrick Williams setDbusProperty( 2431bd79bce8SPatrick Williams asyncResp, "InterfaceEnabled", 2432e93abac6SGinu George "xyz.openbmc_project.Network", 2433d02aad39SEd Tanous sdbusplus::message::object_path( 2434d02aad39SEd Tanous "/xyz/openbmc_project/network") / 2435d02aad39SEd Tanous ifaceId, 2436d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", 2437e93abac6SGinu George "NICEnabled", *interfaceEnabled); 2438eeedda23SJohnathan Mantey } 243935fb5311STejas Patil 244035fb5311STejas Patil if (mtuSize) 244135fb5311STejas Patil { 244235fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 244335fb5311STejas Patil } 2444588c3f0dSKowalski, Kamil }); 2445bf648f77SEd Tanous }); 2446e7caf250SJiaqing Zhao 2447253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2448e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2449e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2450e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2451e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2452253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 2453e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2454e7caf250SJiaqing Zhao { 2455e7caf250SJiaqing Zhao return; 2456e7caf250SJiaqing Zhao } 2457e7caf250SJiaqing Zhao 2458253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2459253f11b8SEd Tanous { 2460bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2461bd79bce8SPatrick Williams managerId); 2462253f11b8SEd Tanous return; 2463253f11b8SEd Tanous } 2464253f11b8SEd Tanous 2465e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2466e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2467e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2468e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2469e7caf250SJiaqing Zhao }, 2470e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2471e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2472e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2473e7caf250SJiaqing Zhao }); 24744a0cb85cSEd Tanous } 2475bf648f77SEd Tanous 24769391bb9cSRapkiewicz, Pawel } // namespace redfish 2477