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; 83*e4588158SJishnu CM bool dnsv4Enabled; 84*e4588158SJishnu CM bool dnsv6Enabled; 85*e4588158SJishnu CM bool ntpv4Enabled; 86*e4588158SJishnu CM bool ntpv6Enabled; 87*e4588158SJishnu CM bool hostNamev4Enabled; 88*e4588158SJishnu CM bool hostNamev6Enabled; 89aa05fb27SJohnathan Mantey bool linkUp; 90eeedda23SJohnathan Mantey bool nicEnabled; 91b10d8db0SRavi Teja bool ipv6AcceptRa; 9282695a5bSJiaqing Zhao std::string dhcpEnabled; 931f8c7b5dSJohnathan Mantey std::string operatingMode; 9482695a5bSJiaqing Zhao std::string hostName; 9582695a5bSJiaqing Zhao std::string defaultGateway; 9682695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 9782695a5bSJiaqing Zhao std::string macAddress; 9817e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 990f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 1000f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 101d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1029391bb9cSRapkiewicz, Pawel }; 1039391bb9cSRapkiewicz, Pawel 1041f8c7b5dSJohnathan Mantey struct DHCPParameters 1051f8c7b5dSJohnathan Mantey { 1061f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 10782695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 10882695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 10982695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1101f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1111f8c7b5dSJohnathan Mantey }; 1121f8c7b5dSJohnathan Mantey 1139391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1149391bb9cSRapkiewicz, Pawel // into full dot notation 1151abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1161abe55efSEd Tanous { 1179391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1189391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1199391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1209391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1219391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1229391bb9cSRapkiewicz, Pawel return netmask; 1239391bb9cSRapkiewicz, Pawel } 1249391bb9cSRapkiewicz, Pawel 12582695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1261f8c7b5dSJohnathan Mantey bool isIPv4) 1271f8c7b5dSJohnathan Mantey { 1281f8c7b5dSJohnathan Mantey if (isIPv4) 1291f8c7b5dSJohnathan Mantey { 1301f8c7b5dSJohnathan Mantey return ( 1311f8c7b5dSJohnathan Mantey (inputDHCP == 1321f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1331f8c7b5dSJohnathan Mantey (inputDHCP == 1341f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1351f8c7b5dSJohnathan Mantey } 1361f8c7b5dSJohnathan Mantey return ((inputDHCP == 1371f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1381f8c7b5dSJohnathan Mantey (inputDHCP == 1391f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1401f8c7b5dSJohnathan Mantey } 1411f8c7b5dSJohnathan Mantey 1422c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1431f8c7b5dSJohnathan Mantey { 1441f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1451f8c7b5dSJohnathan Mantey { 1461f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1471f8c7b5dSJohnathan Mantey } 1483174e4dfSEd Tanous if (isIPv4) 1491f8c7b5dSJohnathan Mantey { 1501f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1511f8c7b5dSJohnathan Mantey } 1523174e4dfSEd Tanous if (isIPv6) 1531f8c7b5dSJohnathan Mantey { 1541f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1551f8c7b5dSJohnathan Mantey } 1561f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1571f8c7b5dSJohnathan Mantey } 1581f8c7b5dSJohnathan Mantey 1594a0cb85cSEd Tanous inline std::string 1604a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string& inputOrigin, 1614a0cb85cSEd Tanous bool isIPv4) 1621abe55efSEd Tanous { 1634a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1641abe55efSEd Tanous { 1654a0cb85cSEd Tanous return "Static"; 1669391bb9cSRapkiewicz, Pawel } 1674a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1681abe55efSEd Tanous { 1694a0cb85cSEd Tanous if (isIPv4) 1701abe55efSEd Tanous { 1714a0cb85cSEd Tanous return "IPv4LinkLocal"; 1721abe55efSEd Tanous } 1734a0cb85cSEd Tanous return "LinkLocal"; 1749391bb9cSRapkiewicz, Pawel } 1754a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1761abe55efSEd Tanous { 1774a0cb85cSEd Tanous if (isIPv4) 1784a0cb85cSEd Tanous { 1794a0cb85cSEd Tanous return "DHCP"; 1804a0cb85cSEd Tanous } 1814a0cb85cSEd Tanous return "DHCPv6"; 1824a0cb85cSEd Tanous } 1834a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1844a0cb85cSEd Tanous { 1854a0cb85cSEd Tanous return "SLAAC"; 1864a0cb85cSEd Tanous } 1874a0cb85cSEd Tanous return ""; 1884a0cb85cSEd Tanous } 1894a0cb85cSEd Tanous 19002cad96eSEd Tanous inline bool extractEthernetInterfaceData( 19102cad96eSEd Tanous const std::string& ethifaceId, 19202cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 1934a0cb85cSEd Tanous EthernetInterfaceData& ethData) 1944a0cb85cSEd Tanous { 1954c9afe43SEd Tanous bool idFound = false; 19602cad96eSEd Tanous for (const auto& objpath : dbusData) 1974a0cb85cSEd Tanous { 19802cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 1994a0cb85cSEd Tanous { 20081ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 201029573d4SEd Tanous { 2024c9afe43SEd Tanous idFound = true; 2034a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2044a0cb85cSEd Tanous { 2054a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2064a0cb85cSEd Tanous { 2074a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2084a0cb85cSEd Tanous { 2094a0cb85cSEd Tanous const std::string* mac = 210abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2114a0cb85cSEd Tanous if (mac != nullptr) 2124a0cb85cSEd Tanous { 21382695a5bSJiaqing Zhao ethData.macAddress = *mac; 2144a0cb85cSEd Tanous } 2154a0cb85cSEd Tanous } 2164a0cb85cSEd Tanous } 2174a0cb85cSEd Tanous } 2184a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2194a0cb85cSEd Tanous { 2204a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2214a0cb85cSEd Tanous { 2224a0cb85cSEd Tanous if (propertyPair.first == "Id") 2234a0cb85cSEd Tanous { 2241b6b96c5SEd Tanous const uint32_t* id = 225abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2264a0cb85cSEd Tanous if (id != nullptr) 2274a0cb85cSEd Tanous { 22817e22024SJiaqing Zhao ethData.vlanId = *id; 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous } 2314a0cb85cSEd Tanous } 2324a0cb85cSEd Tanous } 2334a0cb85cSEd Tanous else if (ifacePair.first == 2344a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2354a0cb85cSEd Tanous { 2364a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2374a0cb85cSEd Tanous { 2384a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2394a0cb85cSEd Tanous { 2402c70f800SEd Tanous const bool* autoNeg = 241abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2422c70f800SEd Tanous if (autoNeg != nullptr) 2434a0cb85cSEd Tanous { 24482695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2454a0cb85cSEd Tanous } 2464a0cb85cSEd Tanous } 2474a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2484a0cb85cSEd Tanous { 2494a0cb85cSEd Tanous const uint32_t* speed = 250abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2514a0cb85cSEd Tanous if (speed != nullptr) 2524a0cb85cSEd Tanous { 2534a0cb85cSEd Tanous ethData.speed = *speed; 2544a0cb85cSEd Tanous } 2554a0cb85cSEd Tanous } 25635fb5311STejas Patil else if (propertyPair.first == "MTU") 25735fb5311STejas Patil { 2583e7a8da6SAnthony const size_t* mtuSize = 2593e7a8da6SAnthony std::get_if<size_t>(&propertyPair.second); 26035fb5311STejas Patil if (mtuSize != nullptr) 26135fb5311STejas Patil { 26235fb5311STejas Patil ethData.mtuSize = *mtuSize; 26335fb5311STejas Patil } 26435fb5311STejas Patil } 265aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 266aa05fb27SJohnathan Mantey { 267aa05fb27SJohnathan Mantey const bool* linkUp = 268aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 269aa05fb27SJohnathan Mantey if (linkUp != nullptr) 270aa05fb27SJohnathan Mantey { 271aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 272aa05fb27SJohnathan Mantey } 273aa05fb27SJohnathan Mantey } 274eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 275eeedda23SJohnathan Mantey { 276eeedda23SJohnathan Mantey const bool* nicEnabled = 277eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 278eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 279eeedda23SJohnathan Mantey { 280eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 281eeedda23SJohnathan Mantey } 282eeedda23SJohnathan Mantey } 283b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 284b10d8db0SRavi Teja { 285b10d8db0SRavi Teja const bool* ipv6AcceptRa = 286b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 287b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 288b10d8db0SRavi Teja { 289b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 290b10d8db0SRavi Teja } 291b10d8db0SRavi Teja } 292f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 293029573d4SEd Tanous { 294029573d4SEd Tanous const std::vector<std::string>* nameservers = 2958d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 296029573d4SEd Tanous &propertyPair.second); 297029573d4SEd Tanous if (nameservers != nullptr) 298029573d4SEd Tanous { 299f23b7296SEd Tanous ethData.nameServers = *nameservers; 3000f6efdc1Smanojkiran.eda@gmail.com } 3010f6efdc1Smanojkiran.eda@gmail.com } 3020f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3030f6efdc1Smanojkiran.eda@gmail.com { 3040f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3058d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3060f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3070f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3080f6efdc1Smanojkiran.eda@gmail.com { 309f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3104a0cb85cSEd Tanous } 3114a0cb85cSEd Tanous } 3122a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3132a133282Smanojkiraneda { 3142c70f800SEd Tanous const std::string* dhcpEnabled = 3151f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3162c70f800SEd Tanous if (dhcpEnabled != nullptr) 3172a133282Smanojkiraneda { 31882695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3192a133282Smanojkiraneda } 3202a133282Smanojkiraneda } 321d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 322d24bfc7aSJennifer Lee { 323d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3248d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 325d24bfc7aSJennifer Lee &propertyPair.second); 326d24bfc7aSJennifer Lee if (domainNames != nullptr) 327d24bfc7aSJennifer Lee { 328f23b7296SEd Tanous ethData.domainnames = *domainNames; 329d24bfc7aSJennifer Lee } 330d24bfc7aSJennifer Lee } 3319010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3329010ec2eSRavi Teja { 3339010ec2eSRavi Teja const std::string* defaultGateway = 3349010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3359010ec2eSRavi Teja if (defaultGateway != nullptr) 3369010ec2eSRavi Teja { 3379010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3389010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3399010ec2eSRavi Teja { 34082695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3419010ec2eSRavi Teja } 3429010ec2eSRavi Teja else 3439010ec2eSRavi Teja { 34482695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3459010ec2eSRavi Teja } 3469010ec2eSRavi Teja } 3479010ec2eSRavi Teja } 3489010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3499010ec2eSRavi Teja { 3509010ec2eSRavi Teja const std::string* defaultGateway6 = 3519010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3529010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3539010ec2eSRavi Teja { 3549010ec2eSRavi Teja std::string defaultGateway6Str = 3559010ec2eSRavi Teja *defaultGateway6; 3569010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3579010ec2eSRavi Teja { 35882695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3599010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3609010ec2eSRavi Teja } 3619010ec2eSRavi Teja else 3629010ec2eSRavi Teja { 36382695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3649010ec2eSRavi Teja defaultGateway6Str; 3659010ec2eSRavi Teja } 3669010ec2eSRavi Teja } 3679010ec2eSRavi Teja } 368029573d4SEd Tanous } 369029573d4SEd Tanous } 370029573d4SEd Tanous } 3711f8c7b5dSJohnathan Mantey 372*e4588158SJishnu CM sdbusplus::message::object_path path( 373*e4588158SJishnu CM "/xyz/openbmc_project/network"); 374*e4588158SJishnu CM sdbusplus::message::object_path dhcp4Path = path / ethifaceId / 375*e4588158SJishnu CM "dhcp4"; 376*e4588158SJishnu CM 377*e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp4Path) 3781f8c7b5dSJohnathan Mantey { 3791f8c7b5dSJohnathan Mantey if (ifacePair.first == 3801f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 3811f8c7b5dSJohnathan Mantey { 3821f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 3831f8c7b5dSJohnathan Mantey { 3841f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 3851f8c7b5dSJohnathan Mantey { 3862c70f800SEd Tanous const bool* dnsEnabled = 3871f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3882c70f800SEd Tanous if (dnsEnabled != nullptr) 3891f8c7b5dSJohnathan Mantey { 390*e4588158SJishnu CM ethData.dnsv4Enabled = *dnsEnabled; 3911f8c7b5dSJohnathan Mantey } 3921f8c7b5dSJohnathan Mantey } 3931f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 3941f8c7b5dSJohnathan Mantey { 3952c70f800SEd Tanous const bool* ntpEnabled = 3961f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3972c70f800SEd Tanous if (ntpEnabled != nullptr) 3981f8c7b5dSJohnathan Mantey { 399*e4588158SJishnu CM ethData.ntpv4Enabled = *ntpEnabled; 4001f8c7b5dSJohnathan Mantey } 4011f8c7b5dSJohnathan Mantey } 4021f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 4031f8c7b5dSJohnathan Mantey { 4042c70f800SEd Tanous const bool* hostNameEnabled = 4051f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4062c70f800SEd Tanous if (hostNameEnabled != nullptr) 4071f8c7b5dSJohnathan Mantey { 408*e4588158SJishnu CM ethData.hostNamev4Enabled = *hostNameEnabled; 409*e4588158SJishnu CM } 410*e4588158SJishnu CM } 411*e4588158SJishnu CM } 412*e4588158SJishnu CM } 413*e4588158SJishnu CM } 414*e4588158SJishnu CM 415*e4588158SJishnu CM sdbusplus::message::object_path dhcp6Path = path / ethifaceId / 416*e4588158SJishnu CM "dhcp6"; 417*e4588158SJishnu CM 418*e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp6Path) 419*e4588158SJishnu CM { 420*e4588158SJishnu CM if (ifacePair.first == 421*e4588158SJishnu CM "xyz.openbmc_project.Network.DHCPConfiguration") 422*e4588158SJishnu CM { 423*e4588158SJishnu CM for (const auto& propertyPair : ifacePair.second) 424*e4588158SJishnu CM { 425*e4588158SJishnu CM if (propertyPair.first == "DNSEnabled") 426*e4588158SJishnu CM { 427*e4588158SJishnu CM const bool* dnsEnabled = 428*e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 429*e4588158SJishnu CM if (dnsEnabled != nullptr) 430*e4588158SJishnu CM { 431*e4588158SJishnu CM ethData.dnsv6Enabled = *dnsEnabled; 432*e4588158SJishnu CM } 433*e4588158SJishnu CM } 434*e4588158SJishnu CM else if (propertyPair.first == "NTPEnabled") 435*e4588158SJishnu CM { 436*e4588158SJishnu CM const bool* ntpEnabled = 437*e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 438*e4588158SJishnu CM if (ntpEnabled != nullptr) 439*e4588158SJishnu CM { 440*e4588158SJishnu CM ethData.ntpv6Enabled = *ntpEnabled; 441*e4588158SJishnu CM } 442*e4588158SJishnu CM } 443*e4588158SJishnu CM else if (propertyPair.first == "HostNameEnabled") 444*e4588158SJishnu CM { 445*e4588158SJishnu CM const bool* hostNameEnabled = 446*e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 447*e4588158SJishnu CM if (hostNameEnabled != nullptr) 448*e4588158SJishnu CM { 449*e4588158SJishnu CM ethData.hostNamev6Enabled = *hostNameEnabled; 4501f8c7b5dSJohnathan Mantey } 4511f8c7b5dSJohnathan Mantey } 4521f8c7b5dSJohnathan Mantey } 4531f8c7b5dSJohnathan Mantey } 4541f8c7b5dSJohnathan Mantey } 455029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 456029573d4SEd Tanous // to check eth number 457029573d4SEd Tanous if (ifacePair.first == 4584a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 4594a0cb85cSEd Tanous { 4604a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 4614a0cb85cSEd Tanous { 4624a0cb85cSEd Tanous if (propertyPair.first == "HostName") 4634a0cb85cSEd Tanous { 4644a0cb85cSEd Tanous const std::string* hostname = 4658d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 4664a0cb85cSEd Tanous if (hostname != nullptr) 4674a0cb85cSEd Tanous { 46882695a5bSJiaqing Zhao ethData.hostName = *hostname; 4694a0cb85cSEd Tanous } 4704a0cb85cSEd Tanous } 4714a0cb85cSEd Tanous } 4724a0cb85cSEd Tanous } 4734a0cb85cSEd Tanous } 4744a0cb85cSEd Tanous } 4754c9afe43SEd Tanous return idFound; 4764a0cb85cSEd Tanous } 4774a0cb85cSEd Tanous 478e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 47977179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 480711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 48177179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 482e48c0fc5SRavi Teja { 48389492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 48489492a15SPatrick Williams ethifaceId; 485e48c0fc5SRavi Teja 486e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 487e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 48881ce609eSEd Tanous for (const auto& objpath : dbusData) 489e48c0fc5SRavi Teja { 490e48c0fc5SRavi Teja // Check if proper pattern for object path appears 491353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 492e48c0fc5SRavi Teja { 4939eb808c1SEd Tanous for (const auto& interface : objpath.second) 494e48c0fc5SRavi Teja { 495e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 496e48c0fc5SRavi Teja { 4973544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 498353163e9STony Lee [](const auto& property) { 499353163e9STony Lee return property.first == "Type"; 500353163e9STony Lee }); 501353163e9STony Lee if (type == interface.second.end()) 502353163e9STony Lee { 503353163e9STony Lee continue; 504353163e9STony Lee } 505353163e9STony Lee 506353163e9STony Lee const std::string* typeStr = 507353163e9STony Lee std::get_if<std::string>(&type->second); 508353163e9STony Lee 509353163e9STony Lee if (typeStr == nullptr || 510353163e9STony Lee (*typeStr != 511353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 512353163e9STony Lee { 513353163e9STony Lee continue; 514353163e9STony Lee } 515353163e9STony Lee 516e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 517e48c0fc5SRavi Teja // appropriate 51877179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 5192c70f800SEd Tanous ipv6Address.id = 520353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5219eb808c1SEd Tanous for (const auto& property : interface.second) 522e48c0fc5SRavi Teja { 523e48c0fc5SRavi Teja if (property.first == "Address") 524e48c0fc5SRavi Teja { 525e48c0fc5SRavi Teja const std::string* address = 526e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 527e48c0fc5SRavi Teja if (address != nullptr) 528e48c0fc5SRavi Teja { 5292c70f800SEd Tanous ipv6Address.address = *address; 530e48c0fc5SRavi Teja } 531e48c0fc5SRavi Teja } 532e48c0fc5SRavi Teja else if (property.first == "Origin") 533e48c0fc5SRavi Teja { 534e48c0fc5SRavi Teja const std::string* origin = 535e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 536e48c0fc5SRavi Teja if (origin != nullptr) 537e48c0fc5SRavi Teja { 5382c70f800SEd Tanous ipv6Address.origin = 539e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 540e48c0fc5SRavi Teja false); 541e48c0fc5SRavi Teja } 542e48c0fc5SRavi Teja } 543e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 544e48c0fc5SRavi Teja { 545e48c0fc5SRavi Teja const uint8_t* prefix = 546e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 547e48c0fc5SRavi Teja if (prefix != nullptr) 548e48c0fc5SRavi Teja { 5492c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 550e48c0fc5SRavi Teja } 551e48c0fc5SRavi Teja } 552889ff694SAsmitha Karunanithi else if (property.first == "Type" || 553889ff694SAsmitha Karunanithi property.first == "Gateway") 554889ff694SAsmitha Karunanithi { 555889ff694SAsmitha Karunanithi // Type & Gateway is not used 556889ff694SAsmitha Karunanithi } 557e48c0fc5SRavi Teja else 558e48c0fc5SRavi Teja { 55962598e31SEd Tanous BMCWEB_LOG_ERROR( 56062598e31SEd Tanous "Got extra property: {} on the {} object", 56162598e31SEd Tanous property.first, objpath.first.str); 562e48c0fc5SRavi Teja } 563e48c0fc5SRavi Teja } 564e48c0fc5SRavi Teja } 565e48c0fc5SRavi Teja } 566e48c0fc5SRavi Teja } 567e48c0fc5SRavi Teja } 568e48c0fc5SRavi Teja } 569e48c0fc5SRavi Teja 5704a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 57177179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 572711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 57377179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 5744a0cb85cSEd Tanous { 57589492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 57689492a15SPatrick Williams ethifaceId; 5774a0cb85cSEd Tanous 5784a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 5794a0cb85cSEd Tanous // single ethernet interface, loop over all of them 58081ce609eSEd Tanous for (const auto& objpath : dbusData) 5814a0cb85cSEd Tanous { 5824a0cb85cSEd Tanous // Check if proper pattern for object path appears 583353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 5844a0cb85cSEd Tanous { 5859eb808c1SEd Tanous for (const auto& interface : objpath.second) 5864a0cb85cSEd Tanous { 5874a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 5884a0cb85cSEd Tanous { 5893544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 590353163e9STony Lee [](const auto& property) { 591353163e9STony Lee return property.first == "Type"; 592353163e9STony Lee }); 593353163e9STony Lee if (type == interface.second.end()) 594353163e9STony Lee { 595353163e9STony Lee continue; 596353163e9STony Lee } 597353163e9STony Lee 598353163e9STony Lee const std::string* typeStr = 599353163e9STony Lee std::get_if<std::string>(&type->second); 600353163e9STony Lee 601353163e9STony Lee if (typeStr == nullptr || 602353163e9STony Lee (*typeStr != 603353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 604353163e9STony Lee { 605353163e9STony Lee continue; 606353163e9STony Lee } 607353163e9STony Lee 6084a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 6094a0cb85cSEd Tanous // appropriate 61077179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 6112c70f800SEd Tanous ipv4Address.id = 612353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 6139eb808c1SEd Tanous for (const auto& property : interface.second) 6144a0cb85cSEd Tanous { 6154a0cb85cSEd Tanous if (property.first == "Address") 6164a0cb85cSEd Tanous { 6174a0cb85cSEd Tanous const std::string* address = 618abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6194a0cb85cSEd Tanous if (address != nullptr) 6204a0cb85cSEd Tanous { 6212c70f800SEd Tanous ipv4Address.address = *address; 6224a0cb85cSEd Tanous } 6234a0cb85cSEd Tanous } 6244a0cb85cSEd Tanous else if (property.first == "Origin") 6254a0cb85cSEd Tanous { 6264a0cb85cSEd Tanous const std::string* origin = 627abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6284a0cb85cSEd Tanous if (origin != nullptr) 6294a0cb85cSEd Tanous { 6302c70f800SEd Tanous ipv4Address.origin = 6314a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 6324a0cb85cSEd Tanous true); 6334a0cb85cSEd Tanous } 6344a0cb85cSEd Tanous } 6354a0cb85cSEd Tanous else if (property.first == "PrefixLength") 6364a0cb85cSEd Tanous { 6374a0cb85cSEd Tanous const uint8_t* mask = 638abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 6394a0cb85cSEd Tanous if (mask != nullptr) 6404a0cb85cSEd Tanous { 6414a0cb85cSEd Tanous // convert it to the string 6422c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 6434a0cb85cSEd Tanous } 6444a0cb85cSEd Tanous } 645889ff694SAsmitha Karunanithi else if (property.first == "Type" || 646889ff694SAsmitha Karunanithi property.first == "Gateway") 647889ff694SAsmitha Karunanithi { 648889ff694SAsmitha Karunanithi // Type & Gateway is not used 649889ff694SAsmitha Karunanithi } 6504a0cb85cSEd Tanous else 6514a0cb85cSEd Tanous { 65262598e31SEd Tanous BMCWEB_LOG_ERROR( 65362598e31SEd Tanous "Got extra property: {} on the {} object", 65462598e31SEd Tanous property.first, objpath.first.str); 6554a0cb85cSEd Tanous } 6564a0cb85cSEd Tanous } 6574a0cb85cSEd Tanous // Check if given address is local, or global 6582c70f800SEd Tanous ipv4Address.linktype = 65911ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 66018659d10SJohnathan Mantey ? LinkType::Local 66118659d10SJohnathan Mantey : LinkType::Global; 6624a0cb85cSEd Tanous } 6634a0cb85cSEd Tanous } 6644a0cb85cSEd Tanous } 6654a0cb85cSEd Tanous } 6664a0cb85cSEd Tanous } 667588c3f0dSKowalski, Kamil 668588c3f0dSKowalski, Kamil /** 66901784826SJohnathan Mantey * @brief Deletes given IPv4 interface 670179db1d7SKowalski, Kamil * 671179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 672179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 673179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 674179db1d7SKowalski, Kamil * 675179db1d7SKowalski, Kamil * @return None 676179db1d7SKowalski, Kamil */ 6779c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 6789c5e585cSRavi Teja const std::string& ipHash, 6798d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6801abe55efSEd Tanous { 68155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 6825e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 6831abe55efSEd Tanous if (ec) 6841abe55efSEd Tanous { 685a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6861abe55efSEd Tanous } 687179db1d7SKowalski, Kamil }, 688179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 6899c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 690179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 691179db1d7SKowalski, Kamil } 692179db1d7SKowalski, Kamil 693244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway( 694244b6d5bSGunnar Mills const std::string& ifaceId, const std::string& gateway, 695244b6d5bSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6969010ec2eSRavi Teja { 6979ae226faSGeorge Liu sdbusplus::asio::setProperty( 6989ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 6999ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 7009ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 7019ae226faSGeorge Liu gateway, [asyncResp](const boost::system::error_code& ec) { 7029010ec2eSRavi Teja if (ec) 7039010ec2eSRavi Teja { 7049010ec2eSRavi Teja messages::internalError(asyncResp->res); 7059010ec2eSRavi Teja return; 7069010ec2eSRavi Teja } 7079010ec2eSRavi Teja asyncResp->res.result(boost::beast::http::status::no_content); 7089ae226faSGeorge Liu }); 7099010ec2eSRavi Teja } 710179db1d7SKowalski, Kamil /** 71101784826SJohnathan Mantey * @brief Creates a static IPv4 entry 712179db1d7SKowalski, Kamil * 71301784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 71401784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 71501784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 71601784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 717179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 718179db1d7SKowalski, Kamil * 719179db1d7SKowalski, Kamil * @return None 720179db1d7SKowalski, Kamil */ 721cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 722cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7238d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7241abe55efSEd Tanous { 7255a39f77aSPatrick Williams auto createIpHandler = [asyncResp, ifaceId, 7265a39f77aSPatrick Williams gateway](const boost::system::error_code& ec) { 7271abe55efSEd Tanous if (ec) 7281abe55efSEd Tanous { 729a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7309010ec2eSRavi Teja return; 731179db1d7SKowalski, Kamil } 7329010ec2eSRavi Teja updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); 7339010ec2eSRavi Teja }; 7349010ec2eSRavi Teja 7359010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 7369010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 737179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 738179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 73901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 740179db1d7SKowalski, Kamil gateway); 741179db1d7SKowalski, Kamil } 742e48c0fc5SRavi Teja 743e48c0fc5SRavi Teja /** 74401784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 74501784826SJohnathan Mantey * static IPv6 entry 74601784826SJohnathan Mantey * 74701784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 74801784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 74901784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 75001784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 75101784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 75201784826SJohnathan Mantey * 75301784826SJohnathan Mantey * @return None 75401784826SJohnathan Mantey */ 7559c5e585cSRavi Teja 7569c5e585cSRavi Teja enum class IpVersion 7579c5e585cSRavi Teja { 7589c5e585cSRavi Teja IpV4, 7599c5e585cSRavi Teja IpV6 7609c5e585cSRavi Teja }; 7619c5e585cSRavi Teja 7629c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 7639c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 7648d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 7659c5e585cSRavi Teja const std::string& gateway, 7668d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 76701784826SJohnathan Mantey { 76801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7699c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 7709c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 77101784826SJohnathan Mantey if (ec) 77201784826SJohnathan Mantey { 77301784826SJohnathan Mantey messages::internalError(asyncResp->res); 77401784826SJohnathan Mantey } 7759c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 7769c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 77701784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7785e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 77923a21a1cSEd Tanous if (ec2) 78001784826SJohnathan Mantey { 78101784826SJohnathan Mantey messages::internalError(asyncResp->res); 78201784826SJohnathan Mantey } 78301784826SJohnathan Mantey }, 78401784826SJohnathan Mantey "xyz.openbmc_project.Network", 78501784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 7869c5e585cSRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address, 7879c5e585cSRavi Teja prefixLength, gateway); 78801784826SJohnathan Mantey }, 78901784826SJohnathan Mantey "xyz.openbmc_project.Network", 7909c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 79101784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 79201784826SJohnathan Mantey } 79301784826SJohnathan Mantey 79401784826SJohnathan Mantey /** 795e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 796e48c0fc5SRavi Teja * 797e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 798e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 799e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 800e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 801e48c0fc5SRavi Teja * 802e48c0fc5SRavi Teja * @return None 803e48c0fc5SRavi Teja */ 80401784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 80501784826SJohnathan Mantey const std::string& address, 8068d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 807e48c0fc5SRavi Teja { 8085a39f77aSPatrick Williams auto createIpHandler = [asyncResp, 8095a39f77aSPatrick Williams address](const boost::system::error_code& ec) { 810e48c0fc5SRavi Teja if (ec) 811e48c0fc5SRavi Teja { 812fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 813fc23ef8aSNitin Kumar Kotania { 814fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 815fc23ef8aSNitin Kumar Kotania "Address"); 816fc23ef8aSNitin Kumar Kotania } 817fc23ef8aSNitin Kumar Kotania else 818fc23ef8aSNitin Kumar Kotania { 819e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 820e48c0fc5SRavi Teja } 821fc23ef8aSNitin Kumar Kotania } 822e48c0fc5SRavi Teja }; 823e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 8244e0453b1SGunnar Mills // does not have associated gateway property 825e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 826e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 827e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 828e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 829e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 830e48c0fc5SRavi Teja ""); 831e48c0fc5SRavi Teja } 832e48c0fc5SRavi Teja 833179db1d7SKowalski, Kamil /** 834179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 835179db1d7SKowalski, Kamil * Object 836179db1d7SKowalski, Kamil * from EntityManager Network Manager 8374a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 838179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 839179db1d7SKowalski, Kamil * into JSON 840179db1d7SKowalski, Kamil */ 841179db1d7SKowalski, Kamil template <typename CallbackFunc> 84281ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 8431abe55efSEd Tanous CallbackFunc&& callback) 8441abe55efSEd Tanous { 845f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 846f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 847f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 848f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 849f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 8508b24275dSEd Tanous const boost::system::error_code& ec, 85102cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 85255c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 85377179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 85477179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 855179db1d7SKowalski, Kamil 8568b24275dSEd Tanous if (ec) 8571abe55efSEd Tanous { 85801784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 859179db1d7SKowalski, Kamil return; 860179db1d7SKowalski, Kamil } 861179db1d7SKowalski, Kamil 862002d39b4SEd Tanous bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); 8634c9afe43SEd Tanous if (!found) 8644c9afe43SEd Tanous { 86501784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 8664c9afe43SEd Tanous return; 8674c9afe43SEd Tanous } 8684c9afe43SEd Tanous 8692c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 870179db1d7SKowalski, Kamil // Fix global GW 8711abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 8721abe55efSEd Tanous { 873c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 874c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 8759010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 8761abe55efSEd Tanous { 87782695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 878179db1d7SKowalski, Kamil } 879179db1d7SKowalski, Kamil } 880179db1d7SKowalski, Kamil 8812c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 8824e0453b1SGunnar Mills // Finally make a callback with useful data 88301784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 884f5892d0dSGeorge Liu }); 885271584abSEd Tanous } 886179db1d7SKowalski, Kamil 887179db1d7SKowalski, Kamil /** 8889391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8899391bb9cSRapkiewicz, Pawel * Manager 8901abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8911abe55efSEd Tanous * into JSON. 8929391bb9cSRapkiewicz, Pawel */ 8939391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8941abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 8951abe55efSEd Tanous { 896f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 897f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 898f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 899f94c4ecfSEd Tanous [callback{std::forward<CallbackFunc>(callback)}]( 9008b24275dSEd Tanous const boost::system::error_code& ec, 901f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 9021abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 9031abe55efSEd Tanous // ethernet interfaces 90477179532SEd Tanous std::vector<std::string> ifaceList; 9052c70f800SEd Tanous ifaceList.reserve(resp.size()); 9068b24275dSEd Tanous if (ec) 9071abe55efSEd Tanous { 9082c70f800SEd Tanous callback(false, ifaceList); 9099391bb9cSRapkiewicz, Pawel return; 9109391bb9cSRapkiewicz, Pawel } 9119391bb9cSRapkiewicz, Pawel 9129391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 9134a0cb85cSEd Tanous for (const auto& objpath : resp) 9141abe55efSEd Tanous { 9159391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 9164a0cb85cSEd Tanous for (const auto& interface : objpath.second) 9171abe55efSEd Tanous { 9181abe55efSEd Tanous // If interface is 9194a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9204a0cb85cSEd Tanous // what we're looking for. 9219391bb9cSRapkiewicz, Pawel if (interface.first == 9221abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9231abe55efSEd Tanous { 9242dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 9252dfd18efSEd Tanous if (ifaceId.empty()) 9261abe55efSEd Tanous { 9272dfd18efSEd Tanous continue; 9289391bb9cSRapkiewicz, Pawel } 9292dfd18efSEd Tanous // and put it into output vector. 93077179532SEd Tanous ifaceList.emplace_back(ifaceId); 9319391bb9cSRapkiewicz, Pawel } 9329391bb9cSRapkiewicz, Pawel } 9339391bb9cSRapkiewicz, Pawel } 9342c5875a2SEd Tanous 9353544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 9362c5875a2SEd Tanous 937a434f2bdSEd Tanous // Finally make a callback with useful data 9382c70f800SEd Tanous callback(true, ifaceList); 939f5892d0dSGeorge Liu }); 940271584abSEd Tanous } 9419391bb9cSRapkiewicz, Pawel 9424f48d5f6SEd Tanous inline void 9434f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 9448d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 9451abe55efSEd Tanous { 946ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 947ab6554f1SJoshi-Mansi if (hostname.length() > 255) 948ab6554f1SJoshi-Mansi { 949ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 950ab6554f1SJoshi-Mansi "HostName"); 951ab6554f1SJoshi-Mansi return; 952ab6554f1SJoshi-Mansi } 9539ae226faSGeorge Liu sdbusplus::asio::setProperty( 9549ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 9559ae226faSGeorge Liu "/xyz/openbmc_project/network/config", 9569ae226faSGeorge Liu "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname, 9575e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 9584a0cb85cSEd Tanous if (ec) 9594a0cb85cSEd Tanous { 960a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 9611abe55efSEd Tanous } 9629ae226faSGeorge Liu }); 963588c3f0dSKowalski, Kamil } 964588c3f0dSKowalski, Kamil 9654f48d5f6SEd Tanous inline void 96635fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 96735fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 96835fb5311STejas Patil { 96989492a15SPatrick Williams sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" + 97089492a15SPatrick Williams ifaceId; 9719ae226faSGeorge Liu sdbusplus::asio::setProperty( 9729ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath, 9739ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize, 9745e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 97535fb5311STejas Patil if (ec) 97635fb5311STejas Patil { 97735fb5311STejas Patil messages::internalError(asyncResp->res); 97835fb5311STejas Patil } 9799ae226faSGeorge Liu }); 98035fb5311STejas Patil } 98135fb5311STejas Patil 98235fb5311STejas Patil inline void 9834f48d5f6SEd Tanous handleDomainnamePatch(const std::string& ifaceId, 984bf648f77SEd Tanous const std::string& domainname, 9858d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 986ab6554f1SJoshi-Mansi { 987ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 9889ae226faSGeorge Liu sdbusplus::asio::setProperty( 9899ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 9909ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 9919ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 9929ae226faSGeorge Liu vectorDomainname, [asyncResp](const boost::system::error_code& ec) { 993ab6554f1SJoshi-Mansi if (ec) 994ab6554f1SJoshi-Mansi { 995ab6554f1SJoshi-Mansi messages::internalError(asyncResp->res); 996ab6554f1SJoshi-Mansi } 9979ae226faSGeorge Liu }); 998ab6554f1SJoshi-Mansi } 999ab6554f1SJoshi-Mansi 10004f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1001bf648f77SEd Tanous { 1002bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 10033544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1004bf648f77SEd Tanous { 1005bf648f77SEd Tanous return false; 1006bf648f77SEd Tanous } 1007bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1008bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1009bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1010bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 10114b242749SEd Tanous const static std::regex pattern( 1012bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1013bf648f77SEd Tanous 1014bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1015bf648f77SEd Tanous } 1016bf648f77SEd Tanous 10174f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1018bf648f77SEd Tanous { 1019bf648f77SEd Tanous // Can have multiple subdomains 1020bf648f77SEd Tanous // Top Level Domain's min length is 2 character 10214b242749SEd Tanous const static std::regex pattern( 10220fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1023bf648f77SEd Tanous 1024bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1025bf648f77SEd Tanous } 1026bf648f77SEd Tanous 10274f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 10288d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1029ab6554f1SJoshi-Mansi { 1030ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1031ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1032ab6554f1SJoshi-Mansi { 1033ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1034ab6554f1SJoshi-Mansi return; 1035ab6554f1SJoshi-Mansi } 1036ab6554f1SJoshi-Mansi 1037ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1038ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1039ab6554f1SJoshi-Mansi { 1040ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1041ab6554f1SJoshi-Mansi return; 1042ab6554f1SJoshi-Mansi } 1043ab6554f1SJoshi-Mansi 1044ab6554f1SJoshi-Mansi std::string hostname; 1045ab6554f1SJoshi-Mansi std::string domainname; 1046ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1047ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1048ab6554f1SJoshi-Mansi 1049ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1050ab6554f1SJoshi-Mansi { 1051ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1052ab6554f1SJoshi-Mansi return; 1053ab6554f1SJoshi-Mansi } 1054ab6554f1SJoshi-Mansi 1055ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1056ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1057ab6554f1SJoshi-Mansi } 1058ab6554f1SJoshi-Mansi 10594f48d5f6SEd Tanous inline void 10604f48d5f6SEd Tanous handleMACAddressPatch(const std::string& ifaceId, 1061bf648f77SEd Tanous const std::string& macAddress, 10628d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1063d577665bSRatan Gupta { 106458283f41SJohnathan Mantey static constexpr std::string_view dbusNotAllowedError = 106558283f41SJohnathan Mantey "xyz.openbmc_project.Common.Error.NotAllowed"; 106658283f41SJohnathan Mantey 10679ae226faSGeorge Liu sdbusplus::asio::setProperty( 10689ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10699ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10709ae226faSGeorge Liu "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress, 10719ae226faSGeorge Liu [asyncResp](const boost::system::error_code& ec, 10725b378546SPatrick Williams const sdbusplus::message_t& msg) { 1073d577665bSRatan Gupta if (ec) 1074d577665bSRatan Gupta { 107558283f41SJohnathan Mantey const sd_bus_error* err = msg.get_error(); 107658283f41SJohnathan Mantey if (err == nullptr) 107758283f41SJohnathan Mantey { 107858283f41SJohnathan Mantey messages::internalError(asyncResp->res); 107958283f41SJohnathan Mantey return; 108058283f41SJohnathan Mantey } 108158283f41SJohnathan Mantey if (err->name == dbusNotAllowedError) 108258283f41SJohnathan Mantey { 108358283f41SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "MACAddress"); 108458283f41SJohnathan Mantey return; 108558283f41SJohnathan Mantey } 1086d577665bSRatan Gupta messages::internalError(asyncResp->res); 1087d577665bSRatan Gupta return; 1088d577665bSRatan Gupta } 10899ae226faSGeorge Liu }); 1090d577665bSRatan Gupta } 1091286b9118SJohnathan Mantey 10924f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 10934f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 10944f48d5f6SEd Tanous const bool v6Value, 10958d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1096da131a9aSJennifer Lee { 10972c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 10989ae226faSGeorge Liu sdbusplus::asio::setProperty( 10999ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 11009ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 11019ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp, 11025e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1103da131a9aSJennifer Lee if (ec) 1104da131a9aSJennifer Lee { 110562598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1106da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1107da131a9aSJennifer Lee return; 1108da131a9aSJennifer Lee } 11098f7e9c19SJayaprakash Mutyala messages::success(asyncResp->res); 11109ae226faSGeorge Liu }); 1111da131a9aSJennifer Lee } 11121f8c7b5dSJohnathan Mantey 11134f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty( 1114eeedda23SJohnathan Mantey const std::string& ifaceId, const std::string& propertyName, 11158d1b46d7Szhanghch05 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1116eeedda23SJohnathan Mantey { 11179ae226faSGeorge Liu sdbusplus::asio::setProperty( 11189ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 11199ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 11209ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, value, 11215e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1122eeedda23SJohnathan Mantey if (ec) 1123eeedda23SJohnathan Mantey { 112462598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1125eeedda23SJohnathan Mantey messages::internalError(asyncResp->res); 1126eeedda23SJohnathan Mantey return; 1127eeedda23SJohnathan Mantey } 11289ae226faSGeorge Liu }); 1129eeedda23SJohnathan Mantey } 1130eeedda23SJohnathan Mantey 1131*e4588158SJishnu CM enum class NetworkType 1132*e4588158SJishnu CM { 1133*e4588158SJishnu CM dhcp4, 1134*e4588158SJishnu CM dhcp6 1135*e4588158SJishnu CM }; 1136*e4588158SJishnu CM 1137*e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1138*e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1139*e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1140da131a9aSJennifer Lee { 114162598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 1142*e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1143*e4588158SJishnu CM path /= ethifaceId; 1144*e4588158SJishnu CM 1145*e4588158SJishnu CM if (type == NetworkType::dhcp4) 1146*e4588158SJishnu CM { 1147*e4588158SJishnu CM path /= "dhcp4"; 1148*e4588158SJishnu CM } 1149*e4588158SJishnu CM else 1150*e4588158SJishnu CM { 1151*e4588158SJishnu CM path /= "dhcp6"; 1152*e4588158SJishnu CM } 1153*e4588158SJishnu CM 11549ae226faSGeorge Liu sdbusplus::asio::setProperty( 1155*e4588158SJishnu CM *crow::connections::systemBus, "xyz.openbmc_project.Network", path, 11569ae226faSGeorge Liu "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value, 11575e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1158da131a9aSJennifer Lee if (ec) 1159da131a9aSJennifer Lee { 116062598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1161da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1162da131a9aSJennifer Lee return; 1163da131a9aSJennifer Lee } 11649ae226faSGeorge Liu }); 1165da131a9aSJennifer Lee } 1166d577665bSRatan Gupta 1167b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1168b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1169b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1170b10d8db0SRavi Teja { 1171b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1172b10d8db0SRavi Teja path /= ifaceId; 1173b10d8db0SRavi Teja sdbusplus::asio::setProperty( 1174b10d8db0SRavi Teja *crow::connections::systemBus, "xyz.openbmc_project.Network", path, 1175b10d8db0SRavi Teja "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA", 1176b10d8db0SRavi Teja ipv6AutoConfigEnabled, 1177b10d8db0SRavi Teja [asyncResp](const boost::system::error_code& ec) { 1178b10d8db0SRavi Teja if (ec) 1179b10d8db0SRavi Teja { 1180b10d8db0SRavi Teja BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1181b10d8db0SRavi Teja messages::internalError(asyncResp->res); 1182b10d8db0SRavi Teja return; 1183b10d8db0SRavi Teja } 1184b10d8db0SRavi Teja messages::success(asyncResp->res); 1185b10d8db0SRavi Teja }); 1186b10d8db0SRavi Teja } 1187b10d8db0SRavi Teja 11884f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId, 11891f8c7b5dSJohnathan Mantey const EthernetInterfaceData& ethData, 1190f23b7296SEd Tanous const DHCPParameters& v4dhcpParms, 1191f23b7296SEd Tanous const DHCPParameters& v6dhcpParms, 11928d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1193da131a9aSJennifer Lee { 119482695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 119582695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1196da131a9aSJennifer Lee 11971f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 11981f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 11991f8c7b5dSJohnathan Mantey 12001f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 12011f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1202da131a9aSJennifer Lee { 1203b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 12041f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 12051f8c7b5dSJohnathan Mantey { 1206bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1207bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 12081f8c7b5dSJohnathan Mantey "OperatingMode"); 1209da131a9aSJennifer Lee return; 1210da131a9aSJennifer Lee } 1211b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 12121f8c7b5dSJohnathan Mantey } 12131f8c7b5dSJohnathan Mantey else 1214da131a9aSJennifer Lee { 12151f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 12161f8c7b5dSJohnathan Mantey } 12171f8c7b5dSJohnathan Mantey 1218*e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1219*e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1220*e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 12211f8c7b5dSJohnathan Mantey { 1222*e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 12231f8c7b5dSJohnathan Mantey } 1224*e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 12251f8c7b5dSJohnathan Mantey { 1226*e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 12271f8c7b5dSJohnathan Mantey } 12281f8c7b5dSJohnathan Mantey 1229*e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1230*e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1231*e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 12321f8c7b5dSJohnathan Mantey { 1233*e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 12341f8c7b5dSJohnathan Mantey } 1235*e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 12361f8c7b5dSJohnathan Mantey { 1237*e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 12381f8c7b5dSJohnathan Mantey } 12391f8c7b5dSJohnathan Mantey 1240*e4588158SJishnu CM bool nextUsev4Domain = ethData.hostNamev4Enabled; 1241*e4588158SJishnu CM bool nextUsev6Domain = ethData.hostNamev6Enabled; 1242*e4588158SJishnu CM if (v4dhcpParms.useDomainName) 12431f8c7b5dSJohnathan Mantey { 1244*e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 12451f8c7b5dSJohnathan Mantey } 1246*e4588158SJishnu CM if (v6dhcpParms.useDomainName) 12471f8c7b5dSJohnathan Mantey { 1248*e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 12491f8c7b5dSJohnathan Mantey } 12501f8c7b5dSJohnathan Mantey 125162598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 12521f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 12531f8c7b5dSJohnathan Mantey asyncResp); 125462598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1255*e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1256*e4588158SJishnu CM NetworkType::dhcp4); 125762598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1258*e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1259*e4588158SJishnu CM NetworkType::dhcp4); 126062598e31SEd Tanous BMCWEB_LOG_DEBUG("set HostNameEnabled..."); 1261*e4588158SJishnu CM setDHCPConfig("HostNameEnabled", nextUsev4Domain, asyncResp, ifaceId, 1262*e4588158SJishnu CM NetworkType::dhcp4); 1263*e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1264*e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1265*e4588158SJishnu CM NetworkType::dhcp6); 1266*e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1267*e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1268*e4588158SJishnu CM NetworkType::dhcp6); 1269*e4588158SJishnu CM BMCWEB_LOG_DEBUG("set HostNameEnabled for dhcp6..."); 1270*e4588158SJishnu CM setDHCPConfig("HostNameEnabled", nextUsev6Domain, asyncResp, ifaceId, 1271*e4588158SJishnu CM NetworkType::dhcp6); 1272da131a9aSJennifer Lee } 127301784826SJohnathan Mantey 127477179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 127577179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 127677179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 127701784826SJohnathan Mantey { 127817a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 127917a897dfSManojkiran Eda return value.origin == "Static"; 128017a897dfSManojkiran Eda }); 128101784826SJohnathan Mantey } 128201784826SJohnathan Mantey 128377179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 128477179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 128577179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 128601784826SJohnathan Mantey { 128717a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 128817a897dfSManojkiran Eda return value.origin == "Static"; 128917a897dfSManojkiran Eda }); 129001784826SJohnathan Mantey } 129101784826SJohnathan Mantey 129277179532SEd Tanous inline void 1293ddd70dcaSEd Tanous handleIPv4StaticPatch(const std::string& ifaceId, 1294ddd70dcaSEd Tanous nlohmann::json::array_t& input, 129577179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 12968d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12971abe55efSEd Tanous { 1298ddd70dcaSEd Tanous if (input.empty()) 1299f476acbfSRatan Gupta { 13002e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1301d1d50814SRavi Teja "IPv4StaticAddresses"); 1302f476acbfSRatan Gupta return; 1303f476acbfSRatan Gupta } 1304f476acbfSRatan Gupta 1305271584abSEd Tanous unsigned entryIdx = 1; 130601784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 130701784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 130801784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 130901784826SJohnathan Mantey // into the NIC. 131077179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 13112c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 131201784826SJohnathan Mantey 1313537174c4SEd Tanous for (nlohmann::json& thisJson : input) 13141abe55efSEd Tanous { 131589492a15SPatrick Williams std::string pathString = "IPv4StaticAddresses/" + 131689492a15SPatrick Williams std::to_string(entryIdx); 1317179db1d7SKowalski, Kamil 131801784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1319f476acbfSRatan Gupta { 1320537174c4SEd Tanous std::optional<std::string> address; 1321537174c4SEd Tanous std::optional<std::string> subnetMask; 1322537174c4SEd Tanous std::optional<std::string> gateway; 1323537174c4SEd Tanous 1324537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 13257e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 13267e27d832SJohnathan Mantey "Gateway", gateway)) 1327537174c4SEd Tanous { 1328f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 132971f52d96SEd Tanous pathString); 1330537174c4SEd Tanous return; 1331179db1d7SKowalski, Kamil } 1332179db1d7SKowalski, Kamil 133301784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 133401784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 133501784826SJohnathan Mantey // current state of the interface. Merge existing state into the 133601784826SJohnathan Mantey // current request. 1337537174c4SEd Tanous if (address) 13381abe55efSEd Tanous { 1339e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 134001784826SJohnathan Mantey { 1341bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1342bf648f77SEd Tanous pathString + "/Address"); 1343e01d0c36SEd Tanous return; 134401784826SJohnathan Mantey } 134501784826SJohnathan Mantey } 134685ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 134701784826SJohnathan Mantey { 1348e01d0c36SEd Tanous address = (nicIpEntry->address); 134901784826SJohnathan Mantey } 135001784826SJohnathan Mantey else 135101784826SJohnathan Mantey { 135201784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 135301784826SJohnathan Mantey pathString + "/Address"); 1354e01d0c36SEd Tanous return; 13554a0cb85cSEd Tanous } 13564a0cb85cSEd Tanous 1357e01d0c36SEd Tanous uint8_t prefixLength = 0; 1358537174c4SEd Tanous if (subnetMask) 13594a0cb85cSEd Tanous { 1360033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1361033f1e4dSEd Tanous &prefixLength)) 13624a0cb85cSEd Tanous { 1363f12894f8SJason M. Bills messages::propertyValueFormatError( 1364537174c4SEd Tanous asyncResp->res, *subnetMask, 13654a0cb85cSEd Tanous pathString + "/SubnetMask"); 1366e01d0c36SEd Tanous return; 13674a0cb85cSEd Tanous } 13684a0cb85cSEd Tanous } 136985ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 13704a0cb85cSEd Tanous { 1371033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 137201784826SJohnathan Mantey &prefixLength)) 13734a0cb85cSEd Tanous { 137401784826SJohnathan Mantey messages::propertyValueFormatError( 137585ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 137601784826SJohnathan Mantey pathString + "/SubnetMask"); 1377e01d0c36SEd Tanous return; 13784a0cb85cSEd Tanous } 13794a0cb85cSEd Tanous } 13801abe55efSEd Tanous else 13811abe55efSEd Tanous { 138201784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 138301784826SJohnathan Mantey pathString + "/SubnetMask"); 1384e01d0c36SEd Tanous return; 138501784826SJohnathan Mantey } 138601784826SJohnathan Mantey 138701784826SJohnathan Mantey if (gateway) 138801784826SJohnathan Mantey { 1389e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 139001784826SJohnathan Mantey { 1391bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1392bf648f77SEd Tanous pathString + "/Gateway"); 1393e01d0c36SEd Tanous return; 139401784826SJohnathan Mantey } 139501784826SJohnathan Mantey } 139685ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 139701784826SJohnathan Mantey { 1398e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 139901784826SJohnathan Mantey } 140001784826SJohnathan Mantey else 14011abe55efSEd Tanous { 1402a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 14034a0cb85cSEd Tanous pathString + "/Gateway"); 140401784826SJohnathan Mantey return; 14054a0cb85cSEd Tanous } 14064a0cb85cSEd Tanous 140785ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 14081abe55efSEd Tanous { 14099c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 141077eb0153SEd Tanous nicIpEntry->id, prefixLength, *address, 141177eb0153SEd Tanous *gateway, asyncResp); 141289492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 141389492a15SPatrick Williams ipv4Data.cend()); 1414588c3f0dSKowalski, Kamil } 141501784826SJohnathan Mantey else 141601784826SJohnathan Mantey { 1417cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1418cb13a392SEd Tanous asyncResp); 14194a0cb85cSEd Tanous } 14204a0cb85cSEd Tanous entryIdx++; 14214a0cb85cSEd Tanous } 142201784826SJohnathan Mantey else 142301784826SJohnathan Mantey { 142485ffe86aSJiaqing Zhao if (nicIpEntry == ipv4Data.cend()) 142501784826SJohnathan Mantey { 142601784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 142701784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 142801784826SJohnathan Mantey // in error, so bail out. 142901784826SJohnathan Mantey if (thisJson.is_null()) 143001784826SJohnathan Mantey { 143101784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 143201784826SJohnathan Mantey return; 143301784826SJohnathan Mantey } 1434f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 143571f52d96SEd Tanous pathString); 143601784826SJohnathan Mantey return; 143701784826SJohnathan Mantey } 143801784826SJohnathan Mantey 143901784826SJohnathan Mantey if (thisJson.is_null()) 144001784826SJohnathan Mantey { 14419c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 144201784826SJohnathan Mantey } 144385ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 144401784826SJohnathan Mantey { 144589492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 144689492a15SPatrick Williams ipv4Data.cend()); 144701784826SJohnathan Mantey } 144801784826SJohnathan Mantey entryIdx++; 144901784826SJohnathan Mantey } 145001784826SJohnathan Mantey } 14514a0cb85cSEd Tanous } 14524a0cb85cSEd Tanous 14534f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1454f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1455f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 14568d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1457f85837bfSRAJESWARAN THILLAIGOVINDAN { 14589ae226faSGeorge Liu sdbusplus::asio::setProperty( 14599ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 14609ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 14619ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 14629ae226faSGeorge Liu updatedStaticNameServers, 14635e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1464f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1465f85837bfSRAJESWARAN THILLAIGOVINDAN { 1466f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1467f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1468f85837bfSRAJESWARAN THILLAIGOVINDAN } 14699ae226faSGeorge Liu }); 1470f85837bfSRAJESWARAN THILLAIGOVINDAN } 1471f85837bfSRAJESWARAN THILLAIGOVINDAN 14724f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 1473ddd70dcaSEd Tanous const std::string& ifaceId, const nlohmann::json::array_t& input, 147477179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 14758d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1476e48c0fc5SRavi Teja { 1477ddd70dcaSEd Tanous if (input.empty()) 1478e48c0fc5SRavi Teja { 14792e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1480e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1481e48c0fc5SRavi Teja return; 1482e48c0fc5SRavi Teja } 1483271584abSEd Tanous size_t entryIdx = 1; 148477179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 14852c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1486f23b7296SEd Tanous for (const nlohmann::json& thisJson : input) 1487e48c0fc5SRavi Teja { 148889492a15SPatrick Williams std::string pathString = "IPv6StaticAddresses/" + 148989492a15SPatrick Williams std::to_string(entryIdx); 1490e48c0fc5SRavi Teja 149101784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1492e48c0fc5SRavi Teja { 1493e48c0fc5SRavi Teja std::optional<std::string> address; 1494e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1495f23b7296SEd Tanous nlohmann::json thisJsonCopy = thisJson; 1496bf648f77SEd Tanous if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 1497bf648f77SEd Tanous address, "PrefixLength", prefixLength)) 1498e48c0fc5SRavi Teja { 1499f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 150071f52d96SEd Tanous pathString); 1501e48c0fc5SRavi Teja return; 1502e48c0fc5SRavi Teja } 1503e48c0fc5SRavi Teja 1504543f4400SEd Tanous const std::string* addr = nullptr; 1505543f4400SEd Tanous uint8_t prefix = 0; 150601784826SJohnathan Mantey 150701784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 150801784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 150901784826SJohnathan Mantey // current state of the interface. Merge existing state into the 151001784826SJohnathan Mantey // current request. 1511e48c0fc5SRavi Teja if (address) 1512e48c0fc5SRavi Teja { 151301784826SJohnathan Mantey addr = &(*address); 1514e48c0fc5SRavi Teja } 151585ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 151601784826SJohnathan Mantey { 151785ffe86aSJiaqing Zhao addr = &(nicIpEntry->address); 151801784826SJohnathan Mantey } 151901784826SJohnathan Mantey else 152001784826SJohnathan Mantey { 152101784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 152201784826SJohnathan Mantey pathString + "/Address"); 152301784826SJohnathan Mantey return; 1524e48c0fc5SRavi Teja } 1525e48c0fc5SRavi Teja 1526e48c0fc5SRavi Teja if (prefixLength) 1527e48c0fc5SRavi Teja { 152801784826SJohnathan Mantey prefix = *prefixLength; 152901784826SJohnathan Mantey } 153085ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 1531e48c0fc5SRavi Teja { 153285ffe86aSJiaqing Zhao prefix = nicIpEntry->prefixLength; 1533e48c0fc5SRavi Teja } 1534e48c0fc5SRavi Teja else 1535e48c0fc5SRavi Teja { 1536e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1537e48c0fc5SRavi Teja pathString + "/PrefixLength"); 153801784826SJohnathan Mantey return; 1539e48c0fc5SRavi Teja } 1540e48c0fc5SRavi Teja 154185ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1542e48c0fc5SRavi Teja { 15439c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 154477eb0153SEd Tanous nicIpEntry->id, prefix, *addr, "", 1545e48c0fc5SRavi Teja asyncResp); 154689492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 154789492a15SPatrick Williams ipv6Data.cend()); 154801784826SJohnathan Mantey } 154901784826SJohnathan Mantey else 155001784826SJohnathan Mantey { 155101784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1552e48c0fc5SRavi Teja } 1553e48c0fc5SRavi Teja entryIdx++; 1554e48c0fc5SRavi Teja } 155501784826SJohnathan Mantey else 155601784826SJohnathan Mantey { 155785ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 155801784826SJohnathan Mantey { 155901784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 156001784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 156101784826SJohnathan Mantey // in error, so bail out. 156201784826SJohnathan Mantey if (thisJson.is_null()) 156301784826SJohnathan Mantey { 156401784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 156501784826SJohnathan Mantey return; 156601784826SJohnathan Mantey } 1567f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 156871f52d96SEd Tanous pathString); 156901784826SJohnathan Mantey return; 157001784826SJohnathan Mantey } 157101784826SJohnathan Mantey 157201784826SJohnathan Mantey if (thisJson.is_null()) 157301784826SJohnathan Mantey { 15749c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 157501784826SJohnathan Mantey } 157685ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 157701784826SJohnathan Mantey { 157889492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 157989492a15SPatrick Williams ipv6Data.cend()); 158001784826SJohnathan Mantey } 158101784826SJohnathan Mantey entryIdx++; 158201784826SJohnathan Mantey } 158301784826SJohnathan Mantey } 1584e48c0fc5SRavi Teja } 1585e48c0fc5SRavi Teja 15867857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 15877857cb8dSJiaqing Zhao { 15887857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 15897857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 15907857cb8dSJiaqing Zhao } 15917857cb8dSJiaqing Zhao 159277179532SEd Tanous inline void 159377179532SEd Tanous parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 159477179532SEd Tanous const std::string& ifaceId, 159577179532SEd Tanous const EthernetInterfaceData& ethData, 159677179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 159777179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) 15984a0cb85cSEd Tanous { 15992c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 160081ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1601ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 1602ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId); 16032c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1604eeedda23SJohnathan Mantey 160513451e39SWilly Tu if constexpr (bmcwebEnableHealthPopulate) 160613451e39SWilly Tu { 160713451e39SWilly Tu constexpr std::array<std::string_view, 1> inventoryForEthernet = { 160813451e39SWilly Tu "xyz.openbmc_project.Inventory.Item.Ethernet"}; 1609eeedda23SJohnathan Mantey auto health = std::make_shared<HealthPopulate>(asyncResp); 16107a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 16117a1dbc48SGeorge Liu "/", 0, inventoryForEthernet, 16127a1dbc48SGeorge Liu [health](const boost::system::error_code& ec, 1613b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& resp) { 1614eeedda23SJohnathan Mantey if (ec) 1615029573d4SEd Tanous { 1616eeedda23SJohnathan Mantey return; 1617eeedda23SJohnathan Mantey } 1618eeedda23SJohnathan Mantey 1619914e2d5dSEd Tanous health->inventory = resp; 16207a1dbc48SGeorge Liu }); 1621eeedda23SJohnathan Mantey 1622eeedda23SJohnathan Mantey health->populate(); 162313451e39SWilly Tu } 1624eeedda23SJohnathan Mantey 1625eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1626eeedda23SJohnathan Mantey { 16270ef0e289SJohnathan Mantey jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 16282c70f800SEd Tanous jsonResponse["Status"]["State"] = "Enabled"; 1629029573d4SEd Tanous } 1630029573d4SEd Tanous else 1631029573d4SEd Tanous { 16322c70f800SEd Tanous jsonResponse["LinkStatus"] = "NoLink"; 16332c70f800SEd Tanous jsonResponse["Status"]["State"] = "Disabled"; 1634029573d4SEd Tanous } 1635aa05fb27SJohnathan Mantey 16362c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 163735fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 163882695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 16392c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 164082695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1641*e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1642*e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1643*e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled; 16442c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1645b10d8db0SRavi Teja translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled" 16461f8c7b5dSJohnathan Mantey : "Disabled"; 1647*e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1648*e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1649*e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled; 1650b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1651b10d8db0SRavi Teja ethData.ipv6AcceptRa; 16522a133282Smanojkiraneda 165382695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 16544a0cb85cSEd Tanous { 165582695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1656ab6554f1SJoshi-Mansi 1657ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1658ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1659ab6554f1SJoshi-Mansi // FQDN 166082695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1661d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1662d24bfc7aSJennifer Lee { 16632c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1664d24bfc7aSJennifer Lee } 16652c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 16664a0cb85cSEd Tanous } 16674a0cb85cSEd Tanous 16687857cb8dSJiaqing Zhao if (ethData.vlanId) 16697857cb8dSJiaqing Zhao { 16707857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Virtual"; 16717857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 16727857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 16737857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 16747857cb8dSJiaqing Zhao 16757857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 16767857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 16777857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 16787857cb8dSJiaqing Zhao boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces", 16797857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 16807857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 16817857cb8dSJiaqing Zhao std::move(relatedInterfaces); 16827857cb8dSJiaqing Zhao } 16837857cb8dSJiaqing Zhao else 16847857cb8dSJiaqing Zhao { 16857857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Physical"; 16867857cb8dSJiaqing Zhao } 16877857cb8dSJiaqing Zhao 16882c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 16892c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 16904a0cb85cSEd Tanous 16912c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 16922c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 16932c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 16942c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 16959eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 16964a0cb85cSEd Tanous { 16972c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1698fa5053a6SGunnar Mills if (gatewayStr.empty()) 1699fa5053a6SGunnar Mills { 1700fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1701fa5053a6SGunnar Mills } 17021476687dSEd Tanous nlohmann::json::object_t ipv4; 17031476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 17041476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 17051476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 17061476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1707fa5053a6SGunnar Mills 17082c70f800SEd Tanous if (ipv4Config.origin == "Static") 1709d1d50814SRavi Teja { 17101476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1711d1d50814SRavi Teja } 17121476687dSEd Tanous 1713b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 171401784826SJohnathan Mantey } 1715d1d50814SRavi Teja 171682695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 17177ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 17187ea79e5eSRavi Teja { 17197ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 17207ea79e5eSRavi Teja } 17217ea79e5eSRavi Teja 17227ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1723e48c0fc5SRavi Teja 17242c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 17252c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 17262c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 17272c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 17287f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 17292c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 17307f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 17319eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1732e48c0fc5SRavi Teja { 17331476687dSEd Tanous nlohmann::json::object_t ipv6; 17341476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 17351476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 17361476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1737f8361275SSunitha Harish 1738b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 17392c70f800SEd Tanous if (ipv6Config.origin == "Static") 1740e48c0fc5SRavi Teja { 17411476687dSEd Tanous nlohmann::json::object_t ipv6Static; 17421476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 17431476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 1744b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 174501784826SJohnathan Mantey } 1746e48c0fc5SRavi Teja } 1747588c3f0dSKowalski, Kamil } 1748588c3f0dSKowalski, Kamil 1749e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1750e7caf250SJiaqing Zhao const std::string& ifaceId, 1751e7caf250SJiaqing Zhao const boost::system::error_code& ec, 1752e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 1753e7caf250SJiaqing Zhao { 1754e7caf250SJiaqing Zhao if (!ec) 1755e7caf250SJiaqing Zhao { 1756e7caf250SJiaqing Zhao return; 1757e7caf250SJiaqing Zhao } 1758e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1759e7caf250SJiaqing Zhao if (dbusError == nullptr) 1760e7caf250SJiaqing Zhao { 1761e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1762e7caf250SJiaqing Zhao return; 1763e7caf250SJiaqing Zhao } 176462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1765e7caf250SJiaqing Zhao 1766e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 1767e7caf250SJiaqing Zhao dbusError->name) 1768e7caf250SJiaqing Zhao { 1769e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1770e7caf250SJiaqing Zhao ifaceId); 1771e7caf250SJiaqing Zhao return; 1772e7caf250SJiaqing Zhao } 1773e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 1774e7caf250SJiaqing Zhao dbusError->name) 1775e7caf250SJiaqing Zhao { 1776e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 1777e7caf250SJiaqing Zhao return; 1778e7caf250SJiaqing Zhao } 1779e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1780e7caf250SJiaqing Zhao } 1781e7caf250SJiaqing Zhao 1782b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1783b5ca3fdcSJiaqing Zhao const std::string& parentInterfaceUri, 1784b5ca3fdcSJiaqing Zhao const std::string& vlanInterface, 1785b5ca3fdcSJiaqing Zhao const boost::system::error_code& ec, 1786b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m 1787b5ca3fdcSJiaqing Zhao 1788b5ca3fdcSJiaqing Zhao ) 1789b5ca3fdcSJiaqing Zhao { 1790b5ca3fdcSJiaqing Zhao if (ec) 1791b5ca3fdcSJiaqing Zhao { 1792b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1793b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 1794b5ca3fdcSJiaqing Zhao { 1795b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1796b5ca3fdcSJiaqing Zhao return; 1797b5ca3fdcSJiaqing Zhao } 179862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1799b5ca3fdcSJiaqing Zhao 1800b5ca3fdcSJiaqing Zhao if (std::string_view( 1801b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 1802b5ca3fdcSJiaqing Zhao dbusError->name) 1803b5ca3fdcSJiaqing Zhao { 1804b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1805b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1806b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1807b5ca3fdcSJiaqing Zhao return; 1808b5ca3fdcSJiaqing Zhao } 1809b5ca3fdcSJiaqing Zhao if (std::string_view( 1810b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 1811b5ca3fdcSJiaqing Zhao dbusError->name) 1812b5ca3fdcSJiaqing Zhao { 1813b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 1814b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 1815b5ca3fdcSJiaqing Zhao return; 1816b5ca3fdcSJiaqing Zhao } 1817b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1818b5ca3fdcSJiaqing Zhao return; 1819b5ca3fdcSJiaqing Zhao } 1820b5ca3fdcSJiaqing Zhao 1821b5ca3fdcSJiaqing Zhao const boost::urls::url vlanInterfaceUri = boost::urls::format( 1822b5ca3fdcSJiaqing Zhao "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface); 1823b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 1824b5ca3fdcSJiaqing Zhao } 1825b5ca3fdcSJiaqing Zhao 1826bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 1827bf648f77SEd Tanous { 1828bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 1829ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 18301476687dSEd Tanous .methods(boost::beast::http::verb::get)( 18311476687dSEd Tanous [&app](const crow::Request& req, 18321476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 18333ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 183445ca1b86SEd Tanous { 183545ca1b86SEd Tanous return; 183645ca1b86SEd Tanous } 183745ca1b86SEd Tanous 1838bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1839bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 1840bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1841bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 1842bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 1843bf648f77SEd Tanous "Ethernet Network Interface Collection"; 1844bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 1845bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 1846bf648f77SEd Tanous 1847bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 1848bf648f77SEd Tanous // preparation 1849002d39b4SEd Tanous getEthernetIfaceList( 185077179532SEd Tanous [asyncResp](const bool& success, 185177179532SEd Tanous const std::vector<std::string>& ifaceList) { 1852bf648f77SEd Tanous if (!success) 18531abe55efSEd Tanous { 1854f12894f8SJason M. Bills messages::internalError(asyncResp->res); 18559391bb9cSRapkiewicz, Pawel return; 18569391bb9cSRapkiewicz, Pawel } 18579391bb9cSRapkiewicz, Pawel 1858002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 1859bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 1860bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 1861bf648f77SEd Tanous { 18621476687dSEd Tanous nlohmann::json::object_t iface; 1863ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 1864ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", 1865ef4c65b7SEd Tanous ifaceItem); 18667857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 1867bf648f77SEd Tanous } 1868bf648f77SEd Tanous 1869002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 1870bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1871bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 1872bf648f77SEd Tanous }); 1873bf648f77SEd Tanous }); 1874bf648f77SEd Tanous 1875b5ca3fdcSJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 1876b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 1877b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 1878b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 1879b5ca3fdcSJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1880b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1881b5ca3fdcSJiaqing Zhao { 1882b5ca3fdcSJiaqing Zhao return; 1883b5ca3fdcSJiaqing Zhao } 1884b5ca3fdcSJiaqing Zhao 1885b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 1886b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 1887b5ca3fdcSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 1888b5ca3fdcSJiaqing Zhao 1889b5ca3fdcSJiaqing Zhao if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", 1890b5ca3fdcSJiaqing Zhao vlanEnable, "VLAN/VLANId", vlanId, 1891b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 1892b5ca3fdcSJiaqing Zhao relatedInterfaces)) 1893b5ca3fdcSJiaqing Zhao { 1894b5ca3fdcSJiaqing Zhao return; 1895b5ca3fdcSJiaqing Zhao } 1896b5ca3fdcSJiaqing Zhao 1897b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 1898b5ca3fdcSJiaqing Zhao { 1899b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 1900b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 1901b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 1902b5ca3fdcSJiaqing Zhao return; 1903b5ca3fdcSJiaqing Zhao } 1904b5ca3fdcSJiaqing Zhao 1905b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 1906b5ca3fdcSJiaqing Zhao if (!json_util::readJson(relatedInterfaces[0], asyncResp->res, 1907b5ca3fdcSJiaqing Zhao "@odata.id", parentInterfaceUri)) 1908b5ca3fdcSJiaqing Zhao { 1909b5ca3fdcSJiaqing Zhao messages::propertyMissing(asyncResp->res, 1910b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1911b5ca3fdcSJiaqing Zhao return; 1912b5ca3fdcSJiaqing Zhao } 191362598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 1914b5ca3fdcSJiaqing Zhao 19156fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 1916b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 1917b5ca3fdcSJiaqing Zhao if (!parsedUri) 1918b5ca3fdcSJiaqing Zhao { 1919b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 1920b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1921b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1922b5ca3fdcSJiaqing Zhao return; 1923b5ca3fdcSJiaqing Zhao } 1924b5ca3fdcSJiaqing Zhao 1925b5ca3fdcSJiaqing Zhao std::string parentInterface; 1926b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 1927b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 1928b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 1929b5ca3fdcSJiaqing Zhao { 1930b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1931b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1932b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1933b5ca3fdcSJiaqing Zhao return; 1934b5ca3fdcSJiaqing Zhao } 1935b5ca3fdcSJiaqing Zhao 1936b5ca3fdcSJiaqing Zhao if (!vlanEnable) 1937b5ca3fdcSJiaqing Zhao { 1938b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 1939b5ca3fdcSJiaqing Zhao // create 1940b5ca3fdcSJiaqing Zhao messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", 1941b5ca3fdcSJiaqing Zhao "false"); 1942b5ca3fdcSJiaqing Zhao return; 1943b5ca3fdcSJiaqing Zhao } 1944b5ca3fdcSJiaqing Zhao 1945b5ca3fdcSJiaqing Zhao std::string vlanInterface = parentInterface + "_" + 1946b5ca3fdcSJiaqing Zhao std::to_string(vlanId); 1947b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 1948b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 1949b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 1950b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 1951b5ca3fdcSJiaqing Zhao afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, 1952b5ca3fdcSJiaqing Zhao m); 1953b5ca3fdcSJiaqing Zhao }, 1954b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 1955b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, 1956b5ca3fdcSJiaqing Zhao vlanId); 1957b5ca3fdcSJiaqing Zhao }); 1958b5ca3fdcSJiaqing Zhao 1959bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 1960ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 1961bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 196245ca1b86SEd Tanous [&app](const crow::Request& req, 1963bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1964bf648f77SEd Tanous const std::string& ifaceId) { 19653ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 196645ca1b86SEd Tanous { 196745ca1b86SEd Tanous return; 196845ca1b86SEd Tanous } 19694a0cb85cSEd Tanous getEthernetIfaceData( 1970bf648f77SEd Tanous ifaceId, 197177179532SEd Tanous [asyncResp, ifaceId](const bool& success, 197277179532SEd Tanous const EthernetInterfaceData& ethData, 197377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 197477179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) { 19754a0cb85cSEd Tanous if (!success) 19761abe55efSEd Tanous { 1977bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 1978bf648f77SEd Tanous // existing object, and other errors 1979002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1980002d39b4SEd Tanous ifaceId); 19814a0cb85cSEd Tanous return; 19829391bb9cSRapkiewicz, Pawel } 19834c9afe43SEd Tanous 19840f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 198593bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 1986002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 19870f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 19880f74e643SEd Tanous "Management Network Interface"; 19890f74e643SEd Tanous 1990002d39b4SEd Tanous parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data); 19919391bb9cSRapkiewicz, Pawel }); 1992bf648f77SEd Tanous }); 19939391bb9cSRapkiewicz, Pawel 1994bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 1995ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 1996bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 199745ca1b86SEd Tanous [&app](const crow::Request& req, 1998bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1999bf648f77SEd Tanous const std::string& ifaceId) { 20003ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 200145ca1b86SEd Tanous { 200245ca1b86SEd Tanous return; 200345ca1b86SEd Tanous } 2004bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2005ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2006d577665bSRatan Gupta std::optional<std::string> macAddress; 20079a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2008ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv4StaticAddresses; 2009ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv6StaticAddresses; 2010f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2011da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 20121f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 2013b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2014eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 201535fb5311STejas Patil std::optional<size_t> mtuSize; 20161f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 20171f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2018b10d8db0SRavi Teja // clang-format off 201915ed6780SWilly Tu if (!json_util::readJsonPatch( 2020b10d8db0SRavi Teja req, asyncResp->res, 2021b10d8db0SRavi Teja "DHCPv4", dhcpv4, 2022b10d8db0SRavi Teja "DHCPv6", dhcpv6, 2023b10d8db0SRavi Teja "FQDN", fqdn, 2024b10d8db0SRavi Teja "HostName", hostname, 2025b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 2026b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 2027b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 2028b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 2029b10d8db0SRavi Teja "MACAddress", macAddress, 2030b10d8db0SRavi Teja "MTUSize", mtuSize, 2031b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 2032b10d8db0SRavi Teja "StaticNameServers", staticNameServers 2033b10d8db0SRavi Teja ) 2034b10d8db0SRavi Teja ) 20351abe55efSEd Tanous { 2036588c3f0dSKowalski, Kamil return; 2037588c3f0dSKowalski, Kamil } 2038b10d8db0SRavi Teja //clang-format on 2039da131a9aSJennifer Lee if (dhcpv4) 2040da131a9aSJennifer Lee { 2041002d39b4SEd Tanous if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 20421f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 204382695a5bSJiaqing Zhao v4dhcpParms.useDnsServers, "UseNTPServers", 204482695a5bSJiaqing Zhao v4dhcpParms.useNtpServers, "UseDomainName", 204582695a5bSJiaqing Zhao v4dhcpParms.useDomainName)) 20461f8c7b5dSJohnathan Mantey { 20471f8c7b5dSJohnathan Mantey return; 20481f8c7b5dSJohnathan Mantey } 20491f8c7b5dSJohnathan Mantey } 20501f8c7b5dSJohnathan Mantey 20511f8c7b5dSJohnathan Mantey if (dhcpv6) 20521f8c7b5dSJohnathan Mantey { 2053002d39b4SEd Tanous if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode", 2054002d39b4SEd Tanous v6dhcpParms.dhcpv6OperatingMode, 2055002d39b4SEd Tanous "UseDNSServers", v6dhcpParms.useDnsServers, 2056002d39b4SEd Tanous "UseNTPServers", v6dhcpParms.useNtpServers, 2057002d39b4SEd Tanous "UseDomainName", 205882695a5bSJiaqing Zhao v6dhcpParms.useDomainName)) 20591f8c7b5dSJohnathan Mantey { 20601f8c7b5dSJohnathan Mantey return; 20611f8c7b5dSJohnathan Mantey } 2062da131a9aSJennifer Lee } 2063da131a9aSJennifer Lee 2064bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2065bf648f77SEd Tanous // for JSON preparation 20664a0cb85cSEd Tanous getEthernetIfaceData( 20672c70f800SEd Tanous ifaceId, 2068bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2069ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2070d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 20719a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2072e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 20731f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 2074bc20089aSEd Tanous dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize, 2075b10d8db0SRavi Teja ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms), 2076f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2077002d39b4SEd Tanous const bool& success, const EthernetInterfaceData& ethData, 207877179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 207977179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) { 20801abe55efSEd Tanous if (!success) 20811abe55efSEd Tanous { 2082588c3f0dSKowalski, Kamil // ... otherwise return error 2083bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2084bf648f77SEd Tanous // existing object, and other errors 2085002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2086002d39b4SEd Tanous ifaceId); 2087588c3f0dSKowalski, Kamil return; 2088588c3f0dSKowalski, Kamil } 2089588c3f0dSKowalski, Kamil 20901f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 20911f8c7b5dSJohnathan Mantey { 2092002d39b4SEd Tanous handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, 2093002d39b4SEd Tanous asyncResp); 20941f8c7b5dSJohnathan Mantey } 20951f8c7b5dSJohnathan Mantey 20960627a2c7SEd Tanous if (hostname) 20971abe55efSEd Tanous { 20980627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 20991abe55efSEd Tanous } 21000627a2c7SEd Tanous 2101b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2102b10d8db0SRavi Teja { 2103b10d8db0SRavi Teja handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled, 2104b10d8db0SRavi Teja asyncResp); 2105b10d8db0SRavi Teja } 2106b10d8db0SRavi Teja 2107ab6554f1SJoshi-Mansi if (fqdn) 2108ab6554f1SJoshi-Mansi { 21092c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2110ab6554f1SJoshi-Mansi } 2111ab6554f1SJoshi-Mansi 2112d577665bSRatan Gupta if (macAddress) 2113d577665bSRatan Gupta { 2114002d39b4SEd Tanous handleMACAddressPatch(ifaceId, *macAddress, asyncResp); 2115d577665bSRatan Gupta } 2116d577665bSRatan Gupta 2117d1d50814SRavi Teja if (ipv4StaticAddresses) 2118d1d50814SRavi Teja { 2119bf648f77SEd Tanous // TODO(ed) for some reason the capture of 2120bf648f77SEd Tanous // ipv4Addresses above is returning a const value, 2121bf648f77SEd Tanous // not a non-const value. This doesn't really work 2122bf648f77SEd Tanous // for us, as we need to be able to efficiently move 2123bf648f77SEd Tanous // out the intermedia nlohmann::json objects. This 2124bf648f77SEd Tanous // makes a copy of the structure, and operates on 2125bf648f77SEd Tanous // that, but could be done more efficiently 2126ddd70dcaSEd Tanous nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses; 2127002d39b4SEd Tanous handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp); 21281abe55efSEd Tanous } 21290627a2c7SEd Tanous 2130f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2131f85837bfSRAJESWARAN THILLAIGOVINDAN { 2132002d39b4SEd Tanous handleStaticNameServersPatch(ifaceId, *staticNameServers, 2133002d39b4SEd Tanous asyncResp); 2134f85837bfSRAJESWARAN THILLAIGOVINDAN } 21359a6fc6feSRavi Teja 21369a6fc6feSRavi Teja if (ipv6DefaultGateway) 21379a6fc6feSRavi Teja { 21389a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 21399a6fc6feSRavi Teja "IPv6DefaultGateway"); 21409a6fc6feSRavi Teja } 2141e48c0fc5SRavi Teja 2142e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2143e48c0fc5SRavi Teja { 2144ddd70dcaSEd Tanous handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses, 2145ddd70dcaSEd Tanous ipv6Data, asyncResp); 2146e48c0fc5SRavi Teja } 2147eeedda23SJohnathan Mantey 2148eeedda23SJohnathan Mantey if (interfaceEnabled) 2149eeedda23SJohnathan Mantey { 2150002d39b4SEd Tanous setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled", 2151002d39b4SEd Tanous *interfaceEnabled, asyncResp); 2152eeedda23SJohnathan Mantey } 215335fb5311STejas Patil 215435fb5311STejas Patil if (mtuSize) 215535fb5311STejas Patil { 215635fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 215735fb5311STejas Patil } 2158588c3f0dSKowalski, Kamil }); 2159bf648f77SEd Tanous }); 2160e7caf250SJiaqing Zhao 2161e7caf250SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2162e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2163e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2164e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2165e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2166e7caf250SJiaqing Zhao const std::string& ifaceId) { 2167e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2168e7caf250SJiaqing Zhao { 2169e7caf250SJiaqing Zhao return; 2170e7caf250SJiaqing Zhao } 2171e7caf250SJiaqing Zhao 2172e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2173e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2174e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2175e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2176e7caf250SJiaqing Zhao }, 2177e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2178e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2179e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2180e7caf250SJiaqing Zhao }); 21814a0cb85cSEd Tanous } 2182bf648f77SEd Tanous 21839391bb9cSRapkiewicz, Pawel } // namespace redfish 2184