19391bb9cSRapkiewicz, Pawel /* 29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 39391bb9cSRapkiewicz, Pawel // 49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License. 69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at 79391bb9cSRapkiewicz, Pawel // 89391bb9cSRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 99391bb9cSRapkiewicz, Pawel // 109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and 149391bb9cSRapkiewicz, Pawel // limitations under the License. 159391bb9cSRapkiewicz, Pawel */ 169391bb9cSRapkiewicz, Pawel #pragma once 179391bb9cSRapkiewicz, Pawel 1813451e39SWilly Tu #include "bmcweb_config.h" 1913451e39SWilly Tu 203ccb3adbSEd Tanous #include "app.hpp" 213ccb3adbSEd Tanous #include "dbus_singleton.hpp" 227a1dbc48SGeorge Liu #include "dbus_utility.hpp" 233ccb3adbSEd Tanous #include "error_messages.hpp" 243ccb3adbSEd Tanous #include "health.hpp" 252c5875a2SEd Tanous #include "human_sort.hpp" 263ccb3adbSEd Tanous #include "query.hpp" 273ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 28033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 293ccb3adbSEd Tanous #include "utils/json_utils.hpp" 30033f1e4dSEd Tanous 31ef4c65b7SEd Tanous #include <boost/url/format.hpp> 321214b7e7SGunnar Mills 337a1dbc48SGeorge Liu #include <array> 34a24526dcSEd Tanous #include <optional> 353544d2a7SEd Tanous #include <ranges> 36ab6554f1SJoshi-Mansi #include <regex> 377a1dbc48SGeorge Liu #include <string_view> 3877179532SEd Tanous #include <vector> 399391bb9cSRapkiewicz, Pawel 401abe55efSEd Tanous namespace redfish 411abe55efSEd Tanous { 429391bb9cSRapkiewicz, Pawel 434a0cb85cSEd Tanous enum class LinkType 444a0cb85cSEd Tanous { 454a0cb85cSEd Tanous Local, 464a0cb85cSEd Tanous Global 474a0cb85cSEd Tanous }; 489391bb9cSRapkiewicz, Pawel 499391bb9cSRapkiewicz, Pawel /** 509391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 519391bb9cSRapkiewicz, Pawel */ 521abe55efSEd Tanous struct IPv4AddressData 531abe55efSEd Tanous { 54179db1d7SKowalski, Kamil std::string id; 554a0cb85cSEd Tanous std::string address; 564a0cb85cSEd Tanous std::string domain; 574a0cb85cSEd Tanous std::string gateway; 589391bb9cSRapkiewicz, Pawel std::string netmask; 599391bb9cSRapkiewicz, Pawel std::string origin; 6077179532SEd Tanous LinkType linktype{}; 6177179532SEd Tanous bool isActive{}; 629391bb9cSRapkiewicz, Pawel }; 639391bb9cSRapkiewicz, Pawel 649391bb9cSRapkiewicz, Pawel /** 65e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 66e48c0fc5SRavi Teja */ 67e48c0fc5SRavi Teja struct IPv6AddressData 68e48c0fc5SRavi Teja { 69e48c0fc5SRavi Teja std::string id; 70e48c0fc5SRavi Teja std::string address; 71e48c0fc5SRavi Teja std::string origin; 7277179532SEd Tanous uint8_t prefixLength = 0; 73e48c0fc5SRavi Teja }; 74e48c0fc5SRavi Teja /** 759391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 769391bb9cSRapkiewicz, Pawel * available from DBus 779391bb9cSRapkiewicz, Pawel */ 781abe55efSEd Tanous struct EthernetInterfaceData 791abe55efSEd Tanous { 804a0cb85cSEd Tanous uint32_t speed; 8135fb5311STejas Patil size_t mtuSize; 8282695a5bSJiaqing Zhao bool autoNeg; 83e4588158SJishnu CM bool dnsv4Enabled; 84e4588158SJishnu CM bool dnsv6Enabled; 85*91c441ecSRavi Teja bool domainv4Enabled; 86*91c441ecSRavi Teja bool domainv6Enabled; 87e4588158SJishnu CM bool ntpv4Enabled; 88e4588158SJishnu CM bool ntpv6Enabled; 89e4588158SJishnu CM bool hostNamev4Enabled; 90e4588158SJishnu CM bool hostNamev6Enabled; 91aa05fb27SJohnathan Mantey bool linkUp; 92eeedda23SJohnathan Mantey bool nicEnabled; 93b10d8db0SRavi Teja bool ipv6AcceptRa; 9482695a5bSJiaqing Zhao std::string dhcpEnabled; 951f8c7b5dSJohnathan Mantey std::string operatingMode; 9682695a5bSJiaqing Zhao std::string hostName; 9782695a5bSJiaqing Zhao std::string defaultGateway; 9882695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 9982695a5bSJiaqing Zhao std::string macAddress; 10017e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 1010f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 1020f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 103d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1049391bb9cSRapkiewicz, Pawel }; 1059391bb9cSRapkiewicz, Pawel 1061f8c7b5dSJohnathan Mantey struct DHCPParameters 1071f8c7b5dSJohnathan Mantey { 1081f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 10982695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 11082695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 11182695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1121f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1131f8c7b5dSJohnathan Mantey }; 1141f8c7b5dSJohnathan Mantey 1159391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1169391bb9cSRapkiewicz, Pawel // into full dot notation 1171abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1181abe55efSEd Tanous { 1199391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1209391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1219391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1229391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1239391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1249391bb9cSRapkiewicz, Pawel return netmask; 1259391bb9cSRapkiewicz, Pawel } 1269391bb9cSRapkiewicz, Pawel 12782695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1281f8c7b5dSJohnathan Mantey bool isIPv4) 1291f8c7b5dSJohnathan Mantey { 1301f8c7b5dSJohnathan Mantey if (isIPv4) 1311f8c7b5dSJohnathan Mantey { 1321f8c7b5dSJohnathan Mantey return ( 1331f8c7b5dSJohnathan Mantey (inputDHCP == 1341f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1351f8c7b5dSJohnathan Mantey (inputDHCP == 1361f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1371f8c7b5dSJohnathan Mantey } 1381f8c7b5dSJohnathan Mantey return ((inputDHCP == 1391f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1401f8c7b5dSJohnathan Mantey (inputDHCP == 1411f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1421f8c7b5dSJohnathan Mantey } 1431f8c7b5dSJohnathan Mantey 1442c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1451f8c7b5dSJohnathan Mantey { 1461f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1471f8c7b5dSJohnathan Mantey { 1481f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1491f8c7b5dSJohnathan Mantey } 1503174e4dfSEd Tanous if (isIPv4) 1511f8c7b5dSJohnathan Mantey { 1521f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1531f8c7b5dSJohnathan Mantey } 1543174e4dfSEd Tanous if (isIPv6) 1551f8c7b5dSJohnathan Mantey { 1561f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1571f8c7b5dSJohnathan Mantey } 1581f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1591f8c7b5dSJohnathan Mantey } 1601f8c7b5dSJohnathan Mantey 1614a0cb85cSEd Tanous inline std::string 1624a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string& inputOrigin, 1634a0cb85cSEd Tanous bool isIPv4) 1641abe55efSEd Tanous { 1654a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1661abe55efSEd Tanous { 1674a0cb85cSEd Tanous return "Static"; 1689391bb9cSRapkiewicz, Pawel } 1694a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1701abe55efSEd Tanous { 1714a0cb85cSEd Tanous if (isIPv4) 1721abe55efSEd Tanous { 1734a0cb85cSEd Tanous return "IPv4LinkLocal"; 1741abe55efSEd Tanous } 1754a0cb85cSEd Tanous return "LinkLocal"; 1769391bb9cSRapkiewicz, Pawel } 1774a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1781abe55efSEd Tanous { 1794a0cb85cSEd Tanous if (isIPv4) 1804a0cb85cSEd Tanous { 1814a0cb85cSEd Tanous return "DHCP"; 1824a0cb85cSEd Tanous } 1834a0cb85cSEd Tanous return "DHCPv6"; 1844a0cb85cSEd Tanous } 1854a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1864a0cb85cSEd Tanous { 1874a0cb85cSEd Tanous return "SLAAC"; 1884a0cb85cSEd Tanous } 1894a0cb85cSEd Tanous return ""; 1904a0cb85cSEd Tanous } 1914a0cb85cSEd Tanous 19202cad96eSEd Tanous inline bool extractEthernetInterfaceData( 19302cad96eSEd Tanous const std::string& ethifaceId, 19402cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 1954a0cb85cSEd Tanous EthernetInterfaceData& ethData) 1964a0cb85cSEd Tanous { 1974c9afe43SEd Tanous bool idFound = false; 19802cad96eSEd Tanous for (const auto& objpath : dbusData) 1994a0cb85cSEd Tanous { 20002cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 2014a0cb85cSEd Tanous { 20281ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 203029573d4SEd Tanous { 2044c9afe43SEd Tanous idFound = true; 2054a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2064a0cb85cSEd Tanous { 2074a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2084a0cb85cSEd Tanous { 2094a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2104a0cb85cSEd Tanous { 2114a0cb85cSEd Tanous const std::string* mac = 212abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2134a0cb85cSEd Tanous if (mac != nullptr) 2144a0cb85cSEd Tanous { 21582695a5bSJiaqing Zhao ethData.macAddress = *mac; 2164a0cb85cSEd Tanous } 2174a0cb85cSEd Tanous } 2184a0cb85cSEd Tanous } 2194a0cb85cSEd Tanous } 2204a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2214a0cb85cSEd Tanous { 2224a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2234a0cb85cSEd Tanous { 2244a0cb85cSEd Tanous if (propertyPair.first == "Id") 2254a0cb85cSEd Tanous { 2261b6b96c5SEd Tanous const uint32_t* id = 227abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2284a0cb85cSEd Tanous if (id != nullptr) 2294a0cb85cSEd Tanous { 23017e22024SJiaqing Zhao ethData.vlanId = *id; 2314a0cb85cSEd Tanous } 2324a0cb85cSEd Tanous } 2334a0cb85cSEd Tanous } 2344a0cb85cSEd Tanous } 2354a0cb85cSEd Tanous else if (ifacePair.first == 2364a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2374a0cb85cSEd Tanous { 2384a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2394a0cb85cSEd Tanous { 2404a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2414a0cb85cSEd Tanous { 2422c70f800SEd Tanous const bool* autoNeg = 243abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2442c70f800SEd Tanous if (autoNeg != nullptr) 2454a0cb85cSEd Tanous { 24682695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2474a0cb85cSEd Tanous } 2484a0cb85cSEd Tanous } 2494a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2504a0cb85cSEd Tanous { 2514a0cb85cSEd Tanous const uint32_t* speed = 252abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2534a0cb85cSEd Tanous if (speed != nullptr) 2544a0cb85cSEd Tanous { 2554a0cb85cSEd Tanous ethData.speed = *speed; 2564a0cb85cSEd Tanous } 2574a0cb85cSEd Tanous } 25835fb5311STejas Patil else if (propertyPair.first == "MTU") 25935fb5311STejas Patil { 2603e7a8da6SAnthony const size_t* mtuSize = 2613e7a8da6SAnthony std::get_if<size_t>(&propertyPair.second); 26235fb5311STejas Patil if (mtuSize != nullptr) 26335fb5311STejas Patil { 26435fb5311STejas Patil ethData.mtuSize = *mtuSize; 26535fb5311STejas Patil } 26635fb5311STejas Patil } 267aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 268aa05fb27SJohnathan Mantey { 269aa05fb27SJohnathan Mantey const bool* linkUp = 270aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 271aa05fb27SJohnathan Mantey if (linkUp != nullptr) 272aa05fb27SJohnathan Mantey { 273aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 274aa05fb27SJohnathan Mantey } 275aa05fb27SJohnathan Mantey } 276eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 277eeedda23SJohnathan Mantey { 278eeedda23SJohnathan Mantey const bool* nicEnabled = 279eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 280eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 281eeedda23SJohnathan Mantey { 282eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 283eeedda23SJohnathan Mantey } 284eeedda23SJohnathan Mantey } 285b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 286b10d8db0SRavi Teja { 287b10d8db0SRavi Teja const bool* ipv6AcceptRa = 288b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 289b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 290b10d8db0SRavi Teja { 291b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 292b10d8db0SRavi Teja } 293b10d8db0SRavi Teja } 294f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 295029573d4SEd Tanous { 296029573d4SEd Tanous const std::vector<std::string>* nameservers = 2978d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 298029573d4SEd Tanous &propertyPair.second); 299029573d4SEd Tanous if (nameservers != nullptr) 300029573d4SEd Tanous { 301f23b7296SEd Tanous ethData.nameServers = *nameservers; 3020f6efdc1Smanojkiran.eda@gmail.com } 3030f6efdc1Smanojkiran.eda@gmail.com } 3040f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3050f6efdc1Smanojkiran.eda@gmail.com { 3060f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3078d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3080f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3090f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3100f6efdc1Smanojkiran.eda@gmail.com { 311f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3124a0cb85cSEd Tanous } 3134a0cb85cSEd Tanous } 3142a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3152a133282Smanojkiraneda { 3162c70f800SEd Tanous const std::string* dhcpEnabled = 3171f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3182c70f800SEd Tanous if (dhcpEnabled != nullptr) 3192a133282Smanojkiraneda { 32082695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3212a133282Smanojkiraneda } 3222a133282Smanojkiraneda } 323d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 324d24bfc7aSJennifer Lee { 325d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3268d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 327d24bfc7aSJennifer Lee &propertyPair.second); 328d24bfc7aSJennifer Lee if (domainNames != nullptr) 329d24bfc7aSJennifer Lee { 330f23b7296SEd Tanous ethData.domainnames = *domainNames; 331d24bfc7aSJennifer Lee } 332d24bfc7aSJennifer Lee } 3339010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3349010ec2eSRavi Teja { 3359010ec2eSRavi Teja const std::string* defaultGateway = 3369010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3379010ec2eSRavi Teja if (defaultGateway != nullptr) 3389010ec2eSRavi Teja { 3399010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3409010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3419010ec2eSRavi Teja { 34282695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3439010ec2eSRavi Teja } 3449010ec2eSRavi Teja else 3459010ec2eSRavi Teja { 34682695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3479010ec2eSRavi Teja } 3489010ec2eSRavi Teja } 3499010ec2eSRavi Teja } 3509010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3519010ec2eSRavi Teja { 3529010ec2eSRavi Teja const std::string* defaultGateway6 = 3539010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3549010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3559010ec2eSRavi Teja { 3569010ec2eSRavi Teja std::string defaultGateway6Str = 3579010ec2eSRavi Teja *defaultGateway6; 3589010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3599010ec2eSRavi Teja { 36082695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3619010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3629010ec2eSRavi Teja } 3639010ec2eSRavi Teja else 3649010ec2eSRavi Teja { 36582695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3669010ec2eSRavi Teja defaultGateway6Str; 3679010ec2eSRavi Teja } 3689010ec2eSRavi Teja } 3699010ec2eSRavi Teja } 370029573d4SEd Tanous } 371029573d4SEd Tanous } 372029573d4SEd Tanous } 3731f8c7b5dSJohnathan Mantey 374e4588158SJishnu CM sdbusplus::message::object_path path( 375e4588158SJishnu CM "/xyz/openbmc_project/network"); 376e4588158SJishnu CM sdbusplus::message::object_path dhcp4Path = path / ethifaceId / 377e4588158SJishnu CM "dhcp4"; 378e4588158SJishnu CM 379e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp4Path) 3801f8c7b5dSJohnathan Mantey { 3811f8c7b5dSJohnathan Mantey if (ifacePair.first == 3821f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 3831f8c7b5dSJohnathan Mantey { 3841f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 3851f8c7b5dSJohnathan Mantey { 3861f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 3871f8c7b5dSJohnathan Mantey { 3882c70f800SEd Tanous const bool* dnsEnabled = 3891f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3902c70f800SEd Tanous if (dnsEnabled != nullptr) 3911f8c7b5dSJohnathan Mantey { 392e4588158SJishnu CM ethData.dnsv4Enabled = *dnsEnabled; 3931f8c7b5dSJohnathan Mantey } 3941f8c7b5dSJohnathan Mantey } 395*91c441ecSRavi Teja else if (propertyPair.first == "DomainEnabled") 396*91c441ecSRavi Teja { 397*91c441ecSRavi Teja const bool* domainEnabled = 398*91c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 399*91c441ecSRavi Teja if (domainEnabled != nullptr) 400*91c441ecSRavi Teja { 401*91c441ecSRavi Teja ethData.domainv4Enabled = *domainEnabled; 402*91c441ecSRavi Teja } 403*91c441ecSRavi Teja } 4041f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 4051f8c7b5dSJohnathan Mantey { 4062c70f800SEd Tanous const bool* ntpEnabled = 4071f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4082c70f800SEd Tanous if (ntpEnabled != nullptr) 4091f8c7b5dSJohnathan Mantey { 410e4588158SJishnu CM ethData.ntpv4Enabled = *ntpEnabled; 4111f8c7b5dSJohnathan Mantey } 4121f8c7b5dSJohnathan Mantey } 4131f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 4141f8c7b5dSJohnathan Mantey { 4152c70f800SEd Tanous const bool* hostNameEnabled = 4161f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4172c70f800SEd Tanous if (hostNameEnabled != nullptr) 4181f8c7b5dSJohnathan Mantey { 419e4588158SJishnu CM ethData.hostNamev4Enabled = *hostNameEnabled; 420e4588158SJishnu CM } 421e4588158SJishnu CM } 422e4588158SJishnu CM } 423e4588158SJishnu CM } 424e4588158SJishnu CM } 425e4588158SJishnu CM 426e4588158SJishnu CM sdbusplus::message::object_path dhcp6Path = path / ethifaceId / 427e4588158SJishnu CM "dhcp6"; 428e4588158SJishnu CM 429e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp6Path) 430e4588158SJishnu CM { 431e4588158SJishnu CM if (ifacePair.first == 432e4588158SJishnu CM "xyz.openbmc_project.Network.DHCPConfiguration") 433e4588158SJishnu CM { 434e4588158SJishnu CM for (const auto& propertyPair : ifacePair.second) 435e4588158SJishnu CM { 436e4588158SJishnu CM if (propertyPair.first == "DNSEnabled") 437e4588158SJishnu CM { 438e4588158SJishnu CM const bool* dnsEnabled = 439e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 440e4588158SJishnu CM if (dnsEnabled != nullptr) 441e4588158SJishnu CM { 442e4588158SJishnu CM ethData.dnsv6Enabled = *dnsEnabled; 443e4588158SJishnu CM } 444e4588158SJishnu CM } 445*91c441ecSRavi Teja if (propertyPair.first == "DomainEnabled") 446*91c441ecSRavi Teja { 447*91c441ecSRavi Teja const bool* domainEnabled = 448*91c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 449*91c441ecSRavi Teja if (domainEnabled != nullptr) 450*91c441ecSRavi Teja { 451*91c441ecSRavi Teja ethData.domainv6Enabled = *domainEnabled; 452*91c441ecSRavi Teja } 453*91c441ecSRavi Teja } 454e4588158SJishnu CM else if (propertyPair.first == "NTPEnabled") 455e4588158SJishnu CM { 456e4588158SJishnu CM const bool* ntpEnabled = 457e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 458e4588158SJishnu CM if (ntpEnabled != nullptr) 459e4588158SJishnu CM { 460e4588158SJishnu CM ethData.ntpv6Enabled = *ntpEnabled; 461e4588158SJishnu CM } 462e4588158SJishnu CM } 463e4588158SJishnu CM else if (propertyPair.first == "HostNameEnabled") 464e4588158SJishnu CM { 465e4588158SJishnu CM const bool* hostNameEnabled = 466e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 467e4588158SJishnu CM if (hostNameEnabled != nullptr) 468e4588158SJishnu CM { 469e4588158SJishnu CM ethData.hostNamev6Enabled = *hostNameEnabled; 4701f8c7b5dSJohnathan Mantey } 4711f8c7b5dSJohnathan Mantey } 4721f8c7b5dSJohnathan Mantey } 4731f8c7b5dSJohnathan Mantey } 4741f8c7b5dSJohnathan Mantey } 475029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 476029573d4SEd Tanous // to check eth number 477029573d4SEd Tanous if (ifacePair.first == 4784a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 4794a0cb85cSEd Tanous { 4804a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 4814a0cb85cSEd Tanous { 4824a0cb85cSEd Tanous if (propertyPair.first == "HostName") 4834a0cb85cSEd Tanous { 4844a0cb85cSEd Tanous const std::string* hostname = 4858d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 4864a0cb85cSEd Tanous if (hostname != nullptr) 4874a0cb85cSEd Tanous { 48882695a5bSJiaqing Zhao ethData.hostName = *hostname; 4894a0cb85cSEd Tanous } 4904a0cb85cSEd Tanous } 4914a0cb85cSEd Tanous } 4924a0cb85cSEd Tanous } 4934a0cb85cSEd Tanous } 4944a0cb85cSEd Tanous } 4954c9afe43SEd Tanous return idFound; 4964a0cb85cSEd Tanous } 4974a0cb85cSEd Tanous 498e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 49977179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 500711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 50177179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 502e48c0fc5SRavi Teja { 50389492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 50489492a15SPatrick Williams ethifaceId; 505e48c0fc5SRavi Teja 506e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 507e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 50881ce609eSEd Tanous for (const auto& objpath : dbusData) 509e48c0fc5SRavi Teja { 510e48c0fc5SRavi Teja // Check if proper pattern for object path appears 511353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 512e48c0fc5SRavi Teja { 5139eb808c1SEd Tanous for (const auto& interface : objpath.second) 514e48c0fc5SRavi Teja { 515e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 516e48c0fc5SRavi Teja { 5173544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 518353163e9STony Lee [](const auto& property) { 519353163e9STony Lee return property.first == "Type"; 520353163e9STony Lee }); 521353163e9STony Lee if (type == interface.second.end()) 522353163e9STony Lee { 523353163e9STony Lee continue; 524353163e9STony Lee } 525353163e9STony Lee 526353163e9STony Lee const std::string* typeStr = 527353163e9STony Lee std::get_if<std::string>(&type->second); 528353163e9STony Lee 529353163e9STony Lee if (typeStr == nullptr || 530353163e9STony Lee (*typeStr != 531353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 532353163e9STony Lee { 533353163e9STony Lee continue; 534353163e9STony Lee } 535353163e9STony Lee 536e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 537e48c0fc5SRavi Teja // appropriate 53877179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 5392c70f800SEd Tanous ipv6Address.id = 540353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5419eb808c1SEd Tanous for (const auto& property : interface.second) 542e48c0fc5SRavi Teja { 543e48c0fc5SRavi Teja if (property.first == "Address") 544e48c0fc5SRavi Teja { 545e48c0fc5SRavi Teja const std::string* address = 546e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 547e48c0fc5SRavi Teja if (address != nullptr) 548e48c0fc5SRavi Teja { 5492c70f800SEd Tanous ipv6Address.address = *address; 550e48c0fc5SRavi Teja } 551e48c0fc5SRavi Teja } 552e48c0fc5SRavi Teja else if (property.first == "Origin") 553e48c0fc5SRavi Teja { 554e48c0fc5SRavi Teja const std::string* origin = 555e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 556e48c0fc5SRavi Teja if (origin != nullptr) 557e48c0fc5SRavi Teja { 5582c70f800SEd Tanous ipv6Address.origin = 559e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 560e48c0fc5SRavi Teja false); 561e48c0fc5SRavi Teja } 562e48c0fc5SRavi Teja } 563e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 564e48c0fc5SRavi Teja { 565e48c0fc5SRavi Teja const uint8_t* prefix = 566e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 567e48c0fc5SRavi Teja if (prefix != nullptr) 568e48c0fc5SRavi Teja { 5692c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 570e48c0fc5SRavi Teja } 571e48c0fc5SRavi Teja } 572889ff694SAsmitha Karunanithi else if (property.first == "Type" || 573889ff694SAsmitha Karunanithi property.first == "Gateway") 574889ff694SAsmitha Karunanithi { 575889ff694SAsmitha Karunanithi // Type & Gateway is not used 576889ff694SAsmitha Karunanithi } 577e48c0fc5SRavi Teja else 578e48c0fc5SRavi Teja { 57962598e31SEd Tanous BMCWEB_LOG_ERROR( 58062598e31SEd Tanous "Got extra property: {} on the {} object", 58162598e31SEd Tanous property.first, objpath.first.str); 582e48c0fc5SRavi Teja } 583e48c0fc5SRavi Teja } 584e48c0fc5SRavi Teja } 585e48c0fc5SRavi Teja } 586e48c0fc5SRavi Teja } 587e48c0fc5SRavi Teja } 588e48c0fc5SRavi Teja } 589e48c0fc5SRavi Teja 5904a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 59177179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 592711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 59377179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 5944a0cb85cSEd Tanous { 59589492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 59689492a15SPatrick Williams ethifaceId; 5974a0cb85cSEd Tanous 5984a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 5994a0cb85cSEd Tanous // single ethernet interface, loop over all of them 60081ce609eSEd Tanous for (const auto& objpath : dbusData) 6014a0cb85cSEd Tanous { 6024a0cb85cSEd Tanous // Check if proper pattern for object path appears 603353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 6044a0cb85cSEd Tanous { 6059eb808c1SEd Tanous for (const auto& interface : objpath.second) 6064a0cb85cSEd Tanous { 6074a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 6084a0cb85cSEd Tanous { 6093544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 610353163e9STony Lee [](const auto& property) { 611353163e9STony Lee return property.first == "Type"; 612353163e9STony Lee }); 613353163e9STony Lee if (type == interface.second.end()) 614353163e9STony Lee { 615353163e9STony Lee continue; 616353163e9STony Lee } 617353163e9STony Lee 618353163e9STony Lee const std::string* typeStr = 619353163e9STony Lee std::get_if<std::string>(&type->second); 620353163e9STony Lee 621353163e9STony Lee if (typeStr == nullptr || 622353163e9STony Lee (*typeStr != 623353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 624353163e9STony Lee { 625353163e9STony Lee continue; 626353163e9STony Lee } 627353163e9STony Lee 6284a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 6294a0cb85cSEd Tanous // appropriate 63077179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 6312c70f800SEd Tanous ipv4Address.id = 632353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 6339eb808c1SEd Tanous for (const auto& property : interface.second) 6344a0cb85cSEd Tanous { 6354a0cb85cSEd Tanous if (property.first == "Address") 6364a0cb85cSEd Tanous { 6374a0cb85cSEd Tanous const std::string* address = 638abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6394a0cb85cSEd Tanous if (address != nullptr) 6404a0cb85cSEd Tanous { 6412c70f800SEd Tanous ipv4Address.address = *address; 6424a0cb85cSEd Tanous } 6434a0cb85cSEd Tanous } 6444a0cb85cSEd Tanous else if (property.first == "Origin") 6454a0cb85cSEd Tanous { 6464a0cb85cSEd Tanous const std::string* origin = 647abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6484a0cb85cSEd Tanous if (origin != nullptr) 6494a0cb85cSEd Tanous { 6502c70f800SEd Tanous ipv4Address.origin = 6514a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 6524a0cb85cSEd Tanous true); 6534a0cb85cSEd Tanous } 6544a0cb85cSEd Tanous } 6554a0cb85cSEd Tanous else if (property.first == "PrefixLength") 6564a0cb85cSEd Tanous { 6574a0cb85cSEd Tanous const uint8_t* mask = 658abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 6594a0cb85cSEd Tanous if (mask != nullptr) 6604a0cb85cSEd Tanous { 6614a0cb85cSEd Tanous // convert it to the string 6622c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 6634a0cb85cSEd Tanous } 6644a0cb85cSEd Tanous } 665889ff694SAsmitha Karunanithi else if (property.first == "Type" || 666889ff694SAsmitha Karunanithi property.first == "Gateway") 667889ff694SAsmitha Karunanithi { 668889ff694SAsmitha Karunanithi // Type & Gateway is not used 669889ff694SAsmitha Karunanithi } 6704a0cb85cSEd Tanous else 6714a0cb85cSEd Tanous { 67262598e31SEd Tanous BMCWEB_LOG_ERROR( 67362598e31SEd Tanous "Got extra property: {} on the {} object", 67462598e31SEd Tanous property.first, objpath.first.str); 6754a0cb85cSEd Tanous } 6764a0cb85cSEd Tanous } 6774a0cb85cSEd Tanous // Check if given address is local, or global 6782c70f800SEd Tanous ipv4Address.linktype = 67911ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 68018659d10SJohnathan Mantey ? LinkType::Local 68118659d10SJohnathan Mantey : LinkType::Global; 6824a0cb85cSEd Tanous } 6834a0cb85cSEd Tanous } 6844a0cb85cSEd Tanous } 6854a0cb85cSEd Tanous } 6864a0cb85cSEd Tanous } 687588c3f0dSKowalski, Kamil 688588c3f0dSKowalski, Kamil /** 68901784826SJohnathan Mantey * @brief Deletes given IPv4 interface 690179db1d7SKowalski, Kamil * 691179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 692179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 693179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 694179db1d7SKowalski, Kamil * 695179db1d7SKowalski, Kamil * @return None 696179db1d7SKowalski, Kamil */ 6979c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 6989c5e585cSRavi Teja const std::string& ipHash, 6998d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7001abe55efSEd Tanous { 70155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7025e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 7031abe55efSEd Tanous if (ec) 7041abe55efSEd Tanous { 705a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7061abe55efSEd Tanous } 707179db1d7SKowalski, Kamil }, 708179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 7099c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 710179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 711179db1d7SKowalski, Kamil } 712179db1d7SKowalski, Kamil 713244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway( 714244b6d5bSGunnar Mills const std::string& ifaceId, const std::string& gateway, 715244b6d5bSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7169010ec2eSRavi Teja { 7179ae226faSGeorge Liu sdbusplus::asio::setProperty( 7189ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 7199ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 7209ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 7219ae226faSGeorge Liu gateway, [asyncResp](const boost::system::error_code& ec) { 7229010ec2eSRavi Teja if (ec) 7239010ec2eSRavi Teja { 7249010ec2eSRavi Teja messages::internalError(asyncResp->res); 7259010ec2eSRavi Teja return; 7269010ec2eSRavi Teja } 7279010ec2eSRavi Teja asyncResp->res.result(boost::beast::http::status::no_content); 7289ae226faSGeorge Liu }); 7299010ec2eSRavi Teja } 730179db1d7SKowalski, Kamil /** 73101784826SJohnathan Mantey * @brief Creates a static IPv4 entry 732179db1d7SKowalski, Kamil * 73301784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 73401784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 73501784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 73601784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 737179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 738179db1d7SKowalski, Kamil * 739179db1d7SKowalski, Kamil * @return None 740179db1d7SKowalski, Kamil */ 741cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 742cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7438d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7441abe55efSEd Tanous { 7455a39f77aSPatrick Williams auto createIpHandler = [asyncResp, ifaceId, 7465a39f77aSPatrick Williams gateway](const boost::system::error_code& ec) { 7471abe55efSEd Tanous if (ec) 7481abe55efSEd Tanous { 749a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7509010ec2eSRavi Teja return; 751179db1d7SKowalski, Kamil } 7529010ec2eSRavi Teja updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); 7539010ec2eSRavi Teja }; 7549010ec2eSRavi Teja 7559010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 7569010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 757179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 758179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 75901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 760179db1d7SKowalski, Kamil gateway); 761179db1d7SKowalski, Kamil } 762e48c0fc5SRavi Teja 763e48c0fc5SRavi Teja /** 76401784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 76501784826SJohnathan Mantey * static IPv6 entry 76601784826SJohnathan Mantey * 76701784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 76801784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 76901784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 77001784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 77101784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 77201784826SJohnathan Mantey * 77301784826SJohnathan Mantey * @return None 77401784826SJohnathan Mantey */ 7759c5e585cSRavi Teja 7769c5e585cSRavi Teja enum class IpVersion 7779c5e585cSRavi Teja { 7789c5e585cSRavi Teja IpV4, 7799c5e585cSRavi Teja IpV6 7809c5e585cSRavi Teja }; 7819c5e585cSRavi Teja 7829c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 7839c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 7848d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 7859c5e585cSRavi Teja const std::string& gateway, 7868d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 78701784826SJohnathan Mantey { 78801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7899c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 7909c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 79101784826SJohnathan Mantey if (ec) 79201784826SJohnathan Mantey { 79301784826SJohnathan Mantey messages::internalError(asyncResp->res); 79401784826SJohnathan Mantey } 7959c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 7969c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 79701784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7985e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 79923a21a1cSEd Tanous if (ec2) 80001784826SJohnathan Mantey { 80101784826SJohnathan Mantey messages::internalError(asyncResp->res); 80201784826SJohnathan Mantey } 80301784826SJohnathan Mantey }, 80401784826SJohnathan Mantey "xyz.openbmc_project.Network", 80501784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 8069c5e585cSRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address, 8079c5e585cSRavi Teja prefixLength, gateway); 80801784826SJohnathan Mantey }, 80901784826SJohnathan Mantey "xyz.openbmc_project.Network", 8109c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 81101784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 81201784826SJohnathan Mantey } 81301784826SJohnathan Mantey 81401784826SJohnathan Mantey /** 815e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 816e48c0fc5SRavi Teja * 817e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 818e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 819e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 820e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 821e48c0fc5SRavi Teja * 822e48c0fc5SRavi Teja * @return None 823e48c0fc5SRavi Teja */ 82401784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 82501784826SJohnathan Mantey const std::string& address, 8268d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 827e48c0fc5SRavi Teja { 8285a39f77aSPatrick Williams auto createIpHandler = [asyncResp, 8295a39f77aSPatrick Williams address](const boost::system::error_code& ec) { 830e48c0fc5SRavi Teja if (ec) 831e48c0fc5SRavi Teja { 832fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 833fc23ef8aSNitin Kumar Kotania { 834fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 835fc23ef8aSNitin Kumar Kotania "Address"); 836fc23ef8aSNitin Kumar Kotania } 837fc23ef8aSNitin Kumar Kotania else 838fc23ef8aSNitin Kumar Kotania { 839e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 840e48c0fc5SRavi Teja } 841fc23ef8aSNitin Kumar Kotania } 842e48c0fc5SRavi Teja }; 843e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 8444e0453b1SGunnar Mills // does not have associated gateway property 845e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 846e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 847e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 848e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 849e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 850e48c0fc5SRavi Teja ""); 851e48c0fc5SRavi Teja } 852e48c0fc5SRavi Teja 853179db1d7SKowalski, Kamil /** 854179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 855179db1d7SKowalski, Kamil * Object 856179db1d7SKowalski, Kamil * from EntityManager Network Manager 8574a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 858179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 859179db1d7SKowalski, Kamil * into JSON 860179db1d7SKowalski, Kamil */ 861179db1d7SKowalski, Kamil template <typename CallbackFunc> 86281ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 8631abe55efSEd Tanous CallbackFunc&& callback) 8641abe55efSEd Tanous { 865f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 866f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 867f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 868f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 869f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 8708b24275dSEd Tanous const boost::system::error_code& ec, 87102cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 87255c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 87377179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 87477179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 875179db1d7SKowalski, Kamil 8768b24275dSEd Tanous if (ec) 8771abe55efSEd Tanous { 87801784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 879179db1d7SKowalski, Kamil return; 880179db1d7SKowalski, Kamil } 881179db1d7SKowalski, Kamil 882002d39b4SEd Tanous bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); 8834c9afe43SEd Tanous if (!found) 8844c9afe43SEd Tanous { 88501784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 8864c9afe43SEd Tanous return; 8874c9afe43SEd Tanous } 8884c9afe43SEd Tanous 8892c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 890179db1d7SKowalski, Kamil // Fix global GW 8911abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 8921abe55efSEd Tanous { 893c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 894c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 8959010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 8961abe55efSEd Tanous { 89782695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 898179db1d7SKowalski, Kamil } 899179db1d7SKowalski, Kamil } 900179db1d7SKowalski, Kamil 9012c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 9024e0453b1SGunnar Mills // Finally make a callback with useful data 90301784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 904f5892d0dSGeorge Liu }); 905271584abSEd Tanous } 906179db1d7SKowalski, Kamil 907179db1d7SKowalski, Kamil /** 9089391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 9099391bb9cSRapkiewicz, Pawel * Manager 9101abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 9111abe55efSEd Tanous * into JSON. 9129391bb9cSRapkiewicz, Pawel */ 9139391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 9141abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 9151abe55efSEd Tanous { 916f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 917f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 918f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 919f94c4ecfSEd Tanous [callback{std::forward<CallbackFunc>(callback)}]( 9208b24275dSEd Tanous const boost::system::error_code& ec, 921f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 9221abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 9231abe55efSEd Tanous // ethernet interfaces 92477179532SEd Tanous std::vector<std::string> ifaceList; 9252c70f800SEd Tanous ifaceList.reserve(resp.size()); 9268b24275dSEd Tanous if (ec) 9271abe55efSEd Tanous { 9282c70f800SEd Tanous callback(false, ifaceList); 9299391bb9cSRapkiewicz, Pawel return; 9309391bb9cSRapkiewicz, Pawel } 9319391bb9cSRapkiewicz, Pawel 9329391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 9334a0cb85cSEd Tanous for (const auto& objpath : resp) 9341abe55efSEd Tanous { 9359391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 9364a0cb85cSEd Tanous for (const auto& interface : objpath.second) 9371abe55efSEd Tanous { 9381abe55efSEd Tanous // If interface is 9394a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9404a0cb85cSEd Tanous // what we're looking for. 9419391bb9cSRapkiewicz, Pawel if (interface.first == 9421abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9431abe55efSEd Tanous { 9442dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 9452dfd18efSEd Tanous if (ifaceId.empty()) 9461abe55efSEd Tanous { 9472dfd18efSEd Tanous continue; 9489391bb9cSRapkiewicz, Pawel } 9492dfd18efSEd Tanous // and put it into output vector. 95077179532SEd Tanous ifaceList.emplace_back(ifaceId); 9519391bb9cSRapkiewicz, Pawel } 9529391bb9cSRapkiewicz, Pawel } 9539391bb9cSRapkiewicz, Pawel } 9542c5875a2SEd Tanous 9553544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 9562c5875a2SEd Tanous 957a434f2bdSEd Tanous // Finally make a callback with useful data 9582c70f800SEd Tanous callback(true, ifaceList); 959f5892d0dSGeorge Liu }); 960271584abSEd Tanous } 9619391bb9cSRapkiewicz, Pawel 9624f48d5f6SEd Tanous inline void 9634f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 9648d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 9651abe55efSEd Tanous { 966ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 967ab6554f1SJoshi-Mansi if (hostname.length() > 255) 968ab6554f1SJoshi-Mansi { 969ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 970ab6554f1SJoshi-Mansi "HostName"); 971ab6554f1SJoshi-Mansi return; 972ab6554f1SJoshi-Mansi } 9739ae226faSGeorge Liu sdbusplus::asio::setProperty( 9749ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 9759ae226faSGeorge Liu "/xyz/openbmc_project/network/config", 9769ae226faSGeorge Liu "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname, 9775e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 9784a0cb85cSEd Tanous if (ec) 9794a0cb85cSEd Tanous { 980a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 9811abe55efSEd Tanous } 9829ae226faSGeorge Liu }); 983588c3f0dSKowalski, Kamil } 984588c3f0dSKowalski, Kamil 9854f48d5f6SEd Tanous inline void 98635fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 98735fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 98835fb5311STejas Patil { 98989492a15SPatrick Williams sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" + 99089492a15SPatrick Williams ifaceId; 9919ae226faSGeorge Liu sdbusplus::asio::setProperty( 9929ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath, 9939ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize, 9945e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 99535fb5311STejas Patil if (ec) 99635fb5311STejas Patil { 99735fb5311STejas Patil messages::internalError(asyncResp->res); 99835fb5311STejas Patil } 9999ae226faSGeorge Liu }); 100035fb5311STejas Patil } 100135fb5311STejas Patil 100235fb5311STejas Patil inline void 10034f48d5f6SEd Tanous handleDomainnamePatch(const std::string& ifaceId, 1004bf648f77SEd Tanous const std::string& domainname, 10058d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1006ab6554f1SJoshi-Mansi { 1007ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 10089ae226faSGeorge Liu sdbusplus::asio::setProperty( 10099ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10109ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10119ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 10129ae226faSGeorge Liu vectorDomainname, [asyncResp](const boost::system::error_code& ec) { 1013ab6554f1SJoshi-Mansi if (ec) 1014ab6554f1SJoshi-Mansi { 1015ab6554f1SJoshi-Mansi messages::internalError(asyncResp->res); 1016ab6554f1SJoshi-Mansi } 10179ae226faSGeorge Liu }); 1018ab6554f1SJoshi-Mansi } 1019ab6554f1SJoshi-Mansi 10204f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1021bf648f77SEd Tanous { 1022bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 10233544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1024bf648f77SEd Tanous { 1025bf648f77SEd Tanous return false; 1026bf648f77SEd Tanous } 1027bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1028bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1029bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1030bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 10314b242749SEd Tanous const static std::regex pattern( 1032bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1033bf648f77SEd Tanous 1034bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1035bf648f77SEd Tanous } 1036bf648f77SEd Tanous 10374f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1038bf648f77SEd Tanous { 1039bf648f77SEd Tanous // Can have multiple subdomains 1040bf648f77SEd Tanous // Top Level Domain's min length is 2 character 10414b242749SEd Tanous const static std::regex pattern( 10420fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1043bf648f77SEd Tanous 1044bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1045bf648f77SEd Tanous } 1046bf648f77SEd Tanous 10474f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 10488d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1049ab6554f1SJoshi-Mansi { 1050ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1051ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1052ab6554f1SJoshi-Mansi { 1053ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1054ab6554f1SJoshi-Mansi return; 1055ab6554f1SJoshi-Mansi } 1056ab6554f1SJoshi-Mansi 1057ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1058ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1059ab6554f1SJoshi-Mansi { 1060ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1061ab6554f1SJoshi-Mansi return; 1062ab6554f1SJoshi-Mansi } 1063ab6554f1SJoshi-Mansi 1064ab6554f1SJoshi-Mansi std::string hostname; 1065ab6554f1SJoshi-Mansi std::string domainname; 1066ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1067ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1068ab6554f1SJoshi-Mansi 1069ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1070ab6554f1SJoshi-Mansi { 1071ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1072ab6554f1SJoshi-Mansi return; 1073ab6554f1SJoshi-Mansi } 1074ab6554f1SJoshi-Mansi 1075ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1076ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1077ab6554f1SJoshi-Mansi } 1078ab6554f1SJoshi-Mansi 10794f48d5f6SEd Tanous inline void 10804f48d5f6SEd Tanous handleMACAddressPatch(const std::string& ifaceId, 1081bf648f77SEd Tanous const std::string& macAddress, 10828d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1083d577665bSRatan Gupta { 108458283f41SJohnathan Mantey static constexpr std::string_view dbusNotAllowedError = 108558283f41SJohnathan Mantey "xyz.openbmc_project.Common.Error.NotAllowed"; 108658283f41SJohnathan Mantey 10879ae226faSGeorge Liu sdbusplus::asio::setProperty( 10889ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10899ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10909ae226faSGeorge Liu "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress, 10919ae226faSGeorge Liu [asyncResp](const boost::system::error_code& ec, 10925b378546SPatrick Williams const sdbusplus::message_t& msg) { 1093d577665bSRatan Gupta if (ec) 1094d577665bSRatan Gupta { 109558283f41SJohnathan Mantey const sd_bus_error* err = msg.get_error(); 109658283f41SJohnathan Mantey if (err == nullptr) 109758283f41SJohnathan Mantey { 109858283f41SJohnathan Mantey messages::internalError(asyncResp->res); 109958283f41SJohnathan Mantey return; 110058283f41SJohnathan Mantey } 110158283f41SJohnathan Mantey if (err->name == dbusNotAllowedError) 110258283f41SJohnathan Mantey { 110358283f41SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "MACAddress"); 110458283f41SJohnathan Mantey return; 110558283f41SJohnathan Mantey } 1106d577665bSRatan Gupta messages::internalError(asyncResp->res); 1107d577665bSRatan Gupta return; 1108d577665bSRatan Gupta } 11099ae226faSGeorge Liu }); 1110d577665bSRatan Gupta } 1111286b9118SJohnathan Mantey 11124f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 11134f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 11144f48d5f6SEd Tanous const bool v6Value, 11158d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1116da131a9aSJennifer Lee { 11172c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 11189ae226faSGeorge Liu sdbusplus::asio::setProperty( 11199ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 11209ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 11219ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp, 11225e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1123da131a9aSJennifer Lee if (ec) 1124da131a9aSJennifer Lee { 112562598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1126da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1127da131a9aSJennifer Lee return; 1128da131a9aSJennifer Lee } 11298f7e9c19SJayaprakash Mutyala messages::success(asyncResp->res); 11309ae226faSGeorge Liu }); 1131da131a9aSJennifer Lee } 11321f8c7b5dSJohnathan Mantey 11334f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty( 1134eeedda23SJohnathan Mantey const std::string& ifaceId, const std::string& propertyName, 11358d1b46d7Szhanghch05 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1136eeedda23SJohnathan Mantey { 11379ae226faSGeorge Liu sdbusplus::asio::setProperty( 11389ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 11399ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 11409ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, value, 11415e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1142eeedda23SJohnathan Mantey if (ec) 1143eeedda23SJohnathan Mantey { 114462598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1145eeedda23SJohnathan Mantey messages::internalError(asyncResp->res); 1146eeedda23SJohnathan Mantey return; 1147eeedda23SJohnathan Mantey } 11489ae226faSGeorge Liu }); 1149eeedda23SJohnathan Mantey } 1150eeedda23SJohnathan Mantey 1151e4588158SJishnu CM enum class NetworkType 1152e4588158SJishnu CM { 1153e4588158SJishnu CM dhcp4, 1154e4588158SJishnu CM dhcp6 1155e4588158SJishnu CM }; 1156e4588158SJishnu CM 1157e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1158e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1159e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1160da131a9aSJennifer Lee { 116162598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 1162e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1163e4588158SJishnu CM path /= ethifaceId; 1164e4588158SJishnu CM 1165e4588158SJishnu CM if (type == NetworkType::dhcp4) 1166e4588158SJishnu CM { 1167e4588158SJishnu CM path /= "dhcp4"; 1168e4588158SJishnu CM } 1169e4588158SJishnu CM else 1170e4588158SJishnu CM { 1171e4588158SJishnu CM path /= "dhcp6"; 1172e4588158SJishnu CM } 1173e4588158SJishnu CM 11749ae226faSGeorge Liu sdbusplus::asio::setProperty( 1175e4588158SJishnu CM *crow::connections::systemBus, "xyz.openbmc_project.Network", path, 11769ae226faSGeorge Liu "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value, 11775e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1178da131a9aSJennifer Lee if (ec) 1179da131a9aSJennifer Lee { 118062598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1181da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1182da131a9aSJennifer Lee return; 1183da131a9aSJennifer Lee } 11849ae226faSGeorge Liu }); 1185da131a9aSJennifer Lee } 1186d577665bSRatan Gupta 1187b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1188b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1189b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1190b10d8db0SRavi Teja { 1191b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1192b10d8db0SRavi Teja path /= ifaceId; 1193b10d8db0SRavi Teja sdbusplus::asio::setProperty( 1194b10d8db0SRavi Teja *crow::connections::systemBus, "xyz.openbmc_project.Network", path, 1195b10d8db0SRavi Teja "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA", 1196b10d8db0SRavi Teja ipv6AutoConfigEnabled, 1197b10d8db0SRavi Teja [asyncResp](const boost::system::error_code& ec) { 1198b10d8db0SRavi Teja if (ec) 1199b10d8db0SRavi Teja { 1200b10d8db0SRavi Teja BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1201b10d8db0SRavi Teja messages::internalError(asyncResp->res); 1202b10d8db0SRavi Teja return; 1203b10d8db0SRavi Teja } 1204b10d8db0SRavi Teja messages::success(asyncResp->res); 1205b10d8db0SRavi Teja }); 1206b10d8db0SRavi Teja } 1207b10d8db0SRavi Teja 12084f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId, 12091f8c7b5dSJohnathan Mantey const EthernetInterfaceData& ethData, 1210f23b7296SEd Tanous const DHCPParameters& v4dhcpParms, 1211f23b7296SEd Tanous const DHCPParameters& v6dhcpParms, 12128d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1213da131a9aSJennifer Lee { 121482695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 121582695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1216da131a9aSJennifer Lee 12171f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 12181f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 12191f8c7b5dSJohnathan Mantey 12201f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 12211f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1222da131a9aSJennifer Lee { 1223b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 12241f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 12251f8c7b5dSJohnathan Mantey { 1226bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1227bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 12281f8c7b5dSJohnathan Mantey "OperatingMode"); 1229da131a9aSJennifer Lee return; 1230da131a9aSJennifer Lee } 1231b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 12321f8c7b5dSJohnathan Mantey } 12331f8c7b5dSJohnathan Mantey else 1234da131a9aSJennifer Lee { 12351f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 12361f8c7b5dSJohnathan Mantey } 12371f8c7b5dSJohnathan Mantey 1238e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1239e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1240e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 12411f8c7b5dSJohnathan Mantey { 1242e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 12431f8c7b5dSJohnathan Mantey } 1244e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 12451f8c7b5dSJohnathan Mantey { 1246e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 12471f8c7b5dSJohnathan Mantey } 12481f8c7b5dSJohnathan Mantey 1249e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1250e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1251e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 12521f8c7b5dSJohnathan Mantey { 1253e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 12541f8c7b5dSJohnathan Mantey } 1255e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 12561f8c7b5dSJohnathan Mantey { 1257e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 12581f8c7b5dSJohnathan Mantey } 12591f8c7b5dSJohnathan Mantey 1260*91c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 1261*91c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1262e4588158SJishnu CM if (v4dhcpParms.useDomainName) 12631f8c7b5dSJohnathan Mantey { 1264e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 12651f8c7b5dSJohnathan Mantey } 1266e4588158SJishnu CM if (v6dhcpParms.useDomainName) 12671f8c7b5dSJohnathan Mantey { 1268e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 12691f8c7b5dSJohnathan Mantey } 12701f8c7b5dSJohnathan Mantey 127162598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 12721f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 12731f8c7b5dSJohnathan Mantey asyncResp); 127462598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1275e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1276e4588158SJishnu CM NetworkType::dhcp4); 127762598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1278e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1279e4588158SJishnu CM NetworkType::dhcp4); 1280*91c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 1281*91c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1282e4588158SJishnu CM NetworkType::dhcp4); 1283e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1284e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1285e4588158SJishnu CM NetworkType::dhcp6); 1286e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1287e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1288e4588158SJishnu CM NetworkType::dhcp6); 1289*91c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 1290*91c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1291e4588158SJishnu CM NetworkType::dhcp6); 1292da131a9aSJennifer Lee } 129301784826SJohnathan Mantey 129477179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 129577179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 129677179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 129701784826SJohnathan Mantey { 129817a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 129917a897dfSManojkiran Eda return value.origin == "Static"; 130017a897dfSManojkiran Eda }); 130101784826SJohnathan Mantey } 130201784826SJohnathan Mantey 130377179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 130477179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 130577179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 130601784826SJohnathan Mantey { 130717a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 130817a897dfSManojkiran Eda return value.origin == "Static"; 130917a897dfSManojkiran Eda }); 131001784826SJohnathan Mantey } 131101784826SJohnathan Mantey 131277179532SEd Tanous inline void 1313ddd70dcaSEd Tanous handleIPv4StaticPatch(const std::string& ifaceId, 1314ddd70dcaSEd Tanous nlohmann::json::array_t& input, 131577179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 13168d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 13171abe55efSEd Tanous { 1318ddd70dcaSEd Tanous if (input.empty()) 1319f476acbfSRatan Gupta { 13202e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1321d1d50814SRavi Teja "IPv4StaticAddresses"); 1322f476acbfSRatan Gupta return; 1323f476acbfSRatan Gupta } 1324f476acbfSRatan Gupta 1325271584abSEd Tanous unsigned entryIdx = 1; 132601784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 132701784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 132801784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 132901784826SJohnathan Mantey // into the NIC. 133077179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 13312c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 133201784826SJohnathan Mantey 1333537174c4SEd Tanous for (nlohmann::json& thisJson : input) 13341abe55efSEd Tanous { 133589492a15SPatrick Williams std::string pathString = "IPv4StaticAddresses/" + 133689492a15SPatrick Williams std::to_string(entryIdx); 1337179db1d7SKowalski, Kamil 133801784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1339f476acbfSRatan Gupta { 1340537174c4SEd Tanous std::optional<std::string> address; 1341537174c4SEd Tanous std::optional<std::string> subnetMask; 1342537174c4SEd Tanous std::optional<std::string> gateway; 1343537174c4SEd Tanous 1344537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 13457e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 13467e27d832SJohnathan Mantey "Gateway", gateway)) 1347537174c4SEd Tanous { 1348f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 134971f52d96SEd Tanous pathString); 1350537174c4SEd Tanous return; 1351179db1d7SKowalski, Kamil } 1352179db1d7SKowalski, Kamil 135301784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 135401784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 135501784826SJohnathan Mantey // current state of the interface. Merge existing state into the 135601784826SJohnathan Mantey // current request. 1357537174c4SEd Tanous if (address) 13581abe55efSEd Tanous { 1359e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 136001784826SJohnathan Mantey { 1361bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1362bf648f77SEd Tanous pathString + "/Address"); 1363e01d0c36SEd Tanous return; 136401784826SJohnathan Mantey } 136501784826SJohnathan Mantey } 136685ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 136701784826SJohnathan Mantey { 1368e01d0c36SEd Tanous address = (nicIpEntry->address); 136901784826SJohnathan Mantey } 137001784826SJohnathan Mantey else 137101784826SJohnathan Mantey { 137201784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 137301784826SJohnathan Mantey pathString + "/Address"); 1374e01d0c36SEd Tanous return; 13754a0cb85cSEd Tanous } 13764a0cb85cSEd Tanous 1377e01d0c36SEd Tanous uint8_t prefixLength = 0; 1378537174c4SEd Tanous if (subnetMask) 13794a0cb85cSEd Tanous { 1380033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1381033f1e4dSEd Tanous &prefixLength)) 13824a0cb85cSEd Tanous { 1383f12894f8SJason M. Bills messages::propertyValueFormatError( 1384537174c4SEd Tanous asyncResp->res, *subnetMask, 13854a0cb85cSEd Tanous pathString + "/SubnetMask"); 1386e01d0c36SEd Tanous return; 13874a0cb85cSEd Tanous } 13884a0cb85cSEd Tanous } 138985ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 13904a0cb85cSEd Tanous { 1391033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 139201784826SJohnathan Mantey &prefixLength)) 13934a0cb85cSEd Tanous { 139401784826SJohnathan Mantey messages::propertyValueFormatError( 139585ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 139601784826SJohnathan Mantey pathString + "/SubnetMask"); 1397e01d0c36SEd Tanous return; 13984a0cb85cSEd Tanous } 13994a0cb85cSEd Tanous } 14001abe55efSEd Tanous else 14011abe55efSEd Tanous { 140201784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 140301784826SJohnathan Mantey pathString + "/SubnetMask"); 1404e01d0c36SEd Tanous return; 140501784826SJohnathan Mantey } 140601784826SJohnathan Mantey 140701784826SJohnathan Mantey if (gateway) 140801784826SJohnathan Mantey { 1409e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 141001784826SJohnathan Mantey { 1411bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1412bf648f77SEd Tanous pathString + "/Gateway"); 1413e01d0c36SEd Tanous return; 141401784826SJohnathan Mantey } 141501784826SJohnathan Mantey } 141685ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 141701784826SJohnathan Mantey { 1418e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 141901784826SJohnathan Mantey } 142001784826SJohnathan Mantey else 14211abe55efSEd Tanous { 1422a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 14234a0cb85cSEd Tanous pathString + "/Gateway"); 142401784826SJohnathan Mantey return; 14254a0cb85cSEd Tanous } 14264a0cb85cSEd Tanous 142785ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 14281abe55efSEd Tanous { 14299c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 143077eb0153SEd Tanous nicIpEntry->id, prefixLength, *address, 143177eb0153SEd Tanous *gateway, asyncResp); 143289492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 143389492a15SPatrick Williams ipv4Data.cend()); 1434588c3f0dSKowalski, Kamil } 143501784826SJohnathan Mantey else 143601784826SJohnathan Mantey { 1437cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1438cb13a392SEd Tanous asyncResp); 14394a0cb85cSEd Tanous } 14404a0cb85cSEd Tanous entryIdx++; 14414a0cb85cSEd Tanous } 144201784826SJohnathan Mantey else 144301784826SJohnathan Mantey { 144485ffe86aSJiaqing Zhao if (nicIpEntry == ipv4Data.cend()) 144501784826SJohnathan Mantey { 144601784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 144701784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 144801784826SJohnathan Mantey // in error, so bail out. 144901784826SJohnathan Mantey if (thisJson.is_null()) 145001784826SJohnathan Mantey { 145101784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 145201784826SJohnathan Mantey return; 145301784826SJohnathan Mantey } 1454f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 145571f52d96SEd Tanous pathString); 145601784826SJohnathan Mantey return; 145701784826SJohnathan Mantey } 145801784826SJohnathan Mantey 145901784826SJohnathan Mantey if (thisJson.is_null()) 146001784826SJohnathan Mantey { 14619c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 146201784826SJohnathan Mantey } 146385ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 146401784826SJohnathan Mantey { 146589492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 146689492a15SPatrick Williams ipv4Data.cend()); 146701784826SJohnathan Mantey } 146801784826SJohnathan Mantey entryIdx++; 146901784826SJohnathan Mantey } 147001784826SJohnathan Mantey } 14714a0cb85cSEd Tanous } 14724a0cb85cSEd Tanous 14734f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1474f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1475f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 14768d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1477f85837bfSRAJESWARAN THILLAIGOVINDAN { 14789ae226faSGeorge Liu sdbusplus::asio::setProperty( 14799ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 14809ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 14819ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 14829ae226faSGeorge Liu updatedStaticNameServers, 14835e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1484f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1485f85837bfSRAJESWARAN THILLAIGOVINDAN { 1486f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1487f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1488f85837bfSRAJESWARAN THILLAIGOVINDAN } 14899ae226faSGeorge Liu }); 1490f85837bfSRAJESWARAN THILLAIGOVINDAN } 1491f85837bfSRAJESWARAN THILLAIGOVINDAN 14924f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 1493ddd70dcaSEd Tanous const std::string& ifaceId, const nlohmann::json::array_t& input, 149477179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 14958d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1496e48c0fc5SRavi Teja { 1497ddd70dcaSEd Tanous if (input.empty()) 1498e48c0fc5SRavi Teja { 14992e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1500e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1501e48c0fc5SRavi Teja return; 1502e48c0fc5SRavi Teja } 1503271584abSEd Tanous size_t entryIdx = 1; 150477179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 15052c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1506f23b7296SEd Tanous for (const nlohmann::json& thisJson : input) 1507e48c0fc5SRavi Teja { 150889492a15SPatrick Williams std::string pathString = "IPv6StaticAddresses/" + 150989492a15SPatrick Williams std::to_string(entryIdx); 1510e48c0fc5SRavi Teja 151101784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1512e48c0fc5SRavi Teja { 1513e48c0fc5SRavi Teja std::optional<std::string> address; 1514e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1515f23b7296SEd Tanous nlohmann::json thisJsonCopy = thisJson; 1516bf648f77SEd Tanous if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 1517bf648f77SEd Tanous address, "PrefixLength", prefixLength)) 1518e48c0fc5SRavi Teja { 1519f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 152071f52d96SEd Tanous pathString); 1521e48c0fc5SRavi Teja return; 1522e48c0fc5SRavi Teja } 1523e48c0fc5SRavi Teja 1524543f4400SEd Tanous const std::string* addr = nullptr; 1525543f4400SEd Tanous uint8_t prefix = 0; 152601784826SJohnathan Mantey 152701784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 152801784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 152901784826SJohnathan Mantey // current state of the interface. Merge existing state into the 153001784826SJohnathan Mantey // current request. 1531e48c0fc5SRavi Teja if (address) 1532e48c0fc5SRavi Teja { 153301784826SJohnathan Mantey addr = &(*address); 1534e48c0fc5SRavi Teja } 153585ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 153601784826SJohnathan Mantey { 153785ffe86aSJiaqing Zhao addr = &(nicIpEntry->address); 153801784826SJohnathan Mantey } 153901784826SJohnathan Mantey else 154001784826SJohnathan Mantey { 154101784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 154201784826SJohnathan Mantey pathString + "/Address"); 154301784826SJohnathan Mantey return; 1544e48c0fc5SRavi Teja } 1545e48c0fc5SRavi Teja 1546e48c0fc5SRavi Teja if (prefixLength) 1547e48c0fc5SRavi Teja { 154801784826SJohnathan Mantey prefix = *prefixLength; 154901784826SJohnathan Mantey } 155085ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 1551e48c0fc5SRavi Teja { 155285ffe86aSJiaqing Zhao prefix = nicIpEntry->prefixLength; 1553e48c0fc5SRavi Teja } 1554e48c0fc5SRavi Teja else 1555e48c0fc5SRavi Teja { 1556e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1557e48c0fc5SRavi Teja pathString + "/PrefixLength"); 155801784826SJohnathan Mantey return; 1559e48c0fc5SRavi Teja } 1560e48c0fc5SRavi Teja 156185ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1562e48c0fc5SRavi Teja { 15639c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 156477eb0153SEd Tanous nicIpEntry->id, prefix, *addr, "", 1565e48c0fc5SRavi Teja asyncResp); 156689492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 156789492a15SPatrick Williams ipv6Data.cend()); 156801784826SJohnathan Mantey } 156901784826SJohnathan Mantey else 157001784826SJohnathan Mantey { 157101784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1572e48c0fc5SRavi Teja } 1573e48c0fc5SRavi Teja entryIdx++; 1574e48c0fc5SRavi Teja } 157501784826SJohnathan Mantey else 157601784826SJohnathan Mantey { 157785ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 157801784826SJohnathan Mantey { 157901784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 158001784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 158101784826SJohnathan Mantey // in error, so bail out. 158201784826SJohnathan Mantey if (thisJson.is_null()) 158301784826SJohnathan Mantey { 158401784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 158501784826SJohnathan Mantey return; 158601784826SJohnathan Mantey } 1587f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 158871f52d96SEd Tanous pathString); 158901784826SJohnathan Mantey return; 159001784826SJohnathan Mantey } 159101784826SJohnathan Mantey 159201784826SJohnathan Mantey if (thisJson.is_null()) 159301784826SJohnathan Mantey { 15949c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 159501784826SJohnathan Mantey } 159685ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 159701784826SJohnathan Mantey { 159889492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 159989492a15SPatrick Williams ipv6Data.cend()); 160001784826SJohnathan Mantey } 160101784826SJohnathan Mantey entryIdx++; 160201784826SJohnathan Mantey } 160301784826SJohnathan Mantey } 1604e48c0fc5SRavi Teja } 1605e48c0fc5SRavi Teja 16067857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 16077857cb8dSJiaqing Zhao { 16087857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 16097857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 16107857cb8dSJiaqing Zhao } 16117857cb8dSJiaqing Zhao 161277179532SEd Tanous inline void 161377179532SEd Tanous parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 161477179532SEd Tanous const std::string& ifaceId, 161577179532SEd Tanous const EthernetInterfaceData& ethData, 161677179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 161777179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) 16184a0cb85cSEd Tanous { 16192c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 162081ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1621ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 1622ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId); 16232c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1624eeedda23SJohnathan Mantey 162513451e39SWilly Tu if constexpr (bmcwebEnableHealthPopulate) 162613451e39SWilly Tu { 162713451e39SWilly Tu constexpr std::array<std::string_view, 1> inventoryForEthernet = { 162813451e39SWilly Tu "xyz.openbmc_project.Inventory.Item.Ethernet"}; 1629eeedda23SJohnathan Mantey auto health = std::make_shared<HealthPopulate>(asyncResp); 16307a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 16317a1dbc48SGeorge Liu "/", 0, inventoryForEthernet, 16327a1dbc48SGeorge Liu [health](const boost::system::error_code& ec, 1633b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& resp) { 1634eeedda23SJohnathan Mantey if (ec) 1635029573d4SEd Tanous { 1636eeedda23SJohnathan Mantey return; 1637eeedda23SJohnathan Mantey } 1638eeedda23SJohnathan Mantey 1639914e2d5dSEd Tanous health->inventory = resp; 16407a1dbc48SGeorge Liu }); 1641eeedda23SJohnathan Mantey 1642eeedda23SJohnathan Mantey health->populate(); 164313451e39SWilly Tu } 1644eeedda23SJohnathan Mantey 1645eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1646eeedda23SJohnathan Mantey { 16470ef0e289SJohnathan Mantey jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 16482c70f800SEd Tanous jsonResponse["Status"]["State"] = "Enabled"; 1649029573d4SEd Tanous } 1650029573d4SEd Tanous else 1651029573d4SEd Tanous { 16522c70f800SEd Tanous jsonResponse["LinkStatus"] = "NoLink"; 16532c70f800SEd Tanous jsonResponse["Status"]["State"] = "Disabled"; 1654029573d4SEd Tanous } 1655aa05fb27SJohnathan Mantey 16562c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 165735fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 165882695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 16592c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 166082695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1661e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1662e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1663e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled; 16642c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1665b10d8db0SRavi Teja translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled" 16661f8c7b5dSJohnathan Mantey : "Disabled"; 1667e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1668e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1669e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled; 1670b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1671b10d8db0SRavi Teja ethData.ipv6AcceptRa; 16722a133282Smanojkiraneda 167382695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 16744a0cb85cSEd Tanous { 167582695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1676ab6554f1SJoshi-Mansi 1677ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1678ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1679ab6554f1SJoshi-Mansi // FQDN 168082695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1681d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1682d24bfc7aSJennifer Lee { 16832c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1684d24bfc7aSJennifer Lee } 16852c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 16864a0cb85cSEd Tanous } 16874a0cb85cSEd Tanous 16887857cb8dSJiaqing Zhao if (ethData.vlanId) 16897857cb8dSJiaqing Zhao { 16907857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Virtual"; 16917857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 16927857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 16937857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 16947857cb8dSJiaqing Zhao 16957857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 16967857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 16977857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 16987857cb8dSJiaqing Zhao boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces", 16997857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 17007857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 17017857cb8dSJiaqing Zhao std::move(relatedInterfaces); 17027857cb8dSJiaqing Zhao } 17037857cb8dSJiaqing Zhao else 17047857cb8dSJiaqing Zhao { 17057857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Physical"; 17067857cb8dSJiaqing Zhao } 17077857cb8dSJiaqing Zhao 17082c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 17092c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 17104a0cb85cSEd Tanous 17112c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 17122c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 17132c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 17142c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 17159eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 17164a0cb85cSEd Tanous { 17172c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1718fa5053a6SGunnar Mills if (gatewayStr.empty()) 1719fa5053a6SGunnar Mills { 1720fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1721fa5053a6SGunnar Mills } 17221476687dSEd Tanous nlohmann::json::object_t ipv4; 17231476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 17241476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 17251476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 17261476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1727fa5053a6SGunnar Mills 17282c70f800SEd Tanous if (ipv4Config.origin == "Static") 1729d1d50814SRavi Teja { 17301476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1731d1d50814SRavi Teja } 17321476687dSEd Tanous 1733b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 173401784826SJohnathan Mantey } 1735d1d50814SRavi Teja 173682695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 17377ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 17387ea79e5eSRavi Teja { 17397ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 17407ea79e5eSRavi Teja } 17417ea79e5eSRavi Teja 17427ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1743e48c0fc5SRavi Teja 17442c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 17452c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 17462c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 17472c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 17487f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 17492c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 17507f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 17519eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1752e48c0fc5SRavi Teja { 17531476687dSEd Tanous nlohmann::json::object_t ipv6; 17541476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 17551476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 17561476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1757f8361275SSunitha Harish 1758b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 17592c70f800SEd Tanous if (ipv6Config.origin == "Static") 1760e48c0fc5SRavi Teja { 17611476687dSEd Tanous nlohmann::json::object_t ipv6Static; 17621476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 17631476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 1764b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 176501784826SJohnathan Mantey } 1766e48c0fc5SRavi Teja } 1767588c3f0dSKowalski, Kamil } 1768588c3f0dSKowalski, Kamil 1769e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1770e7caf250SJiaqing Zhao const std::string& ifaceId, 1771e7caf250SJiaqing Zhao const boost::system::error_code& ec, 1772e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 1773e7caf250SJiaqing Zhao { 1774e7caf250SJiaqing Zhao if (!ec) 1775e7caf250SJiaqing Zhao { 1776e7caf250SJiaqing Zhao return; 1777e7caf250SJiaqing Zhao } 1778e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1779e7caf250SJiaqing Zhao if (dbusError == nullptr) 1780e7caf250SJiaqing Zhao { 1781e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1782e7caf250SJiaqing Zhao return; 1783e7caf250SJiaqing Zhao } 178462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1785e7caf250SJiaqing Zhao 1786e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 1787e7caf250SJiaqing Zhao dbusError->name) 1788e7caf250SJiaqing Zhao { 1789e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1790e7caf250SJiaqing Zhao ifaceId); 1791e7caf250SJiaqing Zhao return; 1792e7caf250SJiaqing Zhao } 1793e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 1794e7caf250SJiaqing Zhao dbusError->name) 1795e7caf250SJiaqing Zhao { 1796e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 1797e7caf250SJiaqing Zhao return; 1798e7caf250SJiaqing Zhao } 1799e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1800e7caf250SJiaqing Zhao } 1801e7caf250SJiaqing Zhao 1802b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1803b5ca3fdcSJiaqing Zhao const std::string& parentInterfaceUri, 1804b5ca3fdcSJiaqing Zhao const std::string& vlanInterface, 1805b5ca3fdcSJiaqing Zhao const boost::system::error_code& ec, 1806b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m 1807b5ca3fdcSJiaqing Zhao 1808b5ca3fdcSJiaqing Zhao ) 1809b5ca3fdcSJiaqing Zhao { 1810b5ca3fdcSJiaqing Zhao if (ec) 1811b5ca3fdcSJiaqing Zhao { 1812b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1813b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 1814b5ca3fdcSJiaqing Zhao { 1815b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1816b5ca3fdcSJiaqing Zhao return; 1817b5ca3fdcSJiaqing Zhao } 181862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1819b5ca3fdcSJiaqing Zhao 1820b5ca3fdcSJiaqing Zhao if (std::string_view( 1821b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 1822b5ca3fdcSJiaqing Zhao dbusError->name) 1823b5ca3fdcSJiaqing Zhao { 1824b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1825b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1826b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1827b5ca3fdcSJiaqing Zhao return; 1828b5ca3fdcSJiaqing Zhao } 1829b5ca3fdcSJiaqing Zhao if (std::string_view( 1830b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 1831b5ca3fdcSJiaqing Zhao dbusError->name) 1832b5ca3fdcSJiaqing Zhao { 1833b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 1834b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 1835b5ca3fdcSJiaqing Zhao return; 1836b5ca3fdcSJiaqing Zhao } 1837b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1838b5ca3fdcSJiaqing Zhao return; 1839b5ca3fdcSJiaqing Zhao } 1840b5ca3fdcSJiaqing Zhao 1841b5ca3fdcSJiaqing Zhao const boost::urls::url vlanInterfaceUri = boost::urls::format( 1842b5ca3fdcSJiaqing Zhao "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface); 1843b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 1844b5ca3fdcSJiaqing Zhao } 1845b5ca3fdcSJiaqing Zhao 1846bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 1847bf648f77SEd Tanous { 1848bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 1849ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 18501476687dSEd Tanous .methods(boost::beast::http::verb::get)( 18511476687dSEd Tanous [&app](const crow::Request& req, 18521476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 18533ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 185445ca1b86SEd Tanous { 185545ca1b86SEd Tanous return; 185645ca1b86SEd Tanous } 185745ca1b86SEd Tanous 1858bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1859bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 1860bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1861bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 1862bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 1863bf648f77SEd Tanous "Ethernet Network Interface Collection"; 1864bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 1865bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 1866bf648f77SEd Tanous 1867bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 1868bf648f77SEd Tanous // preparation 1869002d39b4SEd Tanous getEthernetIfaceList( 187077179532SEd Tanous [asyncResp](const bool& success, 187177179532SEd Tanous const std::vector<std::string>& ifaceList) { 1872bf648f77SEd Tanous if (!success) 18731abe55efSEd Tanous { 1874f12894f8SJason M. Bills messages::internalError(asyncResp->res); 18759391bb9cSRapkiewicz, Pawel return; 18769391bb9cSRapkiewicz, Pawel } 18779391bb9cSRapkiewicz, Pawel 1878002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 1879bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 1880bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 1881bf648f77SEd Tanous { 18821476687dSEd Tanous nlohmann::json::object_t iface; 1883ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 1884ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", 1885ef4c65b7SEd Tanous ifaceItem); 18867857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 1887bf648f77SEd Tanous } 1888bf648f77SEd Tanous 1889002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 1890bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1891bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 1892bf648f77SEd Tanous }); 1893bf648f77SEd Tanous }); 1894bf648f77SEd Tanous 1895b5ca3fdcSJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 1896b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 1897b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 1898b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 1899b5ca3fdcSJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1900b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1901b5ca3fdcSJiaqing Zhao { 1902b5ca3fdcSJiaqing Zhao return; 1903b5ca3fdcSJiaqing Zhao } 1904b5ca3fdcSJiaqing Zhao 1905b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 1906b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 1907b5ca3fdcSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 1908b5ca3fdcSJiaqing Zhao 1909b5ca3fdcSJiaqing Zhao if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", 1910b5ca3fdcSJiaqing Zhao vlanEnable, "VLAN/VLANId", vlanId, 1911b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 1912b5ca3fdcSJiaqing Zhao relatedInterfaces)) 1913b5ca3fdcSJiaqing Zhao { 1914b5ca3fdcSJiaqing Zhao return; 1915b5ca3fdcSJiaqing Zhao } 1916b5ca3fdcSJiaqing Zhao 1917b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 1918b5ca3fdcSJiaqing Zhao { 1919b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 1920b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 1921b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 1922b5ca3fdcSJiaqing Zhao return; 1923b5ca3fdcSJiaqing Zhao } 1924b5ca3fdcSJiaqing Zhao 1925b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 1926b5ca3fdcSJiaqing Zhao if (!json_util::readJson(relatedInterfaces[0], asyncResp->res, 1927b5ca3fdcSJiaqing Zhao "@odata.id", parentInterfaceUri)) 1928b5ca3fdcSJiaqing Zhao { 1929b5ca3fdcSJiaqing Zhao messages::propertyMissing(asyncResp->res, 1930b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1931b5ca3fdcSJiaqing Zhao return; 1932b5ca3fdcSJiaqing Zhao } 193362598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 1934b5ca3fdcSJiaqing Zhao 19356fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 1936b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 1937b5ca3fdcSJiaqing Zhao if (!parsedUri) 1938b5ca3fdcSJiaqing Zhao { 1939b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 1940b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1941b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1942b5ca3fdcSJiaqing Zhao return; 1943b5ca3fdcSJiaqing Zhao } 1944b5ca3fdcSJiaqing Zhao 1945b5ca3fdcSJiaqing Zhao std::string parentInterface; 1946b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 1947b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 1948b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 1949b5ca3fdcSJiaqing Zhao { 1950b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1951b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1952b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1953b5ca3fdcSJiaqing Zhao return; 1954b5ca3fdcSJiaqing Zhao } 1955b5ca3fdcSJiaqing Zhao 1956b5ca3fdcSJiaqing Zhao if (!vlanEnable) 1957b5ca3fdcSJiaqing Zhao { 1958b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 1959b5ca3fdcSJiaqing Zhao // create 1960b5ca3fdcSJiaqing Zhao messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", 1961b5ca3fdcSJiaqing Zhao "false"); 1962b5ca3fdcSJiaqing Zhao return; 1963b5ca3fdcSJiaqing Zhao } 1964b5ca3fdcSJiaqing Zhao 1965b5ca3fdcSJiaqing Zhao std::string vlanInterface = parentInterface + "_" + 1966b5ca3fdcSJiaqing Zhao std::to_string(vlanId); 1967b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 1968b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 1969b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 1970b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 1971b5ca3fdcSJiaqing Zhao afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, 1972b5ca3fdcSJiaqing Zhao m); 1973b5ca3fdcSJiaqing Zhao }, 1974b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 1975b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, 1976b5ca3fdcSJiaqing Zhao vlanId); 1977b5ca3fdcSJiaqing Zhao }); 1978b5ca3fdcSJiaqing Zhao 1979bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 1980ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 1981bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 198245ca1b86SEd Tanous [&app](const crow::Request& req, 1983bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1984bf648f77SEd Tanous const std::string& ifaceId) { 19853ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 198645ca1b86SEd Tanous { 198745ca1b86SEd Tanous return; 198845ca1b86SEd Tanous } 19894a0cb85cSEd Tanous getEthernetIfaceData( 1990bf648f77SEd Tanous ifaceId, 199177179532SEd Tanous [asyncResp, ifaceId](const bool& success, 199277179532SEd Tanous const EthernetInterfaceData& ethData, 199377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 199477179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) { 19954a0cb85cSEd Tanous if (!success) 19961abe55efSEd Tanous { 1997bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 1998bf648f77SEd Tanous // existing object, and other errors 1999002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2000002d39b4SEd Tanous ifaceId); 20014a0cb85cSEd Tanous return; 20029391bb9cSRapkiewicz, Pawel } 20034c9afe43SEd Tanous 20040f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 200593bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2006002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 20070f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 20080f74e643SEd Tanous "Management Network Interface"; 20090f74e643SEd Tanous 2010002d39b4SEd Tanous parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data); 20119391bb9cSRapkiewicz, Pawel }); 2012bf648f77SEd Tanous }); 20139391bb9cSRapkiewicz, Pawel 2014bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2015ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2016bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 201745ca1b86SEd Tanous [&app](const crow::Request& req, 2018bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2019bf648f77SEd Tanous const std::string& ifaceId) { 20203ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 202145ca1b86SEd Tanous { 202245ca1b86SEd Tanous return; 202345ca1b86SEd Tanous } 2024bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2025ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2026d577665bSRatan Gupta std::optional<std::string> macAddress; 20279a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2028ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv4StaticAddresses; 2029ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv6StaticAddresses; 2030f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2031da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 20321f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 2033b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2034eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 203535fb5311STejas Patil std::optional<size_t> mtuSize; 20361f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 20371f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2038b10d8db0SRavi Teja // clang-format off 203915ed6780SWilly Tu if (!json_util::readJsonPatch( 2040b10d8db0SRavi Teja req, asyncResp->res, 2041b10d8db0SRavi Teja "DHCPv4", dhcpv4, 2042b10d8db0SRavi Teja "DHCPv6", dhcpv6, 2043b10d8db0SRavi Teja "FQDN", fqdn, 2044b10d8db0SRavi Teja "HostName", hostname, 2045b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 2046b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 2047b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 2048b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 2049b10d8db0SRavi Teja "MACAddress", macAddress, 2050b10d8db0SRavi Teja "MTUSize", mtuSize, 2051b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 2052b10d8db0SRavi Teja "StaticNameServers", staticNameServers 2053b10d8db0SRavi Teja ) 2054b10d8db0SRavi Teja ) 20551abe55efSEd Tanous { 2056588c3f0dSKowalski, Kamil return; 2057588c3f0dSKowalski, Kamil } 2058b10d8db0SRavi Teja //clang-format on 2059da131a9aSJennifer Lee if (dhcpv4) 2060da131a9aSJennifer Lee { 2061002d39b4SEd Tanous if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 20621f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 206382695a5bSJiaqing Zhao v4dhcpParms.useDnsServers, "UseNTPServers", 206482695a5bSJiaqing Zhao v4dhcpParms.useNtpServers, "UseDomainName", 206582695a5bSJiaqing Zhao v4dhcpParms.useDomainName)) 20661f8c7b5dSJohnathan Mantey { 20671f8c7b5dSJohnathan Mantey return; 20681f8c7b5dSJohnathan Mantey } 20691f8c7b5dSJohnathan Mantey } 20701f8c7b5dSJohnathan Mantey 20711f8c7b5dSJohnathan Mantey if (dhcpv6) 20721f8c7b5dSJohnathan Mantey { 2073002d39b4SEd Tanous if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode", 2074002d39b4SEd Tanous v6dhcpParms.dhcpv6OperatingMode, 2075002d39b4SEd Tanous "UseDNSServers", v6dhcpParms.useDnsServers, 2076002d39b4SEd Tanous "UseNTPServers", v6dhcpParms.useNtpServers, 2077002d39b4SEd Tanous "UseDomainName", 207882695a5bSJiaqing Zhao v6dhcpParms.useDomainName)) 20791f8c7b5dSJohnathan Mantey { 20801f8c7b5dSJohnathan Mantey return; 20811f8c7b5dSJohnathan Mantey } 2082da131a9aSJennifer Lee } 2083da131a9aSJennifer Lee 2084bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2085bf648f77SEd Tanous // for JSON preparation 20864a0cb85cSEd Tanous getEthernetIfaceData( 20872c70f800SEd Tanous ifaceId, 2088bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2089ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2090d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 20919a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2092e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 20931f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 2094bc20089aSEd Tanous dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize, 2095b10d8db0SRavi Teja ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms), 2096f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2097002d39b4SEd Tanous const bool& success, const EthernetInterfaceData& ethData, 209877179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 209977179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) { 21001abe55efSEd Tanous if (!success) 21011abe55efSEd Tanous { 2102588c3f0dSKowalski, Kamil // ... otherwise return error 2103bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2104bf648f77SEd Tanous // existing object, and other errors 2105002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2106002d39b4SEd Tanous ifaceId); 2107588c3f0dSKowalski, Kamil return; 2108588c3f0dSKowalski, Kamil } 2109588c3f0dSKowalski, Kamil 21101f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 21111f8c7b5dSJohnathan Mantey { 2112002d39b4SEd Tanous handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, 2113002d39b4SEd Tanous asyncResp); 21141f8c7b5dSJohnathan Mantey } 21151f8c7b5dSJohnathan Mantey 21160627a2c7SEd Tanous if (hostname) 21171abe55efSEd Tanous { 21180627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 21191abe55efSEd Tanous } 21200627a2c7SEd Tanous 2121b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2122b10d8db0SRavi Teja { 2123b10d8db0SRavi Teja handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled, 2124b10d8db0SRavi Teja asyncResp); 2125b10d8db0SRavi Teja } 2126b10d8db0SRavi Teja 2127ab6554f1SJoshi-Mansi if (fqdn) 2128ab6554f1SJoshi-Mansi { 21292c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2130ab6554f1SJoshi-Mansi } 2131ab6554f1SJoshi-Mansi 2132d577665bSRatan Gupta if (macAddress) 2133d577665bSRatan Gupta { 2134002d39b4SEd Tanous handleMACAddressPatch(ifaceId, *macAddress, asyncResp); 2135d577665bSRatan Gupta } 2136d577665bSRatan Gupta 2137d1d50814SRavi Teja if (ipv4StaticAddresses) 2138d1d50814SRavi Teja { 2139bf648f77SEd Tanous // TODO(ed) for some reason the capture of 2140bf648f77SEd Tanous // ipv4Addresses above is returning a const value, 2141bf648f77SEd Tanous // not a non-const value. This doesn't really work 2142bf648f77SEd Tanous // for us, as we need to be able to efficiently move 2143bf648f77SEd Tanous // out the intermedia nlohmann::json objects. This 2144bf648f77SEd Tanous // makes a copy of the structure, and operates on 2145bf648f77SEd Tanous // that, but could be done more efficiently 2146ddd70dcaSEd Tanous nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses; 2147002d39b4SEd Tanous handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp); 21481abe55efSEd Tanous } 21490627a2c7SEd Tanous 2150f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2151f85837bfSRAJESWARAN THILLAIGOVINDAN { 2152002d39b4SEd Tanous handleStaticNameServersPatch(ifaceId, *staticNameServers, 2153002d39b4SEd Tanous asyncResp); 2154f85837bfSRAJESWARAN THILLAIGOVINDAN } 21559a6fc6feSRavi Teja 21569a6fc6feSRavi Teja if (ipv6DefaultGateway) 21579a6fc6feSRavi Teja { 21589a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 21599a6fc6feSRavi Teja "IPv6DefaultGateway"); 21609a6fc6feSRavi Teja } 2161e48c0fc5SRavi Teja 2162e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2163e48c0fc5SRavi Teja { 2164ddd70dcaSEd Tanous handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses, 2165ddd70dcaSEd Tanous ipv6Data, asyncResp); 2166e48c0fc5SRavi Teja } 2167eeedda23SJohnathan Mantey 2168eeedda23SJohnathan Mantey if (interfaceEnabled) 2169eeedda23SJohnathan Mantey { 2170002d39b4SEd Tanous setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled", 2171002d39b4SEd Tanous *interfaceEnabled, asyncResp); 2172eeedda23SJohnathan Mantey } 217335fb5311STejas Patil 217435fb5311STejas Patil if (mtuSize) 217535fb5311STejas Patil { 217635fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 217735fb5311STejas Patil } 2178588c3f0dSKowalski, Kamil }); 2179bf648f77SEd Tanous }); 2180e7caf250SJiaqing Zhao 2181e7caf250SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2182e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2183e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2184e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2185e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2186e7caf250SJiaqing Zhao const std::string& ifaceId) { 2187e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2188e7caf250SJiaqing Zhao { 2189e7caf250SJiaqing Zhao return; 2190e7caf250SJiaqing Zhao } 2191e7caf250SJiaqing Zhao 2192e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2193e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2194e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2195e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2196e7caf250SJiaqing Zhao }, 2197e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2198e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2199e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2200e7caf250SJiaqing Zhao }); 22014a0cb85cSEd Tanous } 2202bf648f77SEd Tanous 22039391bb9cSRapkiewicz, Pawel } // namespace redfish 2204