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 3111ba3979SEd Tanous #include <boost/algorithm/string/classification.hpp> 3211ba3979SEd Tanous #include <boost/algorithm/string/split.hpp> 33ef4c65b7SEd Tanous #include <boost/url/format.hpp> 341214b7e7SGunnar Mills 357a1dbc48SGeorge Liu #include <array> 36a24526dcSEd Tanous #include <optional> 373544d2a7SEd Tanous #include <ranges> 38ab6554f1SJoshi-Mansi #include <regex> 397a1dbc48SGeorge Liu #include <string_view> 4077179532SEd Tanous #include <vector> 419391bb9cSRapkiewicz, Pawel 421abe55efSEd Tanous namespace redfish 431abe55efSEd Tanous { 449391bb9cSRapkiewicz, Pawel 454a0cb85cSEd Tanous enum class LinkType 464a0cb85cSEd Tanous { 474a0cb85cSEd Tanous Local, 484a0cb85cSEd Tanous Global 494a0cb85cSEd Tanous }; 509391bb9cSRapkiewicz, Pawel 519391bb9cSRapkiewicz, Pawel /** 529391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 539391bb9cSRapkiewicz, Pawel */ 541abe55efSEd Tanous struct IPv4AddressData 551abe55efSEd Tanous { 56179db1d7SKowalski, Kamil std::string id; 574a0cb85cSEd Tanous std::string address; 584a0cb85cSEd Tanous std::string domain; 594a0cb85cSEd Tanous std::string gateway; 609391bb9cSRapkiewicz, Pawel std::string netmask; 619391bb9cSRapkiewicz, Pawel std::string origin; 6277179532SEd Tanous LinkType linktype{}; 6377179532SEd Tanous bool isActive{}; 649391bb9cSRapkiewicz, Pawel }; 659391bb9cSRapkiewicz, Pawel 669391bb9cSRapkiewicz, Pawel /** 67e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 68e48c0fc5SRavi Teja */ 69e48c0fc5SRavi Teja struct IPv6AddressData 70e48c0fc5SRavi Teja { 71e48c0fc5SRavi Teja std::string id; 72e48c0fc5SRavi Teja std::string address; 73e48c0fc5SRavi Teja std::string origin; 7477179532SEd Tanous uint8_t prefixLength = 0; 75e48c0fc5SRavi Teja }; 76e48c0fc5SRavi Teja /** 779391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 789391bb9cSRapkiewicz, Pawel * available from DBus 799391bb9cSRapkiewicz, Pawel */ 801abe55efSEd Tanous struct EthernetInterfaceData 811abe55efSEd Tanous { 824a0cb85cSEd Tanous uint32_t speed; 8335fb5311STejas Patil size_t mtuSize; 8482695a5bSJiaqing Zhao bool autoNeg; 8582695a5bSJiaqing Zhao bool dnsEnabled; 8682695a5bSJiaqing Zhao bool ntpEnabled; 8782695a5bSJiaqing Zhao bool hostNameEnabled; 88aa05fb27SJohnathan Mantey bool linkUp; 89eeedda23SJohnathan Mantey bool nicEnabled; 90b10d8db0SRavi Teja bool ipv6AcceptRa; 9182695a5bSJiaqing Zhao std::string dhcpEnabled; 921f8c7b5dSJohnathan Mantey std::string operatingMode; 9382695a5bSJiaqing Zhao std::string hostName; 9482695a5bSJiaqing Zhao std::string defaultGateway; 9582695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 9682695a5bSJiaqing Zhao std::string macAddress; 9717e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 980f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 990f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 100d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1019391bb9cSRapkiewicz, Pawel }; 1029391bb9cSRapkiewicz, Pawel 1031f8c7b5dSJohnathan Mantey struct DHCPParameters 1041f8c7b5dSJohnathan Mantey { 1051f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 10682695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 10782695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 10882695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1091f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1101f8c7b5dSJohnathan Mantey }; 1111f8c7b5dSJohnathan Mantey 1129391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1139391bb9cSRapkiewicz, Pawel // into full dot notation 1141abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1151abe55efSEd Tanous { 1169391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1179391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1189391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1199391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1209391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1219391bb9cSRapkiewicz, Pawel return netmask; 1229391bb9cSRapkiewicz, Pawel } 1239391bb9cSRapkiewicz, Pawel 12482695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1251f8c7b5dSJohnathan Mantey bool isIPv4) 1261f8c7b5dSJohnathan Mantey { 1271f8c7b5dSJohnathan Mantey if (isIPv4) 1281f8c7b5dSJohnathan Mantey { 1291f8c7b5dSJohnathan Mantey return ( 1301f8c7b5dSJohnathan Mantey (inputDHCP == 1311f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1321f8c7b5dSJohnathan Mantey (inputDHCP == 1331f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1341f8c7b5dSJohnathan Mantey } 1351f8c7b5dSJohnathan Mantey return ((inputDHCP == 1361f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1371f8c7b5dSJohnathan Mantey (inputDHCP == 1381f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1391f8c7b5dSJohnathan Mantey } 1401f8c7b5dSJohnathan Mantey 1412c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1421f8c7b5dSJohnathan Mantey { 1431f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1441f8c7b5dSJohnathan Mantey { 1451f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1461f8c7b5dSJohnathan Mantey } 1473174e4dfSEd Tanous if (isIPv4) 1481f8c7b5dSJohnathan Mantey { 1491f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1501f8c7b5dSJohnathan Mantey } 1513174e4dfSEd Tanous if (isIPv6) 1521f8c7b5dSJohnathan Mantey { 1531f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1541f8c7b5dSJohnathan Mantey } 1551f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1561f8c7b5dSJohnathan Mantey } 1571f8c7b5dSJohnathan Mantey 1584a0cb85cSEd Tanous inline std::string 1594a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string& inputOrigin, 1604a0cb85cSEd Tanous bool isIPv4) 1611abe55efSEd Tanous { 1624a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1631abe55efSEd Tanous { 1644a0cb85cSEd Tanous return "Static"; 1659391bb9cSRapkiewicz, Pawel } 1664a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1671abe55efSEd Tanous { 1684a0cb85cSEd Tanous if (isIPv4) 1691abe55efSEd Tanous { 1704a0cb85cSEd Tanous return "IPv4LinkLocal"; 1711abe55efSEd Tanous } 1724a0cb85cSEd Tanous return "LinkLocal"; 1739391bb9cSRapkiewicz, Pawel } 1744a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1751abe55efSEd Tanous { 1764a0cb85cSEd Tanous if (isIPv4) 1774a0cb85cSEd Tanous { 1784a0cb85cSEd Tanous return "DHCP"; 1794a0cb85cSEd Tanous } 1804a0cb85cSEd Tanous return "DHCPv6"; 1814a0cb85cSEd Tanous } 1824a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1834a0cb85cSEd Tanous { 1844a0cb85cSEd Tanous return "SLAAC"; 1854a0cb85cSEd Tanous } 1864a0cb85cSEd Tanous return ""; 1874a0cb85cSEd Tanous } 1884a0cb85cSEd Tanous 18902cad96eSEd Tanous inline bool extractEthernetInterfaceData( 19002cad96eSEd Tanous const std::string& ethifaceId, 19102cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 1924a0cb85cSEd Tanous EthernetInterfaceData& ethData) 1934a0cb85cSEd Tanous { 1944c9afe43SEd Tanous bool idFound = false; 19502cad96eSEd Tanous for (const auto& objpath : dbusData) 1964a0cb85cSEd Tanous { 19702cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 1984a0cb85cSEd Tanous { 19981ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 200029573d4SEd Tanous { 2014c9afe43SEd Tanous idFound = true; 2024a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2034a0cb85cSEd Tanous { 2044a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2054a0cb85cSEd Tanous { 2064a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2074a0cb85cSEd Tanous { 2084a0cb85cSEd Tanous const std::string* mac = 209abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2104a0cb85cSEd Tanous if (mac != nullptr) 2114a0cb85cSEd Tanous { 21282695a5bSJiaqing Zhao ethData.macAddress = *mac; 2134a0cb85cSEd Tanous } 2144a0cb85cSEd Tanous } 2154a0cb85cSEd Tanous } 2164a0cb85cSEd Tanous } 2174a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2184a0cb85cSEd Tanous { 2194a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2204a0cb85cSEd Tanous { 2214a0cb85cSEd Tanous if (propertyPair.first == "Id") 2224a0cb85cSEd Tanous { 2231b6b96c5SEd Tanous const uint32_t* id = 224abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2254a0cb85cSEd Tanous if (id != nullptr) 2264a0cb85cSEd Tanous { 22717e22024SJiaqing Zhao ethData.vlanId = *id; 2284a0cb85cSEd Tanous } 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous } 2314a0cb85cSEd Tanous } 2324a0cb85cSEd Tanous else if (ifacePair.first == 2334a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2344a0cb85cSEd Tanous { 2354a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2364a0cb85cSEd Tanous { 2374a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2384a0cb85cSEd Tanous { 2392c70f800SEd Tanous const bool* autoNeg = 240abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2412c70f800SEd Tanous if (autoNeg != nullptr) 2424a0cb85cSEd Tanous { 24382695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2444a0cb85cSEd Tanous } 2454a0cb85cSEd Tanous } 2464a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2474a0cb85cSEd Tanous { 2484a0cb85cSEd Tanous const uint32_t* speed = 249abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2504a0cb85cSEd Tanous if (speed != nullptr) 2514a0cb85cSEd Tanous { 2524a0cb85cSEd Tanous ethData.speed = *speed; 2534a0cb85cSEd Tanous } 2544a0cb85cSEd Tanous } 25535fb5311STejas Patil else if (propertyPair.first == "MTU") 25635fb5311STejas Patil { 25735fb5311STejas Patil const uint32_t* mtuSize = 25835fb5311STejas Patil std::get_if<uint32_t>(&propertyPair.second); 25935fb5311STejas Patil if (mtuSize != nullptr) 26035fb5311STejas Patil { 26135fb5311STejas Patil ethData.mtuSize = *mtuSize; 26235fb5311STejas Patil } 26335fb5311STejas Patil } 264aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 265aa05fb27SJohnathan Mantey { 266aa05fb27SJohnathan Mantey const bool* linkUp = 267aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 268aa05fb27SJohnathan Mantey if (linkUp != nullptr) 269aa05fb27SJohnathan Mantey { 270aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 271aa05fb27SJohnathan Mantey } 272aa05fb27SJohnathan Mantey } 273eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 274eeedda23SJohnathan Mantey { 275eeedda23SJohnathan Mantey const bool* nicEnabled = 276eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 277eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 278eeedda23SJohnathan Mantey { 279eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 280eeedda23SJohnathan Mantey } 281eeedda23SJohnathan Mantey } 282b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 283b10d8db0SRavi Teja { 284b10d8db0SRavi Teja const bool* ipv6AcceptRa = 285b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 286b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 287b10d8db0SRavi Teja { 288b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 289b10d8db0SRavi Teja } 290b10d8db0SRavi Teja } 291f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 292029573d4SEd Tanous { 293029573d4SEd Tanous const std::vector<std::string>* nameservers = 2948d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 295029573d4SEd Tanous &propertyPair.second); 296029573d4SEd Tanous if (nameservers != nullptr) 297029573d4SEd Tanous { 298f23b7296SEd Tanous ethData.nameServers = *nameservers; 2990f6efdc1Smanojkiran.eda@gmail.com } 3000f6efdc1Smanojkiran.eda@gmail.com } 3010f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3020f6efdc1Smanojkiran.eda@gmail.com { 3030f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3048d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3050f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3060f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3070f6efdc1Smanojkiran.eda@gmail.com { 308f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3094a0cb85cSEd Tanous } 3104a0cb85cSEd Tanous } 3112a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3122a133282Smanojkiraneda { 3132c70f800SEd Tanous const std::string* dhcpEnabled = 3141f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3152c70f800SEd Tanous if (dhcpEnabled != nullptr) 3162a133282Smanojkiraneda { 31782695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3182a133282Smanojkiraneda } 3192a133282Smanojkiraneda } 320d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 321d24bfc7aSJennifer Lee { 322d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3238d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 324d24bfc7aSJennifer Lee &propertyPair.second); 325d24bfc7aSJennifer Lee if (domainNames != nullptr) 326d24bfc7aSJennifer Lee { 327f23b7296SEd Tanous ethData.domainnames = *domainNames; 328d24bfc7aSJennifer Lee } 329d24bfc7aSJennifer Lee } 3309010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3319010ec2eSRavi Teja { 3329010ec2eSRavi Teja const std::string* defaultGateway = 3339010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3349010ec2eSRavi Teja if (defaultGateway != nullptr) 3359010ec2eSRavi Teja { 3369010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3379010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3389010ec2eSRavi Teja { 33982695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3409010ec2eSRavi Teja } 3419010ec2eSRavi Teja else 3429010ec2eSRavi Teja { 34382695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3449010ec2eSRavi Teja } 3459010ec2eSRavi Teja } 3469010ec2eSRavi Teja } 3479010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3489010ec2eSRavi Teja { 3499010ec2eSRavi Teja const std::string* defaultGateway6 = 3509010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3519010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3529010ec2eSRavi Teja { 3539010ec2eSRavi Teja std::string defaultGateway6Str = 3549010ec2eSRavi Teja *defaultGateway6; 3559010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3569010ec2eSRavi Teja { 35782695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3589010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3599010ec2eSRavi Teja } 3609010ec2eSRavi Teja else 3619010ec2eSRavi Teja { 36282695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3639010ec2eSRavi Teja defaultGateway6Str; 3649010ec2eSRavi Teja } 3659010ec2eSRavi Teja } 3669010ec2eSRavi Teja } 367029573d4SEd Tanous } 368029573d4SEd Tanous } 369029573d4SEd Tanous } 3701f8c7b5dSJohnathan Mantey 3711e3f85e6SJian Zhang if (objpath.first == "/xyz/openbmc_project/network/dhcp") 3721f8c7b5dSJohnathan Mantey { 3731f8c7b5dSJohnathan Mantey if (ifacePair.first == 3741f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 3751f8c7b5dSJohnathan Mantey { 3761f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 3771f8c7b5dSJohnathan Mantey { 3781f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 3791f8c7b5dSJohnathan Mantey { 3802c70f800SEd Tanous const bool* dnsEnabled = 3811f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3822c70f800SEd Tanous if (dnsEnabled != nullptr) 3831f8c7b5dSJohnathan Mantey { 38482695a5bSJiaqing Zhao ethData.dnsEnabled = *dnsEnabled; 3851f8c7b5dSJohnathan Mantey } 3861f8c7b5dSJohnathan Mantey } 3871f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 3881f8c7b5dSJohnathan Mantey { 3892c70f800SEd Tanous const bool* ntpEnabled = 3901f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3912c70f800SEd Tanous if (ntpEnabled != nullptr) 3921f8c7b5dSJohnathan Mantey { 39382695a5bSJiaqing Zhao ethData.ntpEnabled = *ntpEnabled; 3941f8c7b5dSJohnathan Mantey } 3951f8c7b5dSJohnathan Mantey } 3961f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 3971f8c7b5dSJohnathan Mantey { 3982c70f800SEd Tanous const bool* hostNameEnabled = 3991f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4002c70f800SEd Tanous if (hostNameEnabled != nullptr) 4011f8c7b5dSJohnathan Mantey { 40282695a5bSJiaqing Zhao ethData.hostNameEnabled = *hostNameEnabled; 4031f8c7b5dSJohnathan Mantey } 4041f8c7b5dSJohnathan Mantey } 4051f8c7b5dSJohnathan Mantey } 4061f8c7b5dSJohnathan Mantey } 4071f8c7b5dSJohnathan Mantey } 408029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 409029573d4SEd Tanous // to check eth number 410029573d4SEd Tanous if (ifacePair.first == 4114a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 4124a0cb85cSEd Tanous { 4134a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 4144a0cb85cSEd Tanous { 4154a0cb85cSEd Tanous if (propertyPair.first == "HostName") 4164a0cb85cSEd Tanous { 4174a0cb85cSEd Tanous const std::string* hostname = 4188d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 4194a0cb85cSEd Tanous if (hostname != nullptr) 4204a0cb85cSEd Tanous { 42182695a5bSJiaqing Zhao ethData.hostName = *hostname; 4224a0cb85cSEd Tanous } 4234a0cb85cSEd Tanous } 4244a0cb85cSEd Tanous } 4254a0cb85cSEd Tanous } 4264a0cb85cSEd Tanous } 4274a0cb85cSEd Tanous } 4284c9afe43SEd Tanous return idFound; 4294a0cb85cSEd Tanous } 4304a0cb85cSEd Tanous 431e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 43277179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 433711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 43477179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 435e48c0fc5SRavi Teja { 43689492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 43789492a15SPatrick Williams ethifaceId; 438e48c0fc5SRavi Teja 439e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 440e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 44181ce609eSEd Tanous for (const auto& objpath : dbusData) 442e48c0fc5SRavi Teja { 443e48c0fc5SRavi Teja // Check if proper pattern for object path appears 444353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 445e48c0fc5SRavi Teja { 4469eb808c1SEd Tanous for (const auto& interface : objpath.second) 447e48c0fc5SRavi Teja { 448e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 449e48c0fc5SRavi Teja { 4503544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 451353163e9STony Lee [](const auto& property) { 452353163e9STony Lee return property.first == "Type"; 453353163e9STony Lee }); 454353163e9STony Lee if (type == interface.second.end()) 455353163e9STony Lee { 456353163e9STony Lee continue; 457353163e9STony Lee } 458353163e9STony Lee 459353163e9STony Lee const std::string* typeStr = 460353163e9STony Lee std::get_if<std::string>(&type->second); 461353163e9STony Lee 462353163e9STony Lee if (typeStr == nullptr || 463353163e9STony Lee (*typeStr != 464353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 465353163e9STony Lee { 466353163e9STony Lee continue; 467353163e9STony Lee } 468353163e9STony Lee 469e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 470e48c0fc5SRavi Teja // appropriate 47177179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 4722c70f800SEd Tanous ipv6Address.id = 473353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 4749eb808c1SEd Tanous for (const auto& property : interface.second) 475e48c0fc5SRavi Teja { 476e48c0fc5SRavi Teja if (property.first == "Address") 477e48c0fc5SRavi Teja { 478e48c0fc5SRavi Teja const std::string* address = 479e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 480e48c0fc5SRavi Teja if (address != nullptr) 481e48c0fc5SRavi Teja { 4822c70f800SEd Tanous ipv6Address.address = *address; 483e48c0fc5SRavi Teja } 484e48c0fc5SRavi Teja } 485e48c0fc5SRavi Teja else if (property.first == "Origin") 486e48c0fc5SRavi Teja { 487e48c0fc5SRavi Teja const std::string* origin = 488e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 489e48c0fc5SRavi Teja if (origin != nullptr) 490e48c0fc5SRavi Teja { 4912c70f800SEd Tanous ipv6Address.origin = 492e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 493e48c0fc5SRavi Teja false); 494e48c0fc5SRavi Teja } 495e48c0fc5SRavi Teja } 496e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 497e48c0fc5SRavi Teja { 498e48c0fc5SRavi Teja const uint8_t* prefix = 499e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 500e48c0fc5SRavi Teja if (prefix != nullptr) 501e48c0fc5SRavi Teja { 5022c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 503e48c0fc5SRavi Teja } 504e48c0fc5SRavi Teja } 505889ff694SAsmitha Karunanithi else if (property.first == "Type" || 506889ff694SAsmitha Karunanithi property.first == "Gateway") 507889ff694SAsmitha Karunanithi { 508889ff694SAsmitha Karunanithi // Type & Gateway is not used 509889ff694SAsmitha Karunanithi } 510e48c0fc5SRavi Teja else 511e48c0fc5SRavi Teja { 51262598e31SEd Tanous BMCWEB_LOG_ERROR( 51362598e31SEd Tanous "Got extra property: {} on the {} object", 51462598e31SEd Tanous property.first, objpath.first.str); 515e48c0fc5SRavi Teja } 516e48c0fc5SRavi Teja } 517e48c0fc5SRavi Teja } 518e48c0fc5SRavi Teja } 519e48c0fc5SRavi Teja } 520e48c0fc5SRavi Teja } 521e48c0fc5SRavi Teja } 522e48c0fc5SRavi Teja 5234a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 52477179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 525711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 52677179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 5274a0cb85cSEd Tanous { 52889492a15SPatrick Williams const std::string ipPathStart = "/xyz/openbmc_project/network/" + 52989492a15SPatrick Williams ethifaceId; 5304a0cb85cSEd Tanous 5314a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 5324a0cb85cSEd Tanous // single ethernet interface, loop over all of them 53381ce609eSEd Tanous for (const auto& objpath : dbusData) 5344a0cb85cSEd Tanous { 5354a0cb85cSEd Tanous // Check if proper pattern for object path appears 536353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 5374a0cb85cSEd Tanous { 5389eb808c1SEd Tanous for (const auto& interface : objpath.second) 5394a0cb85cSEd Tanous { 5404a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 5414a0cb85cSEd Tanous { 5423544d2a7SEd Tanous auto type = std::ranges::find_if(interface.second, 543353163e9STony Lee [](const auto& property) { 544353163e9STony Lee return property.first == "Type"; 545353163e9STony Lee }); 546353163e9STony Lee if (type == interface.second.end()) 547353163e9STony Lee { 548353163e9STony Lee continue; 549353163e9STony Lee } 550353163e9STony Lee 551353163e9STony Lee const std::string* typeStr = 552353163e9STony Lee std::get_if<std::string>(&type->second); 553353163e9STony Lee 554353163e9STony Lee if (typeStr == nullptr || 555353163e9STony Lee (*typeStr != 556353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 557353163e9STony Lee { 558353163e9STony Lee continue; 559353163e9STony Lee } 560353163e9STony Lee 5614a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 5624a0cb85cSEd Tanous // appropriate 56377179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 5642c70f800SEd Tanous ipv4Address.id = 565353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5669eb808c1SEd Tanous for (const auto& property : interface.second) 5674a0cb85cSEd Tanous { 5684a0cb85cSEd Tanous if (property.first == "Address") 5694a0cb85cSEd Tanous { 5704a0cb85cSEd Tanous const std::string* address = 571abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5724a0cb85cSEd Tanous if (address != nullptr) 5734a0cb85cSEd Tanous { 5742c70f800SEd Tanous ipv4Address.address = *address; 5754a0cb85cSEd Tanous } 5764a0cb85cSEd Tanous } 5774a0cb85cSEd Tanous else if (property.first == "Origin") 5784a0cb85cSEd Tanous { 5794a0cb85cSEd Tanous const std::string* origin = 580abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5814a0cb85cSEd Tanous if (origin != nullptr) 5824a0cb85cSEd Tanous { 5832c70f800SEd Tanous ipv4Address.origin = 5844a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 5854a0cb85cSEd Tanous true); 5864a0cb85cSEd Tanous } 5874a0cb85cSEd Tanous } 5884a0cb85cSEd Tanous else if (property.first == "PrefixLength") 5894a0cb85cSEd Tanous { 5904a0cb85cSEd Tanous const uint8_t* mask = 591abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 5924a0cb85cSEd Tanous if (mask != nullptr) 5934a0cb85cSEd Tanous { 5944a0cb85cSEd Tanous // convert it to the string 5952c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 5964a0cb85cSEd Tanous } 5974a0cb85cSEd Tanous } 598889ff694SAsmitha Karunanithi else if (property.first == "Type" || 599889ff694SAsmitha Karunanithi property.first == "Gateway") 600889ff694SAsmitha Karunanithi { 601889ff694SAsmitha Karunanithi // Type & Gateway is not used 602889ff694SAsmitha Karunanithi } 6034a0cb85cSEd Tanous else 6044a0cb85cSEd Tanous { 60562598e31SEd Tanous BMCWEB_LOG_ERROR( 60662598e31SEd Tanous "Got extra property: {} on the {} object", 60762598e31SEd Tanous property.first, objpath.first.str); 6084a0cb85cSEd Tanous } 6094a0cb85cSEd Tanous } 6104a0cb85cSEd Tanous // Check if given address is local, or global 6112c70f800SEd Tanous ipv4Address.linktype = 61211ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 61318659d10SJohnathan Mantey ? LinkType::Local 61418659d10SJohnathan Mantey : LinkType::Global; 6154a0cb85cSEd Tanous } 6164a0cb85cSEd Tanous } 6174a0cb85cSEd Tanous } 6184a0cb85cSEd Tanous } 6194a0cb85cSEd Tanous } 620588c3f0dSKowalski, Kamil 621588c3f0dSKowalski, Kamil /** 62201784826SJohnathan Mantey * @brief Deletes given IPv4 interface 623179db1d7SKowalski, Kamil * 624179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 625179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 626179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 627179db1d7SKowalski, Kamil * 628179db1d7SKowalski, Kamil * @return None 629179db1d7SKowalski, Kamil */ 6309c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 6319c5e585cSRavi Teja const std::string& ipHash, 6328d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6331abe55efSEd Tanous { 63455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 6355e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 6361abe55efSEd Tanous if (ec) 6371abe55efSEd Tanous { 638a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6391abe55efSEd Tanous } 640179db1d7SKowalski, Kamil }, 641179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 6429c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 643179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 644179db1d7SKowalski, Kamil } 645179db1d7SKowalski, Kamil 646244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway( 647244b6d5bSGunnar Mills const std::string& ifaceId, const std::string& gateway, 648244b6d5bSGunnar Mills const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6499010ec2eSRavi Teja { 6509ae226faSGeorge Liu sdbusplus::asio::setProperty( 6519ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 6529ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 6539ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 6549ae226faSGeorge Liu gateway, [asyncResp](const boost::system::error_code& ec) { 6559010ec2eSRavi Teja if (ec) 6569010ec2eSRavi Teja { 6579010ec2eSRavi Teja messages::internalError(asyncResp->res); 6589010ec2eSRavi Teja return; 6599010ec2eSRavi Teja } 6609010ec2eSRavi Teja asyncResp->res.result(boost::beast::http::status::no_content); 6619ae226faSGeorge Liu }); 6629010ec2eSRavi Teja } 663179db1d7SKowalski, Kamil /** 66401784826SJohnathan Mantey * @brief Creates a static IPv4 entry 665179db1d7SKowalski, Kamil * 66601784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 66701784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 66801784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 66901784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 670179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 671179db1d7SKowalski, Kamil * 672179db1d7SKowalski, Kamil * @return None 673179db1d7SKowalski, Kamil */ 674cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 675cb13a392SEd Tanous const std::string& gateway, const std::string& address, 6768d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 6771abe55efSEd Tanous { 678*5a39f77aSPatrick Williams auto createIpHandler = [asyncResp, ifaceId, 679*5a39f77aSPatrick Williams gateway](const boost::system::error_code& ec) { 6801abe55efSEd Tanous if (ec) 6811abe55efSEd Tanous { 682a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6839010ec2eSRavi Teja return; 684179db1d7SKowalski, Kamil } 6859010ec2eSRavi Teja updateIPv4DefaultGateway(ifaceId, gateway, asyncResp); 6869010ec2eSRavi Teja }; 6879010ec2eSRavi Teja 6889010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 6899010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 690179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 691179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 69201784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 693179db1d7SKowalski, Kamil gateway); 694179db1d7SKowalski, Kamil } 695e48c0fc5SRavi Teja 696e48c0fc5SRavi Teja /** 69701784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 69801784826SJohnathan Mantey * static IPv6 entry 69901784826SJohnathan Mantey * 70001784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 70101784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 70201784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 70301784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 70401784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 70501784826SJohnathan Mantey * 70601784826SJohnathan Mantey * @return None 70701784826SJohnathan Mantey */ 7089c5e585cSRavi Teja 7099c5e585cSRavi Teja enum class IpVersion 7109c5e585cSRavi Teja { 7119c5e585cSRavi Teja IpV4, 7129c5e585cSRavi Teja IpV6 7139c5e585cSRavi Teja }; 7149c5e585cSRavi Teja 7159c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 7169c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 7178d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 7189c5e585cSRavi Teja const std::string& gateway, 7198d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 72001784826SJohnathan Mantey { 72101784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7229c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 7239c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 72401784826SJohnathan Mantey if (ec) 72501784826SJohnathan Mantey { 72601784826SJohnathan Mantey messages::internalError(asyncResp->res); 72701784826SJohnathan Mantey } 7289c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 7299c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 73001784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 7315e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 73223a21a1cSEd Tanous if (ec2) 73301784826SJohnathan Mantey { 73401784826SJohnathan Mantey messages::internalError(asyncResp->res); 73501784826SJohnathan Mantey } 73601784826SJohnathan Mantey }, 73701784826SJohnathan Mantey "xyz.openbmc_project.Network", 73801784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 7399c5e585cSRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address, 7409c5e585cSRavi Teja prefixLength, gateway); 74101784826SJohnathan Mantey }, 74201784826SJohnathan Mantey "xyz.openbmc_project.Network", 7439c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 74401784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 74501784826SJohnathan Mantey } 74601784826SJohnathan Mantey 74701784826SJohnathan Mantey /** 748e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 749e48c0fc5SRavi Teja * 750e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 751e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 752e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 753e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 754e48c0fc5SRavi Teja * 755e48c0fc5SRavi Teja * @return None 756e48c0fc5SRavi Teja */ 75701784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 75801784826SJohnathan Mantey const std::string& address, 7598d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 760e48c0fc5SRavi Teja { 761*5a39f77aSPatrick Williams auto createIpHandler = [asyncResp, 762*5a39f77aSPatrick Williams address](const boost::system::error_code& ec) { 763e48c0fc5SRavi Teja if (ec) 764e48c0fc5SRavi Teja { 765fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 766fc23ef8aSNitin Kumar Kotania { 767fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 768fc23ef8aSNitin Kumar Kotania "Address"); 769fc23ef8aSNitin Kumar Kotania } 770fc23ef8aSNitin Kumar Kotania else 771fc23ef8aSNitin Kumar Kotania { 772e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 773e48c0fc5SRavi Teja } 774fc23ef8aSNitin Kumar Kotania } 775e48c0fc5SRavi Teja }; 776e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 7774e0453b1SGunnar Mills // does not have associated gateway property 778e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 779e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 780e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 781e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 782e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 783e48c0fc5SRavi Teja ""); 784e48c0fc5SRavi Teja } 785e48c0fc5SRavi Teja 786179db1d7SKowalski, Kamil /** 787179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 788179db1d7SKowalski, Kamil * Object 789179db1d7SKowalski, Kamil * from EntityManager Network Manager 7904a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 791179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 792179db1d7SKowalski, Kamil * into JSON 793179db1d7SKowalski, Kamil */ 794179db1d7SKowalski, Kamil template <typename CallbackFunc> 79581ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 7961abe55efSEd Tanous CallbackFunc&& callback) 7971abe55efSEd Tanous { 798f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 799f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 800f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 801f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 802f94c4ecfSEd Tanous callback{std::forward<CallbackFunc>(callback)}]( 8038b24275dSEd Tanous const boost::system::error_code& ec, 80402cad96eSEd Tanous const dbus::utility::ManagedObjectType& resp) { 80555c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 80677179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 80777179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 808179db1d7SKowalski, Kamil 8098b24275dSEd Tanous if (ec) 8101abe55efSEd Tanous { 81101784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 812179db1d7SKowalski, Kamil return; 813179db1d7SKowalski, Kamil } 814179db1d7SKowalski, Kamil 815002d39b4SEd Tanous bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData); 8164c9afe43SEd Tanous if (!found) 8174c9afe43SEd Tanous { 81801784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 8194c9afe43SEd Tanous return; 8204c9afe43SEd Tanous } 8214c9afe43SEd Tanous 8222c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 823179db1d7SKowalski, Kamil // Fix global GW 8241abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 8251abe55efSEd Tanous { 826c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 827c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 8289010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 8291abe55efSEd Tanous { 83082695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 831179db1d7SKowalski, Kamil } 832179db1d7SKowalski, Kamil } 833179db1d7SKowalski, Kamil 8342c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 8354e0453b1SGunnar Mills // Finally make a callback with useful data 83601784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 837f5892d0dSGeorge Liu }); 838271584abSEd Tanous } 839179db1d7SKowalski, Kamil 840179db1d7SKowalski, Kamil /** 8419391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8429391bb9cSRapkiewicz, Pawel * Manager 8431abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8441abe55efSEd Tanous * into JSON. 8459391bb9cSRapkiewicz, Pawel */ 8469391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8471abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 8481abe55efSEd Tanous { 849f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 850f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 851f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 852f94c4ecfSEd Tanous [callback{std::forward<CallbackFunc>(callback)}]( 8538b24275dSEd Tanous const boost::system::error_code& ec, 854f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 8551abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8561abe55efSEd Tanous // ethernet interfaces 85777179532SEd Tanous std::vector<std::string> ifaceList; 8582c70f800SEd Tanous ifaceList.reserve(resp.size()); 8598b24275dSEd Tanous if (ec) 8601abe55efSEd Tanous { 8612c70f800SEd Tanous callback(false, ifaceList); 8629391bb9cSRapkiewicz, Pawel return; 8639391bb9cSRapkiewicz, Pawel } 8649391bb9cSRapkiewicz, Pawel 8659391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8664a0cb85cSEd Tanous for (const auto& objpath : resp) 8671abe55efSEd Tanous { 8689391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 8694a0cb85cSEd Tanous for (const auto& interface : objpath.second) 8701abe55efSEd Tanous { 8711abe55efSEd Tanous // If interface is 8724a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 8734a0cb85cSEd Tanous // what we're looking for. 8749391bb9cSRapkiewicz, Pawel if (interface.first == 8751abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 8761abe55efSEd Tanous { 8772dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 8782dfd18efSEd Tanous if (ifaceId.empty()) 8791abe55efSEd Tanous { 8802dfd18efSEd Tanous continue; 8819391bb9cSRapkiewicz, Pawel } 8822dfd18efSEd Tanous // and put it into output vector. 88377179532SEd Tanous ifaceList.emplace_back(ifaceId); 8849391bb9cSRapkiewicz, Pawel } 8859391bb9cSRapkiewicz, Pawel } 8869391bb9cSRapkiewicz, Pawel } 8872c5875a2SEd Tanous 8883544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 8892c5875a2SEd Tanous 890a434f2bdSEd Tanous // Finally make a callback with useful data 8912c70f800SEd Tanous callback(true, ifaceList); 892f5892d0dSGeorge Liu }); 893271584abSEd Tanous } 8949391bb9cSRapkiewicz, Pawel 8954f48d5f6SEd Tanous inline void 8964f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 8978d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 8981abe55efSEd Tanous { 899ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 900ab6554f1SJoshi-Mansi if (hostname.length() > 255) 901ab6554f1SJoshi-Mansi { 902ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 903ab6554f1SJoshi-Mansi "HostName"); 904ab6554f1SJoshi-Mansi return; 905ab6554f1SJoshi-Mansi } 9069ae226faSGeorge Liu sdbusplus::asio::setProperty( 9079ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 9089ae226faSGeorge Liu "/xyz/openbmc_project/network/config", 9099ae226faSGeorge Liu "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname, 9105e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 9114a0cb85cSEd Tanous if (ec) 9124a0cb85cSEd Tanous { 913a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 9141abe55efSEd Tanous } 9159ae226faSGeorge Liu }); 916588c3f0dSKowalski, Kamil } 917588c3f0dSKowalski, Kamil 9184f48d5f6SEd Tanous inline void 91935fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 92035fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 92135fb5311STejas Patil { 92289492a15SPatrick Williams sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" + 92389492a15SPatrick Williams ifaceId; 9249ae226faSGeorge Liu sdbusplus::asio::setProperty( 9259ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath, 9269ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize, 9275e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 92835fb5311STejas Patil if (ec) 92935fb5311STejas Patil { 93035fb5311STejas Patil messages::internalError(asyncResp->res); 93135fb5311STejas Patil } 9329ae226faSGeorge Liu }); 93335fb5311STejas Patil } 93435fb5311STejas Patil 93535fb5311STejas Patil inline void 9364f48d5f6SEd Tanous handleDomainnamePatch(const std::string& ifaceId, 937bf648f77SEd Tanous const std::string& domainname, 9388d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 939ab6554f1SJoshi-Mansi { 940ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 9419ae226faSGeorge Liu sdbusplus::asio::setProperty( 9429ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 9439ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 9449ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 9459ae226faSGeorge Liu vectorDomainname, [asyncResp](const boost::system::error_code& ec) { 946ab6554f1SJoshi-Mansi if (ec) 947ab6554f1SJoshi-Mansi { 948ab6554f1SJoshi-Mansi messages::internalError(asyncResp->res); 949ab6554f1SJoshi-Mansi } 9509ae226faSGeorge Liu }); 951ab6554f1SJoshi-Mansi } 952ab6554f1SJoshi-Mansi 9534f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 954bf648f77SEd Tanous { 955bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 9563544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 957bf648f77SEd Tanous { 958bf648f77SEd Tanous return false; 959bf648f77SEd Tanous } 960bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 961bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 962bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 963bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 9644b242749SEd Tanous const static std::regex pattern( 965bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 966bf648f77SEd Tanous 967bf648f77SEd Tanous return std::regex_match(hostname, pattern); 968bf648f77SEd Tanous } 969bf648f77SEd Tanous 9704f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 971bf648f77SEd Tanous { 972bf648f77SEd Tanous // Can have multiple subdomains 973bf648f77SEd Tanous // Top Level Domain's min length is 2 character 9744b242749SEd Tanous const static std::regex pattern( 9750fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 976bf648f77SEd Tanous 977bf648f77SEd Tanous return std::regex_match(domainname, pattern); 978bf648f77SEd Tanous } 979bf648f77SEd Tanous 9804f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 9818d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 982ab6554f1SJoshi-Mansi { 983ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 984ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 985ab6554f1SJoshi-Mansi { 986ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 987ab6554f1SJoshi-Mansi return; 988ab6554f1SJoshi-Mansi } 989ab6554f1SJoshi-Mansi 990ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 991ab6554f1SJoshi-Mansi if (pos == std::string::npos) 992ab6554f1SJoshi-Mansi { 993ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 994ab6554f1SJoshi-Mansi return; 995ab6554f1SJoshi-Mansi } 996ab6554f1SJoshi-Mansi 997ab6554f1SJoshi-Mansi std::string hostname; 998ab6554f1SJoshi-Mansi std::string domainname; 999ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1000ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1001ab6554f1SJoshi-Mansi 1002ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1003ab6554f1SJoshi-Mansi { 1004ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1005ab6554f1SJoshi-Mansi return; 1006ab6554f1SJoshi-Mansi } 1007ab6554f1SJoshi-Mansi 1008ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1009ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1010ab6554f1SJoshi-Mansi } 1011ab6554f1SJoshi-Mansi 10124f48d5f6SEd Tanous inline void 10134f48d5f6SEd Tanous handleMACAddressPatch(const std::string& ifaceId, 1014bf648f77SEd Tanous const std::string& macAddress, 10158d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1016d577665bSRatan Gupta { 101758283f41SJohnathan Mantey static constexpr std::string_view dbusNotAllowedError = 101858283f41SJohnathan Mantey "xyz.openbmc_project.Common.Error.NotAllowed"; 101958283f41SJohnathan Mantey 10209ae226faSGeorge Liu sdbusplus::asio::setProperty( 10219ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10229ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10239ae226faSGeorge Liu "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress, 10249ae226faSGeorge Liu [asyncResp](const boost::system::error_code& ec, 10255b378546SPatrick Williams const sdbusplus::message_t& msg) { 1026d577665bSRatan Gupta if (ec) 1027d577665bSRatan Gupta { 102858283f41SJohnathan Mantey const sd_bus_error* err = msg.get_error(); 102958283f41SJohnathan Mantey if (err == nullptr) 103058283f41SJohnathan Mantey { 103158283f41SJohnathan Mantey messages::internalError(asyncResp->res); 103258283f41SJohnathan Mantey return; 103358283f41SJohnathan Mantey } 103458283f41SJohnathan Mantey if (err->name == dbusNotAllowedError) 103558283f41SJohnathan Mantey { 103658283f41SJohnathan Mantey messages::propertyNotWritable(asyncResp->res, "MACAddress"); 103758283f41SJohnathan Mantey return; 103858283f41SJohnathan Mantey } 1039d577665bSRatan Gupta messages::internalError(asyncResp->res); 1040d577665bSRatan Gupta return; 1041d577665bSRatan Gupta } 10429ae226faSGeorge Liu }); 1043d577665bSRatan Gupta } 1044286b9118SJohnathan Mantey 10454f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 10464f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 10474f48d5f6SEd Tanous const bool v6Value, 10488d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1049da131a9aSJennifer Lee { 10502c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 10519ae226faSGeorge Liu sdbusplus::asio::setProperty( 10529ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10539ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10549ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp, 10555e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1056da131a9aSJennifer Lee if (ec) 1057da131a9aSJennifer Lee { 105862598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1059da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1060da131a9aSJennifer Lee return; 1061da131a9aSJennifer Lee } 10628f7e9c19SJayaprakash Mutyala messages::success(asyncResp->res); 10639ae226faSGeorge Liu }); 1064da131a9aSJennifer Lee } 10651f8c7b5dSJohnathan Mantey 10664f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty( 1067eeedda23SJohnathan Mantey const std::string& ifaceId, const std::string& propertyName, 10688d1b46d7Szhanghch05 const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1069eeedda23SJohnathan Mantey { 10709ae226faSGeorge Liu sdbusplus::asio::setProperty( 10719ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10729ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 10739ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", propertyName, value, 10745e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1075eeedda23SJohnathan Mantey if (ec) 1076eeedda23SJohnathan Mantey { 107762598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1078eeedda23SJohnathan Mantey messages::internalError(asyncResp->res); 1079eeedda23SJohnathan Mantey return; 1080eeedda23SJohnathan Mantey } 10819ae226faSGeorge Liu }); 1082eeedda23SJohnathan Mantey } 1083eeedda23SJohnathan Mantey 10844f48d5f6SEd Tanous inline void setDHCPv4Config(const std::string& propertyName, const bool& value, 10858d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1086da131a9aSJennifer Lee { 108762598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 10889ae226faSGeorge Liu sdbusplus::asio::setProperty( 10899ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 10909ae226faSGeorge Liu "/xyz/openbmc_project/network/dhcp", 10919ae226faSGeorge Liu "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value, 10925e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1093da131a9aSJennifer Lee if (ec) 1094da131a9aSJennifer Lee { 109562598e31SEd Tanous BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1096da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1097da131a9aSJennifer Lee return; 1098da131a9aSJennifer Lee } 10999ae226faSGeorge Liu }); 1100da131a9aSJennifer Lee } 1101d577665bSRatan Gupta 1102b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1103b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1104b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1105b10d8db0SRavi Teja { 1106b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1107b10d8db0SRavi Teja path /= ifaceId; 1108b10d8db0SRavi Teja sdbusplus::asio::setProperty( 1109b10d8db0SRavi Teja *crow::connections::systemBus, "xyz.openbmc_project.Network", path, 1110b10d8db0SRavi Teja "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA", 1111b10d8db0SRavi Teja ipv6AutoConfigEnabled, 1112b10d8db0SRavi Teja [asyncResp](const boost::system::error_code& ec) { 1113b10d8db0SRavi Teja if (ec) 1114b10d8db0SRavi Teja { 1115b10d8db0SRavi Teja BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec); 1116b10d8db0SRavi Teja messages::internalError(asyncResp->res); 1117b10d8db0SRavi Teja return; 1118b10d8db0SRavi Teja } 1119b10d8db0SRavi Teja messages::success(asyncResp->res); 1120b10d8db0SRavi Teja }); 1121b10d8db0SRavi Teja } 1122b10d8db0SRavi Teja 11234f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId, 11241f8c7b5dSJohnathan Mantey const EthernetInterfaceData& ethData, 1125f23b7296SEd Tanous const DHCPParameters& v4dhcpParms, 1126f23b7296SEd Tanous const DHCPParameters& v6dhcpParms, 11278d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1128da131a9aSJennifer Lee { 112982695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 113082695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1131da131a9aSJennifer Lee 11321f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 11331f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 11341f8c7b5dSJohnathan Mantey 11351f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 11361f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1137da131a9aSJennifer Lee { 1138b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 11391f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 11401f8c7b5dSJohnathan Mantey { 1141bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1142bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 11431f8c7b5dSJohnathan Mantey "OperatingMode"); 1144da131a9aSJennifer Lee return; 1145da131a9aSJennifer Lee } 1146b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 11471f8c7b5dSJohnathan Mantey } 11481f8c7b5dSJohnathan Mantey else 1149da131a9aSJennifer Lee { 11501f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 11511f8c7b5dSJohnathan Mantey } 11521f8c7b5dSJohnathan Mantey 11531f8c7b5dSJohnathan Mantey bool nextDNS{}; 115482695a5bSJiaqing Zhao if (v4dhcpParms.useDnsServers && v6dhcpParms.useDnsServers) 11551f8c7b5dSJohnathan Mantey { 115682695a5bSJiaqing Zhao if (*v4dhcpParms.useDnsServers != *v6dhcpParms.useDnsServers) 11571f8c7b5dSJohnathan Mantey { 11581f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 11591f8c7b5dSJohnathan Mantey return; 11601f8c7b5dSJohnathan Mantey } 116182695a5bSJiaqing Zhao nextDNS = *v4dhcpParms.useDnsServers; 11621f8c7b5dSJohnathan Mantey } 116382695a5bSJiaqing Zhao else if (v4dhcpParms.useDnsServers) 11641f8c7b5dSJohnathan Mantey { 116582695a5bSJiaqing Zhao nextDNS = *v4dhcpParms.useDnsServers; 11661f8c7b5dSJohnathan Mantey } 116782695a5bSJiaqing Zhao else if (v6dhcpParms.useDnsServers) 11681f8c7b5dSJohnathan Mantey { 116982695a5bSJiaqing Zhao nextDNS = *v6dhcpParms.useDnsServers; 11701f8c7b5dSJohnathan Mantey } 11711f8c7b5dSJohnathan Mantey else 11721f8c7b5dSJohnathan Mantey { 117382695a5bSJiaqing Zhao nextDNS = ethData.dnsEnabled; 11741f8c7b5dSJohnathan Mantey } 11751f8c7b5dSJohnathan Mantey 11761f8c7b5dSJohnathan Mantey bool nextNTP{}; 117782695a5bSJiaqing Zhao if (v4dhcpParms.useNtpServers && v6dhcpParms.useNtpServers) 11781f8c7b5dSJohnathan Mantey { 117982695a5bSJiaqing Zhao if (*v4dhcpParms.useNtpServers != *v6dhcpParms.useNtpServers) 11801f8c7b5dSJohnathan Mantey { 11811f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 11821f8c7b5dSJohnathan Mantey return; 11831f8c7b5dSJohnathan Mantey } 118482695a5bSJiaqing Zhao nextNTP = *v4dhcpParms.useNtpServers; 11851f8c7b5dSJohnathan Mantey } 118682695a5bSJiaqing Zhao else if (v4dhcpParms.useNtpServers) 11871f8c7b5dSJohnathan Mantey { 118882695a5bSJiaqing Zhao nextNTP = *v4dhcpParms.useNtpServers; 11891f8c7b5dSJohnathan Mantey } 119082695a5bSJiaqing Zhao else if (v6dhcpParms.useNtpServers) 11911f8c7b5dSJohnathan Mantey { 119282695a5bSJiaqing Zhao nextNTP = *v6dhcpParms.useNtpServers; 11931f8c7b5dSJohnathan Mantey } 11941f8c7b5dSJohnathan Mantey else 11951f8c7b5dSJohnathan Mantey { 119682695a5bSJiaqing Zhao nextNTP = ethData.ntpEnabled; 11971f8c7b5dSJohnathan Mantey } 11981f8c7b5dSJohnathan Mantey 11991f8c7b5dSJohnathan Mantey bool nextUseDomain{}; 120082695a5bSJiaqing Zhao if (v4dhcpParms.useDomainName && v6dhcpParms.useDomainName) 12011f8c7b5dSJohnathan Mantey { 120282695a5bSJiaqing Zhao if (*v4dhcpParms.useDomainName != *v6dhcpParms.useDomainName) 12031f8c7b5dSJohnathan Mantey { 12041f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 12051f8c7b5dSJohnathan Mantey return; 12061f8c7b5dSJohnathan Mantey } 120782695a5bSJiaqing Zhao nextUseDomain = *v4dhcpParms.useDomainName; 12081f8c7b5dSJohnathan Mantey } 120982695a5bSJiaqing Zhao else if (v4dhcpParms.useDomainName) 12101f8c7b5dSJohnathan Mantey { 121182695a5bSJiaqing Zhao nextUseDomain = *v4dhcpParms.useDomainName; 12121f8c7b5dSJohnathan Mantey } 121382695a5bSJiaqing Zhao else if (v6dhcpParms.useDomainName) 12141f8c7b5dSJohnathan Mantey { 121582695a5bSJiaqing Zhao nextUseDomain = *v6dhcpParms.useDomainName; 12161f8c7b5dSJohnathan Mantey } 12171f8c7b5dSJohnathan Mantey else 12181f8c7b5dSJohnathan Mantey { 121982695a5bSJiaqing Zhao nextUseDomain = ethData.hostNameEnabled; 12201f8c7b5dSJohnathan Mantey } 12211f8c7b5dSJohnathan Mantey 122262598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 12231f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 12241f8c7b5dSJohnathan Mantey asyncResp); 122562598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 12261f8c7b5dSJohnathan Mantey setDHCPv4Config("DNSEnabled", nextDNS, asyncResp); 122762598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 12281f8c7b5dSJohnathan Mantey setDHCPv4Config("NTPEnabled", nextNTP, asyncResp); 122962598e31SEd Tanous BMCWEB_LOG_DEBUG("set HostNameEnabled..."); 12301f8c7b5dSJohnathan Mantey setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp); 1231da131a9aSJennifer Lee } 123201784826SJohnathan Mantey 123377179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 123477179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 123577179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 123601784826SJohnathan Mantey { 123717a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 123817a897dfSManojkiran Eda return value.origin == "Static"; 123917a897dfSManojkiran Eda }); 124001784826SJohnathan Mantey } 124101784826SJohnathan Mantey 124277179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 124377179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 124477179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 124501784826SJohnathan Mantey { 124617a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 124717a897dfSManojkiran Eda return value.origin == "Static"; 124817a897dfSManojkiran Eda }); 124901784826SJohnathan Mantey } 125001784826SJohnathan Mantey 125177179532SEd Tanous inline void 1252ddd70dcaSEd Tanous handleIPv4StaticPatch(const std::string& ifaceId, 1253ddd70dcaSEd Tanous nlohmann::json::array_t& input, 125477179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 12558d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12561abe55efSEd Tanous { 1257ddd70dcaSEd Tanous if (input.empty()) 1258f476acbfSRatan Gupta { 12592e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1260d1d50814SRavi Teja "IPv4StaticAddresses"); 1261f476acbfSRatan Gupta return; 1262f476acbfSRatan Gupta } 1263f476acbfSRatan Gupta 1264271584abSEd Tanous unsigned entryIdx = 1; 126501784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 126601784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 126701784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 126801784826SJohnathan Mantey // into the NIC. 126977179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 12702c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 127101784826SJohnathan Mantey 1272537174c4SEd Tanous for (nlohmann::json& thisJson : input) 12731abe55efSEd Tanous { 127489492a15SPatrick Williams std::string pathString = "IPv4StaticAddresses/" + 127589492a15SPatrick Williams std::to_string(entryIdx); 1276179db1d7SKowalski, Kamil 127701784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1278f476acbfSRatan Gupta { 1279537174c4SEd Tanous std::optional<std::string> address; 1280537174c4SEd Tanous std::optional<std::string> subnetMask; 1281537174c4SEd Tanous std::optional<std::string> gateway; 1282537174c4SEd Tanous 1283537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 12847e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 12857e27d832SJohnathan Mantey "Gateway", gateway)) 1286537174c4SEd Tanous { 1287f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 128871f52d96SEd Tanous pathString); 1289537174c4SEd Tanous return; 1290179db1d7SKowalski, Kamil } 1291179db1d7SKowalski, Kamil 129201784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 129301784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 129401784826SJohnathan Mantey // current state of the interface. Merge existing state into the 129501784826SJohnathan Mantey // current request. 1296537174c4SEd Tanous if (address) 12971abe55efSEd Tanous { 1298e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 129901784826SJohnathan Mantey { 1300bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 1301bf648f77SEd Tanous pathString + "/Address"); 1302e01d0c36SEd Tanous return; 130301784826SJohnathan Mantey } 130401784826SJohnathan Mantey } 130585ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 130601784826SJohnathan Mantey { 1307e01d0c36SEd Tanous address = (nicIpEntry->address); 130801784826SJohnathan Mantey } 130901784826SJohnathan Mantey else 131001784826SJohnathan Mantey { 131101784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 131201784826SJohnathan Mantey pathString + "/Address"); 1313e01d0c36SEd Tanous return; 13144a0cb85cSEd Tanous } 13154a0cb85cSEd Tanous 1316e01d0c36SEd Tanous uint8_t prefixLength = 0; 1317537174c4SEd Tanous if (subnetMask) 13184a0cb85cSEd Tanous { 1319033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1320033f1e4dSEd Tanous &prefixLength)) 13214a0cb85cSEd Tanous { 1322f12894f8SJason M. Bills messages::propertyValueFormatError( 1323537174c4SEd Tanous asyncResp->res, *subnetMask, 13244a0cb85cSEd Tanous pathString + "/SubnetMask"); 1325e01d0c36SEd Tanous return; 13264a0cb85cSEd Tanous } 13274a0cb85cSEd Tanous } 132885ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 13294a0cb85cSEd Tanous { 1330033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 133101784826SJohnathan Mantey &prefixLength)) 13324a0cb85cSEd Tanous { 133301784826SJohnathan Mantey messages::propertyValueFormatError( 133485ffe86aSJiaqing Zhao asyncResp->res, nicIpEntry->netmask, 133501784826SJohnathan Mantey pathString + "/SubnetMask"); 1336e01d0c36SEd Tanous return; 13374a0cb85cSEd Tanous } 13384a0cb85cSEd Tanous } 13391abe55efSEd Tanous else 13401abe55efSEd Tanous { 134101784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 134201784826SJohnathan Mantey pathString + "/SubnetMask"); 1343e01d0c36SEd Tanous return; 134401784826SJohnathan Mantey } 134501784826SJohnathan Mantey 134601784826SJohnathan Mantey if (gateway) 134701784826SJohnathan Mantey { 1348e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 134901784826SJohnathan Mantey { 1350bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1351bf648f77SEd Tanous pathString + "/Gateway"); 1352e01d0c36SEd Tanous return; 135301784826SJohnathan Mantey } 135401784826SJohnathan Mantey } 135585ffe86aSJiaqing Zhao else if (nicIpEntry != ipv4Data.cend()) 135601784826SJohnathan Mantey { 1357e01d0c36SEd Tanous gateway = nicIpEntry->gateway; 135801784826SJohnathan Mantey } 135901784826SJohnathan Mantey else 13601abe55efSEd Tanous { 1361a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13624a0cb85cSEd Tanous pathString + "/Gateway"); 136301784826SJohnathan Mantey return; 13644a0cb85cSEd Tanous } 13654a0cb85cSEd Tanous 136685ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 13671abe55efSEd Tanous { 13689c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId, 136977eb0153SEd Tanous nicIpEntry->id, prefixLength, *address, 137077eb0153SEd Tanous *gateway, asyncResp); 137189492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 137289492a15SPatrick Williams ipv4Data.cend()); 1373588c3f0dSKowalski, Kamil } 137401784826SJohnathan Mantey else 137501784826SJohnathan Mantey { 1376cb13a392SEd Tanous createIPv4(ifaceId, prefixLength, *gateway, *address, 1377cb13a392SEd Tanous asyncResp); 13784a0cb85cSEd Tanous } 13794a0cb85cSEd Tanous entryIdx++; 13804a0cb85cSEd Tanous } 138101784826SJohnathan Mantey else 138201784826SJohnathan Mantey { 138385ffe86aSJiaqing Zhao if (nicIpEntry == ipv4Data.cend()) 138401784826SJohnathan Mantey { 138501784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 138601784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 138701784826SJohnathan Mantey // in error, so bail out. 138801784826SJohnathan Mantey if (thisJson.is_null()) 138901784826SJohnathan Mantey { 139001784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 139101784826SJohnathan Mantey return; 139201784826SJohnathan Mantey } 1393f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 139471f52d96SEd Tanous pathString); 139501784826SJohnathan Mantey return; 139601784826SJohnathan Mantey } 139701784826SJohnathan Mantey 139801784826SJohnathan Mantey if (thisJson.is_null()) 139901784826SJohnathan Mantey { 14009c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 140101784826SJohnathan Mantey } 140285ffe86aSJiaqing Zhao if (nicIpEntry != ipv4Data.cend()) 140301784826SJohnathan Mantey { 140489492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 140589492a15SPatrick Williams ipv4Data.cend()); 140601784826SJohnathan Mantey } 140701784826SJohnathan Mantey entryIdx++; 140801784826SJohnathan Mantey } 140901784826SJohnathan Mantey } 14104a0cb85cSEd Tanous } 14114a0cb85cSEd Tanous 14124f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1413f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1414f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 14158d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1416f85837bfSRAJESWARAN THILLAIGOVINDAN { 14179ae226faSGeorge Liu sdbusplus::asio::setProperty( 14189ae226faSGeorge Liu *crow::connections::systemBus, "xyz.openbmc_project.Network", 14199ae226faSGeorge Liu "/xyz/openbmc_project/network/" + ifaceId, 14209ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 14219ae226faSGeorge Liu updatedStaticNameServers, 14225e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 1423f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1424f85837bfSRAJESWARAN THILLAIGOVINDAN { 1425f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1426f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1427f85837bfSRAJESWARAN THILLAIGOVINDAN } 14289ae226faSGeorge Liu }); 1429f85837bfSRAJESWARAN THILLAIGOVINDAN } 1430f85837bfSRAJESWARAN THILLAIGOVINDAN 14314f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 1432ddd70dcaSEd Tanous const std::string& ifaceId, const nlohmann::json::array_t& input, 143377179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 14348d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1435e48c0fc5SRavi Teja { 1436ddd70dcaSEd Tanous if (input.empty()) 1437e48c0fc5SRavi Teja { 14382e8c4bdaSEd Tanous messages::propertyValueTypeError(asyncResp->res, input, 1439e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1440e48c0fc5SRavi Teja return; 1441e48c0fc5SRavi Teja } 1442271584abSEd Tanous size_t entryIdx = 1; 144377179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 14442c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1445f23b7296SEd Tanous for (const nlohmann::json& thisJson : input) 1446e48c0fc5SRavi Teja { 144789492a15SPatrick Williams std::string pathString = "IPv6StaticAddresses/" + 144889492a15SPatrick Williams std::to_string(entryIdx); 1449e48c0fc5SRavi Teja 145001784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1451e48c0fc5SRavi Teja { 1452e48c0fc5SRavi Teja std::optional<std::string> address; 1453e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1454f23b7296SEd Tanous nlohmann::json thisJsonCopy = thisJson; 1455bf648f77SEd Tanous if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address", 1456bf648f77SEd Tanous address, "PrefixLength", prefixLength)) 1457e48c0fc5SRavi Teja { 1458f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 145971f52d96SEd Tanous pathString); 1460e48c0fc5SRavi Teja return; 1461e48c0fc5SRavi Teja } 1462e48c0fc5SRavi Teja 1463543f4400SEd Tanous const std::string* addr = nullptr; 1464543f4400SEd Tanous uint8_t prefix = 0; 146501784826SJohnathan Mantey 146601784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 146701784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 146801784826SJohnathan Mantey // current state of the interface. Merge existing state into the 146901784826SJohnathan Mantey // current request. 1470e48c0fc5SRavi Teja if (address) 1471e48c0fc5SRavi Teja { 147201784826SJohnathan Mantey addr = &(*address); 1473e48c0fc5SRavi Teja } 147485ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 147501784826SJohnathan Mantey { 147685ffe86aSJiaqing Zhao addr = &(nicIpEntry->address); 147701784826SJohnathan Mantey } 147801784826SJohnathan Mantey else 147901784826SJohnathan Mantey { 148001784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 148101784826SJohnathan Mantey pathString + "/Address"); 148201784826SJohnathan Mantey return; 1483e48c0fc5SRavi Teja } 1484e48c0fc5SRavi Teja 1485e48c0fc5SRavi Teja if (prefixLength) 1486e48c0fc5SRavi Teja { 148701784826SJohnathan Mantey prefix = *prefixLength; 148801784826SJohnathan Mantey } 148985ffe86aSJiaqing Zhao else if (nicIpEntry != ipv6Data.end()) 1490e48c0fc5SRavi Teja { 149185ffe86aSJiaqing Zhao prefix = nicIpEntry->prefixLength; 1492e48c0fc5SRavi Teja } 1493e48c0fc5SRavi Teja else 1494e48c0fc5SRavi Teja { 1495e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1496e48c0fc5SRavi Teja pathString + "/PrefixLength"); 149701784826SJohnathan Mantey return; 1498e48c0fc5SRavi Teja } 1499e48c0fc5SRavi Teja 150085ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1501e48c0fc5SRavi Teja { 15029c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 150377eb0153SEd Tanous nicIpEntry->id, prefix, *addr, "", 1504e48c0fc5SRavi Teja asyncResp); 150589492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 150689492a15SPatrick Williams ipv6Data.cend()); 150701784826SJohnathan Mantey } 150801784826SJohnathan Mantey else 150901784826SJohnathan Mantey { 151001784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1511e48c0fc5SRavi Teja } 1512e48c0fc5SRavi Teja entryIdx++; 1513e48c0fc5SRavi Teja } 151401784826SJohnathan Mantey else 151501784826SJohnathan Mantey { 151685ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 151701784826SJohnathan Mantey { 151801784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 151901784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 152001784826SJohnathan Mantey // in error, so bail out. 152101784826SJohnathan Mantey if (thisJson.is_null()) 152201784826SJohnathan Mantey { 152301784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 152401784826SJohnathan Mantey return; 152501784826SJohnathan Mantey } 1526f818b04dSEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJson, 152771f52d96SEd Tanous pathString); 152801784826SJohnathan Mantey return; 152901784826SJohnathan Mantey } 153001784826SJohnathan Mantey 153101784826SJohnathan Mantey if (thisJson.is_null()) 153201784826SJohnathan Mantey { 15339c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 153401784826SJohnathan Mantey } 153585ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 153601784826SJohnathan Mantey { 153789492a15SPatrick Williams nicIpEntry = getNextStaticIpEntry(++nicIpEntry, 153889492a15SPatrick Williams ipv6Data.cend()); 153901784826SJohnathan Mantey } 154001784826SJohnathan Mantey entryIdx++; 154101784826SJohnathan Mantey } 154201784826SJohnathan Mantey } 1543e48c0fc5SRavi Teja } 1544e48c0fc5SRavi Teja 15457857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 15467857cb8dSJiaqing Zhao { 15477857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 15487857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 15497857cb8dSJiaqing Zhao } 15507857cb8dSJiaqing Zhao 155177179532SEd Tanous inline void 155277179532SEd Tanous parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 155377179532SEd Tanous const std::string& ifaceId, 155477179532SEd Tanous const EthernetInterfaceData& ethData, 155577179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 155677179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) 15574a0cb85cSEd Tanous { 15582c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 155981ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1560ef4c65b7SEd Tanous jsonResponse["@odata.id"] = boost::urls::format( 1561ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId); 15622c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1563eeedda23SJohnathan Mantey 156413451e39SWilly Tu if constexpr (bmcwebEnableHealthPopulate) 156513451e39SWilly Tu { 156613451e39SWilly Tu constexpr std::array<std::string_view, 1> inventoryForEthernet = { 156713451e39SWilly Tu "xyz.openbmc_project.Inventory.Item.Ethernet"}; 1568eeedda23SJohnathan Mantey auto health = std::make_shared<HealthPopulate>(asyncResp); 15697a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 15707a1dbc48SGeorge Liu "/", 0, inventoryForEthernet, 15717a1dbc48SGeorge Liu [health](const boost::system::error_code& ec, 1572b9d36b47SEd Tanous const dbus::utility::MapperGetSubTreePathsResponse& resp) { 1573eeedda23SJohnathan Mantey if (ec) 1574029573d4SEd Tanous { 1575eeedda23SJohnathan Mantey return; 1576eeedda23SJohnathan Mantey } 1577eeedda23SJohnathan Mantey 1578914e2d5dSEd Tanous health->inventory = resp; 15797a1dbc48SGeorge Liu }); 1580eeedda23SJohnathan Mantey 1581eeedda23SJohnathan Mantey health->populate(); 158213451e39SWilly Tu } 1583eeedda23SJohnathan Mantey 1584eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1585eeedda23SJohnathan Mantey { 15860ef0e289SJohnathan Mantey jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 15872c70f800SEd Tanous jsonResponse["Status"]["State"] = "Enabled"; 1588029573d4SEd Tanous } 1589029573d4SEd Tanous else 1590029573d4SEd Tanous { 15912c70f800SEd Tanous jsonResponse["LinkStatus"] = "NoLink"; 15922c70f800SEd Tanous jsonResponse["Status"]["State"] = "Disabled"; 1593029573d4SEd Tanous } 1594aa05fb27SJohnathan Mantey 15952c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 159635fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 159782695a5bSJiaqing Zhao jsonResponse["MACAddress"] = ethData.macAddress; 15982c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 159982695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 160082695a5bSJiaqing Zhao jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpEnabled; 160182695a5bSJiaqing Zhao jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsEnabled; 160282695a5bSJiaqing Zhao jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNameEnabled; 16031f8c7b5dSJohnathan Mantey 16042c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1605b10d8db0SRavi Teja translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled" 16061f8c7b5dSJohnathan Mantey : "Disabled"; 160782695a5bSJiaqing Zhao jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpEnabled; 160882695a5bSJiaqing Zhao jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsEnabled; 160982695a5bSJiaqing Zhao jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNameEnabled; 1610b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1611b10d8db0SRavi Teja ethData.ipv6AcceptRa; 16122a133282Smanojkiraneda 161382695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 16144a0cb85cSEd Tanous { 161582695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1616ab6554f1SJoshi-Mansi 1617ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1618ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1619ab6554f1SJoshi-Mansi // FQDN 162082695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1621d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1622d24bfc7aSJennifer Lee { 16232c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1624d24bfc7aSJennifer Lee } 16252c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 16264a0cb85cSEd Tanous } 16274a0cb85cSEd Tanous 16287857cb8dSJiaqing Zhao if (ethData.vlanId) 16297857cb8dSJiaqing Zhao { 16307857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Virtual"; 16317857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 16327857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 16337857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 16347857cb8dSJiaqing Zhao 16357857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 16367857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 16377857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 16387857cb8dSJiaqing Zhao boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces", 16397857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 16407857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 16417857cb8dSJiaqing Zhao std::move(relatedInterfaces); 16427857cb8dSJiaqing Zhao } 16437857cb8dSJiaqing Zhao else 16447857cb8dSJiaqing Zhao { 16457857cb8dSJiaqing Zhao jsonResponse["EthernetInterfaceType"] = "Physical"; 16467857cb8dSJiaqing Zhao } 16477857cb8dSJiaqing Zhao 16482c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 16492c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 16504a0cb85cSEd Tanous 16512c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 16522c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 16532c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 16542c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 16559eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 16564a0cb85cSEd Tanous { 16572c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1658fa5053a6SGunnar Mills if (gatewayStr.empty()) 1659fa5053a6SGunnar Mills { 1660fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1661fa5053a6SGunnar Mills } 16621476687dSEd Tanous nlohmann::json::object_t ipv4; 16631476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 16641476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 16651476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 16661476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1667fa5053a6SGunnar Mills 16682c70f800SEd Tanous if (ipv4Config.origin == "Static") 1669d1d50814SRavi Teja { 16701476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1671d1d50814SRavi Teja } 16721476687dSEd Tanous 1673b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 167401784826SJohnathan Mantey } 1675d1d50814SRavi Teja 167682695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 16777ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 16787ea79e5eSRavi Teja { 16797ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 16807ea79e5eSRavi Teja } 16817ea79e5eSRavi Teja 16827ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1683e48c0fc5SRavi Teja 16842c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 16852c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 16862c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 16872c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 16887f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 16892c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 16907f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 16919eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1692e48c0fc5SRavi Teja { 16931476687dSEd Tanous nlohmann::json::object_t ipv6; 16941476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 16951476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 16961476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1697f8361275SSunitha Harish 1698b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 16992c70f800SEd Tanous if (ipv6Config.origin == "Static") 1700e48c0fc5SRavi Teja { 17011476687dSEd Tanous nlohmann::json::object_t ipv6Static; 17021476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 17031476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 1704b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 170501784826SJohnathan Mantey } 1706e48c0fc5SRavi Teja } 1707588c3f0dSKowalski, Kamil } 1708588c3f0dSKowalski, Kamil 1709e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1710e7caf250SJiaqing Zhao const std::string& ifaceId, 1711e7caf250SJiaqing Zhao const boost::system::error_code& ec, 1712e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 1713e7caf250SJiaqing Zhao { 1714e7caf250SJiaqing Zhao if (!ec) 1715e7caf250SJiaqing Zhao { 1716e7caf250SJiaqing Zhao return; 1717e7caf250SJiaqing Zhao } 1718e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1719e7caf250SJiaqing Zhao if (dbusError == nullptr) 1720e7caf250SJiaqing Zhao { 1721e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1722e7caf250SJiaqing Zhao return; 1723e7caf250SJiaqing Zhao } 172462598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1725e7caf250SJiaqing Zhao 1726e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 1727e7caf250SJiaqing Zhao dbusError->name) 1728e7caf250SJiaqing Zhao { 1729e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1730e7caf250SJiaqing Zhao ifaceId); 1731e7caf250SJiaqing Zhao return; 1732e7caf250SJiaqing Zhao } 1733e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 1734e7caf250SJiaqing Zhao dbusError->name) 1735e7caf250SJiaqing Zhao { 1736e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 1737e7caf250SJiaqing Zhao return; 1738e7caf250SJiaqing Zhao } 1739e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 1740e7caf250SJiaqing Zhao } 1741e7caf250SJiaqing Zhao 1742b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1743b5ca3fdcSJiaqing Zhao const std::string& parentInterfaceUri, 1744b5ca3fdcSJiaqing Zhao const std::string& vlanInterface, 1745b5ca3fdcSJiaqing Zhao const boost::system::error_code& ec, 1746b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m 1747b5ca3fdcSJiaqing Zhao 1748b5ca3fdcSJiaqing Zhao ) 1749b5ca3fdcSJiaqing Zhao { 1750b5ca3fdcSJiaqing Zhao if (ec) 1751b5ca3fdcSJiaqing Zhao { 1752b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 1753b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 1754b5ca3fdcSJiaqing Zhao { 1755b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1756b5ca3fdcSJiaqing Zhao return; 1757b5ca3fdcSJiaqing Zhao } 175862598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 1759b5ca3fdcSJiaqing Zhao 1760b5ca3fdcSJiaqing Zhao if (std::string_view( 1761b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 1762b5ca3fdcSJiaqing Zhao dbusError->name) 1763b5ca3fdcSJiaqing Zhao { 1764b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1765b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1766b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1767b5ca3fdcSJiaqing Zhao return; 1768b5ca3fdcSJiaqing Zhao } 1769b5ca3fdcSJiaqing Zhao if (std::string_view( 1770b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 1771b5ca3fdcSJiaqing Zhao dbusError->name) 1772b5ca3fdcSJiaqing Zhao { 1773b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 1774b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 1775b5ca3fdcSJiaqing Zhao return; 1776b5ca3fdcSJiaqing Zhao } 1777b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 1778b5ca3fdcSJiaqing Zhao return; 1779b5ca3fdcSJiaqing Zhao } 1780b5ca3fdcSJiaqing Zhao 1781b5ca3fdcSJiaqing Zhao const boost::urls::url vlanInterfaceUri = boost::urls::format( 1782b5ca3fdcSJiaqing Zhao "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface); 1783b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 1784b5ca3fdcSJiaqing Zhao } 1785b5ca3fdcSJiaqing Zhao 1786bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 1787bf648f77SEd Tanous { 1788bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 1789ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 17901476687dSEd Tanous .methods(boost::beast::http::verb::get)( 17911476687dSEd Tanous [&app](const crow::Request& req, 17921476687dSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 17933ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 179445ca1b86SEd Tanous { 179545ca1b86SEd Tanous return; 179645ca1b86SEd Tanous } 179745ca1b86SEd Tanous 1798bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1799bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 1800bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1801bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 1802bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 1803bf648f77SEd Tanous "Ethernet Network Interface Collection"; 1804bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 1805bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 1806bf648f77SEd Tanous 1807bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 1808bf648f77SEd Tanous // preparation 1809002d39b4SEd Tanous getEthernetIfaceList( 181077179532SEd Tanous [asyncResp](const bool& success, 181177179532SEd Tanous const std::vector<std::string>& ifaceList) { 1812bf648f77SEd Tanous if (!success) 18131abe55efSEd Tanous { 1814f12894f8SJason M. Bills messages::internalError(asyncResp->res); 18159391bb9cSRapkiewicz, Pawel return; 18169391bb9cSRapkiewicz, Pawel } 18179391bb9cSRapkiewicz, Pawel 1818002d39b4SEd Tanous nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"]; 1819bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 1820bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 1821bf648f77SEd Tanous { 18221476687dSEd Tanous nlohmann::json::object_t iface; 1823ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 1824ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", 1825ef4c65b7SEd Tanous ifaceItem); 18267857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 1827bf648f77SEd Tanous } 1828bf648f77SEd Tanous 1829002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size(); 1830bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 1831bf648f77SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 1832bf648f77SEd Tanous }); 1833bf648f77SEd Tanous }); 1834bf648f77SEd Tanous 1835b5ca3fdcSJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 1836b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 1837b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 1838b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 1839b5ca3fdcSJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1840b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1841b5ca3fdcSJiaqing Zhao { 1842b5ca3fdcSJiaqing Zhao return; 1843b5ca3fdcSJiaqing Zhao } 1844b5ca3fdcSJiaqing Zhao 1845b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 1846b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 1847b5ca3fdcSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 1848b5ca3fdcSJiaqing Zhao 1849b5ca3fdcSJiaqing Zhao if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable", 1850b5ca3fdcSJiaqing Zhao vlanEnable, "VLAN/VLANId", vlanId, 1851b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 1852b5ca3fdcSJiaqing Zhao relatedInterfaces)) 1853b5ca3fdcSJiaqing Zhao { 1854b5ca3fdcSJiaqing Zhao return; 1855b5ca3fdcSJiaqing Zhao } 1856b5ca3fdcSJiaqing Zhao 1857b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 1858b5ca3fdcSJiaqing Zhao { 1859b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 1860b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 1861b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 1862b5ca3fdcSJiaqing Zhao return; 1863b5ca3fdcSJiaqing Zhao } 1864b5ca3fdcSJiaqing Zhao 1865b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 1866b5ca3fdcSJiaqing Zhao if (!json_util::readJson(relatedInterfaces[0], asyncResp->res, 1867b5ca3fdcSJiaqing Zhao "@odata.id", parentInterfaceUri)) 1868b5ca3fdcSJiaqing Zhao { 1869b5ca3fdcSJiaqing Zhao messages::propertyMissing(asyncResp->res, 1870b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1871b5ca3fdcSJiaqing Zhao return; 1872b5ca3fdcSJiaqing Zhao } 187362598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 1874b5ca3fdcSJiaqing Zhao 18756fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 1876b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 1877b5ca3fdcSJiaqing Zhao if (!parsedUri) 1878b5ca3fdcSJiaqing Zhao { 1879b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 1880b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1881b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1882b5ca3fdcSJiaqing Zhao return; 1883b5ca3fdcSJiaqing Zhao } 1884b5ca3fdcSJiaqing Zhao 1885b5ca3fdcSJiaqing Zhao std::string parentInterface; 1886b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 1887b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 1888b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 1889b5ca3fdcSJiaqing Zhao { 1890b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 1891b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 1892b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 1893b5ca3fdcSJiaqing Zhao return; 1894b5ca3fdcSJiaqing Zhao } 1895b5ca3fdcSJiaqing Zhao 1896b5ca3fdcSJiaqing Zhao if (!vlanEnable) 1897b5ca3fdcSJiaqing Zhao { 1898b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 1899b5ca3fdcSJiaqing Zhao // create 1900b5ca3fdcSJiaqing Zhao messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable", 1901b5ca3fdcSJiaqing Zhao "false"); 1902b5ca3fdcSJiaqing Zhao return; 1903b5ca3fdcSJiaqing Zhao } 1904b5ca3fdcSJiaqing Zhao 1905b5ca3fdcSJiaqing Zhao std::string vlanInterface = parentInterface + "_" + 1906b5ca3fdcSJiaqing Zhao std::to_string(vlanId); 1907b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 1908b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 1909b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 1910b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 1911b5ca3fdcSJiaqing Zhao afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec, 1912b5ca3fdcSJiaqing Zhao m); 1913b5ca3fdcSJiaqing Zhao }, 1914b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 1915b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface, 1916b5ca3fdcSJiaqing Zhao vlanId); 1917b5ca3fdcSJiaqing Zhao }); 1918b5ca3fdcSJiaqing Zhao 1919bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 1920ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 1921bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 192245ca1b86SEd Tanous [&app](const crow::Request& req, 1923bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1924bf648f77SEd Tanous const std::string& ifaceId) { 19253ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 192645ca1b86SEd Tanous { 192745ca1b86SEd Tanous return; 192845ca1b86SEd Tanous } 19294a0cb85cSEd Tanous getEthernetIfaceData( 1930bf648f77SEd Tanous ifaceId, 193177179532SEd Tanous [asyncResp, ifaceId](const bool& success, 193277179532SEd Tanous const EthernetInterfaceData& ethData, 193377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 193477179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) { 19354a0cb85cSEd Tanous if (!success) 19361abe55efSEd Tanous { 1937bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 1938bf648f77SEd Tanous // existing object, and other errors 1939002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 1940002d39b4SEd Tanous ifaceId); 19414a0cb85cSEd Tanous return; 19429391bb9cSRapkiewicz, Pawel } 19434c9afe43SEd Tanous 19440f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 194593bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 1946002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 19470f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 19480f74e643SEd Tanous "Management Network Interface"; 19490f74e643SEd Tanous 1950002d39b4SEd Tanous parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data); 19519391bb9cSRapkiewicz, Pawel }); 1952bf648f77SEd Tanous }); 19539391bb9cSRapkiewicz, Pawel 1954bf648f77SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 1955ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 1956bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 195745ca1b86SEd Tanous [&app](const crow::Request& req, 1958bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1959bf648f77SEd Tanous const std::string& ifaceId) { 19603ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 196145ca1b86SEd Tanous { 196245ca1b86SEd Tanous return; 196345ca1b86SEd Tanous } 1964bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1965ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 1966d577665bSRatan Gupta std::optional<std::string> macAddress; 19679a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1968ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv4StaticAddresses; 1969ddd70dcaSEd Tanous std::optional<nlohmann::json::array_t> ipv6StaticAddresses; 1970f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 1971da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 19721f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 1973b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 1974eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 197535fb5311STejas Patil std::optional<size_t> mtuSize; 19761f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 19771f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 1978b10d8db0SRavi Teja // clang-format off 197915ed6780SWilly Tu if (!json_util::readJsonPatch( 1980b10d8db0SRavi Teja req, asyncResp->res, 1981b10d8db0SRavi Teja "DHCPv4", dhcpv4, 1982b10d8db0SRavi Teja "DHCPv6", dhcpv6, 1983b10d8db0SRavi Teja "FQDN", fqdn, 1984b10d8db0SRavi Teja "HostName", hostname, 1985b10d8db0SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, 1986b10d8db0SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, 1987b10d8db0SRavi Teja "IPv6StaticAddresses", ipv6StaticAddresses, 1988b10d8db0SRavi Teja "InterfaceEnabled", interfaceEnabled, 1989b10d8db0SRavi Teja "MACAddress", macAddress, 1990b10d8db0SRavi Teja "MTUSize", mtuSize, 1991b10d8db0SRavi Teja "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled, 1992b10d8db0SRavi Teja "StaticNameServers", staticNameServers 1993b10d8db0SRavi Teja ) 1994b10d8db0SRavi Teja ) 19951abe55efSEd Tanous { 1996588c3f0dSKowalski, Kamil return; 1997588c3f0dSKowalski, Kamil } 1998b10d8db0SRavi Teja //clang-format on 1999da131a9aSJennifer Lee if (dhcpv4) 2000da131a9aSJennifer Lee { 2001002d39b4SEd Tanous if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled", 20021f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 200382695a5bSJiaqing Zhao v4dhcpParms.useDnsServers, "UseNTPServers", 200482695a5bSJiaqing Zhao v4dhcpParms.useNtpServers, "UseDomainName", 200582695a5bSJiaqing Zhao v4dhcpParms.useDomainName)) 20061f8c7b5dSJohnathan Mantey { 20071f8c7b5dSJohnathan Mantey return; 20081f8c7b5dSJohnathan Mantey } 20091f8c7b5dSJohnathan Mantey } 20101f8c7b5dSJohnathan Mantey 20111f8c7b5dSJohnathan Mantey if (dhcpv6) 20121f8c7b5dSJohnathan Mantey { 2013002d39b4SEd Tanous if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode", 2014002d39b4SEd Tanous v6dhcpParms.dhcpv6OperatingMode, 2015002d39b4SEd Tanous "UseDNSServers", v6dhcpParms.useDnsServers, 2016002d39b4SEd Tanous "UseNTPServers", v6dhcpParms.useNtpServers, 2017002d39b4SEd Tanous "UseDomainName", 201882695a5bSJiaqing Zhao v6dhcpParms.useDomainName)) 20191f8c7b5dSJohnathan Mantey { 20201f8c7b5dSJohnathan Mantey return; 20211f8c7b5dSJohnathan Mantey } 2022da131a9aSJennifer Lee } 2023da131a9aSJennifer Lee 2024bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2025bf648f77SEd Tanous // for JSON preparation 20264a0cb85cSEd Tanous getEthernetIfaceData( 20272c70f800SEd Tanous ifaceId, 2028bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2029ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2030d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 20319a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2032e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 20331f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 2034bc20089aSEd Tanous dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize, 2035b10d8db0SRavi Teja ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms), 2036f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2037002d39b4SEd Tanous const bool& success, const EthernetInterfaceData& ethData, 203877179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 203977179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data) { 20401abe55efSEd Tanous if (!success) 20411abe55efSEd Tanous { 2042588c3f0dSKowalski, Kamil // ... otherwise return error 2043bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2044bf648f77SEd Tanous // existing object, and other errors 2045002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2046002d39b4SEd Tanous ifaceId); 2047588c3f0dSKowalski, Kamil return; 2048588c3f0dSKowalski, Kamil } 2049588c3f0dSKowalski, Kamil 20501f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 20511f8c7b5dSJohnathan Mantey { 2052002d39b4SEd Tanous handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms, 2053002d39b4SEd Tanous asyncResp); 20541f8c7b5dSJohnathan Mantey } 20551f8c7b5dSJohnathan Mantey 20560627a2c7SEd Tanous if (hostname) 20571abe55efSEd Tanous { 20580627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 20591abe55efSEd Tanous } 20600627a2c7SEd Tanous 2061b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2062b10d8db0SRavi Teja { 2063b10d8db0SRavi Teja handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled, 2064b10d8db0SRavi Teja asyncResp); 2065b10d8db0SRavi Teja } 2066b10d8db0SRavi Teja 2067ab6554f1SJoshi-Mansi if (fqdn) 2068ab6554f1SJoshi-Mansi { 20692c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2070ab6554f1SJoshi-Mansi } 2071ab6554f1SJoshi-Mansi 2072d577665bSRatan Gupta if (macAddress) 2073d577665bSRatan Gupta { 2074002d39b4SEd Tanous handleMACAddressPatch(ifaceId, *macAddress, asyncResp); 2075d577665bSRatan Gupta } 2076d577665bSRatan Gupta 2077d1d50814SRavi Teja if (ipv4StaticAddresses) 2078d1d50814SRavi Teja { 2079bf648f77SEd Tanous // TODO(ed) for some reason the capture of 2080bf648f77SEd Tanous // ipv4Addresses above is returning a const value, 2081bf648f77SEd Tanous // not a non-const value. This doesn't really work 2082bf648f77SEd Tanous // for us, as we need to be able to efficiently move 2083bf648f77SEd Tanous // out the intermedia nlohmann::json objects. This 2084bf648f77SEd Tanous // makes a copy of the structure, and operates on 2085bf648f77SEd Tanous // that, but could be done more efficiently 2086ddd70dcaSEd Tanous nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses; 2087002d39b4SEd Tanous handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp); 20881abe55efSEd Tanous } 20890627a2c7SEd Tanous 2090f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2091f85837bfSRAJESWARAN THILLAIGOVINDAN { 2092002d39b4SEd Tanous handleStaticNameServersPatch(ifaceId, *staticNameServers, 2093002d39b4SEd Tanous asyncResp); 2094f85837bfSRAJESWARAN THILLAIGOVINDAN } 20959a6fc6feSRavi Teja 20969a6fc6feSRavi Teja if (ipv6DefaultGateway) 20979a6fc6feSRavi Teja { 20989a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 20999a6fc6feSRavi Teja "IPv6DefaultGateway"); 21009a6fc6feSRavi Teja } 2101e48c0fc5SRavi Teja 2102e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2103e48c0fc5SRavi Teja { 2104ddd70dcaSEd Tanous handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses, 2105ddd70dcaSEd Tanous ipv6Data, asyncResp); 2106e48c0fc5SRavi Teja } 2107eeedda23SJohnathan Mantey 2108eeedda23SJohnathan Mantey if (interfaceEnabled) 2109eeedda23SJohnathan Mantey { 2110002d39b4SEd Tanous setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled", 2111002d39b4SEd Tanous *interfaceEnabled, asyncResp); 2112eeedda23SJohnathan Mantey } 211335fb5311STejas Patil 211435fb5311STejas Patil if (mtuSize) 211535fb5311STejas Patil { 211635fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 211735fb5311STejas Patil } 2118588c3f0dSKowalski, Kamil }); 2119bf648f77SEd Tanous }); 2120e7caf250SJiaqing Zhao 2121e7caf250SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/") 2122e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2123e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2124e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2125e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2126e7caf250SJiaqing Zhao const std::string& ifaceId) { 2127e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2128e7caf250SJiaqing Zhao { 2129e7caf250SJiaqing Zhao return; 2130e7caf250SJiaqing Zhao } 2131e7caf250SJiaqing Zhao 2132e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2133e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2134e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2135e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2136e7caf250SJiaqing Zhao }, 2137e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2138e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2139e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2140e7caf250SJiaqing Zhao }); 21414a0cb85cSEd Tanous } 2142bf648f77SEd Tanous 21439391bb9cSRapkiewicz, Pawel } // namespace redfish 2144