19391bb9cSRapkiewicz, Pawel /* 26be832e2SEd Tanous Copyright (c) 2018 Intel Corporation 36be832e2SEd Tanous 46be832e2SEd Tanous Licensed under the Apache License, Version 2.0 (the "License"); 56be832e2SEd Tanous you may not use this file except in compliance with the License. 66be832e2SEd Tanous You may obtain a copy of the License at 76be832e2SEd Tanous 86be832e2SEd Tanous http://www.apache.org/licenses/LICENSE-2.0 96be832e2SEd Tanous 106be832e2SEd Tanous Unless required by applicable law or agreed to in writing, software 116be832e2SEd Tanous distributed under the License is distributed on an "AS IS" BASIS, 126be832e2SEd Tanous WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136be832e2SEd Tanous See the License for the specific language governing permissions and 146be832e2SEd Tanous 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; 1214652c640SAsmitha 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, 862ab0d4390SRavi Teja "Gateway", staticGateway.gateway, "ProtocolType", 863ce73d5c8SSunitha Harish staticGateway.protocol); 864ce73d5c8SSunitha Harish if (!success) 865ce73d5c8SSunitha Harish { 866ce73d5c8SSunitha Harish return false; 867ce73d5c8SSunitha Harish } 868ce73d5c8SSunitha Harish } 869ce73d5c8SSunitha Harish } 870ce73d5c8SSunitha Harish return true; 871ce73d5c8SSunitha Harish } 872ce73d5c8SSunitha Harish 87301784826SJohnathan Mantey /** 874e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 875e48c0fc5SRavi Teja * 876e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 877e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 878e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 879e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 880e48c0fc5SRavi Teja * 881e48c0fc5SRavi Teja * @return None 882e48c0fc5SRavi Teja */ 88301784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 88401784826SJohnathan Mantey const std::string& address, 8858d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 886e48c0fc5SRavi Teja { 887ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 888ce73d5c8SSunitha Harish path /= ifaceId; 889ce73d5c8SSunitha Harish 890bd79bce8SPatrick Williams auto createIpHandler = 891bd79bce8SPatrick Williams [asyncResp, address](const boost::system::error_code& ec) { 892e48c0fc5SRavi Teja if (ec) 893e48c0fc5SRavi Teja { 894fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 895fc23ef8aSNitin Kumar Kotania { 896fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 897fc23ef8aSNitin Kumar Kotania "Address"); 898fc23ef8aSNitin Kumar Kotania } 899fc23ef8aSNitin Kumar Kotania else 900fc23ef8aSNitin Kumar Kotania { 901e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 902e48c0fc5SRavi Teja } 903fc23ef8aSNitin Kumar Kotania } 904e48c0fc5SRavi Teja }; 905ce73d5c8SSunitha Harish // Passing null for gateway, as per redfish spec IPv6StaticAddresses 906ce73d5c8SSunitha Harish // object does not have associated gateway property 907e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 908ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 909e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 910e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 911e48c0fc5SRavi Teja ""); 912e48c0fc5SRavi Teja } 913e48c0fc5SRavi Teja 914179db1d7SKowalski, Kamil /** 915ce73d5c8SSunitha Harish * @brief Deletes given IPv6 Static Gateway 916ce73d5c8SSunitha Harish * 917ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be deleted 918ce73d5c8SSunitha Harish * @param[in] ipHash DBus Hash id of IP that should be deleted 919ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 920ce73d5c8SSunitha Harish * 921ce73d5c8SSunitha Harish * @return None 922ce73d5c8SSunitha Harish */ 923ce73d5c8SSunitha Harish inline void 924739b27b2SRavi Teja deleteIPv6Gateway(std::string_view ifaceId, std::string_view gatewayId, 925ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 926ce73d5c8SSunitha Harish { 927ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 928739b27b2SRavi Teja path /= ifaceId; 929ce73d5c8SSunitha Harish path /= gatewayId; 930ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 931ce73d5c8SSunitha Harish [asyncResp](const boost::system::error_code& ec) { 932ce73d5c8SSunitha Harish if (ec) 933ce73d5c8SSunitha Harish { 934ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 935ce73d5c8SSunitha Harish } 936ce73d5c8SSunitha Harish }, 937ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 938ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 939ce73d5c8SSunitha Harish } 940ce73d5c8SSunitha Harish 941ce73d5c8SSunitha Harish /** 942ce73d5c8SSunitha Harish * @brief Creates IPv6 static default gateway with given data 943ce73d5c8SSunitha Harish * 944ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be added 945ce73d5c8SSunitha Harish * @param[in] gateway Gateway address that needs to be added 946ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 947ce73d5c8SSunitha Harish * 948ce73d5c8SSunitha Harish * @return None 949ce73d5c8SSunitha Harish */ 950ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway( 951ab0d4390SRavi Teja std::string_view ifaceId, std::string_view gateway, 952ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 953ce73d5c8SSunitha Harish { 954ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 955ce73d5c8SSunitha Harish path /= ifaceId; 956ce73d5c8SSunitha Harish auto createIpHandler = [asyncResp](const boost::system::error_code& ec) { 957ce73d5c8SSunitha Harish if (ec) 958ce73d5c8SSunitha Harish { 959ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 960ce73d5c8SSunitha Harish } 961ce73d5c8SSunitha Harish }; 962ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 963ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 964ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway", 965ab0d4390SRavi Teja gateway, "xyz.openbmc_project.Network.IP.Protocol.IPv6"); 966ce73d5c8SSunitha Harish } 967ce73d5c8SSunitha Harish 968ce73d5c8SSunitha Harish /** 969ce73d5c8SSunitha Harish * @brief Deletes the IPv6 default gateway entry for this interface and 970ce73d5c8SSunitha Harish * creates a replacement IPv6 default gateway entry 971ce73d5c8SSunitha Harish * 972ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface upon which to create the IPv6 973ce73d5c8SSunitha Harish * entry 974ce73d5c8SSunitha Harish * @param[in] gateway IPv6 gateway to assign to this interface 975ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 976ce73d5c8SSunitha Harish * 977ce73d5c8SSunitha Harish * @return None 978ce73d5c8SSunitha Harish */ 979ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway( 980ce73d5c8SSunitha Harish std::string_view ifaceId, std::string_view gatewayId, 981ab0d4390SRavi Teja std::string_view gateway, 982ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 983ce73d5c8SSunitha Harish { 984ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 985739b27b2SRavi Teja path /= ifaceId; 986ce73d5c8SSunitha Harish path /= gatewayId; 987ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 988ab0d4390SRavi Teja [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) { 989ce73d5c8SSunitha Harish if (ec) 990ce73d5c8SSunitha Harish { 991ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 992ce73d5c8SSunitha Harish return; 993ce73d5c8SSunitha Harish } 994ab0d4390SRavi Teja createIPv6DefaultGateway(ifaceId, gateway, asyncResp); 995ce73d5c8SSunitha Harish }, 996ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 997ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 998ce73d5c8SSunitha Harish } 999ce73d5c8SSunitha Harish 1000ce73d5c8SSunitha Harish /** 1001ce73d5c8SSunitha Harish * @brief Sets IPv6 default gateway with given data 1002ce73d5c8SSunitha Harish * 1003ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose gateway should be added 1004ce73d5c8SSunitha Harish * @param[in] input Contains address that needs to be added 1005ce73d5c8SSunitha Harish * @param[in] staticGatewayData Current static gateways in the system 1006ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 1007ce73d5c8SSunitha Harish * 1008ce73d5c8SSunitha Harish * @return None 1009ce73d5c8SSunitha Harish */ 1010ce73d5c8SSunitha Harish 1011ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway( 10123dfed536SEd Tanous const std::string& ifaceId, 10133dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1014ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& staticGatewayData, 1015ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1016ce73d5c8SSunitha Harish { 1017ce73d5c8SSunitha Harish size_t entryIdx = 1; 1018ce73d5c8SSunitha Harish std::vector<StaticGatewayData>::const_iterator staticGatewayEntry = 1019ce73d5c8SSunitha Harish staticGatewayData.begin(); 1020ce73d5c8SSunitha Harish 10213dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 10223dfed536SEd Tanous input) 1023ce73d5c8SSunitha Harish { 1024ce73d5c8SSunitha Harish // find the next gateway entry 1025ce73d5c8SSunitha Harish while (staticGatewayEntry != staticGatewayData.end()) 1026ce73d5c8SSunitha Harish { 1027ce73d5c8SSunitha Harish if (staticGatewayEntry->protocol == 1028ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.IP.Protocol.IPv6") 1029ce73d5c8SSunitha Harish { 1030ce73d5c8SSunitha Harish break; 1031ce73d5c8SSunitha Harish } 1032ce73d5c8SSunitha Harish staticGatewayEntry++; 1033ce73d5c8SSunitha Harish } 1034bd79bce8SPatrick Williams std::string pathString = 1035bd79bce8SPatrick Williams "IPv6StaticDefaultGateways/" + std::to_string(entryIdx); 10363dfed536SEd Tanous nlohmann::json::object_t* obj = 10373dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 10383dfed536SEd Tanous if (obj == nullptr) 1039ce73d5c8SSunitha Harish { 1040ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1041ce73d5c8SSunitha Harish { 1042ce73d5c8SSunitha Harish messages::resourceCannotBeDeleted(asyncResp->res); 1043ce73d5c8SSunitha Harish return; 1044ce73d5c8SSunitha Harish } 1045739b27b2SRavi Teja deleteIPv6Gateway(ifaceId, staticGatewayEntry->id, asyncResp); 1046ce73d5c8SSunitha Harish return; 1047ce73d5c8SSunitha Harish } 10483dfed536SEd Tanous if (obj->empty()) 1049ce73d5c8SSunitha Harish { 1050ce73d5c8SSunitha Harish // Do nothing, but make sure the entry exists. 1051ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1052ce73d5c8SSunitha Harish { 10533dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 1054ce73d5c8SSunitha Harish pathString); 1055ce73d5c8SSunitha Harish return; 1056ce73d5c8SSunitha Harish } 1057ce73d5c8SSunitha Harish } 1058ce73d5c8SSunitha Harish std::optional<std::string> address; 1059ce73d5c8SSunitha Harish 1060ab0d4390SRavi Teja if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", 1061ab0d4390SRavi Teja address)) 1062ce73d5c8SSunitha Harish { 1063ce73d5c8SSunitha Harish return; 1064ce73d5c8SSunitha Harish } 1065ce73d5c8SSunitha Harish const std::string* addr = nullptr; 1066ce73d5c8SSunitha Harish if (address) 1067ce73d5c8SSunitha Harish { 1068ce73d5c8SSunitha Harish addr = &(*address); 1069ce73d5c8SSunitha Harish } 1070ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1071ce73d5c8SSunitha Harish { 1072ce73d5c8SSunitha Harish addr = &(staticGatewayEntry->gateway); 1073ce73d5c8SSunitha Harish } 1074ce73d5c8SSunitha Harish else 1075ce73d5c8SSunitha Harish { 1076ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, pathString + "/Address"); 1077ce73d5c8SSunitha Harish return; 1078ce73d5c8SSunitha Harish } 1079ce73d5c8SSunitha Harish if (staticGatewayEntry != staticGatewayData.end()) 1080ce73d5c8SSunitha Harish { 1081ce73d5c8SSunitha Harish deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id, 1082ab0d4390SRavi Teja *addr, asyncResp); 1083ce73d5c8SSunitha Harish staticGatewayEntry++; 1084ce73d5c8SSunitha Harish } 1085ce73d5c8SSunitha Harish else 1086ce73d5c8SSunitha Harish { 1087ab0d4390SRavi Teja createIPv6DefaultGateway(ifaceId, *addr, asyncResp); 1088ce73d5c8SSunitha Harish } 1089ce73d5c8SSunitha Harish entryIdx++; 1090ce73d5c8SSunitha Harish } 1091ce73d5c8SSunitha Harish } 1092ce73d5c8SSunitha Harish 1093ce73d5c8SSunitha Harish /** 1094179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 1095179db1d7SKowalski, Kamil * Object 1096179db1d7SKowalski, Kamil * from EntityManager Network Manager 10974a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 1098179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 1099179db1d7SKowalski, Kamil * into JSON 1100179db1d7SKowalski, Kamil */ 1101179db1d7SKowalski, Kamil template <typename CallbackFunc> 110281ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 11031abe55efSEd Tanous CallbackFunc&& callback) 11041abe55efSEd Tanous { 1105f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1106f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1107f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1108f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 11098cb2c024SEd Tanous callback = std::forward<CallbackFunc>(callback)]( 11108b24275dSEd Tanous const boost::system::error_code& ec, 11113dfed536SEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 111255c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 111377179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 111477179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 1115ce73d5c8SSunitha Harish std::vector<StaticGatewayData> ipv6GatewayData; 1116179db1d7SKowalski, Kamil 11178b24275dSEd Tanous if (ec) 11181abe55efSEd Tanous { 1119ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1120179db1d7SKowalski, Kamil return; 1121179db1d7SKowalski, Kamil } 1122179db1d7SKowalski, Kamil 1123bd79bce8SPatrick Williams bool found = 1124bd79bce8SPatrick Williams extractEthernetInterfaceData(ethifaceId, resp, ethData); 11254c9afe43SEd Tanous if (!found) 11264c9afe43SEd Tanous { 1127ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 11284c9afe43SEd Tanous return; 11294c9afe43SEd Tanous } 11304c9afe43SEd Tanous 11312c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 1132179db1d7SKowalski, Kamil // Fix global GW 11331abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 11341abe55efSEd Tanous { 1135c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 1136c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 11379010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 11381abe55efSEd Tanous { 113982695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 1140179db1d7SKowalski, Kamil } 1141179db1d7SKowalski, Kamil } 1142179db1d7SKowalski, Kamil 11432c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 1144bd79bce8SPatrick Williams if (!extractIPv6DefaultGatewayData(ethifaceId, resp, 1145bd79bce8SPatrick Williams ipv6GatewayData)) 1146ce73d5c8SSunitha Harish { 1147ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1148ce73d5c8SSunitha Harish } 11494e0453b1SGunnar Mills // Finally make a callback with useful data 1150ce73d5c8SSunitha Harish callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1151f5892d0dSGeorge Liu }); 1152271584abSEd Tanous } 1153179db1d7SKowalski, Kamil 1154179db1d7SKowalski, Kamil /** 11559391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 11569391bb9cSRapkiewicz, Pawel * Manager 11571abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 11581abe55efSEd Tanous * into JSON. 11599391bb9cSRapkiewicz, Pawel */ 11609391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 11611abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 11621abe55efSEd Tanous { 1163f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1164f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1165f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 11668cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 11678b24275dSEd Tanous const boost::system::error_code& ec, 1168f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 11691abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 11701abe55efSEd Tanous // ethernet interfaces 117177179532SEd Tanous std::vector<std::string> ifaceList; 11722c70f800SEd Tanous ifaceList.reserve(resp.size()); 11738b24275dSEd Tanous if (ec) 11741abe55efSEd Tanous { 11752c70f800SEd Tanous callback(false, ifaceList); 11769391bb9cSRapkiewicz, Pawel return; 11779391bb9cSRapkiewicz, Pawel } 11789391bb9cSRapkiewicz, Pawel 11799391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 11804a0cb85cSEd Tanous for (const auto& objpath : resp) 11811abe55efSEd Tanous { 11829391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 11834a0cb85cSEd Tanous for (const auto& interface : objpath.second) 11841abe55efSEd Tanous { 11851abe55efSEd Tanous // If interface is 11864a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 11874a0cb85cSEd Tanous // what we're looking for. 11889391bb9cSRapkiewicz, Pawel if (interface.first == 11891abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 11901abe55efSEd Tanous { 11912dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 11922dfd18efSEd Tanous if (ifaceId.empty()) 11931abe55efSEd Tanous { 11942dfd18efSEd Tanous continue; 11959391bb9cSRapkiewicz, Pawel } 11962dfd18efSEd Tanous // and put it into output vector. 119777179532SEd Tanous ifaceList.emplace_back(ifaceId); 11989391bb9cSRapkiewicz, Pawel } 11999391bb9cSRapkiewicz, Pawel } 12009391bb9cSRapkiewicz, Pawel } 12012c5875a2SEd Tanous 12023544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 12032c5875a2SEd Tanous 1204a434f2bdSEd Tanous // Finally make a callback with useful data 12052c70f800SEd Tanous callback(true, ifaceList); 1206f5892d0dSGeorge Liu }); 1207271584abSEd Tanous } 12089391bb9cSRapkiewicz, Pawel 12094f48d5f6SEd Tanous inline void 12104f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 12118d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12121abe55efSEd Tanous { 1213ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 1214ab6554f1SJoshi-Mansi if (hostname.length() > 255) 1215ab6554f1SJoshi-Mansi { 1216ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 1217ab6554f1SJoshi-Mansi "HostName"); 1218ab6554f1SJoshi-Mansi return; 1219ab6554f1SJoshi-Mansi } 1220d02aad39SEd Tanous setDbusProperty( 1221e93abac6SGinu George asyncResp, "HostName", "xyz.openbmc_project.Network", 1222d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network/config"), 1223d02aad39SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1224e93abac6SGinu George hostname); 1225588c3f0dSKowalski, Kamil } 1226588c3f0dSKowalski, Kamil 12274f48d5f6SEd Tanous inline void 122835fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 122935fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 123035fb5311STejas Patil { 1231d02aad39SEd Tanous sdbusplus::message::object_path objPath("/xyz/openbmc_project/network"); 1232d02aad39SEd Tanous objPath /= ifaceId; 1233e93abac6SGinu George setDbusProperty(asyncResp, "MTUSize", "xyz.openbmc_project.Network", 1234e93abac6SGinu George objPath, "xyz.openbmc_project.Network.EthernetInterface", 1235e93abac6SGinu George "MTU", mtuSize); 123635fb5311STejas Patil } 123735fb5311STejas Patil 1238bd79bce8SPatrick Williams inline void handleDomainnamePatch( 1239bd79bce8SPatrick Williams const std::string& ifaceId, const std::string& domainname, 12408d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1241ab6554f1SJoshi-Mansi { 1242ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 1243d02aad39SEd Tanous setDbusProperty( 1244e93abac6SGinu George asyncResp, "FQDN", "xyz.openbmc_project.Network", 1245d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1246d02aad39SEd Tanous ifaceId, 1247e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 1248d02aad39SEd Tanous vectorDomainname); 1249ab6554f1SJoshi-Mansi } 1250ab6554f1SJoshi-Mansi 12514f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1252bf648f77SEd Tanous { 1253bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 12543544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1255bf648f77SEd Tanous { 1256bf648f77SEd Tanous return false; 1257bf648f77SEd Tanous } 1258bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1259bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1260bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1261bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 12624b242749SEd Tanous const static std::regex pattern( 1263bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1264bf648f77SEd Tanous 1265bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1266bf648f77SEd Tanous } 1267bf648f77SEd Tanous 12684f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1269bf648f77SEd Tanous { 1270bf648f77SEd Tanous // Can have multiple subdomains 1271bf648f77SEd Tanous // Top Level Domain's min length is 2 character 12724b242749SEd Tanous const static std::regex pattern( 12730fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1274bf648f77SEd Tanous 1275bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1276bf648f77SEd Tanous } 1277bf648f77SEd Tanous 12784f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 12798d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1280ab6554f1SJoshi-Mansi { 1281ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1282ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1283ab6554f1SJoshi-Mansi { 1284ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1285ab6554f1SJoshi-Mansi return; 1286ab6554f1SJoshi-Mansi } 1287ab6554f1SJoshi-Mansi 1288ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1289ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1290ab6554f1SJoshi-Mansi { 1291ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1292ab6554f1SJoshi-Mansi return; 1293ab6554f1SJoshi-Mansi } 1294ab6554f1SJoshi-Mansi 1295ab6554f1SJoshi-Mansi std::string hostname; 1296ab6554f1SJoshi-Mansi std::string domainname; 1297ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1298ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1299ab6554f1SJoshi-Mansi 1300ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1301ab6554f1SJoshi-Mansi { 1302ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1303ab6554f1SJoshi-Mansi return; 1304ab6554f1SJoshi-Mansi } 1305ab6554f1SJoshi-Mansi 1306ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1307ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1308ab6554f1SJoshi-Mansi } 1309ab6554f1SJoshi-Mansi 1310bd79bce8SPatrick Williams inline void handleMACAddressPatch( 1311bd79bce8SPatrick Williams const std::string& ifaceId, const std::string& macAddress, 13128d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1313d577665bSRatan Gupta { 1314d02aad39SEd Tanous setDbusProperty( 1315e93abac6SGinu George asyncResp, "MACAddress", "xyz.openbmc_project.Network", 1316d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1317d02aad39SEd Tanous ifaceId, 1318e93abac6SGinu George "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress); 1319d577665bSRatan Gupta } 1320286b9118SJohnathan Mantey 13214f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 13224f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 13234f48d5f6SEd Tanous const bool v6Value, 13248d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1325da131a9aSJennifer Lee { 13262c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 1327d02aad39SEd Tanous setDbusProperty( 1328e93abac6SGinu George asyncResp, "DHCPv4", "xyz.openbmc_project.Network", 1329d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1330d02aad39SEd Tanous ifaceId, 1331e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp); 1332eeedda23SJohnathan Mantey } 1333eeedda23SJohnathan Mantey 1334e4588158SJishnu CM enum class NetworkType 1335e4588158SJishnu CM { 1336e4588158SJishnu CM dhcp4, 1337e4588158SJishnu CM dhcp6 1338e4588158SJishnu CM }; 1339e4588158SJishnu CM 1340e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1341e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1342e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1343da131a9aSJennifer Lee { 134462598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 13451847f2a0SAsmitha Karunanithi std::string redfishPropertyName; 1346e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1347e4588158SJishnu CM path /= ethifaceId; 1348e4588158SJishnu CM 1349e4588158SJishnu CM if (type == NetworkType::dhcp4) 1350e4588158SJishnu CM { 1351e4588158SJishnu CM path /= "dhcp4"; 13521847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv4"; 1353e4588158SJishnu CM } 1354e4588158SJishnu CM else 1355e4588158SJishnu CM { 1356e4588158SJishnu CM path /= "dhcp6"; 13571847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv6"; 1358e4588158SJishnu CM } 1359e4588158SJishnu CM 1360e93abac6SGinu George setDbusProperty( 1361e93abac6SGinu George asyncResp, redfishPropertyName, "xyz.openbmc_project.Network", path, 1362e93abac6SGinu George "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value); 1363da131a9aSJennifer Lee } 1364d577665bSRatan Gupta 1365b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1366b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1367b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1368b10d8db0SRavi Teja { 1369b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1370b10d8db0SRavi Teja path /= ifaceId; 1371e93abac6SGinu George setDbusProperty(asyncResp, 13721847f2a0SAsmitha Karunanithi "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 1373e93abac6SGinu George "xyz.openbmc_project.Network", path, 1374e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", 1375e93abac6SGinu George "IPv6AcceptRA", ipv6AutoConfigEnabled); 1376b10d8db0SRavi Teja } 1377b10d8db0SRavi Teja 1378bd79bce8SPatrick Williams inline void handleDHCPPatch( 1379bd79bce8SPatrick Williams const std::string& ifaceId, const EthernetInterfaceData& ethData, 1380bd79bce8SPatrick Williams const DHCPParameters& v4dhcpParms, const DHCPParameters& v6dhcpParms, 13818d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1382da131a9aSJennifer Lee { 138382695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 138482695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1385da131a9aSJennifer Lee 1386743eb1c0SJohnathan Mantey if (ipv4Active) 1387743eb1c0SJohnathan Mantey { 1388743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1389743eb1c0SJohnathan Mantey } 13901f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 13911f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 13921f8c7b5dSJohnathan Mantey 13931f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 13941f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1395da131a9aSJennifer Lee { 1396b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 13971f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 13981f8c7b5dSJohnathan Mantey { 1399bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1400bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 14011f8c7b5dSJohnathan Mantey "OperatingMode"); 1402da131a9aSJennifer Lee return; 1403da131a9aSJennifer Lee } 1404b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 14051f8c7b5dSJohnathan Mantey } 14061f8c7b5dSJohnathan Mantey else 1407da131a9aSJennifer Lee { 14081f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 14091f8c7b5dSJohnathan Mantey } 14101f8c7b5dSJohnathan Mantey 1411e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1412e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1413e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 14141f8c7b5dSJohnathan Mantey { 1415e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 14161f8c7b5dSJohnathan Mantey } 1417e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 14181f8c7b5dSJohnathan Mantey { 1419e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 14201f8c7b5dSJohnathan Mantey } 14211f8c7b5dSJohnathan Mantey 1422e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1423e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1424e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 14251f8c7b5dSJohnathan Mantey { 1426e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 14271f8c7b5dSJohnathan Mantey } 1428e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 14291f8c7b5dSJohnathan Mantey { 1430e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 14311f8c7b5dSJohnathan Mantey } 14321f8c7b5dSJohnathan Mantey 143391c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 143491c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1435e4588158SJishnu CM if (v4dhcpParms.useDomainName) 14361f8c7b5dSJohnathan Mantey { 1437e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 14381f8c7b5dSJohnathan Mantey } 1439e4588158SJishnu CM if (v6dhcpParms.useDomainName) 14401f8c7b5dSJohnathan Mantey { 1441e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 14421f8c7b5dSJohnathan Mantey } 14431f8c7b5dSJohnathan Mantey 144462598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 14451f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 14461f8c7b5dSJohnathan Mantey asyncResp); 144762598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1448e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1449e4588158SJishnu CM NetworkType::dhcp4); 145062598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1451e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1452e4588158SJishnu CM NetworkType::dhcp4); 145391c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 145491c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1455e4588158SJishnu CM NetworkType::dhcp4); 1456e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1457e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1458e4588158SJishnu CM NetworkType::dhcp6); 1459e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1460e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1461e4588158SJishnu CM NetworkType::dhcp6); 146291c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 146391c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1464e4588158SJishnu CM NetworkType::dhcp6); 1465da131a9aSJennifer Lee } 146601784826SJohnathan Mantey 146777179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 146877179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 146977179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 147001784826SJohnathan Mantey { 147117a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 147217a897dfSManojkiran Eda return value.origin == "Static"; 147317a897dfSManojkiran Eda }); 147401784826SJohnathan Mantey } 147501784826SJohnathan Mantey 147677179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 147777179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 147877179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 147901784826SJohnathan Mantey { 148017a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 148117a897dfSManojkiran Eda return value.origin == "Static"; 148217a897dfSManojkiran Eda }); 148301784826SJohnathan Mantey } 148401784826SJohnathan Mantey 1485*6e1a52faSEd Tanous enum class AddrChange 14861abe55efSEd Tanous { 1487*6e1a52faSEd Tanous Noop, 1488*6e1a52faSEd Tanous Delete, 1489*6e1a52faSEd Tanous Update, 1490*6e1a52faSEd Tanous }; 1491*6e1a52faSEd Tanous 1492*6e1a52faSEd Tanous // Struct representing a dbus change 1493*6e1a52faSEd Tanous struct AddressPatch 1494*6e1a52faSEd Tanous { 1495*6e1a52faSEd Tanous std::string address; 1496*6e1a52faSEd Tanous std::string gateway; 1497*6e1a52faSEd Tanous uint8_t prefixLength = 0; 1498*6e1a52faSEd Tanous std::string existingDbusId; 1499*6e1a52faSEd Tanous AddrChange operation = AddrChange::Noop; 1500*6e1a52faSEd Tanous }; 1501*6e1a52faSEd Tanous 1502*6e1a52faSEd Tanous inline bool parseAddresses( 1503*6e1a52faSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1504*6e1a52faSEd Tanous const std::vector<IPv4AddressData>& ipv4Data, crow::Response& res, 1505*6e1a52faSEd Tanous std::vector<AddressPatch>& addressesOut, std::string& gatewayOut) 1506*6e1a52faSEd Tanous { 150777179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 15082c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 150901784826SJohnathan Mantey 1510*6e1a52faSEd Tanous std::string lastGatewayPath; 1511*6e1a52faSEd Tanous size_t entryIdx = 0; 15123dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 15133dfed536SEd Tanous input) 15141abe55efSEd Tanous { 1515bd79bce8SPatrick Williams std::string pathString = 1516*6e1a52faSEd Tanous std::format("IPv4StaticAddresses/{}", entryIdx); 1517*6e1a52faSEd Tanous AddressPatch& thisAddress = addressesOut.emplace_back(); 15183dfed536SEd Tanous nlohmann::json::object_t* obj = 15193dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 1520743eb1c0SJohnathan Mantey if (nicIpEntry != ipv4Data.cend()) 1521743eb1c0SJohnathan Mantey { 1522*6e1a52faSEd Tanous thisAddress.existingDbusId = nicIpEntry->id; 1523743eb1c0SJohnathan Mantey } 1524743eb1c0SJohnathan Mantey 1525*6e1a52faSEd Tanous if (obj == nullptr) 1526*6e1a52faSEd Tanous { 1527*6e1a52faSEd Tanous if (thisAddress.existingDbusId.empty()) 1528*6e1a52faSEd Tanous { 1529*6e1a52faSEd Tanous // Received a DELETE action on an entry not assigned to the NIC 1530*6e1a52faSEd Tanous messages::resourceCannotBeDeleted(res); 1531*6e1a52faSEd Tanous return false; 1532*6e1a52faSEd Tanous } 1533*6e1a52faSEd Tanous thisAddress.operation = AddrChange::Delete; 1534*6e1a52faSEd Tanous } 1535*6e1a52faSEd Tanous else 1536f476acbfSRatan Gupta { 1537537174c4SEd Tanous std::optional<std::string> address; 1538537174c4SEd Tanous std::optional<std::string> gateway; 1539*6e1a52faSEd Tanous std::optional<std::string> subnetMask; 1540*6e1a52faSEd Tanous if (!obj->empty()) 1541*6e1a52faSEd Tanous { 1542afc474aeSMyung Bae if (!json_util::readJsonObject( // 1543*6e1a52faSEd Tanous *obj, res, // 1544afc474aeSMyung Bae "Address", address, // 1545afc474aeSMyung Bae "Gateway", gateway, // 1546afc474aeSMyung Bae "SubnetMask", subnetMask // 1547afc474aeSMyung Bae )) 1548537174c4SEd Tanous { 1549*6e1a52faSEd Tanous messages::propertyValueFormatError(res, *obj, pathString); 1550*6e1a52faSEd Tanous return false; 1551179db1d7SKowalski, Kamil } 1552*6e1a52faSEd Tanous } 155301784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 155401784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 155501784826SJohnathan Mantey // current state of the interface. Merge existing state into the 155601784826SJohnathan Mantey // current request. 1557537174c4SEd Tanous if (address) 15581abe55efSEd Tanous { 1559e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 156001784826SJohnathan Mantey { 1561*6e1a52faSEd Tanous messages::propertyValueFormatError(res, *address, 1562bf648f77SEd Tanous pathString + "/Address"); 1563*6e1a52faSEd Tanous return false; 156401784826SJohnathan Mantey } 1565*6e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 1566*6e1a52faSEd Tanous thisAddress.address = *address; 156701784826SJohnathan Mantey } 1568*6e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 156901784826SJohnathan Mantey { 1570*6e1a52faSEd Tanous messages::propertyMissing(res, pathString + "/Address"); 1571*6e1a52faSEd Tanous return false; 157201784826SJohnathan Mantey } 157301784826SJohnathan Mantey else 157401784826SJohnathan Mantey { 1575*6e1a52faSEd Tanous thisAddress.address = nicIpEntry->address; 15764a0cb85cSEd Tanous } 15774a0cb85cSEd Tanous 1578537174c4SEd Tanous if (subnetMask) 15794a0cb85cSEd Tanous { 1580*6e1a52faSEd Tanous uint8_t prefixLength = 0; 1581033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1582033f1e4dSEd Tanous &prefixLength)) 15834a0cb85cSEd Tanous { 1584f12894f8SJason M. Bills messages::propertyValueFormatError( 1585*6e1a52faSEd Tanous res, *subnetMask, pathString + "/SubnetMask"); 1586*6e1a52faSEd Tanous return false; 15874a0cb85cSEd Tanous } 1588*6e1a52faSEd Tanous thisAddress.prefixLength = prefixLength; 1589*6e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 15904a0cb85cSEd Tanous } 1591*6e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 15924a0cb85cSEd Tanous { 1593*6e1a52faSEd Tanous messages::propertyMissing(res, pathString + "/SubnetMask"); 1594*6e1a52faSEd Tanous return false; 15954a0cb85cSEd Tanous } 15961abe55efSEd Tanous else 15971abe55efSEd Tanous { 1598*6e1a52faSEd Tanous uint8_t prefixLength = 0; 1599*6e1a52faSEd Tanous // Ignore return code. It came from internal, it's it's invalid 1600*6e1a52faSEd Tanous // nothing we can do 1601*6e1a52faSEd Tanous ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 1602*6e1a52faSEd Tanous &prefixLength); 160301784826SJohnathan Mantey 1604*6e1a52faSEd Tanous thisAddress.prefixLength = prefixLength; 1605*6e1a52faSEd Tanous } 160601784826SJohnathan Mantey if (gateway) 160701784826SJohnathan Mantey { 1608e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 160901784826SJohnathan Mantey { 1610*6e1a52faSEd Tanous messages::propertyValueFormatError(res, *gateway, 1611bf648f77SEd Tanous pathString + "/Gateway"); 1612*6e1a52faSEd Tanous return false; 161301784826SJohnathan Mantey } 1614*6e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 1615*6e1a52faSEd Tanous thisAddress.gateway = *gateway; 161601784826SJohnathan Mantey } 1617*6e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 161801784826SJohnathan Mantey { 1619*6e1a52faSEd Tanous // Default to null gateway 1620*6e1a52faSEd Tanous gateway = ""; 162101784826SJohnathan Mantey } 162201784826SJohnathan Mantey else 16231abe55efSEd Tanous { 1624*6e1a52faSEd Tanous thisAddress.gateway = nicIpEntry->gateway; 16254a0cb85cSEd Tanous } 16264a0cb85cSEd Tanous 1627*6e1a52faSEd Tanous // Changing gateway from existing 1628*6e1a52faSEd Tanous if (!thisAddress.gateway.empty() && 1629*6e1a52faSEd Tanous thisAddress.gateway != "0.0.0.0") 1630743eb1c0SJohnathan Mantey { 1631*6e1a52faSEd Tanous if (!gatewayOut.empty() && gatewayOut != thisAddress.gateway) 1632743eb1c0SJohnathan Mantey { 1633743eb1c0SJohnathan Mantey // A NIC can only have a single active gateway value. 1634743eb1c0SJohnathan Mantey // If any gateway in the array of static addresses 1635743eb1c0SJohnathan Mantey // mismatch the PATCH is in error. 1636743eb1c0SJohnathan Mantey std::string arg1 = pathString + "/Gateway"; 1637*6e1a52faSEd Tanous std::string arg2 = lastGatewayPath + "/Gateway"; 1638*6e1a52faSEd Tanous messages::propertyValueConflict(res, arg1, arg2); 1639*6e1a52faSEd Tanous return false; 1640*6e1a52faSEd Tanous } 1641*6e1a52faSEd Tanous gatewayOut = thisAddress.gateway; 1642*6e1a52faSEd Tanous lastGatewayPath = pathString; 1643743eb1c0SJohnathan Mantey } 1644743eb1c0SJohnathan Mantey } 1645*6e1a52faSEd Tanous nicIpEntry++; 1646*6e1a52faSEd Tanous nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend()); 1647*6e1a52faSEd Tanous entryIdx++; 1648743eb1c0SJohnathan Mantey } 1649743eb1c0SJohnathan Mantey 1650*6e1a52faSEd Tanous // Delete the remaining IPs 1651*6e1a52faSEd Tanous while (nicIpEntry != ipv4Data.cend()) 16521abe55efSEd Tanous { 1653*6e1a52faSEd Tanous AddressPatch& thisAddress = addressesOut.emplace_back(); 1654*6e1a52faSEd Tanous thisAddress.operation = AddrChange::Delete; 1655*6e1a52faSEd Tanous thisAddress.existingDbusId = nicIpEntry->id; 1656*6e1a52faSEd Tanous nicIpEntry++; 1657*6e1a52faSEd Tanous nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend()); 1658588c3f0dSKowalski, Kamil } 1659*6e1a52faSEd Tanous 1660*6e1a52faSEd Tanous return true; 16614a0cb85cSEd Tanous } 1662*6e1a52faSEd Tanous 1663*6e1a52faSEd Tanous inline void handleIPv4StaticPatch( 1664*6e1a52faSEd Tanous const std::string& ifaceId, 1665*6e1a52faSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1666*6e1a52faSEd Tanous const EthernetInterfaceData& ethData, 1667*6e1a52faSEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1668*6e1a52faSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 166901784826SJohnathan Mantey { 1670*6e1a52faSEd Tanous std::vector<AddressPatch> addresses; 1671*6e1a52faSEd Tanous std::string gatewayOut; 1672*6e1a52faSEd Tanous if (!parseAddresses(input, ipv4Data, asyncResp->res, addresses, gatewayOut)) 167301784826SJohnathan Mantey { 1674743eb1c0SJohnathan Mantey return; 1675743eb1c0SJohnathan Mantey } 1676*6e1a52faSEd Tanous 1677*6e1a52faSEd Tanous // If we're setting the gateway to something new, delete the 1678*6e1a52faSEd Tanous // existing so we won't conflict 1679*6e1a52faSEd Tanous if (!ethData.defaultGateway.empty() && ethData.defaultGateway != gatewayOut) 1680*6e1a52faSEd Tanous { 1681*6e1a52faSEd Tanous updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1682743eb1c0SJohnathan Mantey } 1683*6e1a52faSEd Tanous 1684*6e1a52faSEd Tanous for (const AddressPatch& address : addresses) 1685*6e1a52faSEd Tanous { 1686*6e1a52faSEd Tanous switch (address.operation) 1687*6e1a52faSEd Tanous { 1688*6e1a52faSEd Tanous case AddrChange::Delete: 1689*6e1a52faSEd Tanous { 1690*6e1a52faSEd Tanous BMCWEB_LOG_ERROR("Deleting id {} on interface {}", 1691*6e1a52faSEd Tanous address.existingDbusId, ifaceId); 1692*6e1a52faSEd Tanous deleteIPAddress(ifaceId, address.existingDbusId, asyncResp); 1693*6e1a52faSEd Tanous } 1694*6e1a52faSEd Tanous break; 1695*6e1a52faSEd Tanous case AddrChange::Update: 1696*6e1a52faSEd Tanous { 1697*6e1a52faSEd Tanous // Update is a delete then a recreate 1698*6e1a52faSEd Tanous // Only need to update if there is an existing ip at this index 1699*6e1a52faSEd Tanous if (!address.existingDbusId.empty()) 1700*6e1a52faSEd Tanous { 1701*6e1a52faSEd Tanous BMCWEB_LOG_ERROR("Deleting id {} on interface {}", 1702*6e1a52faSEd Tanous address.existingDbusId, ifaceId); 1703*6e1a52faSEd Tanous deleteAndCreateIPAddress( 1704*6e1a52faSEd Tanous IpVersion::IpV4, ifaceId, address.existingDbusId, 1705*6e1a52faSEd Tanous address.prefixLength, address.address, address.gateway, 1706*6e1a52faSEd Tanous asyncResp); 1707*6e1a52faSEd Tanous } 1708*6e1a52faSEd Tanous else 1709*6e1a52faSEd Tanous { 1710*6e1a52faSEd Tanous // Otherwise, just create a new one 1711*6e1a52faSEd Tanous BMCWEB_LOG_ERROR( 1712*6e1a52faSEd Tanous "creating ip {} prefix {} gateway {} on interface {}", 1713*6e1a52faSEd Tanous address.address, address.prefixLength, address.gateway, 1714*6e1a52faSEd Tanous ifaceId); 1715*6e1a52faSEd Tanous createIPv4(ifaceId, address.prefixLength, address.gateway, 1716*6e1a52faSEd Tanous address.address, asyncResp); 1717*6e1a52faSEd Tanous } 1718*6e1a52faSEd Tanous } 1719*6e1a52faSEd Tanous break; 1720*6e1a52faSEd Tanous default: 1721*6e1a52faSEd Tanous { 1722*6e1a52faSEd Tanous // Leave alone 1723*6e1a52faSEd Tanous } 1724*6e1a52faSEd Tanous break; 1725*6e1a52faSEd Tanous } 1726*6e1a52faSEd Tanous } 1727*6e1a52faSEd Tanous 1728*6e1a52faSEd Tanous // now update to the new gateway. 1729*6e1a52faSEd Tanous // Default gateway is already empty, so no need to update if we're clearing 1730*6e1a52faSEd Tanous if (!gatewayOut.empty() && ethData.defaultGateway != gatewayOut) 1731*6e1a52faSEd Tanous { 1732*6e1a52faSEd Tanous updateIPv4DefaultGateway(ifaceId, gatewayOut, asyncResp); 173301784826SJohnathan Mantey } 17344a0cb85cSEd Tanous } 17354a0cb85cSEd Tanous 17364f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1737f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1738f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 17398d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1740f85837bfSRAJESWARAN THILLAIGOVINDAN { 17411847f2a0SAsmitha Karunanithi setDbusProperty( 1742e93abac6SGinu George asyncResp, "StaticNameServers", "xyz.openbmc_project.Network", 17431847f2a0SAsmitha Karunanithi sdbusplus::message::object_path("/xyz/openbmc_project/network") / 17441847f2a0SAsmitha Karunanithi ifaceId, 17459ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 1746e93abac6SGinu George updatedStaticNameServers); 1747f85837bfSRAJESWARAN THILLAIGOVINDAN } 1748f85837bfSRAJESWARAN THILLAIGOVINDAN 17494f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 17503dfed536SEd Tanous const std::string& ifaceId, 17513dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 175277179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 17538d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1754e48c0fc5SRavi Teja { 1755271584abSEd Tanous size_t entryIdx = 1; 175677179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 17572c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 17583dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 17593dfed536SEd Tanous input) 1760e48c0fc5SRavi Teja { 1761bd79bce8SPatrick Williams std::string pathString = 1762bd79bce8SPatrick Williams "IPv6StaticAddresses/" + std::to_string(entryIdx); 17633dfed536SEd Tanous nlohmann::json::object_t* obj = 17643dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 17653dfed536SEd Tanous if (obj != nullptr && !obj->empty()) 1766e48c0fc5SRavi Teja { 1767e48c0fc5SRavi Teja std::optional<std::string> address; 1768e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 17693dfed536SEd Tanous nlohmann::json::object_t thisJsonCopy = *obj; 1770afc474aeSMyung Bae if (!json_util::readJsonObject( // 1771afc474aeSMyung Bae thisJsonCopy, asyncResp->res, // 1772afc474aeSMyung Bae "Address", address, // 1773afc474aeSMyung Bae "PrefixLength", prefixLength // 1774afc474aeSMyung Bae )) 1775e48c0fc5SRavi Teja { 17763dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJsonCopy, 177771f52d96SEd Tanous pathString); 1778e48c0fc5SRavi Teja return; 1779e48c0fc5SRavi Teja } 1780e48c0fc5SRavi Teja 178101784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 178201784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 178301784826SJohnathan Mantey // current state of the interface. Merge existing state into the 178401784826SJohnathan Mantey // current request. 1785d547d8d2SEd Tanous if (!address) 1786e48c0fc5SRavi Teja { 1787d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 178801784826SJohnathan Mantey { 178901784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 179001784826SJohnathan Mantey pathString + "/Address"); 179101784826SJohnathan Mantey return; 1792e48c0fc5SRavi Teja } 1793d547d8d2SEd Tanous address = nicIpEntry->address; 1794d547d8d2SEd Tanous } 1795e48c0fc5SRavi Teja 1796d547d8d2SEd Tanous if (!prefixLength) 1797e48c0fc5SRavi Teja { 1798d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 1799e48c0fc5SRavi Teja { 1800e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1801e48c0fc5SRavi Teja pathString + "/PrefixLength"); 180201784826SJohnathan Mantey return; 1803e48c0fc5SRavi Teja } 1804d547d8d2SEd Tanous prefixLength = nicIpEntry->prefixLength; 1805d547d8d2SEd Tanous } 1806e48c0fc5SRavi Teja 180785ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1808e48c0fc5SRavi Teja { 18099c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 1810d547d8d2SEd Tanous nicIpEntry->id, *prefixLength, 1811d547d8d2SEd Tanous *address, "", asyncResp); 1812bd79bce8SPatrick Williams nicIpEntry = 1813bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend()); 181401784826SJohnathan Mantey } 181501784826SJohnathan Mantey else 181601784826SJohnathan Mantey { 1817d547d8d2SEd Tanous createIPv6(ifaceId, *prefixLength, *address, asyncResp); 1818e48c0fc5SRavi Teja } 1819e48c0fc5SRavi Teja entryIdx++; 1820e48c0fc5SRavi Teja } 182101784826SJohnathan Mantey else 182201784826SJohnathan Mantey { 182385ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 182401784826SJohnathan Mantey { 182501784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 182601784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 182701784826SJohnathan Mantey // in error, so bail out. 18283dfed536SEd Tanous if (obj == nullptr) 182901784826SJohnathan Mantey { 183001784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 183101784826SJohnathan Mantey return; 183201784826SJohnathan Mantey } 18333dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 183471f52d96SEd Tanous pathString); 183501784826SJohnathan Mantey return; 183601784826SJohnathan Mantey } 183701784826SJohnathan Mantey 18383dfed536SEd Tanous if (obj == nullptr) 183901784826SJohnathan Mantey { 18409c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 184101784826SJohnathan Mantey } 184285ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 184301784826SJohnathan Mantey { 1844bd79bce8SPatrick Williams nicIpEntry = 1845bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend()); 184601784826SJohnathan Mantey } 184701784826SJohnathan Mantey entryIdx++; 184801784826SJohnathan Mantey } 184901784826SJohnathan Mantey } 1850e48c0fc5SRavi Teja } 1851e48c0fc5SRavi Teja 18527857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 18537857cb8dSJiaqing Zhao { 18547857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 18557857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 18567857cb8dSJiaqing Zhao } 18577857cb8dSJiaqing Zhao 1858bd79bce8SPatrick Williams inline void parseInterfaceData( 1859bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1860bd79bce8SPatrick Williams const std::string& ifaceId, const EthernetInterfaceData& ethData, 186177179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1862ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 1863ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) 18644a0cb85cSEd Tanous { 18652c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 186681ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1867253f11b8SEd Tanous jsonResponse["@odata.id"] = 1868253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 1869253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId); 18702c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1871eeedda23SJohnathan Mantey 1872eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1873eeedda23SJohnathan Mantey { 1874539d8c6bSEd Tanous jsonResponse["LinkStatus"] = 1875539d8c6bSEd Tanous ethData.linkUp ? ethernet_interface::LinkStatus::LinkUp 1876539d8c6bSEd Tanous : ethernet_interface::LinkStatus::LinkDown; 1877539d8c6bSEd Tanous jsonResponse["Status"]["State"] = resource::State::Enabled; 1878029573d4SEd Tanous } 1879029573d4SEd Tanous else 1880029573d4SEd Tanous { 1881539d8c6bSEd Tanous jsonResponse["LinkStatus"] = ethernet_interface::LinkStatus::NoLink; 1882539d8c6bSEd Tanous jsonResponse["Status"]["State"] = resource::State::Disabled; 1883029573d4SEd Tanous } 1884aa05fb27SJohnathan Mantey 18852c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 188635fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 18874652c640SAsmitha Karunanithi if (ethData.macAddress) 18884652c640SAsmitha Karunanithi { 18894652c640SAsmitha Karunanithi jsonResponse["MACAddress"] = *ethData.macAddress; 18904652c640SAsmitha Karunanithi } 18912c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 189282695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1893e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1894e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1895de9ad764SRavi Teja jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled; 18962c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1897bd79bce8SPatrick Williams translateDhcpEnabledToBool(ethData.dhcpEnabled, false) 1898bd79bce8SPatrick Williams ? "Enabled" 18991f8c7b5dSJohnathan Mantey : "Disabled"; 1900e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1901e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1902de9ad764SRavi Teja jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled; 1903b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1904b10d8db0SRavi Teja ethData.ipv6AcceptRa; 19052a133282Smanojkiraneda 190682695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 19074a0cb85cSEd Tanous { 190882695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1909ab6554f1SJoshi-Mansi 1910ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1911ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1912ab6554f1SJoshi-Mansi // FQDN 191382695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1914d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1915d24bfc7aSJennifer Lee { 19162c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1917d24bfc7aSJennifer Lee } 19182c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 19194a0cb85cSEd Tanous } 19204a0cb85cSEd Tanous 19217857cb8dSJiaqing Zhao if (ethData.vlanId) 19227857cb8dSJiaqing Zhao { 1923539d8c6bSEd Tanous jsonResponse["EthernetInterfaceType"] = 1924539d8c6bSEd Tanous ethernet_interface::EthernetDeviceType::Virtual; 19257857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 19267857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 19277857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 19287857cb8dSJiaqing Zhao 19297857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 19307857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 19317857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 1932253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces", 1933253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, 19347857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 19357857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 19367857cb8dSJiaqing Zhao std::move(relatedInterfaces); 19377857cb8dSJiaqing Zhao } 19387857cb8dSJiaqing Zhao else 19397857cb8dSJiaqing Zhao { 1940539d8c6bSEd Tanous jsonResponse["EthernetInterfaceType"] = 1941539d8c6bSEd Tanous ethernet_interface::EthernetDeviceType::Physical; 19427857cb8dSJiaqing Zhao } 19437857cb8dSJiaqing Zhao 19442c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 19452c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 19464a0cb85cSEd Tanous 19472c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 19482c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 19492c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 19502c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 19519eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 19524a0cb85cSEd Tanous { 19532c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1954fa5053a6SGunnar Mills if (gatewayStr.empty()) 1955fa5053a6SGunnar Mills { 1956fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1957fa5053a6SGunnar Mills } 19581476687dSEd Tanous nlohmann::json::object_t ipv4; 19591476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 19601476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 19611476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 19621476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1963fa5053a6SGunnar Mills 19642c70f800SEd Tanous if (ipv4Config.origin == "Static") 1965d1d50814SRavi Teja { 19661476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1967d1d50814SRavi Teja } 19681476687dSEd Tanous 1969b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 197001784826SJohnathan Mantey } 1971d1d50814SRavi Teja 197282695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 19737ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 19747ea79e5eSRavi Teja { 19757ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 19767ea79e5eSRavi Teja } 19777ea79e5eSRavi Teja 19787ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1979e48c0fc5SRavi Teja 1980ce73d5c8SSunitha Harish nlohmann::json::array_t ipv6StaticGatewayArray; 1981ce73d5c8SSunitha Harish for (const auto& ipv6GatewayConfig : ipv6GatewayData) 1982ce73d5c8SSunitha Harish { 1983ce73d5c8SSunitha Harish nlohmann::json::object_t ipv6Gateway; 1984ce73d5c8SSunitha Harish ipv6Gateway["Address"] = ipv6GatewayConfig.gateway; 1985ce73d5c8SSunitha Harish ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway)); 1986ce73d5c8SSunitha Harish } 1987ce73d5c8SSunitha Harish jsonResponse["IPv6StaticDefaultGateways"] = 1988ce73d5c8SSunitha Harish std::move(ipv6StaticGatewayArray); 1989ce73d5c8SSunitha Harish 19902c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 19912c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 19922c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 19932c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 19947f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 19952c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 19967f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 19979eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1998e48c0fc5SRavi Teja { 19991476687dSEd Tanous nlohmann::json::object_t ipv6; 20001476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 20011476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 20021476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 2003f8361275SSunitha Harish 2004b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 20052c70f800SEd Tanous if (ipv6Config.origin == "Static") 2006e48c0fc5SRavi Teja { 20071476687dSEd Tanous nlohmann::json::object_t ipv6Static; 20081476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 20091476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 2010b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 201101784826SJohnathan Mantey } 2012e48c0fc5SRavi Teja } 2013588c3f0dSKowalski, Kamil } 2014588c3f0dSKowalski, Kamil 2015e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2016e7caf250SJiaqing Zhao const std::string& ifaceId, 2017e7caf250SJiaqing Zhao const boost::system::error_code& ec, 2018e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 2019e7caf250SJiaqing Zhao { 2020e7caf250SJiaqing Zhao if (!ec) 2021e7caf250SJiaqing Zhao { 2022e7caf250SJiaqing Zhao return; 2023e7caf250SJiaqing Zhao } 2024e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2025e7caf250SJiaqing Zhao if (dbusError == nullptr) 2026e7caf250SJiaqing Zhao { 2027e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2028e7caf250SJiaqing Zhao return; 2029e7caf250SJiaqing Zhao } 203062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2031e7caf250SJiaqing Zhao 2032e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 2033e7caf250SJiaqing Zhao dbusError->name) 2034e7caf250SJiaqing Zhao { 2035e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2036e7caf250SJiaqing Zhao ifaceId); 2037e7caf250SJiaqing Zhao return; 2038e7caf250SJiaqing Zhao } 2039e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 2040e7caf250SJiaqing Zhao dbusError->name) 2041e7caf250SJiaqing Zhao { 2042e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 2043e7caf250SJiaqing Zhao return; 2044e7caf250SJiaqing Zhao } 2045e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2046e7caf250SJiaqing Zhao } 2047e7caf250SJiaqing Zhao 2048bd79bce8SPatrick Williams inline void afterVlanCreate( 2049bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2050bd79bce8SPatrick Williams const std::string& parentInterfaceUri, const std::string& vlanInterface, 2051bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& m 2052b5ca3fdcSJiaqing Zhao 2053b5ca3fdcSJiaqing Zhao ) 2054b5ca3fdcSJiaqing Zhao { 2055b5ca3fdcSJiaqing Zhao if (ec) 2056b5ca3fdcSJiaqing Zhao { 2057b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2058b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 2059b5ca3fdcSJiaqing Zhao { 2060b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2061b5ca3fdcSJiaqing Zhao return; 2062b5ca3fdcSJiaqing Zhao } 206362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2064b5ca3fdcSJiaqing Zhao 2065b5ca3fdcSJiaqing Zhao if (std::string_view( 2066b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 2067b5ca3fdcSJiaqing Zhao dbusError->name) 2068b5ca3fdcSJiaqing Zhao { 2069b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2070b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2071b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2072b5ca3fdcSJiaqing Zhao return; 2073b5ca3fdcSJiaqing Zhao } 2074b5ca3fdcSJiaqing Zhao if (std::string_view( 2075b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 2076b5ca3fdcSJiaqing Zhao dbusError->name) 2077b5ca3fdcSJiaqing Zhao { 2078b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 2079b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 2080b5ca3fdcSJiaqing Zhao return; 2081b5ca3fdcSJiaqing Zhao } 2082b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2083b5ca3fdcSJiaqing Zhao return; 2084b5ca3fdcSJiaqing Zhao } 2085b5ca3fdcSJiaqing Zhao 2086253f11b8SEd Tanous const boost::urls::url vlanInterfaceUri = 2087253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2088253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface); 2089b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 2090b5ca3fdcSJiaqing Zhao } 2091b5ca3fdcSJiaqing Zhao 2092bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 2093bf648f77SEd Tanous { 2094253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2095ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 20961476687dSEd Tanous .methods(boost::beast::http::verb::get)( 20971476687dSEd Tanous [&app](const crow::Request& req, 2098253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2099253f11b8SEd Tanous const std::string& managerId) { 21003ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 210145ca1b86SEd Tanous { 210245ca1b86SEd Tanous return; 210345ca1b86SEd Tanous } 210445ca1b86SEd Tanous 2105253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2106253f11b8SEd Tanous { 2107bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2108bd79bce8SPatrick Williams managerId); 2109253f11b8SEd Tanous return; 2110253f11b8SEd Tanous } 2111253f11b8SEd Tanous 2112bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2113bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 2114bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2115bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/EthernetInterfaces", 2116253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2117bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 2118bf648f77SEd Tanous "Ethernet Network Interface Collection"; 2119bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 2120bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 2121bf648f77SEd Tanous 2122bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 2123bf648f77SEd Tanous // preparation 2124002d39b4SEd Tanous getEthernetIfaceList( 212577179532SEd Tanous [asyncResp](const bool& success, 212677179532SEd Tanous const std::vector<std::string>& ifaceList) { 2127bf648f77SEd Tanous if (!success) 21281abe55efSEd Tanous { 2129f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21309391bb9cSRapkiewicz, Pawel return; 21319391bb9cSRapkiewicz, Pawel } 21329391bb9cSRapkiewicz, Pawel 2133bd79bce8SPatrick Williams nlohmann::json& ifaceArray = 2134bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 2135bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 2136bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 2137bf648f77SEd Tanous { 21381476687dSEd Tanous nlohmann::json::object_t iface; 2139ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 2140253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2141253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem); 21427857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 2143bf648f77SEd Tanous } 2144bf648f77SEd Tanous 2145bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 2146bd79bce8SPatrick Williams ifaceArray.size(); 2147bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = 2148bd79bce8SPatrick Williams boost::urls::format( 2149253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces", 2150253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2151bf648f77SEd Tanous }); 2152bf648f77SEd Tanous }); 2153bf648f77SEd Tanous 2154253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2155b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 2156b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 2157b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 2158253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2159253f11b8SEd Tanous const std::string& managerId) { 2160b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2161b5ca3fdcSJiaqing Zhao { 2162b5ca3fdcSJiaqing Zhao return; 2163b5ca3fdcSJiaqing Zhao } 2164b5ca3fdcSJiaqing Zhao 2165253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2166253f11b8SEd Tanous { 2167bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2168bd79bce8SPatrick Williams managerId); 2169253f11b8SEd Tanous return; 2170253f11b8SEd Tanous } 2171253f11b8SEd Tanous 2172b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 2173b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 21743dfed536SEd Tanous std::vector<nlohmann::json::object_t> relatedInterfaces; 2175b5ca3fdcSJiaqing Zhao 2176afc474aeSMyung Bae if (!json_util::readJsonPatch( // 2177afc474aeSMyung Bae req, asyncResp->res, // 2178afc474aeSMyung Bae "Links/RelatedInterfaces", relatedInterfaces, // 2179afc474aeSMyung Bae "VLAN/VLANEnable", vlanEnable, // 2180afc474aeSMyung Bae "VLAN/VLANId", vlanId // 2181afc474aeSMyung Bae )) 2182b5ca3fdcSJiaqing Zhao { 2183b5ca3fdcSJiaqing Zhao return; 2184b5ca3fdcSJiaqing Zhao } 2185b5ca3fdcSJiaqing Zhao 2186b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 2187b5ca3fdcSJiaqing Zhao { 2188b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 2189b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2190b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 2191b5ca3fdcSJiaqing Zhao return; 2192b5ca3fdcSJiaqing Zhao } 2193b5ca3fdcSJiaqing Zhao 2194b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 2195bd79bce8SPatrick Williams if (!json_util::readJsonObject(relatedInterfaces[0], 2196bd79bce8SPatrick Williams asyncResp->res, "@odata.id", 2197bd79bce8SPatrick Williams parentInterfaceUri)) 2198b5ca3fdcSJiaqing Zhao { 2199bd79bce8SPatrick Williams messages::propertyMissing( 2200bd79bce8SPatrick Williams asyncResp->res, "Links/RelatedInterfaces/0/@odata.id"); 2201b5ca3fdcSJiaqing Zhao return; 2202b5ca3fdcSJiaqing Zhao } 220362598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 2204b5ca3fdcSJiaqing Zhao 22056fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 2206b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 2207b5ca3fdcSJiaqing Zhao if (!parsedUri) 2208b5ca3fdcSJiaqing Zhao { 2209b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 2210b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2211b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2212b5ca3fdcSJiaqing Zhao return; 2213b5ca3fdcSJiaqing Zhao } 2214b5ca3fdcSJiaqing Zhao 2215b5ca3fdcSJiaqing Zhao std::string parentInterface; 2216b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 2217b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 2218b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 2219b5ca3fdcSJiaqing Zhao { 2220b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2221b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2222b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2223b5ca3fdcSJiaqing Zhao return; 2224b5ca3fdcSJiaqing Zhao } 2225b5ca3fdcSJiaqing Zhao 2226b5ca3fdcSJiaqing Zhao if (!vlanEnable) 2227b5ca3fdcSJiaqing Zhao { 2228b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 2229b5ca3fdcSJiaqing Zhao // create 2230bd79bce8SPatrick Williams messages::propertyValueIncorrect( 2231bd79bce8SPatrick Williams asyncResp->res, "VLAN/VLANEnable", "false"); 2232b5ca3fdcSJiaqing Zhao return; 2233b5ca3fdcSJiaqing Zhao } 2234b5ca3fdcSJiaqing Zhao 2235bd79bce8SPatrick Williams std::string vlanInterface = 2236bd79bce8SPatrick Williams parentInterface + "_" + std::to_string(vlanId); 2237b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 2238b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 2239b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 2240b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 2241bd79bce8SPatrick Williams afterVlanCreate(asyncResp, parentInterfaceUri, 2242bd79bce8SPatrick Williams vlanInterface, ec, m); 2243b5ca3fdcSJiaqing Zhao }, 2244bd79bce8SPatrick Williams "xyz.openbmc_project.Network", 2245bd79bce8SPatrick Williams "/xyz/openbmc_project/network", 2246bd79bce8SPatrick Williams "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 2247bd79bce8SPatrick Williams parentInterface, vlanId); 2248b5ca3fdcSJiaqing Zhao }); 2249b5ca3fdcSJiaqing Zhao 2250253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2251ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 2252bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 225345ca1b86SEd Tanous [&app](const crow::Request& req, 2254bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2255253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 22563ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 225745ca1b86SEd Tanous { 225845ca1b86SEd Tanous return; 225945ca1b86SEd Tanous } 2260253f11b8SEd Tanous 2261253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2262253f11b8SEd Tanous { 2263bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2264bd79bce8SPatrick Williams managerId); 2265253f11b8SEd Tanous return; 2266253f11b8SEd Tanous } 2267253f11b8SEd Tanous 22684a0cb85cSEd Tanous getEthernetIfaceData( 2269bf648f77SEd Tanous ifaceId, 2270bd79bce8SPatrick Williams [asyncResp, ifaceId]( 2271bd79bce8SPatrick Williams const bool& success, 2272bd79bce8SPatrick Williams const EthernetInterfaceData& ethData, 227377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2274ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2275ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 22764a0cb85cSEd Tanous if (!success) 22771abe55efSEd Tanous { 2278bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2279bf648f77SEd Tanous // existing object, and other errors 2280bd79bce8SPatrick Williams messages::resourceNotFound( 2281bd79bce8SPatrick Williams asyncResp->res, "EthernetInterface", ifaceId); 22824a0cb85cSEd Tanous return; 22839391bb9cSRapkiewicz, Pawel } 22844c9afe43SEd Tanous 22850f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 228693bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2287bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2288bd79bce8SPatrick Williams "Manager Ethernet Interface"; 22890f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 22900f74e643SEd Tanous "Management Network Interface"; 22910f74e643SEd Tanous 2292bd79bce8SPatrick Williams parseInterfaceData(asyncResp, ifaceId, ethData, 2293bd79bce8SPatrick Williams ipv4Data, ipv6Data, ipv6GatewayData); 22949391bb9cSRapkiewicz, Pawel }); 2295bf648f77SEd Tanous }); 22969391bb9cSRapkiewicz, Pawel 2297253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2298ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2299bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 230045ca1b86SEd Tanous [&app](const crow::Request& req, 2301bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2302253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 23033ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 230445ca1b86SEd Tanous { 230545ca1b86SEd Tanous return; 230645ca1b86SEd Tanous } 2307253f11b8SEd Tanous 2308253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2309253f11b8SEd Tanous { 2310bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2311bd79bce8SPatrick Williams managerId); 2312253f11b8SEd Tanous return; 2313253f11b8SEd Tanous } 2314253f11b8SEd Tanous 2315bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2316ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2317d577665bSRatan Gupta std::optional<std::string> macAddress; 23189a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2319bd79bce8SPatrick Williams std::optional<std::vector< 2320bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23213dfed536SEd Tanous ipv4StaticAddresses; 2322bd79bce8SPatrick Williams std::optional<std::vector< 2323bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23243dfed536SEd Tanous ipv6StaticAddresses; 2325bd79bce8SPatrick Williams std::optional<std::vector< 2326bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23273dfed536SEd Tanous ipv6StaticDefaultGateways; 2328f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2329b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2330eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 233135fb5311STejas Patil std::optional<size_t> mtuSize; 23321f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 23331f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2334afc474aeSMyung Bae 2335afc474aeSMyung Bae if (!json_util::readJsonPatch( // 2336afc474aeSMyung Bae req, asyncResp->res, // 2337afc474aeSMyung Bae "DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled, // 2338afc474aeSMyung Bae "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers, // 2339afc474aeSMyung Bae "DHCPv4/UseDomainName", v4dhcpParms.useDomainName, // 2340afc474aeSMyung Bae "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers, // 2341afc474aeSMyung Bae "DHCPv6/OperatingMode", 2342afc474aeSMyung Bae v6dhcpParms.dhcpv6OperatingMode, // 2343afc474aeSMyung Bae "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers, // 2344afc474aeSMyung Bae "DHCPv6/UseDomainName", v6dhcpParms.useDomainName, // 2345afc474aeSMyung Bae "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers, // 2346afc474aeSMyung Bae "FQDN", fqdn, // 2347afc474aeSMyung Bae "HostName", hostname, // 2348afc474aeSMyung Bae "InterfaceEnabled", interfaceEnabled, // 2349afc474aeSMyung Bae "IPv4StaticAddresses", ipv4StaticAddresses, // 2350afc474aeSMyung Bae "IPv6DefaultGateway", ipv6DefaultGateway, // 2351afc474aeSMyung Bae "IPv6StaticAddresses", ipv6StaticAddresses, // 2352afc474aeSMyung Bae "IPv6StaticDefaultGateways", 2353afc474aeSMyung Bae ipv6StaticDefaultGateways, // 2354afc474aeSMyung Bae "InterfaceEnabled", interfaceEnabled, // 2355afc474aeSMyung Bae "MACAddress", macAddress, // 2356afc474aeSMyung Bae "MTUSize", mtuSize, // 2357afc474aeSMyung Bae "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 2358afc474aeSMyung Bae ipv6AutoConfigEnabled, // 2359afc474aeSMyung Bae "StaticNameServers", staticNameServers // 2360afc474aeSMyung Bae )) 23611abe55efSEd Tanous { 2362588c3f0dSKowalski, Kamil return; 2363588c3f0dSKowalski, Kamil } 2364da131a9aSJennifer Lee 2365bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2366bf648f77SEd Tanous // for JSON preparation 23674a0cb85cSEd Tanous getEthernetIfaceData( 23682c70f800SEd Tanous ifaceId, 2369bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2370ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2371d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 23729a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2373e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 2374bd79bce8SPatrick Williams ipv6StaticDefaultGateway = 2375bd79bce8SPatrick Williams std::move(ipv6StaticDefaultGateways), 23763dfed536SEd Tanous staticNameServers = std::move(staticNameServers), mtuSize, 2377bd79bce8SPatrick Williams ipv6AutoConfigEnabled, 2378bd79bce8SPatrick Williams v4dhcpParms = std::move(v4dhcpParms), 2379f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2380bd79bce8SPatrick Williams const bool success, 2381bd79bce8SPatrick Williams const EthernetInterfaceData& ethData, 238277179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2383ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2384bd79bce8SPatrick Williams const std::vector<StaticGatewayData>& 2385bd79bce8SPatrick Williams ipv6GatewayData) mutable { 23861abe55efSEd Tanous if (!success) 23871abe55efSEd Tanous { 2388588c3f0dSKowalski, Kamil // ... otherwise return error 2389bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2390bf648f77SEd Tanous // existing object, and other errors 2391bd79bce8SPatrick Williams messages::resourceNotFound( 2392bd79bce8SPatrick Williams asyncResp->res, "EthernetInterface", ifaceId); 2393588c3f0dSKowalski, Kamil return; 2394588c3f0dSKowalski, Kamil } 2395588c3f0dSKowalski, Kamil 2396bd79bce8SPatrick Williams handleDHCPPatch(ifaceId, ethData, v4dhcpParms, 2397bd79bce8SPatrick Williams v6dhcpParms, asyncResp); 23981f8c7b5dSJohnathan Mantey 23990627a2c7SEd Tanous if (hostname) 24001abe55efSEd Tanous { 24010627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 24021abe55efSEd Tanous } 24030627a2c7SEd Tanous 2404b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2405b10d8db0SRavi Teja { 2406bd79bce8SPatrick Williams handleSLAACAutoConfigPatch( 2407bd79bce8SPatrick Williams ifaceId, *ipv6AutoConfigEnabled, asyncResp); 2408b10d8db0SRavi Teja } 2409b10d8db0SRavi Teja 2410ab6554f1SJoshi-Mansi if (fqdn) 2411ab6554f1SJoshi-Mansi { 24122c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2413ab6554f1SJoshi-Mansi } 2414ab6554f1SJoshi-Mansi 2415d577665bSRatan Gupta if (macAddress) 2416d577665bSRatan Gupta { 2417bd79bce8SPatrick Williams handleMACAddressPatch(ifaceId, *macAddress, 2418bd79bce8SPatrick Williams asyncResp); 2419d577665bSRatan Gupta } 2420d577665bSRatan Gupta 2421d1d50814SRavi Teja if (ipv4StaticAddresses) 2422d1d50814SRavi Teja { 2423bd79bce8SPatrick Williams handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, 2424bd79bce8SPatrick Williams ethData, ipv4Data, asyncResp); 24251abe55efSEd Tanous } 24260627a2c7SEd Tanous 2427f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2428f85837bfSRAJESWARAN THILLAIGOVINDAN { 2429bd79bce8SPatrick Williams handleStaticNameServersPatch( 2430bd79bce8SPatrick Williams ifaceId, *staticNameServers, asyncResp); 2431f85837bfSRAJESWARAN THILLAIGOVINDAN } 24329a6fc6feSRavi Teja 24339a6fc6feSRavi Teja if (ipv6DefaultGateway) 24349a6fc6feSRavi Teja { 24359a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 24369a6fc6feSRavi Teja "IPv6DefaultGateway"); 24379a6fc6feSRavi Teja } 2438e48c0fc5SRavi Teja 2439e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2440e48c0fc5SRavi Teja { 2441bd79bce8SPatrick Williams handleIPv6StaticAddressesPatch(ifaceId, 2442bd79bce8SPatrick Williams *ipv6StaticAddresses, 2443ddd70dcaSEd Tanous ipv6Data, asyncResp); 2444e48c0fc5SRavi Teja } 2445eeedda23SJohnathan Mantey 2446ce73d5c8SSunitha Harish if (ipv6StaticDefaultGateway) 2447ce73d5c8SSunitha Harish { 2448bd79bce8SPatrick Williams handleIPv6DefaultGateway( 2449bd79bce8SPatrick Williams ifaceId, *ipv6StaticDefaultGateway, 2450ce73d5c8SSunitha Harish ipv6GatewayData, asyncResp); 2451ce73d5c8SSunitha Harish } 2452ce73d5c8SSunitha Harish 2453eeedda23SJohnathan Mantey if (interfaceEnabled) 2454eeedda23SJohnathan Mantey { 2455bd79bce8SPatrick Williams setDbusProperty( 2456bd79bce8SPatrick Williams asyncResp, "InterfaceEnabled", 2457e93abac6SGinu George "xyz.openbmc_project.Network", 2458d02aad39SEd Tanous sdbusplus::message::object_path( 2459d02aad39SEd Tanous "/xyz/openbmc_project/network") / 2460d02aad39SEd Tanous ifaceId, 2461d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", 2462e93abac6SGinu George "NICEnabled", *interfaceEnabled); 2463eeedda23SJohnathan Mantey } 246435fb5311STejas Patil 246535fb5311STejas Patil if (mtuSize) 246635fb5311STejas Patil { 246735fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 246835fb5311STejas Patil } 2469588c3f0dSKowalski, Kamil }); 2470bf648f77SEd Tanous }); 2471e7caf250SJiaqing Zhao 2472253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2473e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2474e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2475e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2476e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2477253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 2478e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2479e7caf250SJiaqing Zhao { 2480e7caf250SJiaqing Zhao return; 2481e7caf250SJiaqing Zhao } 2482e7caf250SJiaqing Zhao 2483253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2484253f11b8SEd Tanous { 2485bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2486bd79bce8SPatrick Williams managerId); 2487253f11b8SEd Tanous return; 2488253f11b8SEd Tanous } 2489253f11b8SEd Tanous 2490e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2491e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2492e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2493e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2494e7caf250SJiaqing Zhao }, 2495e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2496e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2497e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2498e7caf250SJiaqing Zhao }); 24994a0cb85cSEd Tanous } 2500bf648f77SEd Tanous 25019391bb9cSRapkiewicz, Pawel } // namespace redfish 2502