140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation 49391bb9cSRapkiewicz, Pawel #pragma once 59391bb9cSRapkiewicz, Pawel 63ccb3adbSEd Tanous #include "app.hpp" 73ccb3adbSEd Tanous #include "dbus_singleton.hpp" 87a1dbc48SGeorge Liu #include "dbus_utility.hpp" 93ccb3adbSEd Tanous #include "error_messages.hpp" 10539d8c6bSEd Tanous #include "generated/enums/ethernet_interface.hpp" 11539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 122c5875a2SEd Tanous #include "human_sort.hpp" 133ccb3adbSEd Tanous #include "query.hpp" 143ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 15033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 163ccb3adbSEd Tanous #include "utils/json_utils.hpp" 17033f1e4dSEd Tanous 18ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp> 19ef4c65b7SEd Tanous #include <boost/url/format.hpp> 201214b7e7SGunnar Mills 217a1dbc48SGeorge Liu #include <array> 223dfed536SEd Tanous #include <cstddef> 23ce73d5c8SSunitha Harish #include <memory> 24a24526dcSEd Tanous #include <optional> 253544d2a7SEd Tanous #include <ranges> 26ab6554f1SJoshi-Mansi #include <regex> 277a1dbc48SGeorge Liu #include <string_view> 283dfed536SEd Tanous #include <variant> 2977179532SEd Tanous #include <vector> 309391bb9cSRapkiewicz, Pawel 311abe55efSEd Tanous namespace redfish 321abe55efSEd Tanous { 339391bb9cSRapkiewicz, Pawel 344a0cb85cSEd Tanous enum class LinkType 354a0cb85cSEd Tanous { 364a0cb85cSEd Tanous Local, 374a0cb85cSEd Tanous Global 384a0cb85cSEd Tanous }; 399391bb9cSRapkiewicz, Pawel 40743eb1c0SJohnathan Mantey enum class IpVersion 41743eb1c0SJohnathan Mantey { 42743eb1c0SJohnathan Mantey IpV4, 43743eb1c0SJohnathan Mantey IpV6 44743eb1c0SJohnathan Mantey }; 45743eb1c0SJohnathan Mantey 469391bb9cSRapkiewicz, Pawel /** 479391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 489391bb9cSRapkiewicz, Pawel */ 491abe55efSEd Tanous struct IPv4AddressData 501abe55efSEd Tanous { 51179db1d7SKowalski, Kamil std::string id; 524a0cb85cSEd Tanous std::string address; 534a0cb85cSEd Tanous std::string domain; 544a0cb85cSEd Tanous std::string gateway; 559391bb9cSRapkiewicz, Pawel std::string netmask; 569391bb9cSRapkiewicz, Pawel std::string origin; 5777179532SEd Tanous LinkType linktype{}; 5877179532SEd Tanous bool isActive{}; 599391bb9cSRapkiewicz, Pawel }; 609391bb9cSRapkiewicz, Pawel 619391bb9cSRapkiewicz, Pawel /** 62e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 63e48c0fc5SRavi Teja */ 64e48c0fc5SRavi Teja struct IPv6AddressData 65e48c0fc5SRavi Teja { 66e48c0fc5SRavi Teja std::string id; 67e48c0fc5SRavi Teja std::string address; 68e48c0fc5SRavi Teja std::string origin; 6977179532SEd Tanous uint8_t prefixLength = 0; 70e48c0fc5SRavi Teja }; 71ce73d5c8SSunitha Harish 72ce73d5c8SSunitha Harish /** 73ce73d5c8SSunitha Harish * Structure for keeping static route data required by Redfish 74ce73d5c8SSunitha Harish */ 75ce73d5c8SSunitha Harish struct StaticGatewayData 76ce73d5c8SSunitha Harish { 77ce73d5c8SSunitha Harish std::string id; 78ce73d5c8SSunitha Harish std::string gateway; 79ce73d5c8SSunitha Harish size_t prefixLength = 0; 80ce73d5c8SSunitha Harish std::string protocol; 81ce73d5c8SSunitha Harish }; 82ce73d5c8SSunitha Harish 83e48c0fc5SRavi Teja /** 849391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 859391bb9cSRapkiewicz, Pawel * available from DBus 869391bb9cSRapkiewicz, Pawel */ 871abe55efSEd Tanous struct EthernetInterfaceData 881abe55efSEd Tanous { 894a0cb85cSEd Tanous uint32_t speed; 9035fb5311STejas Patil size_t mtuSize; 9182695a5bSJiaqing Zhao bool autoNeg; 92e4588158SJishnu CM bool dnsv4Enabled; 93e4588158SJishnu CM bool dnsv6Enabled; 9491c441ecSRavi Teja bool domainv4Enabled; 9591c441ecSRavi Teja bool domainv6Enabled; 96e4588158SJishnu CM bool ntpv4Enabled; 97e4588158SJishnu CM bool ntpv6Enabled; 98e4588158SJishnu CM bool hostNamev4Enabled; 99e4588158SJishnu CM bool hostNamev6Enabled; 100aa05fb27SJohnathan Mantey bool linkUp; 101eeedda23SJohnathan Mantey bool nicEnabled; 102b10d8db0SRavi Teja bool ipv6AcceptRa; 10382695a5bSJiaqing Zhao std::string dhcpEnabled; 1041f8c7b5dSJohnathan Mantey std::string operatingMode; 10582695a5bSJiaqing Zhao std::string hostName; 10682695a5bSJiaqing Zhao std::string defaultGateway; 10782695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 108ce73d5c8SSunitha Harish std::string ipv6StaticDefaultGateway; 1094652c640SAsmitha Karunanithi std::optional<std::string> macAddress; 11017e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 1110f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 1120f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 113d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1149391bb9cSRapkiewicz, Pawel }; 1159391bb9cSRapkiewicz, Pawel 1161f8c7b5dSJohnathan Mantey struct DHCPParameters 1171f8c7b5dSJohnathan Mantey { 1181f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 11982695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 12082695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 12182695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1221f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1231f8c7b5dSJohnathan Mantey }; 1241f8c7b5dSJohnathan Mantey 1259391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1269391bb9cSRapkiewicz, Pawel // into full dot notation 1271abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1281abe55efSEd Tanous { 1299391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1309391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1319391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1329391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1339391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1349391bb9cSRapkiewicz, Pawel return netmask; 1359391bb9cSRapkiewicz, Pawel } 1369391bb9cSRapkiewicz, Pawel 13782695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1381f8c7b5dSJohnathan Mantey bool isIPv4) 1391f8c7b5dSJohnathan Mantey { 1401f8c7b5dSJohnathan Mantey if (isIPv4) 1411f8c7b5dSJohnathan Mantey { 1421f8c7b5dSJohnathan Mantey return ( 1431f8c7b5dSJohnathan Mantey (inputDHCP == 1441f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1451f8c7b5dSJohnathan Mantey (inputDHCP == 1466e78b680SAsmitha Karunanithi "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both") || 1476e78b680SAsmitha Karunanithi (inputDHCP == 1486e78b680SAsmitha Karunanithi "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4v6stateless")); 1491f8c7b5dSJohnathan Mantey } 1501f8c7b5dSJohnathan Mantey return ((inputDHCP == 1511f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1521f8c7b5dSJohnathan Mantey (inputDHCP == 1531f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1541f8c7b5dSJohnathan Mantey } 1551f8c7b5dSJohnathan Mantey 1562c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1571f8c7b5dSJohnathan Mantey { 1581f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1591f8c7b5dSJohnathan Mantey { 1601f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1611f8c7b5dSJohnathan Mantey } 1623174e4dfSEd Tanous if (isIPv4) 1631f8c7b5dSJohnathan Mantey { 1641f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1651f8c7b5dSJohnathan Mantey } 1663174e4dfSEd Tanous if (isIPv6) 1671f8c7b5dSJohnathan Mantey { 1681f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1691f8c7b5dSJohnathan Mantey } 1701f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1711f8c7b5dSJohnathan Mantey } 1721f8c7b5dSJohnathan Mantey 173bd79bce8SPatrick Williams inline std::string translateAddressOriginDbusToRedfish( 174bd79bce8SPatrick Williams const std::string& inputOrigin, bool isIPv4) 1751abe55efSEd Tanous { 1764a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1771abe55efSEd Tanous { 1784a0cb85cSEd Tanous return "Static"; 1799391bb9cSRapkiewicz, Pawel } 1804a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1811abe55efSEd Tanous { 1824a0cb85cSEd Tanous if (isIPv4) 1831abe55efSEd Tanous { 1844a0cb85cSEd Tanous return "IPv4LinkLocal"; 1851abe55efSEd Tanous } 1864a0cb85cSEd Tanous return "LinkLocal"; 1879391bb9cSRapkiewicz, Pawel } 1884a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1891abe55efSEd Tanous { 1904a0cb85cSEd Tanous if (isIPv4) 1914a0cb85cSEd Tanous { 1924a0cb85cSEd Tanous return "DHCP"; 1934a0cb85cSEd Tanous } 1944a0cb85cSEd Tanous return "DHCPv6"; 1954a0cb85cSEd Tanous } 1964a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1974a0cb85cSEd Tanous { 1984a0cb85cSEd Tanous return "SLAAC"; 1994a0cb85cSEd Tanous } 2004a0cb85cSEd Tanous return ""; 2014a0cb85cSEd Tanous } 2024a0cb85cSEd Tanous 20302cad96eSEd Tanous inline bool extractEthernetInterfaceData( 20402cad96eSEd Tanous const std::string& ethifaceId, 20502cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 2064a0cb85cSEd Tanous EthernetInterfaceData& ethData) 2074a0cb85cSEd Tanous { 2084c9afe43SEd Tanous bool idFound = false; 20902cad96eSEd Tanous for (const auto& objpath : dbusData) 2104a0cb85cSEd Tanous { 21102cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 2124a0cb85cSEd Tanous { 21381ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 214029573d4SEd Tanous { 2154c9afe43SEd Tanous idFound = true; 2164a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2174a0cb85cSEd Tanous { 2184a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2194a0cb85cSEd Tanous { 2204a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2214a0cb85cSEd Tanous { 2224a0cb85cSEd Tanous const std::string* mac = 223abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2244a0cb85cSEd Tanous if (mac != nullptr) 2254a0cb85cSEd Tanous { 22682695a5bSJiaqing Zhao ethData.macAddress = *mac; 2274a0cb85cSEd Tanous } 2284a0cb85cSEd Tanous } 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous } 2314a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2324a0cb85cSEd Tanous { 2334a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2344a0cb85cSEd Tanous { 2354a0cb85cSEd Tanous if (propertyPair.first == "Id") 2364a0cb85cSEd Tanous { 2371b6b96c5SEd Tanous const uint32_t* id = 238abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2394a0cb85cSEd Tanous if (id != nullptr) 2404a0cb85cSEd Tanous { 24117e22024SJiaqing Zhao ethData.vlanId = *id; 2424a0cb85cSEd Tanous } 2434a0cb85cSEd Tanous } 2444a0cb85cSEd Tanous } 2454a0cb85cSEd Tanous } 2464a0cb85cSEd Tanous else if (ifacePair.first == 2474a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2484a0cb85cSEd Tanous { 2494a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2504a0cb85cSEd Tanous { 2514a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2524a0cb85cSEd Tanous { 2532c70f800SEd Tanous const bool* autoNeg = 254abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2552c70f800SEd Tanous if (autoNeg != nullptr) 2564a0cb85cSEd Tanous { 25782695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2584a0cb85cSEd Tanous } 2594a0cb85cSEd Tanous } 2604a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2614a0cb85cSEd Tanous { 2624a0cb85cSEd Tanous const uint32_t* speed = 263abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2644a0cb85cSEd Tanous if (speed != nullptr) 2654a0cb85cSEd Tanous { 2664a0cb85cSEd Tanous ethData.speed = *speed; 2674a0cb85cSEd Tanous } 2684a0cb85cSEd Tanous } 26935fb5311STejas Patil else if (propertyPair.first == "MTU") 27035fb5311STejas Patil { 2713e7a8da6SAnthony const size_t* mtuSize = 2723e7a8da6SAnthony std::get_if<size_t>(&propertyPair.second); 27335fb5311STejas Patil if (mtuSize != nullptr) 27435fb5311STejas Patil { 27535fb5311STejas Patil ethData.mtuSize = *mtuSize; 27635fb5311STejas Patil } 27735fb5311STejas Patil } 278aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 279aa05fb27SJohnathan Mantey { 280aa05fb27SJohnathan Mantey const bool* linkUp = 281aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 282aa05fb27SJohnathan Mantey if (linkUp != nullptr) 283aa05fb27SJohnathan Mantey { 284aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 285aa05fb27SJohnathan Mantey } 286aa05fb27SJohnathan Mantey } 287eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 288eeedda23SJohnathan Mantey { 289eeedda23SJohnathan Mantey const bool* nicEnabled = 290eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 291eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 292eeedda23SJohnathan Mantey { 293eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 294eeedda23SJohnathan Mantey } 295eeedda23SJohnathan Mantey } 296b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 297b10d8db0SRavi Teja { 298b10d8db0SRavi Teja const bool* ipv6AcceptRa = 299b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 300b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 301b10d8db0SRavi Teja { 302b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 303b10d8db0SRavi Teja } 304b10d8db0SRavi Teja } 305f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 306029573d4SEd Tanous { 307029573d4SEd Tanous const std::vector<std::string>* nameservers = 3088d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 309029573d4SEd Tanous &propertyPair.second); 310029573d4SEd Tanous if (nameservers != nullptr) 311029573d4SEd Tanous { 312f23b7296SEd Tanous ethData.nameServers = *nameservers; 3130f6efdc1Smanojkiran.eda@gmail.com } 3140f6efdc1Smanojkiran.eda@gmail.com } 3150f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3160f6efdc1Smanojkiran.eda@gmail.com { 3170f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3188d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3190f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3200f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3210f6efdc1Smanojkiran.eda@gmail.com { 322f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3234a0cb85cSEd Tanous } 3244a0cb85cSEd Tanous } 3252a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3262a133282Smanojkiraneda { 3272c70f800SEd Tanous const std::string* dhcpEnabled = 3281f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3292c70f800SEd Tanous if (dhcpEnabled != nullptr) 3302a133282Smanojkiraneda { 33182695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3322a133282Smanojkiraneda } 3332a133282Smanojkiraneda } 334d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 335d24bfc7aSJennifer Lee { 336d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3378d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 338d24bfc7aSJennifer Lee &propertyPair.second); 339d24bfc7aSJennifer Lee if (domainNames != nullptr) 340d24bfc7aSJennifer Lee { 341f23b7296SEd Tanous ethData.domainnames = *domainNames; 342d24bfc7aSJennifer Lee } 343d24bfc7aSJennifer Lee } 3449010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3459010ec2eSRavi Teja { 3469010ec2eSRavi Teja const std::string* defaultGateway = 3479010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3489010ec2eSRavi Teja if (defaultGateway != nullptr) 3499010ec2eSRavi Teja { 3509010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3519010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3529010ec2eSRavi Teja { 35382695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3549010ec2eSRavi Teja } 3559010ec2eSRavi Teja else 3569010ec2eSRavi Teja { 35782695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3589010ec2eSRavi Teja } 3599010ec2eSRavi Teja } 3609010ec2eSRavi Teja } 3619010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3629010ec2eSRavi Teja { 3639010ec2eSRavi Teja const std::string* defaultGateway6 = 3649010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3659010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3669010ec2eSRavi Teja { 3679010ec2eSRavi Teja std::string defaultGateway6Str = 3689010ec2eSRavi Teja *defaultGateway6; 3699010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3709010ec2eSRavi Teja { 37182695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3729010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3739010ec2eSRavi Teja } 3749010ec2eSRavi Teja else 3759010ec2eSRavi Teja { 37682695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3779010ec2eSRavi Teja defaultGateway6Str; 3789010ec2eSRavi Teja } 3799010ec2eSRavi Teja } 3809010ec2eSRavi Teja } 381029573d4SEd Tanous } 382029573d4SEd Tanous } 383029573d4SEd Tanous } 3841f8c7b5dSJohnathan Mantey 385e4588158SJishnu CM sdbusplus::message::object_path path( 386e4588158SJishnu CM "/xyz/openbmc_project/network"); 387bd79bce8SPatrick Williams sdbusplus::message::object_path dhcp4Path = 388bd79bce8SPatrick Williams path / ethifaceId / "dhcp4"; 389e4588158SJishnu CM 390e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp4Path) 3911f8c7b5dSJohnathan Mantey { 3921f8c7b5dSJohnathan Mantey if (ifacePair.first == 3931f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 3941f8c7b5dSJohnathan Mantey { 3951f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 3961f8c7b5dSJohnathan Mantey { 3971f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 3981f8c7b5dSJohnathan Mantey { 3992c70f800SEd Tanous const bool* dnsEnabled = 4001f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4012c70f800SEd Tanous if (dnsEnabled != nullptr) 4021f8c7b5dSJohnathan Mantey { 403e4588158SJishnu CM ethData.dnsv4Enabled = *dnsEnabled; 4041f8c7b5dSJohnathan Mantey } 4051f8c7b5dSJohnathan Mantey } 40691c441ecSRavi Teja else if (propertyPair.first == "DomainEnabled") 40791c441ecSRavi Teja { 40891c441ecSRavi Teja const bool* domainEnabled = 40991c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 41091c441ecSRavi Teja if (domainEnabled != nullptr) 41191c441ecSRavi Teja { 41291c441ecSRavi Teja ethData.domainv4Enabled = *domainEnabled; 41391c441ecSRavi Teja } 41491c441ecSRavi Teja } 4151f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 4161f8c7b5dSJohnathan Mantey { 4172c70f800SEd Tanous const bool* ntpEnabled = 4181f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4192c70f800SEd Tanous if (ntpEnabled != nullptr) 4201f8c7b5dSJohnathan Mantey { 421e4588158SJishnu CM ethData.ntpv4Enabled = *ntpEnabled; 4221f8c7b5dSJohnathan Mantey } 4231f8c7b5dSJohnathan Mantey } 4241f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 4251f8c7b5dSJohnathan Mantey { 4262c70f800SEd Tanous const bool* hostNameEnabled = 4271f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4282c70f800SEd Tanous if (hostNameEnabled != nullptr) 4291f8c7b5dSJohnathan Mantey { 430e4588158SJishnu CM ethData.hostNamev4Enabled = *hostNameEnabled; 431e4588158SJishnu CM } 432e4588158SJishnu CM } 433e4588158SJishnu CM } 434e4588158SJishnu CM } 435e4588158SJishnu CM } 436e4588158SJishnu CM 437bd79bce8SPatrick Williams sdbusplus::message::object_path dhcp6Path = 438bd79bce8SPatrick Williams path / ethifaceId / "dhcp6"; 439e4588158SJishnu CM 440e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp6Path) 441e4588158SJishnu CM { 442e4588158SJishnu CM if (ifacePair.first == 443e4588158SJishnu CM "xyz.openbmc_project.Network.DHCPConfiguration") 444e4588158SJishnu CM { 445e4588158SJishnu CM for (const auto& propertyPair : ifacePair.second) 446e4588158SJishnu CM { 447e4588158SJishnu CM if (propertyPair.first == "DNSEnabled") 448e4588158SJishnu CM { 449e4588158SJishnu CM const bool* dnsEnabled = 450e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 451e4588158SJishnu CM if (dnsEnabled != nullptr) 452e4588158SJishnu CM { 453e4588158SJishnu CM ethData.dnsv6Enabled = *dnsEnabled; 454e4588158SJishnu CM } 455e4588158SJishnu CM } 45691c441ecSRavi Teja if (propertyPair.first == "DomainEnabled") 45791c441ecSRavi Teja { 45891c441ecSRavi Teja const bool* domainEnabled = 45991c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 46091c441ecSRavi Teja if (domainEnabled != nullptr) 46191c441ecSRavi Teja { 46291c441ecSRavi Teja ethData.domainv6Enabled = *domainEnabled; 46391c441ecSRavi Teja } 46491c441ecSRavi Teja } 465e4588158SJishnu CM else if (propertyPair.first == "NTPEnabled") 466e4588158SJishnu CM { 467e4588158SJishnu CM const bool* ntpEnabled = 468e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 469e4588158SJishnu CM if (ntpEnabled != nullptr) 470e4588158SJishnu CM { 471e4588158SJishnu CM ethData.ntpv6Enabled = *ntpEnabled; 472e4588158SJishnu CM } 473e4588158SJishnu CM } 474e4588158SJishnu CM else if (propertyPair.first == "HostNameEnabled") 475e4588158SJishnu CM { 476e4588158SJishnu CM const bool* hostNameEnabled = 477e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 478e4588158SJishnu CM if (hostNameEnabled != nullptr) 479e4588158SJishnu CM { 480e4588158SJishnu CM ethData.hostNamev6Enabled = *hostNameEnabled; 4811f8c7b5dSJohnathan Mantey } 4821f8c7b5dSJohnathan Mantey } 4831f8c7b5dSJohnathan Mantey } 4841f8c7b5dSJohnathan Mantey } 4851f8c7b5dSJohnathan Mantey } 486029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 487029573d4SEd Tanous // to check eth number 488029573d4SEd Tanous if (ifacePair.first == 4894a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 4904a0cb85cSEd Tanous { 4914a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 4924a0cb85cSEd Tanous { 4934a0cb85cSEd Tanous if (propertyPair.first == "HostName") 4944a0cb85cSEd Tanous { 4954a0cb85cSEd Tanous const std::string* hostname = 4968d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 4974a0cb85cSEd Tanous if (hostname != nullptr) 4984a0cb85cSEd Tanous { 49982695a5bSJiaqing Zhao ethData.hostName = *hostname; 5004a0cb85cSEd Tanous } 5014a0cb85cSEd Tanous } 5024a0cb85cSEd Tanous } 5034a0cb85cSEd Tanous } 5044a0cb85cSEd Tanous } 5054a0cb85cSEd Tanous } 5064c9afe43SEd Tanous return idFound; 5074a0cb85cSEd Tanous } 5084a0cb85cSEd Tanous 509e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 51077179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 511711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 51277179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 513e48c0fc5SRavi Teja { 514bd79bce8SPatrick Williams const std::string ipPathStart = 515bd79bce8SPatrick Williams "/xyz/openbmc_project/network/" + ethifaceId; 516e48c0fc5SRavi Teja 517e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 518e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 51981ce609eSEd Tanous for (const auto& objpath : dbusData) 520e48c0fc5SRavi Teja { 521e48c0fc5SRavi Teja // Check if proper pattern for object path appears 522353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 523e48c0fc5SRavi Teja { 5249eb808c1SEd Tanous for (const auto& interface : objpath.second) 525e48c0fc5SRavi Teja { 526e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 527e48c0fc5SRavi Teja { 528bd79bce8SPatrick Williams auto type = std::ranges::find_if( 529bd79bce8SPatrick Williams interface.second, [](const auto& property) { 530353163e9STony Lee return property.first == "Type"; 531353163e9STony Lee }); 532353163e9STony Lee if (type == interface.second.end()) 533353163e9STony Lee { 534353163e9STony Lee continue; 535353163e9STony Lee } 536353163e9STony Lee 537353163e9STony Lee const std::string* typeStr = 538353163e9STony Lee std::get_if<std::string>(&type->second); 539353163e9STony Lee 540353163e9STony Lee if (typeStr == nullptr || 541353163e9STony Lee (*typeStr != 542353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 543353163e9STony Lee { 544353163e9STony Lee continue; 545353163e9STony Lee } 546353163e9STony Lee 547e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 548e48c0fc5SRavi Teja // appropriate 54977179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 5502c70f800SEd Tanous ipv6Address.id = 551353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5529eb808c1SEd Tanous for (const auto& property : interface.second) 553e48c0fc5SRavi Teja { 554e48c0fc5SRavi Teja if (property.first == "Address") 555e48c0fc5SRavi Teja { 556e48c0fc5SRavi Teja const std::string* address = 557e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 558e48c0fc5SRavi Teja if (address != nullptr) 559e48c0fc5SRavi Teja { 5602c70f800SEd Tanous ipv6Address.address = *address; 561e48c0fc5SRavi Teja } 562e48c0fc5SRavi Teja } 563e48c0fc5SRavi Teja else if (property.first == "Origin") 564e48c0fc5SRavi Teja { 565e48c0fc5SRavi Teja const std::string* origin = 566e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 567e48c0fc5SRavi Teja if (origin != nullptr) 568e48c0fc5SRavi Teja { 5692c70f800SEd Tanous ipv6Address.origin = 570e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 571e48c0fc5SRavi Teja false); 572e48c0fc5SRavi Teja } 573e48c0fc5SRavi Teja } 574e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 575e48c0fc5SRavi Teja { 576e48c0fc5SRavi Teja const uint8_t* prefix = 577e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 578e48c0fc5SRavi Teja if (prefix != nullptr) 579e48c0fc5SRavi Teja { 5802c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 581e48c0fc5SRavi Teja } 582e48c0fc5SRavi Teja } 583889ff694SAsmitha Karunanithi else if (property.first == "Type" || 584889ff694SAsmitha Karunanithi property.first == "Gateway") 585889ff694SAsmitha Karunanithi { 586889ff694SAsmitha Karunanithi // Type & Gateway is not used 587889ff694SAsmitha Karunanithi } 588e48c0fc5SRavi Teja else 589e48c0fc5SRavi Teja { 59062598e31SEd Tanous BMCWEB_LOG_ERROR( 59162598e31SEd Tanous "Got extra property: {} on the {} object", 59262598e31SEd Tanous property.first, objpath.first.str); 593e48c0fc5SRavi Teja } 594e48c0fc5SRavi Teja } 595e48c0fc5SRavi Teja } 596e48c0fc5SRavi Teja } 597e48c0fc5SRavi Teja } 598e48c0fc5SRavi Teja } 599e48c0fc5SRavi Teja } 600e48c0fc5SRavi Teja 6014a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 60277179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 603711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 60477179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 6054a0cb85cSEd Tanous { 606bd79bce8SPatrick Williams const std::string ipPathStart = 607bd79bce8SPatrick Williams "/xyz/openbmc_project/network/" + ethifaceId; 6084a0cb85cSEd Tanous 6094a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 6104a0cb85cSEd Tanous // single ethernet interface, loop over all of them 61181ce609eSEd Tanous for (const auto& objpath : dbusData) 6124a0cb85cSEd Tanous { 6134a0cb85cSEd Tanous // Check if proper pattern for object path appears 614353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 6154a0cb85cSEd Tanous { 6169eb808c1SEd Tanous for (const auto& interface : objpath.second) 6174a0cb85cSEd Tanous { 6184a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 6194a0cb85cSEd Tanous { 620bd79bce8SPatrick Williams auto type = std::ranges::find_if( 621bd79bce8SPatrick Williams interface.second, [](const auto& property) { 622353163e9STony Lee return property.first == "Type"; 623353163e9STony Lee }); 624353163e9STony Lee if (type == interface.second.end()) 625353163e9STony Lee { 626353163e9STony Lee continue; 627353163e9STony Lee } 628353163e9STony Lee 629353163e9STony Lee const std::string* typeStr = 630353163e9STony Lee std::get_if<std::string>(&type->second); 631353163e9STony Lee 632353163e9STony Lee if (typeStr == nullptr || 633353163e9STony Lee (*typeStr != 634353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 635353163e9STony Lee { 636353163e9STony Lee continue; 637353163e9STony Lee } 638353163e9STony Lee 6394a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 6404a0cb85cSEd Tanous // appropriate 64177179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 6422c70f800SEd Tanous ipv4Address.id = 643353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 6449eb808c1SEd Tanous for (const auto& property : interface.second) 6454a0cb85cSEd Tanous { 6464a0cb85cSEd Tanous if (property.first == "Address") 6474a0cb85cSEd Tanous { 6484a0cb85cSEd Tanous const std::string* address = 649abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6504a0cb85cSEd Tanous if (address != nullptr) 6514a0cb85cSEd Tanous { 6522c70f800SEd Tanous ipv4Address.address = *address; 6534a0cb85cSEd Tanous } 6544a0cb85cSEd Tanous } 6554a0cb85cSEd Tanous else if (property.first == "Origin") 6564a0cb85cSEd Tanous { 6574a0cb85cSEd Tanous const std::string* origin = 658abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6594a0cb85cSEd Tanous if (origin != nullptr) 6604a0cb85cSEd Tanous { 6612c70f800SEd Tanous ipv4Address.origin = 6624a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 6634a0cb85cSEd Tanous true); 6644a0cb85cSEd Tanous } 6654a0cb85cSEd Tanous } 6664a0cb85cSEd Tanous else if (property.first == "PrefixLength") 6674a0cb85cSEd Tanous { 6684a0cb85cSEd Tanous const uint8_t* mask = 669abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 6704a0cb85cSEd Tanous if (mask != nullptr) 6714a0cb85cSEd Tanous { 6724a0cb85cSEd Tanous // convert it to the string 6732c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 6744a0cb85cSEd Tanous } 6754a0cb85cSEd Tanous } 676889ff694SAsmitha Karunanithi else if (property.first == "Type" || 677889ff694SAsmitha Karunanithi property.first == "Gateway") 678889ff694SAsmitha Karunanithi { 679889ff694SAsmitha Karunanithi // Type & Gateway is not used 680889ff694SAsmitha Karunanithi } 6814a0cb85cSEd Tanous else 6824a0cb85cSEd Tanous { 68362598e31SEd Tanous BMCWEB_LOG_ERROR( 68462598e31SEd Tanous "Got extra property: {} on the {} object", 68562598e31SEd Tanous property.first, objpath.first.str); 6864a0cb85cSEd Tanous } 6874a0cb85cSEd Tanous } 6884a0cb85cSEd Tanous // Check if given address is local, or global 6892c70f800SEd Tanous ipv4Address.linktype = 69011ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 69118659d10SJohnathan Mantey ? LinkType::Local 69218659d10SJohnathan Mantey : LinkType::Global; 6934a0cb85cSEd Tanous } 6944a0cb85cSEd Tanous } 6954a0cb85cSEd Tanous } 6964a0cb85cSEd Tanous } 6974a0cb85cSEd Tanous } 698588c3f0dSKowalski, Kamil 699588c3f0dSKowalski, Kamil /** 700743eb1c0SJohnathan Mantey * @brief Modifies the default gateway assigned to the NIC 701743eb1c0SJohnathan Mantey * 702743eb1c0SJohnathan Mantey * @param[in] ifaceId Id of network interface whose default gateway is to be 703743eb1c0SJohnathan Mantey * changed 704743eb1c0SJohnathan Mantey * @param[in] gateway The new gateway value. Assigning an empty string 705743eb1c0SJohnathan Mantey * causes the gateway to be deleted 706743eb1c0SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 707743eb1c0SJohnathan Mantey * 708743eb1c0SJohnathan Mantey * @return None 709743eb1c0SJohnathan Mantey */ 710743eb1c0SJohnathan Mantey inline void updateIPv4DefaultGateway( 711743eb1c0SJohnathan Mantey const std::string& ifaceId, const std::string& gateway, 712743eb1c0SJohnathan Mantey const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 713743eb1c0SJohnathan Mantey { 714743eb1c0SJohnathan Mantey setDbusProperty( 715e93abac6SGinu George asyncResp, "Gateway", "xyz.openbmc_project.Network", 716743eb1c0SJohnathan Mantey sdbusplus::message::object_path("/xyz/openbmc_project/network") / 717743eb1c0SJohnathan Mantey ifaceId, 718743eb1c0SJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 719e93abac6SGinu George gateway); 720743eb1c0SJohnathan Mantey } 721743eb1c0SJohnathan Mantey 722743eb1c0SJohnathan Mantey /** 723743eb1c0SJohnathan Mantey * @brief Deletes given static IP address for the interface 724179db1d7SKowalski, Kamil * 725179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 726179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 727179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 728179db1d7SKowalski, Kamil * 729179db1d7SKowalski, Kamil * @return None 730179db1d7SKowalski, Kamil */ 7319c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 7329c5e585cSRavi Teja const std::string& ipHash, 7338d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7341abe55efSEd Tanous { 73555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7365e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 7371abe55efSEd Tanous if (ec) 7381abe55efSEd Tanous { 739a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7401abe55efSEd Tanous } 741179db1d7SKowalski, Kamil }, 742179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 7439c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 744179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 745179db1d7SKowalski, Kamil } 746179db1d7SKowalski, Kamil 747179db1d7SKowalski, Kamil /** 74801784826SJohnathan Mantey * @brief Creates a static IPv4 entry 749179db1d7SKowalski, Kamil * 75001784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 75101784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 75201784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 75301784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 754179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 755179db1d7SKowalski, Kamil * 756179db1d7SKowalski, Kamil * @return None 757179db1d7SKowalski, Kamil */ 758cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 759cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7608d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7611abe55efSEd Tanous { 762bd79bce8SPatrick Williams auto createIpHandler = 763bd79bce8SPatrick Williams [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) { 7641abe55efSEd Tanous if (ec) 7651abe55efSEd Tanous { 766a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7679010ec2eSRavi Teja return; 768179db1d7SKowalski, Kamil } 7699010ec2eSRavi Teja }; 7709010ec2eSRavi Teja 7719010ec2eSRavi Teja crow::connections::systemBus->async_method_call( 7729010ec2eSRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 773179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 774179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 77501784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 776179db1d7SKowalski, Kamil gateway); 777179db1d7SKowalski, Kamil } 778e48c0fc5SRavi Teja 779e48c0fc5SRavi Teja /** 780743eb1c0SJohnathan Mantey * @brief Deletes the IP entry for this interface and creates a replacement 781743eb1c0SJohnathan Mantey * static entry 78201784826SJohnathan Mantey * 78301784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 78401784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 785743eb1c0SJohnathan Mantey * @param[in] prefixLength Prefix syntax for the subnet mask 786743eb1c0SJohnathan Mantey * @param[in] address Address to assign to this interface 787743eb1c0SJohnathan Mantey * @param[in] numStaticAddrs Count of IPv4 static addresses 78801784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 78901784826SJohnathan Mantey * 79001784826SJohnathan Mantey * @return None 79101784826SJohnathan Mantey */ 7929c5e585cSRavi Teja 7939c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 7949c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 7958d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 7969c5e585cSRavi Teja const std::string& gateway, 7978d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 79801784826SJohnathan Mantey { 79901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8009c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 8019c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 80201784826SJohnathan Mantey if (ec) 80301784826SJohnathan Mantey { 80401784826SJohnathan Mantey messages::internalError(asyncResp->res); 80501784826SJohnathan Mantey } 8069c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 8079c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 80801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 8095e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 81023a21a1cSEd Tanous if (ec2) 81101784826SJohnathan Mantey { 81201784826SJohnathan Mantey messages::internalError(asyncResp->res); 81301784826SJohnathan Mantey } 81401784826SJohnathan Mantey }, 81501784826SJohnathan Mantey "xyz.openbmc_project.Network", 81601784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 817bd79bce8SPatrick Williams "xyz.openbmc_project.Network.IP.Create", "IP", protocol, 818bd79bce8SPatrick Williams address, prefixLength, gateway); 81901784826SJohnathan Mantey }, 82001784826SJohnathan Mantey "xyz.openbmc_project.Network", 8219c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 82201784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 82301784826SJohnathan Mantey } 82401784826SJohnathan Mantey 825ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData( 826ce73d5c8SSunitha Harish const std::string& ethifaceId, 827ce73d5c8SSunitha Harish const dbus::utility::ManagedObjectType& dbusData, 828ce73d5c8SSunitha Harish std::vector<StaticGatewayData>& staticGatewayConfig) 829ce73d5c8SSunitha Harish { 830ce73d5c8SSunitha Harish std::string staticGatewayPathStart("/xyz/openbmc_project/network/"); 831ce73d5c8SSunitha Harish staticGatewayPathStart += ethifaceId; 832ce73d5c8SSunitha Harish 833ce73d5c8SSunitha Harish for (const auto& objpath : dbusData) 834ce73d5c8SSunitha Harish { 835ce73d5c8SSunitha Harish if (!std::string_view(objpath.first.str) 836ce73d5c8SSunitha Harish .starts_with(staticGatewayPathStart)) 837ce73d5c8SSunitha Harish { 838ce73d5c8SSunitha Harish continue; 839ce73d5c8SSunitha Harish } 840ce73d5c8SSunitha Harish for (const auto& interface : objpath.second) 841ce73d5c8SSunitha Harish { 842ce73d5c8SSunitha Harish if (interface.first != "xyz.openbmc_project.Network.StaticGateway") 843ce73d5c8SSunitha Harish { 844ce73d5c8SSunitha Harish continue; 845ce73d5c8SSunitha Harish } 846ce73d5c8SSunitha Harish StaticGatewayData& staticGateway = 847ce73d5c8SSunitha Harish staticGatewayConfig.emplace_back(); 848ce73d5c8SSunitha Harish staticGateway.id = objpath.first.filename(); 849ce73d5c8SSunitha Harish 850ce73d5c8SSunitha Harish bool success = sdbusplus::unpackPropertiesNoThrow( 851ce73d5c8SSunitha Harish redfish::dbus_utils::UnpackErrorPrinter(), interface.second, 852ab0d4390SRavi Teja "Gateway", staticGateway.gateway, "ProtocolType", 853ce73d5c8SSunitha Harish staticGateway.protocol); 854ce73d5c8SSunitha Harish if (!success) 855ce73d5c8SSunitha Harish { 856ce73d5c8SSunitha Harish return false; 857ce73d5c8SSunitha Harish } 858ce73d5c8SSunitha Harish } 859ce73d5c8SSunitha Harish } 860ce73d5c8SSunitha Harish return true; 861ce73d5c8SSunitha Harish } 862ce73d5c8SSunitha Harish 86301784826SJohnathan Mantey /** 864e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 865e48c0fc5SRavi Teja * 866e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 867e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 868e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 869e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 870e48c0fc5SRavi Teja * 871e48c0fc5SRavi Teja * @return None 872e48c0fc5SRavi Teja */ 87301784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 87401784826SJohnathan Mantey const std::string& address, 8758d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 876e48c0fc5SRavi Teja { 877ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 878ce73d5c8SSunitha Harish path /= ifaceId; 879ce73d5c8SSunitha Harish 880bd79bce8SPatrick Williams auto createIpHandler = 881bd79bce8SPatrick Williams [asyncResp, address](const boost::system::error_code& ec) { 882e48c0fc5SRavi Teja if (ec) 883e48c0fc5SRavi Teja { 884fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 885fc23ef8aSNitin Kumar Kotania { 886fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 887fc23ef8aSNitin Kumar Kotania "Address"); 888fc23ef8aSNitin Kumar Kotania } 889fc23ef8aSNitin Kumar Kotania else 890fc23ef8aSNitin Kumar Kotania { 891e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 892e48c0fc5SRavi Teja } 893fc23ef8aSNitin Kumar Kotania } 894e48c0fc5SRavi Teja }; 895ce73d5c8SSunitha Harish // Passing null for gateway, as per redfish spec IPv6StaticAddresses 896ce73d5c8SSunitha Harish // object does not have associated gateway property 897e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 898ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 899e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 900e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 901e48c0fc5SRavi Teja ""); 902e48c0fc5SRavi Teja } 903e48c0fc5SRavi Teja 904179db1d7SKowalski, Kamil /** 905ce73d5c8SSunitha Harish * @brief Deletes given IPv6 Static Gateway 906ce73d5c8SSunitha Harish * 907ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be deleted 908ce73d5c8SSunitha Harish * @param[in] ipHash DBus Hash id of IP that should be deleted 909ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 910ce73d5c8SSunitha Harish * 911ce73d5c8SSunitha Harish * @return None 912ce73d5c8SSunitha Harish */ 913ce73d5c8SSunitha Harish inline void 914739b27b2SRavi Teja deleteIPv6Gateway(std::string_view ifaceId, std::string_view gatewayId, 915ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 916ce73d5c8SSunitha Harish { 917ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 918739b27b2SRavi Teja path /= ifaceId; 919ce73d5c8SSunitha Harish path /= gatewayId; 920ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 921ce73d5c8SSunitha Harish [asyncResp](const boost::system::error_code& ec) { 922ce73d5c8SSunitha Harish if (ec) 923ce73d5c8SSunitha Harish { 924ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 925ce73d5c8SSunitha Harish } 926ce73d5c8SSunitha Harish }, 927ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 928ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 929ce73d5c8SSunitha Harish } 930ce73d5c8SSunitha Harish 931ce73d5c8SSunitha Harish /** 932ce73d5c8SSunitha Harish * @brief Creates IPv6 static default gateway with given data 933ce73d5c8SSunitha Harish * 934ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be added 935ce73d5c8SSunitha Harish * @param[in] gateway Gateway address that needs to be added 936ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 937ce73d5c8SSunitha Harish * 938ce73d5c8SSunitha Harish * @return None 939ce73d5c8SSunitha Harish */ 940ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway( 941*cf91c8c4SAsmitha Karunanithi std::string_view ifaceId, const std::string& gateway, 942ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 943ce73d5c8SSunitha Harish { 944ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 945ce73d5c8SSunitha Harish path /= ifaceId; 946ce73d5c8SSunitha Harish auto createIpHandler = [asyncResp](const boost::system::error_code& ec) { 947ce73d5c8SSunitha Harish if (ec) 948ce73d5c8SSunitha Harish { 949ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 950ce73d5c8SSunitha Harish } 951ce73d5c8SSunitha Harish }; 952ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 953ce73d5c8SSunitha Harish std::move(createIpHandler), "xyz.openbmc_project.Network", path, 954ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway", 955ab0d4390SRavi Teja gateway, "xyz.openbmc_project.Network.IP.Protocol.IPv6"); 956ce73d5c8SSunitha Harish } 957ce73d5c8SSunitha Harish 958ce73d5c8SSunitha Harish /** 959ce73d5c8SSunitha Harish * @brief Deletes the IPv6 default gateway entry for this interface and 960ce73d5c8SSunitha Harish * creates a replacement IPv6 default gateway entry 961ce73d5c8SSunitha Harish * 962ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface upon which to create the IPv6 963ce73d5c8SSunitha Harish * entry 964ce73d5c8SSunitha Harish * @param[in] gateway IPv6 gateway to assign to this interface 965ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 966ce73d5c8SSunitha Harish * 967ce73d5c8SSunitha Harish * @return None 968ce73d5c8SSunitha Harish */ 969ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway( 970ce73d5c8SSunitha Harish std::string_view ifaceId, std::string_view gatewayId, 971*cf91c8c4SAsmitha Karunanithi const std::string& gateway, 972ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 973ce73d5c8SSunitha Harish { 974ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 975739b27b2SRavi Teja path /= ifaceId; 976ce73d5c8SSunitha Harish path /= gatewayId; 977ce73d5c8SSunitha Harish crow::connections::systemBus->async_method_call( 978ab0d4390SRavi Teja [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) { 979ce73d5c8SSunitha Harish if (ec) 980ce73d5c8SSunitha Harish { 981ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 982ce73d5c8SSunitha Harish return; 983ce73d5c8SSunitha Harish } 984ab0d4390SRavi Teja createIPv6DefaultGateway(ifaceId, gateway, asyncResp); 985ce73d5c8SSunitha Harish }, 986ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 987ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 988ce73d5c8SSunitha Harish } 989ce73d5c8SSunitha Harish 990ce73d5c8SSunitha Harish /** 991ce73d5c8SSunitha Harish * @brief Sets IPv6 default gateway with given data 992ce73d5c8SSunitha Harish * 993ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose gateway should be added 994ce73d5c8SSunitha Harish * @param[in] input Contains address that needs to be added 995ce73d5c8SSunitha Harish * @param[in] staticGatewayData Current static gateways in the system 996ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 997ce73d5c8SSunitha Harish * 998ce73d5c8SSunitha Harish * @return None 999ce73d5c8SSunitha Harish */ 1000ce73d5c8SSunitha Harish 1001ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway( 10023dfed536SEd Tanous const std::string& ifaceId, 10033dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1004ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& staticGatewayData, 1005ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1006ce73d5c8SSunitha Harish { 1007ce73d5c8SSunitha Harish size_t entryIdx = 1; 1008ce73d5c8SSunitha Harish std::vector<StaticGatewayData>::const_iterator staticGatewayEntry = 1009ce73d5c8SSunitha Harish staticGatewayData.begin(); 1010ce73d5c8SSunitha Harish 10113dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 10123dfed536SEd Tanous input) 1013ce73d5c8SSunitha Harish { 1014ce73d5c8SSunitha Harish // find the next gateway entry 1015ce73d5c8SSunitha Harish while (staticGatewayEntry != staticGatewayData.end()) 1016ce73d5c8SSunitha Harish { 1017ce73d5c8SSunitha Harish if (staticGatewayEntry->protocol == 1018ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.IP.Protocol.IPv6") 1019ce73d5c8SSunitha Harish { 1020ce73d5c8SSunitha Harish break; 1021ce73d5c8SSunitha Harish } 1022ce73d5c8SSunitha Harish staticGatewayEntry++; 1023ce73d5c8SSunitha Harish } 1024bd79bce8SPatrick Williams std::string pathString = 1025bd79bce8SPatrick Williams "IPv6StaticDefaultGateways/" + std::to_string(entryIdx); 10263dfed536SEd Tanous nlohmann::json::object_t* obj = 10273dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 10283dfed536SEd Tanous if (obj == nullptr) 1029ce73d5c8SSunitha Harish { 1030ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1031ce73d5c8SSunitha Harish { 1032ce73d5c8SSunitha Harish messages::resourceCannotBeDeleted(asyncResp->res); 1033ce73d5c8SSunitha Harish return; 1034ce73d5c8SSunitha Harish } 1035739b27b2SRavi Teja deleteIPv6Gateway(ifaceId, staticGatewayEntry->id, asyncResp); 1036ce73d5c8SSunitha Harish return; 1037ce73d5c8SSunitha Harish } 10383dfed536SEd Tanous if (obj->empty()) 1039ce73d5c8SSunitha Harish { 1040ce73d5c8SSunitha Harish // Do nothing, but make sure the entry exists. 1041ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1042ce73d5c8SSunitha Harish { 10433dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 1044ce73d5c8SSunitha Harish pathString); 1045ce73d5c8SSunitha Harish return; 1046ce73d5c8SSunitha Harish } 1047ce73d5c8SSunitha Harish } 1048ce73d5c8SSunitha Harish std::optional<std::string> address; 1049ce73d5c8SSunitha Harish 1050ab0d4390SRavi Teja if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", 1051ab0d4390SRavi Teja address)) 1052ce73d5c8SSunitha Harish { 1053ce73d5c8SSunitha Harish return; 1054ce73d5c8SSunitha Harish } 1055ce73d5c8SSunitha Harish const std::string* addr = nullptr; 1056ce73d5c8SSunitha Harish if (address) 1057ce73d5c8SSunitha Harish { 1058ce73d5c8SSunitha Harish addr = &(*address); 1059ce73d5c8SSunitha Harish } 1060ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1061ce73d5c8SSunitha Harish { 1062ce73d5c8SSunitha Harish addr = &(staticGatewayEntry->gateway); 1063ce73d5c8SSunitha Harish } 1064ce73d5c8SSunitha Harish else 1065ce73d5c8SSunitha Harish { 1066ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, pathString + "/Address"); 1067ce73d5c8SSunitha Harish return; 1068ce73d5c8SSunitha Harish } 1069ce73d5c8SSunitha Harish if (staticGatewayEntry != staticGatewayData.end()) 1070ce73d5c8SSunitha Harish { 1071ce73d5c8SSunitha Harish deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id, 1072ab0d4390SRavi Teja *addr, asyncResp); 1073ce73d5c8SSunitha Harish staticGatewayEntry++; 1074ce73d5c8SSunitha Harish } 1075ce73d5c8SSunitha Harish else 1076ce73d5c8SSunitha Harish { 1077ab0d4390SRavi Teja createIPv6DefaultGateway(ifaceId, *addr, asyncResp); 1078ce73d5c8SSunitha Harish } 1079ce73d5c8SSunitha Harish entryIdx++; 1080ce73d5c8SSunitha Harish } 1081ce73d5c8SSunitha Harish } 1082ce73d5c8SSunitha Harish 1083ce73d5c8SSunitha Harish /** 1084179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 1085179db1d7SKowalski, Kamil * Object 1086179db1d7SKowalski, Kamil * from EntityManager Network Manager 10874a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 1088179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 1089179db1d7SKowalski, Kamil * into JSON 1090179db1d7SKowalski, Kamil */ 1091179db1d7SKowalski, Kamil template <typename CallbackFunc> 109281ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 10931abe55efSEd Tanous CallbackFunc&& callback) 10941abe55efSEd Tanous { 1095f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1096f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1097f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1098f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 10998cb2c024SEd Tanous callback = std::forward<CallbackFunc>(callback)]( 11008b24275dSEd Tanous const boost::system::error_code& ec, 11013dfed536SEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 110255c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 110377179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 110477179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 1105ce73d5c8SSunitha Harish std::vector<StaticGatewayData> ipv6GatewayData; 1106179db1d7SKowalski, Kamil 11078b24275dSEd Tanous if (ec) 11081abe55efSEd Tanous { 1109ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1110179db1d7SKowalski, Kamil return; 1111179db1d7SKowalski, Kamil } 1112179db1d7SKowalski, Kamil 1113bd79bce8SPatrick Williams bool found = 1114bd79bce8SPatrick Williams extractEthernetInterfaceData(ethifaceId, resp, ethData); 11154c9afe43SEd Tanous if (!found) 11164c9afe43SEd Tanous { 1117ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 11184c9afe43SEd Tanous return; 11194c9afe43SEd Tanous } 11204c9afe43SEd Tanous 11212c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 1122179db1d7SKowalski, Kamil // Fix global GW 11231abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 11241abe55efSEd Tanous { 1125c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 1126c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 11279010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 11281abe55efSEd Tanous { 112982695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 1130179db1d7SKowalski, Kamil } 1131179db1d7SKowalski, Kamil } 1132179db1d7SKowalski, Kamil 11332c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 1134bd79bce8SPatrick Williams if (!extractIPv6DefaultGatewayData(ethifaceId, resp, 1135bd79bce8SPatrick Williams ipv6GatewayData)) 1136ce73d5c8SSunitha Harish { 1137ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1138ce73d5c8SSunitha Harish } 11394e0453b1SGunnar Mills // Finally make a callback with useful data 1140ce73d5c8SSunitha Harish callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1141f5892d0dSGeorge Liu }); 1142271584abSEd Tanous } 1143179db1d7SKowalski, Kamil 1144179db1d7SKowalski, Kamil /** 11459391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 11469391bb9cSRapkiewicz, Pawel * Manager 11471abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 11481abe55efSEd Tanous * into JSON. 11499391bb9cSRapkiewicz, Pawel */ 11509391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 11511abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 11521abe55efSEd Tanous { 1153f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1154f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1155f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 11568cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 11578b24275dSEd Tanous const boost::system::error_code& ec, 1158f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 11591abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 11601abe55efSEd Tanous // ethernet interfaces 116177179532SEd Tanous std::vector<std::string> ifaceList; 11622c70f800SEd Tanous ifaceList.reserve(resp.size()); 11638b24275dSEd Tanous if (ec) 11641abe55efSEd Tanous { 11652c70f800SEd Tanous callback(false, ifaceList); 11669391bb9cSRapkiewicz, Pawel return; 11679391bb9cSRapkiewicz, Pawel } 11689391bb9cSRapkiewicz, Pawel 11699391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 11704a0cb85cSEd Tanous for (const auto& objpath : resp) 11711abe55efSEd Tanous { 11729391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 11734a0cb85cSEd Tanous for (const auto& interface : objpath.second) 11741abe55efSEd Tanous { 11751abe55efSEd Tanous // If interface is 11764a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 11774a0cb85cSEd Tanous // what we're looking for. 11789391bb9cSRapkiewicz, Pawel if (interface.first == 11791abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 11801abe55efSEd Tanous { 11812dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 11822dfd18efSEd Tanous if (ifaceId.empty()) 11831abe55efSEd Tanous { 11842dfd18efSEd Tanous continue; 11859391bb9cSRapkiewicz, Pawel } 11862dfd18efSEd Tanous // and put it into output vector. 118777179532SEd Tanous ifaceList.emplace_back(ifaceId); 11889391bb9cSRapkiewicz, Pawel } 11899391bb9cSRapkiewicz, Pawel } 11909391bb9cSRapkiewicz, Pawel } 11912c5875a2SEd Tanous 11923544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 11932c5875a2SEd Tanous 1194a434f2bdSEd Tanous // Finally make a callback with useful data 11952c70f800SEd Tanous callback(true, ifaceList); 1196f5892d0dSGeorge Liu }); 1197271584abSEd Tanous } 11989391bb9cSRapkiewicz, Pawel 11994f48d5f6SEd Tanous inline void 12004f48d5f6SEd Tanous handleHostnamePatch(const std::string& hostname, 12018d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12021abe55efSEd Tanous { 1203ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 1204ab6554f1SJoshi-Mansi if (hostname.length() > 255) 1205ab6554f1SJoshi-Mansi { 1206ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 1207ab6554f1SJoshi-Mansi "HostName"); 1208ab6554f1SJoshi-Mansi return; 1209ab6554f1SJoshi-Mansi } 1210d02aad39SEd Tanous setDbusProperty( 1211e93abac6SGinu George asyncResp, "HostName", "xyz.openbmc_project.Network", 1212d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network/config"), 1213d02aad39SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1214e93abac6SGinu George hostname); 1215588c3f0dSKowalski, Kamil } 1216588c3f0dSKowalski, Kamil 12174f48d5f6SEd Tanous inline void 121835fb5311STejas Patil handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize, 121935fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 122035fb5311STejas Patil { 1221d02aad39SEd Tanous sdbusplus::message::object_path objPath("/xyz/openbmc_project/network"); 1222d02aad39SEd Tanous objPath /= ifaceId; 1223e93abac6SGinu George setDbusProperty(asyncResp, "MTUSize", "xyz.openbmc_project.Network", 1224e93abac6SGinu George objPath, "xyz.openbmc_project.Network.EthernetInterface", 1225e93abac6SGinu George "MTU", mtuSize); 122635fb5311STejas Patil } 122735fb5311STejas Patil 1228bd79bce8SPatrick Williams inline void handleDomainnamePatch( 1229bd79bce8SPatrick Williams const std::string& ifaceId, const std::string& domainname, 12308d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1231ab6554f1SJoshi-Mansi { 1232ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 1233d02aad39SEd Tanous setDbusProperty( 1234e93abac6SGinu George asyncResp, "FQDN", "xyz.openbmc_project.Network", 1235d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1236d02aad39SEd Tanous ifaceId, 1237e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 1238d02aad39SEd Tanous vectorDomainname); 1239ab6554f1SJoshi-Mansi } 1240ab6554f1SJoshi-Mansi 12414f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1242bf648f77SEd Tanous { 1243bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 12443544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1245bf648f77SEd Tanous { 1246bf648f77SEd Tanous return false; 1247bf648f77SEd Tanous } 1248bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1249bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1250bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1251bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 12524b242749SEd Tanous const static std::regex pattern( 1253bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1254bf648f77SEd Tanous 1255bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1256bf648f77SEd Tanous } 1257bf648f77SEd Tanous 12584f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1259bf648f77SEd Tanous { 1260bf648f77SEd Tanous // Can have multiple subdomains 1261bf648f77SEd Tanous // Top Level Domain's min length is 2 character 12624b242749SEd Tanous const static std::regex pattern( 12630fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1264bf648f77SEd Tanous 1265bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1266bf648f77SEd Tanous } 1267bf648f77SEd Tanous 12684f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 12698d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1270ab6554f1SJoshi-Mansi { 1271ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1272ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1273ab6554f1SJoshi-Mansi { 1274ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1275ab6554f1SJoshi-Mansi return; 1276ab6554f1SJoshi-Mansi } 1277ab6554f1SJoshi-Mansi 1278ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1279ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1280ab6554f1SJoshi-Mansi { 1281ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1282ab6554f1SJoshi-Mansi return; 1283ab6554f1SJoshi-Mansi } 1284ab6554f1SJoshi-Mansi 1285ab6554f1SJoshi-Mansi std::string hostname; 1286ab6554f1SJoshi-Mansi std::string domainname; 1287ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1288ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1289ab6554f1SJoshi-Mansi 1290ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1291ab6554f1SJoshi-Mansi { 1292ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1293ab6554f1SJoshi-Mansi return; 1294ab6554f1SJoshi-Mansi } 1295ab6554f1SJoshi-Mansi 1296ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1297ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1298ab6554f1SJoshi-Mansi } 1299ab6554f1SJoshi-Mansi 1300bd79bce8SPatrick Williams inline void handleMACAddressPatch( 1301bd79bce8SPatrick Williams const std::string& ifaceId, const std::string& macAddress, 13028d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1303d577665bSRatan Gupta { 1304d02aad39SEd Tanous setDbusProperty( 1305e93abac6SGinu George asyncResp, "MACAddress", "xyz.openbmc_project.Network", 1306d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1307d02aad39SEd Tanous ifaceId, 1308e93abac6SGinu George "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress); 1309d577665bSRatan Gupta } 1310286b9118SJohnathan Mantey 13114f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 13124f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 13134f48d5f6SEd Tanous const bool v6Value, 13148d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1315da131a9aSJennifer Lee { 13162c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 1317d02aad39SEd Tanous setDbusProperty( 1318e93abac6SGinu George asyncResp, "DHCPv4", "xyz.openbmc_project.Network", 1319d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1320d02aad39SEd Tanous ifaceId, 1321e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp); 1322eeedda23SJohnathan Mantey } 1323eeedda23SJohnathan Mantey 1324e4588158SJishnu CM enum class NetworkType 1325e4588158SJishnu CM { 1326e4588158SJishnu CM dhcp4, 1327e4588158SJishnu CM dhcp6 1328e4588158SJishnu CM }; 1329e4588158SJishnu CM 1330e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1331e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1332e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1333da131a9aSJennifer Lee { 133462598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 13351847f2a0SAsmitha Karunanithi std::string redfishPropertyName; 1336e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1337e4588158SJishnu CM path /= ethifaceId; 1338e4588158SJishnu CM 1339e4588158SJishnu CM if (type == NetworkType::dhcp4) 1340e4588158SJishnu CM { 1341e4588158SJishnu CM path /= "dhcp4"; 13421847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv4"; 1343e4588158SJishnu CM } 1344e4588158SJishnu CM else 1345e4588158SJishnu CM { 1346e4588158SJishnu CM path /= "dhcp6"; 13471847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv6"; 1348e4588158SJishnu CM } 1349e4588158SJishnu CM 1350e93abac6SGinu George setDbusProperty( 1351e93abac6SGinu George asyncResp, redfishPropertyName, "xyz.openbmc_project.Network", path, 1352e93abac6SGinu George "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value); 1353da131a9aSJennifer Lee } 1354d577665bSRatan Gupta 1355b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1356b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1357b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1358b10d8db0SRavi Teja { 1359b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1360b10d8db0SRavi Teja path /= ifaceId; 1361e93abac6SGinu George setDbusProperty(asyncResp, 13621847f2a0SAsmitha Karunanithi "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 1363e93abac6SGinu George "xyz.openbmc_project.Network", path, 1364e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", 1365e93abac6SGinu George "IPv6AcceptRA", ipv6AutoConfigEnabled); 1366b10d8db0SRavi Teja } 1367b10d8db0SRavi Teja 1368bd79bce8SPatrick Williams inline void handleDHCPPatch( 1369bd79bce8SPatrick Williams const std::string& ifaceId, const EthernetInterfaceData& ethData, 1370bd79bce8SPatrick Williams const DHCPParameters& v4dhcpParms, const DHCPParameters& v6dhcpParms, 13718d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1372da131a9aSJennifer Lee { 137382695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 137482695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1375da131a9aSJennifer Lee 1376743eb1c0SJohnathan Mantey if (ipv4Active) 1377743eb1c0SJohnathan Mantey { 1378743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1379743eb1c0SJohnathan Mantey } 13801f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 13811f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 13821f8c7b5dSJohnathan Mantey 13831f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 13841f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1385da131a9aSJennifer Lee { 1386b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 13871f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 13881f8c7b5dSJohnathan Mantey { 1389bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1390bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 13911f8c7b5dSJohnathan Mantey "OperatingMode"); 1392da131a9aSJennifer Lee return; 1393da131a9aSJennifer Lee } 1394b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 13951f8c7b5dSJohnathan Mantey } 13961f8c7b5dSJohnathan Mantey else 1397da131a9aSJennifer Lee { 13981f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 13991f8c7b5dSJohnathan Mantey } 14001f8c7b5dSJohnathan Mantey 1401e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1402e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1403e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 14041f8c7b5dSJohnathan Mantey { 1405e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 14061f8c7b5dSJohnathan Mantey } 1407e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 14081f8c7b5dSJohnathan Mantey { 1409e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 14101f8c7b5dSJohnathan Mantey } 14111f8c7b5dSJohnathan Mantey 1412e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1413e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1414e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 14151f8c7b5dSJohnathan Mantey { 1416e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 14171f8c7b5dSJohnathan Mantey } 1418e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 14191f8c7b5dSJohnathan Mantey { 1420e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 14211f8c7b5dSJohnathan Mantey } 14221f8c7b5dSJohnathan Mantey 142391c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 142491c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1425e4588158SJishnu CM if (v4dhcpParms.useDomainName) 14261f8c7b5dSJohnathan Mantey { 1427e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 14281f8c7b5dSJohnathan Mantey } 1429e4588158SJishnu CM if (v6dhcpParms.useDomainName) 14301f8c7b5dSJohnathan Mantey { 1431e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 14321f8c7b5dSJohnathan Mantey } 14331f8c7b5dSJohnathan Mantey 143462598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 14351f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 14361f8c7b5dSJohnathan Mantey asyncResp); 143762598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1438e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1439e4588158SJishnu CM NetworkType::dhcp4); 144062598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1441e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1442e4588158SJishnu CM NetworkType::dhcp4); 144391c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 144491c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1445e4588158SJishnu CM NetworkType::dhcp4); 1446e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1447e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1448e4588158SJishnu CM NetworkType::dhcp6); 1449e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1450e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1451e4588158SJishnu CM NetworkType::dhcp6); 145291c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 145391c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1454e4588158SJishnu CM NetworkType::dhcp6); 1455da131a9aSJennifer Lee } 145601784826SJohnathan Mantey 145777179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 145877179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 145977179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 146001784826SJohnathan Mantey { 146117a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 146217a897dfSManojkiran Eda return value.origin == "Static"; 146317a897dfSManojkiran Eda }); 146401784826SJohnathan Mantey } 146501784826SJohnathan Mantey 146677179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 146777179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 146877179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 146901784826SJohnathan Mantey { 147017a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 147117a897dfSManojkiran Eda return value.origin == "Static"; 147217a897dfSManojkiran Eda }); 147301784826SJohnathan Mantey } 147401784826SJohnathan Mantey 14756e1a52faSEd Tanous enum class AddrChange 14761abe55efSEd Tanous { 14776e1a52faSEd Tanous Noop, 14786e1a52faSEd Tanous Delete, 14796e1a52faSEd Tanous Update, 14806e1a52faSEd Tanous }; 14816e1a52faSEd Tanous 14826e1a52faSEd Tanous // Struct representing a dbus change 14836e1a52faSEd Tanous struct AddressPatch 14846e1a52faSEd Tanous { 14856e1a52faSEd Tanous std::string address; 14866e1a52faSEd Tanous std::string gateway; 14876e1a52faSEd Tanous uint8_t prefixLength = 0; 14886e1a52faSEd Tanous std::string existingDbusId; 14896e1a52faSEd Tanous AddrChange operation = AddrChange::Noop; 14906e1a52faSEd Tanous }; 14916e1a52faSEd Tanous 14926e1a52faSEd Tanous inline bool parseAddresses( 14936e1a52faSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 14946e1a52faSEd Tanous const std::vector<IPv4AddressData>& ipv4Data, crow::Response& res, 14956e1a52faSEd Tanous std::vector<AddressPatch>& addressesOut, std::string& gatewayOut) 14966e1a52faSEd Tanous { 149777179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 14982c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 149901784826SJohnathan Mantey 15006e1a52faSEd Tanous std::string lastGatewayPath; 15016e1a52faSEd Tanous size_t entryIdx = 0; 15023dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 15033dfed536SEd Tanous input) 15041abe55efSEd Tanous { 1505bd79bce8SPatrick Williams std::string pathString = 15066e1a52faSEd Tanous std::format("IPv4StaticAddresses/{}", entryIdx); 15076e1a52faSEd Tanous AddressPatch& thisAddress = addressesOut.emplace_back(); 15083dfed536SEd Tanous nlohmann::json::object_t* obj = 15093dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 1510743eb1c0SJohnathan Mantey if (nicIpEntry != ipv4Data.cend()) 1511743eb1c0SJohnathan Mantey { 15126e1a52faSEd Tanous thisAddress.existingDbusId = nicIpEntry->id; 1513743eb1c0SJohnathan Mantey } 1514743eb1c0SJohnathan Mantey 15156e1a52faSEd Tanous if (obj == nullptr) 15166e1a52faSEd Tanous { 15176e1a52faSEd Tanous if (thisAddress.existingDbusId.empty()) 15186e1a52faSEd Tanous { 15196e1a52faSEd Tanous // Received a DELETE action on an entry not assigned to the NIC 15206e1a52faSEd Tanous messages::resourceCannotBeDeleted(res); 15216e1a52faSEd Tanous return false; 15226e1a52faSEd Tanous } 15236e1a52faSEd Tanous thisAddress.operation = AddrChange::Delete; 15246e1a52faSEd Tanous } 15256e1a52faSEd Tanous else 1526f476acbfSRatan Gupta { 1527537174c4SEd Tanous std::optional<std::string> address; 1528537174c4SEd Tanous std::optional<std::string> gateway; 15296e1a52faSEd Tanous std::optional<std::string> subnetMask; 15306e1a52faSEd Tanous if (!obj->empty()) 15316e1a52faSEd Tanous { 1532afc474aeSMyung Bae if (!json_util::readJsonObject( // 15336e1a52faSEd Tanous *obj, res, // 1534afc474aeSMyung Bae "Address", address, // 1535afc474aeSMyung Bae "Gateway", gateway, // 1536afc474aeSMyung Bae "SubnetMask", subnetMask // 1537afc474aeSMyung Bae )) 1538537174c4SEd Tanous { 15396e1a52faSEd Tanous messages::propertyValueFormatError(res, *obj, pathString); 15406e1a52faSEd Tanous return false; 1541179db1d7SKowalski, Kamil } 15426e1a52faSEd Tanous } 154301784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 154401784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 154501784826SJohnathan Mantey // current state of the interface. Merge existing state into the 154601784826SJohnathan Mantey // current request. 1547537174c4SEd Tanous if (address) 15481abe55efSEd Tanous { 1549e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 155001784826SJohnathan Mantey { 15516e1a52faSEd Tanous messages::propertyValueFormatError(res, *address, 1552bf648f77SEd Tanous pathString + "/Address"); 15536e1a52faSEd Tanous return false; 155401784826SJohnathan Mantey } 15556e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 15566e1a52faSEd Tanous thisAddress.address = *address; 155701784826SJohnathan Mantey } 15586e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 155901784826SJohnathan Mantey { 15606e1a52faSEd Tanous messages::propertyMissing(res, pathString + "/Address"); 15616e1a52faSEd Tanous return false; 156201784826SJohnathan Mantey } 156301784826SJohnathan Mantey else 156401784826SJohnathan Mantey { 15656e1a52faSEd Tanous thisAddress.address = nicIpEntry->address; 15664a0cb85cSEd Tanous } 15674a0cb85cSEd Tanous 1568537174c4SEd Tanous if (subnetMask) 15694a0cb85cSEd Tanous { 15706e1a52faSEd Tanous uint8_t prefixLength = 0; 1571033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1572033f1e4dSEd Tanous &prefixLength)) 15734a0cb85cSEd Tanous { 1574f12894f8SJason M. Bills messages::propertyValueFormatError( 15756e1a52faSEd Tanous res, *subnetMask, pathString + "/SubnetMask"); 15766e1a52faSEd Tanous return false; 15774a0cb85cSEd Tanous } 15786e1a52faSEd Tanous thisAddress.prefixLength = prefixLength; 15796e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 15804a0cb85cSEd Tanous } 15816e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 15824a0cb85cSEd Tanous { 15836e1a52faSEd Tanous messages::propertyMissing(res, pathString + "/SubnetMask"); 15846e1a52faSEd Tanous return false; 15854a0cb85cSEd Tanous } 15861abe55efSEd Tanous else 15871abe55efSEd Tanous { 15886e1a52faSEd Tanous uint8_t prefixLength = 0; 15896e1a52faSEd Tanous // Ignore return code. It came from internal, it's it's invalid 15906e1a52faSEd Tanous // nothing we can do 15916e1a52faSEd Tanous ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 15926e1a52faSEd Tanous &prefixLength); 159301784826SJohnathan Mantey 15946e1a52faSEd Tanous thisAddress.prefixLength = prefixLength; 15956e1a52faSEd Tanous } 159601784826SJohnathan Mantey if (gateway) 159701784826SJohnathan Mantey { 1598e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 159901784826SJohnathan Mantey { 16006e1a52faSEd Tanous messages::propertyValueFormatError(res, *gateway, 1601bf648f77SEd Tanous pathString + "/Gateway"); 16026e1a52faSEd Tanous return false; 160301784826SJohnathan Mantey } 16046e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 16056e1a52faSEd Tanous thisAddress.gateway = *gateway; 160601784826SJohnathan Mantey } 16076e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 160801784826SJohnathan Mantey { 16096e1a52faSEd Tanous // Default to null gateway 16106e1a52faSEd Tanous gateway = ""; 161101784826SJohnathan Mantey } 161201784826SJohnathan Mantey else 16131abe55efSEd Tanous { 16146e1a52faSEd Tanous thisAddress.gateway = nicIpEntry->gateway; 16154a0cb85cSEd Tanous } 16164a0cb85cSEd Tanous 16176e1a52faSEd Tanous // Changing gateway from existing 16186e1a52faSEd Tanous if (!thisAddress.gateway.empty() && 16196e1a52faSEd Tanous thisAddress.gateway != "0.0.0.0") 1620743eb1c0SJohnathan Mantey { 16216e1a52faSEd Tanous if (!gatewayOut.empty() && gatewayOut != thisAddress.gateway) 1622743eb1c0SJohnathan Mantey { 1623743eb1c0SJohnathan Mantey // A NIC can only have a single active gateway value. 1624743eb1c0SJohnathan Mantey // If any gateway in the array of static addresses 1625743eb1c0SJohnathan Mantey // mismatch the PATCH is in error. 1626743eb1c0SJohnathan Mantey std::string arg1 = pathString + "/Gateway"; 16276e1a52faSEd Tanous std::string arg2 = lastGatewayPath + "/Gateway"; 16286e1a52faSEd Tanous messages::propertyValueConflict(res, arg1, arg2); 16296e1a52faSEd Tanous return false; 16306e1a52faSEd Tanous } 16316e1a52faSEd Tanous gatewayOut = thisAddress.gateway; 16326e1a52faSEd Tanous lastGatewayPath = pathString; 1633743eb1c0SJohnathan Mantey } 1634743eb1c0SJohnathan Mantey } 16356e1a52faSEd Tanous nicIpEntry++; 16366e1a52faSEd Tanous nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend()); 16376e1a52faSEd Tanous entryIdx++; 1638743eb1c0SJohnathan Mantey } 1639743eb1c0SJohnathan Mantey 16406e1a52faSEd Tanous // Delete the remaining IPs 16416e1a52faSEd Tanous while (nicIpEntry != ipv4Data.cend()) 16421abe55efSEd Tanous { 16436e1a52faSEd Tanous AddressPatch& thisAddress = addressesOut.emplace_back(); 16446e1a52faSEd Tanous thisAddress.operation = AddrChange::Delete; 16456e1a52faSEd Tanous thisAddress.existingDbusId = nicIpEntry->id; 16466e1a52faSEd Tanous nicIpEntry++; 16476e1a52faSEd Tanous nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend()); 1648588c3f0dSKowalski, Kamil } 16496e1a52faSEd Tanous 16506e1a52faSEd Tanous return true; 16514a0cb85cSEd Tanous } 16526e1a52faSEd Tanous 16536e1a52faSEd Tanous inline void handleIPv4StaticPatch( 16546e1a52faSEd Tanous const std::string& ifaceId, 16556e1a52faSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 16566e1a52faSEd Tanous const EthernetInterfaceData& ethData, 16576e1a52faSEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 16586e1a52faSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 165901784826SJohnathan Mantey { 16606e1a52faSEd Tanous std::vector<AddressPatch> addresses; 16616e1a52faSEd Tanous std::string gatewayOut; 16626e1a52faSEd Tanous if (!parseAddresses(input, ipv4Data, asyncResp->res, addresses, gatewayOut)) 166301784826SJohnathan Mantey { 1664743eb1c0SJohnathan Mantey return; 1665743eb1c0SJohnathan Mantey } 16666e1a52faSEd Tanous 16676e1a52faSEd Tanous // If we're setting the gateway to something new, delete the 16686e1a52faSEd Tanous // existing so we won't conflict 16696e1a52faSEd Tanous if (!ethData.defaultGateway.empty() && ethData.defaultGateway != gatewayOut) 16706e1a52faSEd Tanous { 16716e1a52faSEd Tanous updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1672743eb1c0SJohnathan Mantey } 16736e1a52faSEd Tanous 16746e1a52faSEd Tanous for (const AddressPatch& address : addresses) 16756e1a52faSEd Tanous { 16766e1a52faSEd Tanous switch (address.operation) 16776e1a52faSEd Tanous { 16786e1a52faSEd Tanous case AddrChange::Delete: 16796e1a52faSEd Tanous { 16806e1a52faSEd Tanous BMCWEB_LOG_ERROR("Deleting id {} on interface {}", 16816e1a52faSEd Tanous address.existingDbusId, ifaceId); 16826e1a52faSEd Tanous deleteIPAddress(ifaceId, address.existingDbusId, asyncResp); 16836e1a52faSEd Tanous } 16846e1a52faSEd Tanous break; 16856e1a52faSEd Tanous case AddrChange::Update: 16866e1a52faSEd Tanous { 16876e1a52faSEd Tanous // Update is a delete then a recreate 16886e1a52faSEd Tanous // Only need to update if there is an existing ip at this index 16896e1a52faSEd Tanous if (!address.existingDbusId.empty()) 16906e1a52faSEd Tanous { 16916e1a52faSEd Tanous BMCWEB_LOG_ERROR("Deleting id {} on interface {}", 16926e1a52faSEd Tanous address.existingDbusId, ifaceId); 16936e1a52faSEd Tanous deleteAndCreateIPAddress( 16946e1a52faSEd Tanous IpVersion::IpV4, ifaceId, address.existingDbusId, 16956e1a52faSEd Tanous address.prefixLength, address.address, address.gateway, 16966e1a52faSEd Tanous asyncResp); 16976e1a52faSEd Tanous } 16986e1a52faSEd Tanous else 16996e1a52faSEd Tanous { 17006e1a52faSEd Tanous // Otherwise, just create a new one 17016e1a52faSEd Tanous BMCWEB_LOG_ERROR( 17026e1a52faSEd Tanous "creating ip {} prefix {} gateway {} on interface {}", 17036e1a52faSEd Tanous address.address, address.prefixLength, address.gateway, 17046e1a52faSEd Tanous ifaceId); 17056e1a52faSEd Tanous createIPv4(ifaceId, address.prefixLength, address.gateway, 17066e1a52faSEd Tanous address.address, asyncResp); 17076e1a52faSEd Tanous } 17086e1a52faSEd Tanous } 17096e1a52faSEd Tanous break; 17106e1a52faSEd Tanous default: 17116e1a52faSEd Tanous { 17126e1a52faSEd Tanous // Leave alone 17136e1a52faSEd Tanous } 17146e1a52faSEd Tanous break; 17156e1a52faSEd Tanous } 17166e1a52faSEd Tanous } 17176e1a52faSEd Tanous 17186e1a52faSEd Tanous // now update to the new gateway. 17196e1a52faSEd Tanous // Default gateway is already empty, so no need to update if we're clearing 17206e1a52faSEd Tanous if (!gatewayOut.empty() && ethData.defaultGateway != gatewayOut) 17216e1a52faSEd Tanous { 17226e1a52faSEd Tanous updateIPv4DefaultGateway(ifaceId, gatewayOut, asyncResp); 172301784826SJohnathan Mantey } 17244a0cb85cSEd Tanous } 17254a0cb85cSEd Tanous 17264f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1727f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1728f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 17298d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1730f85837bfSRAJESWARAN THILLAIGOVINDAN { 17311847f2a0SAsmitha Karunanithi setDbusProperty( 1732e93abac6SGinu George asyncResp, "StaticNameServers", "xyz.openbmc_project.Network", 17331847f2a0SAsmitha Karunanithi sdbusplus::message::object_path("/xyz/openbmc_project/network") / 17341847f2a0SAsmitha Karunanithi ifaceId, 17359ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 1736e93abac6SGinu George updatedStaticNameServers); 1737f85837bfSRAJESWARAN THILLAIGOVINDAN } 1738f85837bfSRAJESWARAN THILLAIGOVINDAN 17394f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 17403dfed536SEd Tanous const std::string& ifaceId, 17413dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 174277179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 17438d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1744e48c0fc5SRavi Teja { 1745271584abSEd Tanous size_t entryIdx = 1; 174677179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 17472c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 17483dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 17493dfed536SEd Tanous input) 1750e48c0fc5SRavi Teja { 1751bd79bce8SPatrick Williams std::string pathString = 1752bd79bce8SPatrick Williams "IPv6StaticAddresses/" + std::to_string(entryIdx); 17533dfed536SEd Tanous nlohmann::json::object_t* obj = 17543dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 17553dfed536SEd Tanous if (obj != nullptr && !obj->empty()) 1756e48c0fc5SRavi Teja { 1757e48c0fc5SRavi Teja std::optional<std::string> address; 1758e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 17593dfed536SEd Tanous nlohmann::json::object_t thisJsonCopy = *obj; 1760afc474aeSMyung Bae if (!json_util::readJsonObject( // 1761afc474aeSMyung Bae thisJsonCopy, asyncResp->res, // 1762afc474aeSMyung Bae "Address", address, // 1763afc474aeSMyung Bae "PrefixLength", prefixLength // 1764afc474aeSMyung Bae )) 1765e48c0fc5SRavi Teja { 17663dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJsonCopy, 176771f52d96SEd Tanous pathString); 1768e48c0fc5SRavi Teja return; 1769e48c0fc5SRavi Teja } 1770e48c0fc5SRavi Teja 177101784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 177201784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 177301784826SJohnathan Mantey // current state of the interface. Merge existing state into the 177401784826SJohnathan Mantey // current request. 1775d547d8d2SEd Tanous if (!address) 1776e48c0fc5SRavi Teja { 1777d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 177801784826SJohnathan Mantey { 177901784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 178001784826SJohnathan Mantey pathString + "/Address"); 178101784826SJohnathan Mantey return; 1782e48c0fc5SRavi Teja } 1783d547d8d2SEd Tanous address = nicIpEntry->address; 1784d547d8d2SEd Tanous } 1785e48c0fc5SRavi Teja 1786d547d8d2SEd Tanous if (!prefixLength) 1787e48c0fc5SRavi Teja { 1788d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 1789e48c0fc5SRavi Teja { 1790e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1791e48c0fc5SRavi Teja pathString + "/PrefixLength"); 179201784826SJohnathan Mantey return; 1793e48c0fc5SRavi Teja } 1794d547d8d2SEd Tanous prefixLength = nicIpEntry->prefixLength; 1795d547d8d2SEd Tanous } 1796e48c0fc5SRavi Teja 179785ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1798e48c0fc5SRavi Teja { 17999c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 1800d547d8d2SEd Tanous nicIpEntry->id, *prefixLength, 1801d547d8d2SEd Tanous *address, "", asyncResp); 1802bd79bce8SPatrick Williams nicIpEntry = 1803bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend()); 180401784826SJohnathan Mantey } 180501784826SJohnathan Mantey else 180601784826SJohnathan Mantey { 1807d547d8d2SEd Tanous createIPv6(ifaceId, *prefixLength, *address, asyncResp); 1808e48c0fc5SRavi Teja } 1809e48c0fc5SRavi Teja entryIdx++; 1810e48c0fc5SRavi Teja } 181101784826SJohnathan Mantey else 181201784826SJohnathan Mantey { 181385ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 181401784826SJohnathan Mantey { 181501784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 181601784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 181701784826SJohnathan Mantey // in error, so bail out. 18183dfed536SEd Tanous if (obj == nullptr) 181901784826SJohnathan Mantey { 182001784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 182101784826SJohnathan Mantey return; 182201784826SJohnathan Mantey } 18233dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 182471f52d96SEd Tanous pathString); 182501784826SJohnathan Mantey return; 182601784826SJohnathan Mantey } 182701784826SJohnathan Mantey 18283dfed536SEd Tanous if (obj == nullptr) 182901784826SJohnathan Mantey { 18309c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 183101784826SJohnathan Mantey } 183285ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 183301784826SJohnathan Mantey { 1834bd79bce8SPatrick Williams nicIpEntry = 1835bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend()); 183601784826SJohnathan Mantey } 183701784826SJohnathan Mantey entryIdx++; 183801784826SJohnathan Mantey } 183901784826SJohnathan Mantey } 1840e48c0fc5SRavi Teja } 1841e48c0fc5SRavi Teja 18427857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 18437857cb8dSJiaqing Zhao { 18447857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 18457857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 18467857cb8dSJiaqing Zhao } 18477857cb8dSJiaqing Zhao 1848bd79bce8SPatrick Williams inline void parseInterfaceData( 1849bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1850bd79bce8SPatrick Williams const std::string& ifaceId, const EthernetInterfaceData& ethData, 185177179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1852ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 1853ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) 18544a0cb85cSEd Tanous { 18552c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 185681ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1857253f11b8SEd Tanous jsonResponse["@odata.id"] = 1858253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 1859253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId); 18602c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1861eeedda23SJohnathan Mantey 1862eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1863eeedda23SJohnathan Mantey { 1864539d8c6bSEd Tanous jsonResponse["LinkStatus"] = 1865539d8c6bSEd Tanous ethData.linkUp ? ethernet_interface::LinkStatus::LinkUp 1866539d8c6bSEd Tanous : ethernet_interface::LinkStatus::LinkDown; 1867539d8c6bSEd Tanous jsonResponse["Status"]["State"] = resource::State::Enabled; 1868029573d4SEd Tanous } 1869029573d4SEd Tanous else 1870029573d4SEd Tanous { 1871539d8c6bSEd Tanous jsonResponse["LinkStatus"] = ethernet_interface::LinkStatus::NoLink; 1872539d8c6bSEd Tanous jsonResponse["Status"]["State"] = resource::State::Disabled; 1873029573d4SEd Tanous } 1874aa05fb27SJohnathan Mantey 18752c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 187635fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 18774652c640SAsmitha Karunanithi if (ethData.macAddress) 18784652c640SAsmitha Karunanithi { 18794652c640SAsmitha Karunanithi jsonResponse["MACAddress"] = *ethData.macAddress; 18804652c640SAsmitha Karunanithi } 18812c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 188282695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1883e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1884e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1885de9ad764SRavi Teja jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled; 18862c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1887bd79bce8SPatrick Williams translateDhcpEnabledToBool(ethData.dhcpEnabled, false) 1888bd79bce8SPatrick Williams ? "Enabled" 18891f8c7b5dSJohnathan Mantey : "Disabled"; 1890e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1891e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1892de9ad764SRavi Teja jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled; 1893b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1894b10d8db0SRavi Teja ethData.ipv6AcceptRa; 18952a133282Smanojkiraneda 189682695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 18974a0cb85cSEd Tanous { 189882695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1899ab6554f1SJoshi-Mansi 1900ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1901ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1902ab6554f1SJoshi-Mansi // FQDN 190382695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1904d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1905d24bfc7aSJennifer Lee { 19062c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1907d24bfc7aSJennifer Lee } 19082c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 19094a0cb85cSEd Tanous } 19104a0cb85cSEd Tanous 19117857cb8dSJiaqing Zhao if (ethData.vlanId) 19127857cb8dSJiaqing Zhao { 1913539d8c6bSEd Tanous jsonResponse["EthernetInterfaceType"] = 1914539d8c6bSEd Tanous ethernet_interface::EthernetDeviceType::Virtual; 19157857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 19167857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 19177857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 19187857cb8dSJiaqing Zhao 19197857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 19207857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 19217857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 1922253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces", 1923253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, 19247857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 19257857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 19267857cb8dSJiaqing Zhao std::move(relatedInterfaces); 19277857cb8dSJiaqing Zhao } 19287857cb8dSJiaqing Zhao else 19297857cb8dSJiaqing Zhao { 1930539d8c6bSEd Tanous jsonResponse["EthernetInterfaceType"] = 1931539d8c6bSEd Tanous ethernet_interface::EthernetDeviceType::Physical; 19327857cb8dSJiaqing Zhao } 19337857cb8dSJiaqing Zhao 19342c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 19352c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 19364a0cb85cSEd Tanous 19372c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 19382c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 19392c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 19402c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 19419eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 19424a0cb85cSEd Tanous { 19432c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1944fa5053a6SGunnar Mills if (gatewayStr.empty()) 1945fa5053a6SGunnar Mills { 1946fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1947fa5053a6SGunnar Mills } 19481476687dSEd Tanous nlohmann::json::object_t ipv4; 19491476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 19501476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 19511476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 19521476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1953fa5053a6SGunnar Mills 19542c70f800SEd Tanous if (ipv4Config.origin == "Static") 1955d1d50814SRavi Teja { 19561476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1957d1d50814SRavi Teja } 19581476687dSEd Tanous 1959b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 196001784826SJohnathan Mantey } 1961d1d50814SRavi Teja 196282695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 19637ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 19647ea79e5eSRavi Teja { 19657ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 19667ea79e5eSRavi Teja } 19677ea79e5eSRavi Teja 19687ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 1969e48c0fc5SRavi Teja 1970ce73d5c8SSunitha Harish nlohmann::json::array_t ipv6StaticGatewayArray; 1971ce73d5c8SSunitha Harish for (const auto& ipv6GatewayConfig : ipv6GatewayData) 1972ce73d5c8SSunitha Harish { 1973ce73d5c8SSunitha Harish nlohmann::json::object_t ipv6Gateway; 1974ce73d5c8SSunitha Harish ipv6Gateway["Address"] = ipv6GatewayConfig.gateway; 1975ce73d5c8SSunitha Harish ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway)); 1976ce73d5c8SSunitha Harish } 1977ce73d5c8SSunitha Harish jsonResponse["IPv6StaticDefaultGateways"] = 1978ce73d5c8SSunitha Harish std::move(ipv6StaticGatewayArray); 1979ce73d5c8SSunitha Harish 19802c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 19812c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 19822c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 19832c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 19847f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 19852c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 19867f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 19879eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 1988e48c0fc5SRavi Teja { 19891476687dSEd Tanous nlohmann::json::object_t ipv6; 19901476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 19911476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 19921476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 1993f8361275SSunitha Harish 1994b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 19952c70f800SEd Tanous if (ipv6Config.origin == "Static") 1996e48c0fc5SRavi Teja { 19971476687dSEd Tanous nlohmann::json::object_t ipv6Static; 19981476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 19991476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 2000b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 200101784826SJohnathan Mantey } 2002e48c0fc5SRavi Teja } 2003588c3f0dSKowalski, Kamil } 2004588c3f0dSKowalski, Kamil 2005e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2006e7caf250SJiaqing Zhao const std::string& ifaceId, 2007e7caf250SJiaqing Zhao const boost::system::error_code& ec, 2008e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 2009e7caf250SJiaqing Zhao { 2010e7caf250SJiaqing Zhao if (!ec) 2011e7caf250SJiaqing Zhao { 2012e7caf250SJiaqing Zhao return; 2013e7caf250SJiaqing Zhao } 2014e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2015e7caf250SJiaqing Zhao if (dbusError == nullptr) 2016e7caf250SJiaqing Zhao { 2017e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2018e7caf250SJiaqing Zhao return; 2019e7caf250SJiaqing Zhao } 202062598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2021e7caf250SJiaqing Zhao 2022e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 2023e7caf250SJiaqing Zhao dbusError->name) 2024e7caf250SJiaqing Zhao { 2025e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2026e7caf250SJiaqing Zhao ifaceId); 2027e7caf250SJiaqing Zhao return; 2028e7caf250SJiaqing Zhao } 2029e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 2030e7caf250SJiaqing Zhao dbusError->name) 2031e7caf250SJiaqing Zhao { 2032e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 2033e7caf250SJiaqing Zhao return; 2034e7caf250SJiaqing Zhao } 2035e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2036e7caf250SJiaqing Zhao } 2037e7caf250SJiaqing Zhao 2038bd79bce8SPatrick Williams inline void afterVlanCreate( 2039bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2040bd79bce8SPatrick Williams const std::string& parentInterfaceUri, const std::string& vlanInterface, 2041bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& m 2042b5ca3fdcSJiaqing Zhao 2043b5ca3fdcSJiaqing Zhao ) 2044b5ca3fdcSJiaqing Zhao { 2045b5ca3fdcSJiaqing Zhao if (ec) 2046b5ca3fdcSJiaqing Zhao { 2047b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2048b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 2049b5ca3fdcSJiaqing Zhao { 2050b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2051b5ca3fdcSJiaqing Zhao return; 2052b5ca3fdcSJiaqing Zhao } 205362598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2054b5ca3fdcSJiaqing Zhao 2055b5ca3fdcSJiaqing Zhao if (std::string_view( 2056b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 2057b5ca3fdcSJiaqing Zhao dbusError->name) 2058b5ca3fdcSJiaqing Zhao { 2059b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2060b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2061b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2062b5ca3fdcSJiaqing Zhao return; 2063b5ca3fdcSJiaqing Zhao } 2064b5ca3fdcSJiaqing Zhao if (std::string_view( 2065b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 2066b5ca3fdcSJiaqing Zhao dbusError->name) 2067b5ca3fdcSJiaqing Zhao { 2068b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 2069b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 2070b5ca3fdcSJiaqing Zhao return; 2071b5ca3fdcSJiaqing Zhao } 2072b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2073b5ca3fdcSJiaqing Zhao return; 2074b5ca3fdcSJiaqing Zhao } 2075b5ca3fdcSJiaqing Zhao 2076253f11b8SEd Tanous const boost::urls::url vlanInterfaceUri = 2077253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2078253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface); 2079b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 2080b5ca3fdcSJiaqing Zhao } 2081b5ca3fdcSJiaqing Zhao 2082bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 2083bf648f77SEd Tanous { 2084253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2085ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 20861476687dSEd Tanous .methods(boost::beast::http::verb::get)( 20871476687dSEd Tanous [&app](const crow::Request& req, 2088253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2089253f11b8SEd Tanous const std::string& managerId) { 20903ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 209145ca1b86SEd Tanous { 209245ca1b86SEd Tanous return; 209345ca1b86SEd Tanous } 209445ca1b86SEd Tanous 2095253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2096253f11b8SEd Tanous { 2097bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2098bd79bce8SPatrick Williams managerId); 2099253f11b8SEd Tanous return; 2100253f11b8SEd Tanous } 2101253f11b8SEd Tanous 2102bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2103bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 2104bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2105bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/EthernetInterfaces", 2106253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2107bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 2108bf648f77SEd Tanous "Ethernet Network Interface Collection"; 2109bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 2110bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 2111bf648f77SEd Tanous 2112bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 2113bf648f77SEd Tanous // preparation 2114002d39b4SEd Tanous getEthernetIfaceList( 211577179532SEd Tanous [asyncResp](const bool& success, 211677179532SEd Tanous const std::vector<std::string>& ifaceList) { 2117bf648f77SEd Tanous if (!success) 21181abe55efSEd Tanous { 2119f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21209391bb9cSRapkiewicz, Pawel return; 21219391bb9cSRapkiewicz, Pawel } 21229391bb9cSRapkiewicz, Pawel 2123bd79bce8SPatrick Williams nlohmann::json& ifaceArray = 2124bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 2125bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 2126bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 2127bf648f77SEd Tanous { 21281476687dSEd Tanous nlohmann::json::object_t iface; 2129ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 2130253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2131253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem); 21327857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 2133bf648f77SEd Tanous } 2134bf648f77SEd Tanous 2135bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 2136bd79bce8SPatrick Williams ifaceArray.size(); 2137bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = 2138bd79bce8SPatrick Williams boost::urls::format( 2139253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces", 2140253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2141bf648f77SEd Tanous }); 2142bf648f77SEd Tanous }); 2143bf648f77SEd Tanous 2144253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2145b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 2146b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 2147b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 2148253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2149253f11b8SEd Tanous const std::string& managerId) { 2150b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2151b5ca3fdcSJiaqing Zhao { 2152b5ca3fdcSJiaqing Zhao return; 2153b5ca3fdcSJiaqing Zhao } 2154b5ca3fdcSJiaqing Zhao 2155253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2156253f11b8SEd Tanous { 2157bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2158bd79bce8SPatrick Williams managerId); 2159253f11b8SEd Tanous return; 2160253f11b8SEd Tanous } 2161253f11b8SEd Tanous 2162b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 2163b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 21643dfed536SEd Tanous std::vector<nlohmann::json::object_t> relatedInterfaces; 2165b5ca3fdcSJiaqing Zhao 2166afc474aeSMyung Bae if (!json_util::readJsonPatch( // 2167afc474aeSMyung Bae req, asyncResp->res, // 2168afc474aeSMyung Bae "Links/RelatedInterfaces", relatedInterfaces, // 2169afc474aeSMyung Bae "VLAN/VLANEnable", vlanEnable, // 2170afc474aeSMyung Bae "VLAN/VLANId", vlanId // 2171afc474aeSMyung Bae )) 2172b5ca3fdcSJiaqing Zhao { 2173b5ca3fdcSJiaqing Zhao return; 2174b5ca3fdcSJiaqing Zhao } 2175b5ca3fdcSJiaqing Zhao 2176b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 2177b5ca3fdcSJiaqing Zhao { 2178b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 2179b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2180b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 2181b5ca3fdcSJiaqing Zhao return; 2182b5ca3fdcSJiaqing Zhao } 2183b5ca3fdcSJiaqing Zhao 2184b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 2185bd79bce8SPatrick Williams if (!json_util::readJsonObject(relatedInterfaces[0], 2186bd79bce8SPatrick Williams asyncResp->res, "@odata.id", 2187bd79bce8SPatrick Williams parentInterfaceUri)) 2188b5ca3fdcSJiaqing Zhao { 2189bd79bce8SPatrick Williams messages::propertyMissing( 2190bd79bce8SPatrick Williams asyncResp->res, "Links/RelatedInterfaces/0/@odata.id"); 2191b5ca3fdcSJiaqing Zhao return; 2192b5ca3fdcSJiaqing Zhao } 219362598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 2194b5ca3fdcSJiaqing Zhao 21956fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 2196b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 2197b5ca3fdcSJiaqing Zhao if (!parsedUri) 2198b5ca3fdcSJiaqing Zhao { 2199b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 2200b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2201b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2202b5ca3fdcSJiaqing Zhao return; 2203b5ca3fdcSJiaqing Zhao } 2204b5ca3fdcSJiaqing Zhao 2205b5ca3fdcSJiaqing Zhao std::string parentInterface; 2206b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 2207b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 2208b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 2209b5ca3fdcSJiaqing Zhao { 2210b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2211b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2212b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2213b5ca3fdcSJiaqing Zhao return; 2214b5ca3fdcSJiaqing Zhao } 2215b5ca3fdcSJiaqing Zhao 2216b5ca3fdcSJiaqing Zhao if (!vlanEnable) 2217b5ca3fdcSJiaqing Zhao { 2218b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 2219b5ca3fdcSJiaqing Zhao // create 2220bd79bce8SPatrick Williams messages::propertyValueIncorrect( 2221bd79bce8SPatrick Williams asyncResp->res, "VLAN/VLANEnable", "false"); 2222b5ca3fdcSJiaqing Zhao return; 2223b5ca3fdcSJiaqing Zhao } 2224b5ca3fdcSJiaqing Zhao 2225bd79bce8SPatrick Williams std::string vlanInterface = 2226bd79bce8SPatrick Williams parentInterface + "_" + std::to_string(vlanId); 2227b5ca3fdcSJiaqing Zhao crow::connections::systemBus->async_method_call( 2228b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 2229b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 2230b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 2231bd79bce8SPatrick Williams afterVlanCreate(asyncResp, parentInterfaceUri, 2232bd79bce8SPatrick Williams vlanInterface, ec, m); 2233b5ca3fdcSJiaqing Zhao }, 2234bd79bce8SPatrick Williams "xyz.openbmc_project.Network", 2235bd79bce8SPatrick Williams "/xyz/openbmc_project/network", 2236bd79bce8SPatrick Williams "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 2237bd79bce8SPatrick Williams parentInterface, vlanId); 2238b5ca3fdcSJiaqing Zhao }); 2239b5ca3fdcSJiaqing Zhao 2240253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2241ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 2242bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 224345ca1b86SEd Tanous [&app](const crow::Request& req, 2244bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2245253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 22463ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 224745ca1b86SEd Tanous { 224845ca1b86SEd Tanous return; 224945ca1b86SEd Tanous } 2250253f11b8SEd Tanous 2251253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2252253f11b8SEd Tanous { 2253bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2254bd79bce8SPatrick Williams managerId); 2255253f11b8SEd Tanous return; 2256253f11b8SEd Tanous } 2257253f11b8SEd Tanous 22584a0cb85cSEd Tanous getEthernetIfaceData( 2259bf648f77SEd Tanous ifaceId, 2260bd79bce8SPatrick Williams [asyncResp, ifaceId]( 2261bd79bce8SPatrick Williams const bool& success, 2262bd79bce8SPatrick Williams const EthernetInterfaceData& ethData, 226377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2264ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2265ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 22664a0cb85cSEd Tanous if (!success) 22671abe55efSEd Tanous { 2268bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2269bf648f77SEd Tanous // existing object, and other errors 2270bd79bce8SPatrick Williams messages::resourceNotFound( 2271bd79bce8SPatrick Williams asyncResp->res, "EthernetInterface", ifaceId); 22724a0cb85cSEd Tanous return; 22739391bb9cSRapkiewicz, Pawel } 22744c9afe43SEd Tanous 22750f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 227693bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2277bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2278bd79bce8SPatrick Williams "Manager Ethernet Interface"; 22790f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 22800f74e643SEd Tanous "Management Network Interface"; 22810f74e643SEd Tanous 2282bd79bce8SPatrick Williams parseInterfaceData(asyncResp, ifaceId, ethData, 2283bd79bce8SPatrick Williams ipv4Data, ipv6Data, ipv6GatewayData); 22849391bb9cSRapkiewicz, Pawel }); 2285bf648f77SEd Tanous }); 22869391bb9cSRapkiewicz, Pawel 2287253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2288ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2289bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 229045ca1b86SEd Tanous [&app](const crow::Request& req, 2291bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2292253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 22933ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 229445ca1b86SEd Tanous { 229545ca1b86SEd Tanous return; 229645ca1b86SEd Tanous } 2297253f11b8SEd Tanous 2298253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2299253f11b8SEd Tanous { 2300bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2301bd79bce8SPatrick Williams managerId); 2302253f11b8SEd Tanous return; 2303253f11b8SEd Tanous } 2304253f11b8SEd Tanous 2305bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2306ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2307d577665bSRatan Gupta std::optional<std::string> macAddress; 23089a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2309bd79bce8SPatrick Williams std::optional<std::vector< 2310bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23113dfed536SEd Tanous ipv4StaticAddresses; 2312bd79bce8SPatrick Williams std::optional<std::vector< 2313bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23143dfed536SEd Tanous ipv6StaticAddresses; 2315bd79bce8SPatrick Williams std::optional<std::vector< 2316bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23173dfed536SEd Tanous ipv6StaticDefaultGateways; 2318f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2319b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2320eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 232135fb5311STejas Patil std::optional<size_t> mtuSize; 23221f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 23231f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2324afc474aeSMyung Bae 2325afc474aeSMyung Bae if (!json_util::readJsonPatch( // 2326afc474aeSMyung Bae req, asyncResp->res, // 2327afc474aeSMyung Bae "DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled, // 2328afc474aeSMyung Bae "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers, // 2329afc474aeSMyung Bae "DHCPv4/UseDomainName", v4dhcpParms.useDomainName, // 2330afc474aeSMyung Bae "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers, // 2331afc474aeSMyung Bae "DHCPv6/OperatingMode", 2332afc474aeSMyung Bae v6dhcpParms.dhcpv6OperatingMode, // 2333afc474aeSMyung Bae "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers, // 2334afc474aeSMyung Bae "DHCPv6/UseDomainName", v6dhcpParms.useDomainName, // 2335afc474aeSMyung Bae "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers, // 2336afc474aeSMyung Bae "FQDN", fqdn, // 2337afc474aeSMyung Bae "HostName", hostname, // 2338afc474aeSMyung Bae "InterfaceEnabled", interfaceEnabled, // 2339afc474aeSMyung Bae "IPv4StaticAddresses", ipv4StaticAddresses, // 2340afc474aeSMyung Bae "IPv6DefaultGateway", ipv6DefaultGateway, // 2341afc474aeSMyung Bae "IPv6StaticAddresses", ipv6StaticAddresses, // 2342afc474aeSMyung Bae "IPv6StaticDefaultGateways", 2343afc474aeSMyung Bae ipv6StaticDefaultGateways, // 2344afc474aeSMyung Bae "InterfaceEnabled", interfaceEnabled, // 2345afc474aeSMyung Bae "MACAddress", macAddress, // 2346afc474aeSMyung Bae "MTUSize", mtuSize, // 2347afc474aeSMyung Bae "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 2348afc474aeSMyung Bae ipv6AutoConfigEnabled, // 2349afc474aeSMyung Bae "StaticNameServers", staticNameServers // 2350afc474aeSMyung Bae )) 23511abe55efSEd Tanous { 2352588c3f0dSKowalski, Kamil return; 2353588c3f0dSKowalski, Kamil } 2354da131a9aSJennifer Lee 2355bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2356bf648f77SEd Tanous // for JSON preparation 23574a0cb85cSEd Tanous getEthernetIfaceData( 23582c70f800SEd Tanous ifaceId, 2359bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2360ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2361d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 23629a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2363e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 2364bd79bce8SPatrick Williams ipv6StaticDefaultGateway = 2365bd79bce8SPatrick Williams std::move(ipv6StaticDefaultGateways), 23663dfed536SEd Tanous staticNameServers = std::move(staticNameServers), mtuSize, 2367bd79bce8SPatrick Williams ipv6AutoConfigEnabled, 2368bd79bce8SPatrick Williams v4dhcpParms = std::move(v4dhcpParms), 2369f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2370bd79bce8SPatrick Williams const bool success, 2371bd79bce8SPatrick Williams const EthernetInterfaceData& ethData, 237277179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2373ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2374bd79bce8SPatrick Williams const std::vector<StaticGatewayData>& 2375bd79bce8SPatrick Williams ipv6GatewayData) mutable { 23761abe55efSEd Tanous if (!success) 23771abe55efSEd Tanous { 2378588c3f0dSKowalski, Kamil // ... otherwise return error 2379bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2380bf648f77SEd Tanous // existing object, and other errors 2381bd79bce8SPatrick Williams messages::resourceNotFound( 2382bd79bce8SPatrick Williams asyncResp->res, "EthernetInterface", ifaceId); 2383588c3f0dSKowalski, Kamil return; 2384588c3f0dSKowalski, Kamil } 2385588c3f0dSKowalski, Kamil 2386bd79bce8SPatrick Williams handleDHCPPatch(ifaceId, ethData, v4dhcpParms, 2387bd79bce8SPatrick Williams v6dhcpParms, asyncResp); 23881f8c7b5dSJohnathan Mantey 23890627a2c7SEd Tanous if (hostname) 23901abe55efSEd Tanous { 23910627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 23921abe55efSEd Tanous } 23930627a2c7SEd Tanous 2394b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2395b10d8db0SRavi Teja { 2396bd79bce8SPatrick Williams handleSLAACAutoConfigPatch( 2397bd79bce8SPatrick Williams ifaceId, *ipv6AutoConfigEnabled, asyncResp); 2398b10d8db0SRavi Teja } 2399b10d8db0SRavi Teja 2400ab6554f1SJoshi-Mansi if (fqdn) 2401ab6554f1SJoshi-Mansi { 24022c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2403ab6554f1SJoshi-Mansi } 2404ab6554f1SJoshi-Mansi 2405d577665bSRatan Gupta if (macAddress) 2406d577665bSRatan Gupta { 2407bd79bce8SPatrick Williams handleMACAddressPatch(ifaceId, *macAddress, 2408bd79bce8SPatrick Williams asyncResp); 2409d577665bSRatan Gupta } 2410d577665bSRatan Gupta 2411d1d50814SRavi Teja if (ipv4StaticAddresses) 2412d1d50814SRavi Teja { 2413bd79bce8SPatrick Williams handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, 2414bd79bce8SPatrick Williams ethData, ipv4Data, asyncResp); 24151abe55efSEd Tanous } 24160627a2c7SEd Tanous 2417f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2418f85837bfSRAJESWARAN THILLAIGOVINDAN { 2419bd79bce8SPatrick Williams handleStaticNameServersPatch( 2420bd79bce8SPatrick Williams ifaceId, *staticNameServers, asyncResp); 2421f85837bfSRAJESWARAN THILLAIGOVINDAN } 24229a6fc6feSRavi Teja 24239a6fc6feSRavi Teja if (ipv6DefaultGateway) 24249a6fc6feSRavi Teja { 24259a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 24269a6fc6feSRavi Teja "IPv6DefaultGateway"); 24279a6fc6feSRavi Teja } 2428e48c0fc5SRavi Teja 2429e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2430e48c0fc5SRavi Teja { 2431bd79bce8SPatrick Williams handleIPv6StaticAddressesPatch(ifaceId, 2432bd79bce8SPatrick Williams *ipv6StaticAddresses, 2433ddd70dcaSEd Tanous ipv6Data, asyncResp); 2434e48c0fc5SRavi Teja } 2435eeedda23SJohnathan Mantey 2436ce73d5c8SSunitha Harish if (ipv6StaticDefaultGateway) 2437ce73d5c8SSunitha Harish { 2438bd79bce8SPatrick Williams handleIPv6DefaultGateway( 2439bd79bce8SPatrick Williams ifaceId, *ipv6StaticDefaultGateway, 2440ce73d5c8SSunitha Harish ipv6GatewayData, asyncResp); 2441ce73d5c8SSunitha Harish } 2442ce73d5c8SSunitha Harish 2443eeedda23SJohnathan Mantey if (interfaceEnabled) 2444eeedda23SJohnathan Mantey { 2445bd79bce8SPatrick Williams setDbusProperty( 2446bd79bce8SPatrick Williams asyncResp, "InterfaceEnabled", 2447e93abac6SGinu George "xyz.openbmc_project.Network", 2448d02aad39SEd Tanous sdbusplus::message::object_path( 2449d02aad39SEd Tanous "/xyz/openbmc_project/network") / 2450d02aad39SEd Tanous ifaceId, 2451d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", 2452e93abac6SGinu George "NICEnabled", *interfaceEnabled); 2453eeedda23SJohnathan Mantey } 245435fb5311STejas Patil 245535fb5311STejas Patil if (mtuSize) 245635fb5311STejas Patil { 245735fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 245835fb5311STejas Patil } 2459588c3f0dSKowalski, Kamil }); 2460bf648f77SEd Tanous }); 2461e7caf250SJiaqing Zhao 2462253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2463e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2464e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2465e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2466e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2467253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 2468e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2469e7caf250SJiaqing Zhao { 2470e7caf250SJiaqing Zhao return; 2471e7caf250SJiaqing Zhao } 2472e7caf250SJiaqing Zhao 2473253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2474253f11b8SEd Tanous { 2475bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2476bd79bce8SPatrick Williams managerId); 2477253f11b8SEd Tanous return; 2478253f11b8SEd Tanous } 2479253f11b8SEd Tanous 2480e7caf250SJiaqing Zhao crow::connections::systemBus->async_method_call( 2481e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2482e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2483e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2484e7caf250SJiaqing Zhao }, 2485e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2486e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2487e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2488e7caf250SJiaqing Zhao }); 24894a0cb85cSEd Tanous } 2490bf648f77SEd Tanous 24919391bb9cSRapkiewicz, Pawel } // namespace redfish 2492