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 6d7857201SEd Tanous #include "bmcweb_config.h" 7d7857201SEd Tanous 83ccb3adbSEd Tanous #include "app.hpp" 9d7857201SEd Tanous #include "async_resp.hpp" 107a1dbc48SGeorge Liu #include "dbus_utility.hpp" 113ccb3adbSEd Tanous #include "error_messages.hpp" 12539d8c6bSEd Tanous #include "generated/enums/ethernet_interface.hpp" 13539d8c6bSEd Tanous #include "generated/enums/resource.hpp" 14d7857201SEd Tanous #include "http_request.hpp" 15d7857201SEd Tanous #include "http_response.hpp" 162c5875a2SEd Tanous #include "human_sort.hpp" 17d7857201SEd Tanous #include "logging.hpp" 183ccb3adbSEd Tanous #include "query.hpp" 193ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 20d7857201SEd Tanous #include "utility.hpp" 21d7857201SEd Tanous #include "utils/dbus_utils.hpp" 22033f1e4dSEd Tanous #include "utils/ip_utils.hpp" 233ccb3adbSEd Tanous #include "utils/json_utils.hpp" 24033f1e4dSEd Tanous 25d7857201SEd Tanous #include <systemd/sd-bus.h> 261214b7e7SGunnar Mills 27d7857201SEd Tanous #include <boost/beast/http/verb.hpp> 28d7857201SEd Tanous #include <boost/system/error_code.hpp> 29d7857201SEd Tanous #include <boost/system/result.hpp> 30d7857201SEd Tanous #include <boost/url/format.hpp> 31d7857201SEd Tanous #include <boost/url/parse.hpp> 32d7857201SEd Tanous #include <boost/url/url.hpp> 33d7857201SEd Tanous #include <boost/url/url_view.hpp> 34d7857201SEd Tanous #include <sdbusplus/message.hpp> 35d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp> 36d7857201SEd Tanous #include <sdbusplus/unpack_properties.hpp> 37d7857201SEd Tanous 38d7857201SEd Tanous #include <algorithm> 39d7857201SEd Tanous #include <cctype> 403dfed536SEd Tanous #include <cstddef> 41d7857201SEd Tanous #include <cstdint> 42d7857201SEd Tanous #include <format> 43d7857201SEd Tanous #include <functional> 44ce73d5c8SSunitha Harish #include <memory> 45a24526dcSEd Tanous #include <optional> 463544d2a7SEd Tanous #include <ranges> 47ab6554f1SJoshi-Mansi #include <regex> 48d7857201SEd Tanous #include <string> 497a1dbc48SGeorge Liu #include <string_view> 50d7857201SEd Tanous #include <utility> 513dfed536SEd Tanous #include <variant> 5277179532SEd Tanous #include <vector> 539391bb9cSRapkiewicz, Pawel 541abe55efSEd Tanous namespace redfish 551abe55efSEd Tanous { 569391bb9cSRapkiewicz, Pawel 574a0cb85cSEd Tanous enum class LinkType 584a0cb85cSEd Tanous { 594a0cb85cSEd Tanous Local, 604a0cb85cSEd Tanous Global 614a0cb85cSEd Tanous }; 629391bb9cSRapkiewicz, Pawel 63743eb1c0SJohnathan Mantey enum class IpVersion 64743eb1c0SJohnathan Mantey { 65743eb1c0SJohnathan Mantey IpV4, 66743eb1c0SJohnathan Mantey IpV6 67743eb1c0SJohnathan Mantey }; 68743eb1c0SJohnathan Mantey 699391bb9cSRapkiewicz, Pawel /** 709391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 719391bb9cSRapkiewicz, Pawel */ 721abe55efSEd Tanous struct IPv4AddressData 731abe55efSEd Tanous { 74179db1d7SKowalski, Kamil std::string id; 754a0cb85cSEd Tanous std::string address; 764a0cb85cSEd Tanous std::string domain; 774a0cb85cSEd Tanous std::string gateway; 789391bb9cSRapkiewicz, Pawel std::string netmask; 799391bb9cSRapkiewicz, Pawel std::string origin; 8077179532SEd Tanous LinkType linktype{}; 8177179532SEd Tanous bool isActive{}; 829391bb9cSRapkiewicz, Pawel }; 839391bb9cSRapkiewicz, Pawel 849391bb9cSRapkiewicz, Pawel /** 85e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 86e48c0fc5SRavi Teja */ 87e48c0fc5SRavi Teja struct IPv6AddressData 88e48c0fc5SRavi Teja { 89e48c0fc5SRavi Teja std::string id; 90e48c0fc5SRavi Teja std::string address; 91e48c0fc5SRavi Teja std::string origin; 9277179532SEd Tanous uint8_t prefixLength = 0; 93e48c0fc5SRavi Teja }; 94ce73d5c8SSunitha Harish 95ce73d5c8SSunitha Harish /** 96ce73d5c8SSunitha Harish * Structure for keeping static route data required by Redfish 97ce73d5c8SSunitha Harish */ 98ce73d5c8SSunitha Harish struct StaticGatewayData 99ce73d5c8SSunitha Harish { 100ce73d5c8SSunitha Harish std::string id; 101ce73d5c8SSunitha Harish std::string gateway; 102ce73d5c8SSunitha Harish size_t prefixLength = 0; 103ce73d5c8SSunitha Harish std::string protocol; 104ce73d5c8SSunitha Harish }; 105ce73d5c8SSunitha Harish 106e48c0fc5SRavi Teja /** 1079391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 1089391bb9cSRapkiewicz, Pawel * available from DBus 1099391bb9cSRapkiewicz, Pawel */ 1101abe55efSEd Tanous struct EthernetInterfaceData 1111abe55efSEd Tanous { 1124a0cb85cSEd Tanous uint32_t speed; 11335fb5311STejas Patil size_t mtuSize; 11482695a5bSJiaqing Zhao bool autoNeg; 115e4588158SJishnu CM bool dnsv4Enabled; 116e4588158SJishnu CM bool dnsv6Enabled; 11791c441ecSRavi Teja bool domainv4Enabled; 11891c441ecSRavi Teja bool domainv6Enabled; 119e4588158SJishnu CM bool ntpv4Enabled; 120e4588158SJishnu CM bool ntpv6Enabled; 121e4588158SJishnu CM bool hostNamev4Enabled; 122e4588158SJishnu CM bool hostNamev6Enabled; 123aa05fb27SJohnathan Mantey bool linkUp; 124eeedda23SJohnathan Mantey bool nicEnabled; 125b10d8db0SRavi Teja bool ipv6AcceptRa; 12682695a5bSJiaqing Zhao std::string dhcpEnabled; 1271f8c7b5dSJohnathan Mantey std::string operatingMode; 12882695a5bSJiaqing Zhao std::string hostName; 12982695a5bSJiaqing Zhao std::string defaultGateway; 13082695a5bSJiaqing Zhao std::string ipv6DefaultGateway; 131ce73d5c8SSunitha Harish std::string ipv6StaticDefaultGateway; 1324652c640SAsmitha Karunanithi std::optional<std::string> macAddress; 13317e22024SJiaqing Zhao std::optional<uint32_t> vlanId; 1340f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> nameServers; 1350f6efdc1Smanojkiran.eda@gmail.com std::vector<std::string> staticNameServers; 136d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1379391bb9cSRapkiewicz, Pawel }; 1389391bb9cSRapkiewicz, Pawel 1391f8c7b5dSJohnathan Mantey struct DHCPParameters 1401f8c7b5dSJohnathan Mantey { 1411f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 14282695a5bSJiaqing Zhao std::optional<bool> useDnsServers; 14382695a5bSJiaqing Zhao std::optional<bool> useNtpServers; 14482695a5bSJiaqing Zhao std::optional<bool> useDomainName; 1451f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1461f8c7b5dSJohnathan Mantey }; 1471f8c7b5dSJohnathan Mantey 1489391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1499391bb9cSRapkiewicz, Pawel // into full dot notation 1501abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1511abe55efSEd Tanous { 1529391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1539391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1549391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1559391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1569391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1579391bb9cSRapkiewicz, Pawel return netmask; 1589391bb9cSRapkiewicz, Pawel } 1599391bb9cSRapkiewicz, Pawel 16082695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP, 1611f8c7b5dSJohnathan Mantey bool isIPv4) 1621f8c7b5dSJohnathan Mantey { 1631f8c7b5dSJohnathan Mantey if (isIPv4) 1641f8c7b5dSJohnathan Mantey { 1651f8c7b5dSJohnathan Mantey return ( 1661f8c7b5dSJohnathan Mantey (inputDHCP == 1671f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1681f8c7b5dSJohnathan Mantey (inputDHCP == 1696e78b680SAsmitha Karunanithi "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both") || 1706e78b680SAsmitha Karunanithi (inputDHCP == 1716e78b680SAsmitha Karunanithi "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4v6stateless")); 1721f8c7b5dSJohnathan Mantey } 1731f8c7b5dSJohnathan Mantey return ((inputDHCP == 1741f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1751f8c7b5dSJohnathan Mantey (inputDHCP == 1761f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1771f8c7b5dSJohnathan Mantey } 1781f8c7b5dSJohnathan Mantey 1792c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6) 1801f8c7b5dSJohnathan Mantey { 1811f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1821f8c7b5dSJohnathan Mantey { 1831f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1841f8c7b5dSJohnathan Mantey } 1853174e4dfSEd Tanous if (isIPv4) 1861f8c7b5dSJohnathan Mantey { 1871f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1881f8c7b5dSJohnathan Mantey } 1893174e4dfSEd Tanous if (isIPv6) 1901f8c7b5dSJohnathan Mantey { 1911f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1921f8c7b5dSJohnathan Mantey } 1931f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1941f8c7b5dSJohnathan Mantey } 1951f8c7b5dSJohnathan Mantey 196bd79bce8SPatrick Williams inline std::string translateAddressOriginDbusToRedfish( 197bd79bce8SPatrick Williams const std::string& inputOrigin, bool isIPv4) 1981abe55efSEd Tanous { 1994a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 2001abe55efSEd Tanous { 2014a0cb85cSEd Tanous return "Static"; 2029391bb9cSRapkiewicz, Pawel } 2034a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 2041abe55efSEd Tanous { 2054a0cb85cSEd Tanous if (isIPv4) 2061abe55efSEd Tanous { 2074a0cb85cSEd Tanous return "IPv4LinkLocal"; 2081abe55efSEd Tanous } 2094a0cb85cSEd Tanous return "LinkLocal"; 2109391bb9cSRapkiewicz, Pawel } 2114a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 2121abe55efSEd Tanous { 2134a0cb85cSEd Tanous if (isIPv4) 2144a0cb85cSEd Tanous { 2154a0cb85cSEd Tanous return "DHCP"; 2164a0cb85cSEd Tanous } 2174a0cb85cSEd Tanous return "DHCPv6"; 2184a0cb85cSEd Tanous } 2194a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 2204a0cb85cSEd Tanous { 2214a0cb85cSEd Tanous return "SLAAC"; 2224a0cb85cSEd Tanous } 2234a0cb85cSEd Tanous return ""; 2244a0cb85cSEd Tanous } 2254a0cb85cSEd Tanous 22602cad96eSEd Tanous inline bool extractEthernetInterfaceData( 22702cad96eSEd Tanous const std::string& ethifaceId, 22802cad96eSEd Tanous const dbus::utility::ManagedObjectType& dbusData, 2294a0cb85cSEd Tanous EthernetInterfaceData& ethData) 2304a0cb85cSEd Tanous { 2314c9afe43SEd Tanous bool idFound = false; 23202cad96eSEd Tanous for (const auto& objpath : dbusData) 2334a0cb85cSEd Tanous { 23402cad96eSEd Tanous for (const auto& ifacePair : objpath.second) 2354a0cb85cSEd Tanous { 23681ce609eSEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId) 237029573d4SEd Tanous { 2384c9afe43SEd Tanous idFound = true; 2394a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2404a0cb85cSEd Tanous { 2414a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2424a0cb85cSEd Tanous { 2434a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2444a0cb85cSEd Tanous { 2454a0cb85cSEd Tanous const std::string* mac = 246abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2474a0cb85cSEd Tanous if (mac != nullptr) 2484a0cb85cSEd Tanous { 24982695a5bSJiaqing Zhao ethData.macAddress = *mac; 2504a0cb85cSEd Tanous } 2514a0cb85cSEd Tanous } 2524a0cb85cSEd Tanous } 2534a0cb85cSEd Tanous } 2544a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2554a0cb85cSEd Tanous { 2564a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2574a0cb85cSEd Tanous { 2584a0cb85cSEd Tanous if (propertyPair.first == "Id") 2594a0cb85cSEd Tanous { 2601b6b96c5SEd Tanous const uint32_t* id = 261abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2624a0cb85cSEd Tanous if (id != nullptr) 2634a0cb85cSEd Tanous { 26417e22024SJiaqing Zhao ethData.vlanId = *id; 2654a0cb85cSEd Tanous } 2664a0cb85cSEd Tanous } 2674a0cb85cSEd Tanous } 2684a0cb85cSEd Tanous } 2694a0cb85cSEd Tanous else if (ifacePair.first == 2704a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2714a0cb85cSEd Tanous { 2724a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 2734a0cb85cSEd Tanous { 2744a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2754a0cb85cSEd Tanous { 2762c70f800SEd Tanous const bool* autoNeg = 277abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2782c70f800SEd Tanous if (autoNeg != nullptr) 2794a0cb85cSEd Tanous { 28082695a5bSJiaqing Zhao ethData.autoNeg = *autoNeg; 2814a0cb85cSEd Tanous } 2824a0cb85cSEd Tanous } 2834a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2844a0cb85cSEd Tanous { 2854a0cb85cSEd Tanous const uint32_t* speed = 286abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2874a0cb85cSEd Tanous if (speed != nullptr) 2884a0cb85cSEd Tanous { 2894a0cb85cSEd Tanous ethData.speed = *speed; 2904a0cb85cSEd Tanous } 2914a0cb85cSEd Tanous } 29235fb5311STejas Patil else if (propertyPair.first == "MTU") 29335fb5311STejas Patil { 2943e7a8da6SAnthony const size_t* mtuSize = 2953e7a8da6SAnthony std::get_if<size_t>(&propertyPair.second); 29635fb5311STejas Patil if (mtuSize != nullptr) 29735fb5311STejas Patil { 29835fb5311STejas Patil ethData.mtuSize = *mtuSize; 29935fb5311STejas Patil } 30035fb5311STejas Patil } 301aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 302aa05fb27SJohnathan Mantey { 303aa05fb27SJohnathan Mantey const bool* linkUp = 304aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 305aa05fb27SJohnathan Mantey if (linkUp != nullptr) 306aa05fb27SJohnathan Mantey { 307aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 308aa05fb27SJohnathan Mantey } 309aa05fb27SJohnathan Mantey } 310eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 311eeedda23SJohnathan Mantey { 312eeedda23SJohnathan Mantey const bool* nicEnabled = 313eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 314eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 315eeedda23SJohnathan Mantey { 316eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 317eeedda23SJohnathan Mantey } 318eeedda23SJohnathan Mantey } 319b10d8db0SRavi Teja else if (propertyPair.first == "IPv6AcceptRA") 320b10d8db0SRavi Teja { 321b10d8db0SRavi Teja const bool* ipv6AcceptRa = 322b10d8db0SRavi Teja std::get_if<bool>(&propertyPair.second); 323b10d8db0SRavi Teja if (ipv6AcceptRa != nullptr) 324b10d8db0SRavi Teja { 325b10d8db0SRavi Teja ethData.ipv6AcceptRa = *ipv6AcceptRa; 326b10d8db0SRavi Teja } 327b10d8db0SRavi Teja } 328f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 329029573d4SEd Tanous { 330029573d4SEd Tanous const std::vector<std::string>* nameservers = 3318d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 332029573d4SEd Tanous &propertyPair.second); 333029573d4SEd Tanous if (nameservers != nullptr) 334029573d4SEd Tanous { 335f23b7296SEd Tanous ethData.nameServers = *nameservers; 3360f6efdc1Smanojkiran.eda@gmail.com } 3370f6efdc1Smanojkiran.eda@gmail.com } 3380f6efdc1Smanojkiran.eda@gmail.com else if (propertyPair.first == "StaticNameServers") 3390f6efdc1Smanojkiran.eda@gmail.com { 3400f6efdc1Smanojkiran.eda@gmail.com const std::vector<std::string>* staticNameServers = 3418d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 3420f6efdc1Smanojkiran.eda@gmail.com &propertyPair.second); 3430f6efdc1Smanojkiran.eda@gmail.com if (staticNameServers != nullptr) 3440f6efdc1Smanojkiran.eda@gmail.com { 345f23b7296SEd Tanous ethData.staticNameServers = *staticNameServers; 3464a0cb85cSEd Tanous } 3474a0cb85cSEd Tanous } 3482a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3492a133282Smanojkiraneda { 3502c70f800SEd Tanous const std::string* dhcpEnabled = 3511f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3522c70f800SEd Tanous if (dhcpEnabled != nullptr) 3532a133282Smanojkiraneda { 35482695a5bSJiaqing Zhao ethData.dhcpEnabled = *dhcpEnabled; 3552a133282Smanojkiraneda } 3562a133282Smanojkiraneda } 357d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 358d24bfc7aSJennifer Lee { 359d24bfc7aSJennifer Lee const std::vector<std::string>* domainNames = 3608d78b7a9SPatrick Williams std::get_if<std::vector<std::string>>( 361d24bfc7aSJennifer Lee &propertyPair.second); 362d24bfc7aSJennifer Lee if (domainNames != nullptr) 363d24bfc7aSJennifer Lee { 364f23b7296SEd Tanous ethData.domainnames = *domainNames; 365d24bfc7aSJennifer Lee } 366d24bfc7aSJennifer Lee } 3679010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway") 3689010ec2eSRavi Teja { 3699010ec2eSRavi Teja const std::string* defaultGateway = 3709010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3719010ec2eSRavi Teja if (defaultGateway != nullptr) 3729010ec2eSRavi Teja { 3739010ec2eSRavi Teja std::string defaultGatewayStr = *defaultGateway; 3749010ec2eSRavi Teja if (defaultGatewayStr.empty()) 3759010ec2eSRavi Teja { 37682695a5bSJiaqing Zhao ethData.defaultGateway = "0.0.0.0"; 3779010ec2eSRavi Teja } 3789010ec2eSRavi Teja else 3799010ec2eSRavi Teja { 38082695a5bSJiaqing Zhao ethData.defaultGateway = defaultGatewayStr; 3819010ec2eSRavi Teja } 3829010ec2eSRavi Teja } 3839010ec2eSRavi Teja } 3849010ec2eSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3859010ec2eSRavi Teja { 3869010ec2eSRavi Teja const std::string* defaultGateway6 = 3879010ec2eSRavi Teja std::get_if<std::string>(&propertyPair.second); 3889010ec2eSRavi Teja if (defaultGateway6 != nullptr) 3899010ec2eSRavi Teja { 3909010ec2eSRavi Teja std::string defaultGateway6Str = 3919010ec2eSRavi Teja *defaultGateway6; 3929010ec2eSRavi Teja if (defaultGateway6Str.empty()) 3939010ec2eSRavi Teja { 39482695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 3959010ec2eSRavi Teja "0:0:0:0:0:0:0:0"; 3969010ec2eSRavi Teja } 3979010ec2eSRavi Teja else 3989010ec2eSRavi Teja { 39982695a5bSJiaqing Zhao ethData.ipv6DefaultGateway = 4009010ec2eSRavi Teja defaultGateway6Str; 4019010ec2eSRavi Teja } 4029010ec2eSRavi Teja } 4039010ec2eSRavi Teja } 404029573d4SEd Tanous } 405029573d4SEd Tanous } 406029573d4SEd Tanous } 4071f8c7b5dSJohnathan Mantey 408e4588158SJishnu CM sdbusplus::message::object_path path( 409e4588158SJishnu CM "/xyz/openbmc_project/network"); 410bd79bce8SPatrick Williams sdbusplus::message::object_path dhcp4Path = 411bd79bce8SPatrick Williams path / ethifaceId / "dhcp4"; 412e4588158SJishnu CM 413e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp4Path) 4141f8c7b5dSJohnathan Mantey { 4151f8c7b5dSJohnathan Mantey if (ifacePair.first == 4161f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 4171f8c7b5dSJohnathan Mantey { 4181f8c7b5dSJohnathan Mantey for (const auto& propertyPair : ifacePair.second) 4191f8c7b5dSJohnathan Mantey { 4201f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 4211f8c7b5dSJohnathan Mantey { 4222c70f800SEd Tanous const bool* dnsEnabled = 4231f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4242c70f800SEd Tanous if (dnsEnabled != nullptr) 4251f8c7b5dSJohnathan Mantey { 426e4588158SJishnu CM ethData.dnsv4Enabled = *dnsEnabled; 4271f8c7b5dSJohnathan Mantey } 4281f8c7b5dSJohnathan Mantey } 42991c441ecSRavi Teja else if (propertyPair.first == "DomainEnabled") 43091c441ecSRavi Teja { 43191c441ecSRavi Teja const bool* domainEnabled = 43291c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 43391c441ecSRavi Teja if (domainEnabled != nullptr) 43491c441ecSRavi Teja { 43591c441ecSRavi Teja ethData.domainv4Enabled = *domainEnabled; 43691c441ecSRavi Teja } 43791c441ecSRavi Teja } 4381f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 4391f8c7b5dSJohnathan Mantey { 4402c70f800SEd Tanous const bool* ntpEnabled = 4411f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4422c70f800SEd Tanous if (ntpEnabled != nullptr) 4431f8c7b5dSJohnathan Mantey { 444e4588158SJishnu CM ethData.ntpv4Enabled = *ntpEnabled; 4451f8c7b5dSJohnathan Mantey } 4461f8c7b5dSJohnathan Mantey } 4471f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 4481f8c7b5dSJohnathan Mantey { 4492c70f800SEd Tanous const bool* hostNameEnabled = 4501f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 4512c70f800SEd Tanous if (hostNameEnabled != nullptr) 4521f8c7b5dSJohnathan Mantey { 453e4588158SJishnu CM ethData.hostNamev4Enabled = *hostNameEnabled; 454e4588158SJishnu CM } 455e4588158SJishnu CM } 456e4588158SJishnu CM } 457e4588158SJishnu CM } 458e4588158SJishnu CM } 459e4588158SJishnu CM 460bd79bce8SPatrick Williams sdbusplus::message::object_path dhcp6Path = 461bd79bce8SPatrick Williams path / ethifaceId / "dhcp6"; 462e4588158SJishnu CM 463e4588158SJishnu CM if (sdbusplus::message::object_path(objpath.first) == dhcp6Path) 464e4588158SJishnu CM { 465e4588158SJishnu CM if (ifacePair.first == 466e4588158SJishnu CM "xyz.openbmc_project.Network.DHCPConfiguration") 467e4588158SJishnu CM { 468e4588158SJishnu CM for (const auto& propertyPair : ifacePair.second) 469e4588158SJishnu CM { 470e4588158SJishnu CM if (propertyPair.first == "DNSEnabled") 471e4588158SJishnu CM { 472e4588158SJishnu CM const bool* dnsEnabled = 473e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 474e4588158SJishnu CM if (dnsEnabled != nullptr) 475e4588158SJishnu CM { 476e4588158SJishnu CM ethData.dnsv6Enabled = *dnsEnabled; 477e4588158SJishnu CM } 478e4588158SJishnu CM } 47991c441ecSRavi Teja if (propertyPair.first == "DomainEnabled") 48091c441ecSRavi Teja { 48191c441ecSRavi Teja const bool* domainEnabled = 48291c441ecSRavi Teja std::get_if<bool>(&propertyPair.second); 48391c441ecSRavi Teja if (domainEnabled != nullptr) 48491c441ecSRavi Teja { 48591c441ecSRavi Teja ethData.domainv6Enabled = *domainEnabled; 48691c441ecSRavi Teja } 48791c441ecSRavi Teja } 488e4588158SJishnu CM else if (propertyPair.first == "NTPEnabled") 489e4588158SJishnu CM { 490e4588158SJishnu CM const bool* ntpEnabled = 491e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 492e4588158SJishnu CM if (ntpEnabled != nullptr) 493e4588158SJishnu CM { 494e4588158SJishnu CM ethData.ntpv6Enabled = *ntpEnabled; 495e4588158SJishnu CM } 496e4588158SJishnu CM } 497e4588158SJishnu CM else if (propertyPair.first == "HostNameEnabled") 498e4588158SJishnu CM { 499e4588158SJishnu CM const bool* hostNameEnabled = 500e4588158SJishnu CM std::get_if<bool>(&propertyPair.second); 501e4588158SJishnu CM if (hostNameEnabled != nullptr) 502e4588158SJishnu CM { 503e4588158SJishnu CM ethData.hostNamev6Enabled = *hostNameEnabled; 5041f8c7b5dSJohnathan Mantey } 5051f8c7b5dSJohnathan Mantey } 5061f8c7b5dSJohnathan Mantey } 5071f8c7b5dSJohnathan Mantey } 5081f8c7b5dSJohnathan Mantey } 509029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 510029573d4SEd Tanous // to check eth number 511029573d4SEd Tanous if (ifacePair.first == 5124a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 5134a0cb85cSEd Tanous { 5144a0cb85cSEd Tanous for (const auto& propertyPair : ifacePair.second) 5154a0cb85cSEd Tanous { 5164a0cb85cSEd Tanous if (propertyPair.first == "HostName") 5174a0cb85cSEd Tanous { 5184a0cb85cSEd Tanous const std::string* hostname = 5198d78b7a9SPatrick Williams std::get_if<std::string>(&propertyPair.second); 5204a0cb85cSEd Tanous if (hostname != nullptr) 5214a0cb85cSEd Tanous { 52282695a5bSJiaqing Zhao ethData.hostName = *hostname; 5234a0cb85cSEd Tanous } 5244a0cb85cSEd Tanous } 5254a0cb85cSEd Tanous } 5264a0cb85cSEd Tanous } 5274a0cb85cSEd Tanous } 5284a0cb85cSEd Tanous } 5294c9afe43SEd Tanous return idFound; 5304a0cb85cSEd Tanous } 5314a0cb85cSEd Tanous 532e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 53377179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId, 534711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 53577179532SEd Tanous std::vector<IPv6AddressData>& ipv6Config) 536e48c0fc5SRavi Teja { 537bd79bce8SPatrick Williams const std::string ipPathStart = 538bd79bce8SPatrick Williams "/xyz/openbmc_project/network/" + ethifaceId; 539e48c0fc5SRavi Teja 540e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 541e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 54281ce609eSEd Tanous for (const auto& objpath : dbusData) 543e48c0fc5SRavi Teja { 544e48c0fc5SRavi Teja // Check if proper pattern for object path appears 545353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 546e48c0fc5SRavi Teja { 5479eb808c1SEd Tanous for (const auto& interface : objpath.second) 548e48c0fc5SRavi Teja { 549e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 550e48c0fc5SRavi Teja { 551bd79bce8SPatrick Williams auto type = std::ranges::find_if( 552bd79bce8SPatrick Williams interface.second, [](const auto& property) { 553353163e9STony Lee return property.first == "Type"; 554353163e9STony Lee }); 555353163e9STony Lee if (type == interface.second.end()) 556353163e9STony Lee { 557353163e9STony Lee continue; 558353163e9STony Lee } 559353163e9STony Lee 560353163e9STony Lee const std::string* typeStr = 561353163e9STony Lee std::get_if<std::string>(&type->second); 562353163e9STony Lee 563353163e9STony Lee if (typeStr == nullptr || 564353163e9STony Lee (*typeStr != 565353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv6")) 566353163e9STony Lee { 567353163e9STony Lee continue; 568353163e9STony Lee } 569353163e9STony Lee 570e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 571e48c0fc5SRavi Teja // appropriate 57277179532SEd Tanous IPv6AddressData& ipv6Address = ipv6Config.emplace_back(); 5732c70f800SEd Tanous ipv6Address.id = 574353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 5759eb808c1SEd Tanous for (const auto& property : interface.second) 576e48c0fc5SRavi Teja { 577e48c0fc5SRavi Teja if (property.first == "Address") 578e48c0fc5SRavi Teja { 579e48c0fc5SRavi Teja const std::string* address = 580e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 581e48c0fc5SRavi Teja if (address != nullptr) 582e48c0fc5SRavi Teja { 5832c70f800SEd Tanous ipv6Address.address = *address; 584e48c0fc5SRavi Teja } 585e48c0fc5SRavi Teja } 586e48c0fc5SRavi Teja else if (property.first == "Origin") 587e48c0fc5SRavi Teja { 588e48c0fc5SRavi Teja const std::string* origin = 589e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 590e48c0fc5SRavi Teja if (origin != nullptr) 591e48c0fc5SRavi Teja { 5922c70f800SEd Tanous ipv6Address.origin = 593e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 594e48c0fc5SRavi Teja false); 595e48c0fc5SRavi Teja } 596e48c0fc5SRavi Teja } 597e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 598e48c0fc5SRavi Teja { 599e48c0fc5SRavi Teja const uint8_t* prefix = 600e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 601e48c0fc5SRavi Teja if (prefix != nullptr) 602e48c0fc5SRavi Teja { 6032c70f800SEd Tanous ipv6Address.prefixLength = *prefix; 604e48c0fc5SRavi Teja } 605e48c0fc5SRavi Teja } 606889ff694SAsmitha Karunanithi else if (property.first == "Type" || 607889ff694SAsmitha Karunanithi property.first == "Gateway") 608889ff694SAsmitha Karunanithi { 609889ff694SAsmitha Karunanithi // Type & Gateway is not used 610889ff694SAsmitha Karunanithi } 611e48c0fc5SRavi Teja else 612e48c0fc5SRavi Teja { 61362598e31SEd Tanous BMCWEB_LOG_ERROR( 61462598e31SEd Tanous "Got extra property: {} on the {} object", 61562598e31SEd Tanous property.first, objpath.first.str); 616e48c0fc5SRavi Teja } 617e48c0fc5SRavi Teja } 618e48c0fc5SRavi Teja } 619e48c0fc5SRavi Teja } 620e48c0fc5SRavi Teja } 621e48c0fc5SRavi Teja } 622e48c0fc5SRavi Teja } 623e48c0fc5SRavi Teja 6244a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 62577179532SEd Tanous inline void extractIPData(const std::string& ethifaceId, 626711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& dbusData, 62777179532SEd Tanous std::vector<IPv4AddressData>& ipv4Config) 6284a0cb85cSEd Tanous { 629bd79bce8SPatrick Williams const std::string ipPathStart = 630bd79bce8SPatrick Williams "/xyz/openbmc_project/network/" + ethifaceId; 6314a0cb85cSEd Tanous 6324a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 6334a0cb85cSEd Tanous // single ethernet interface, loop over all of them 63481ce609eSEd Tanous for (const auto& objpath : dbusData) 6354a0cb85cSEd Tanous { 6364a0cb85cSEd Tanous // Check if proper pattern for object path appears 637353163e9STony Lee if (objpath.first.str.starts_with(ipPathStart + "/")) 6384a0cb85cSEd Tanous { 6399eb808c1SEd Tanous for (const auto& interface : objpath.second) 6404a0cb85cSEd Tanous { 6414a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 6424a0cb85cSEd Tanous { 643bd79bce8SPatrick Williams auto type = std::ranges::find_if( 644bd79bce8SPatrick Williams interface.second, [](const auto& property) { 645353163e9STony Lee return property.first == "Type"; 646353163e9STony Lee }); 647353163e9STony Lee if (type == interface.second.end()) 648353163e9STony Lee { 649353163e9STony Lee continue; 650353163e9STony Lee } 651353163e9STony Lee 652353163e9STony Lee const std::string* typeStr = 653353163e9STony Lee std::get_if<std::string>(&type->second); 654353163e9STony Lee 655353163e9STony Lee if (typeStr == nullptr || 656353163e9STony Lee (*typeStr != 657353163e9STony Lee "xyz.openbmc_project.Network.IP.Protocol.IPv4")) 658353163e9STony Lee { 659353163e9STony Lee continue; 660353163e9STony Lee } 661353163e9STony Lee 6624a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 6634a0cb85cSEd Tanous // appropriate 66477179532SEd Tanous IPv4AddressData& ipv4Address = ipv4Config.emplace_back(); 6652c70f800SEd Tanous ipv4Address.id = 666353163e9STony Lee objpath.first.str.substr(ipPathStart.size()); 6679eb808c1SEd Tanous for (const auto& property : interface.second) 6684a0cb85cSEd Tanous { 6694a0cb85cSEd Tanous if (property.first == "Address") 6704a0cb85cSEd Tanous { 6714a0cb85cSEd Tanous const std::string* address = 672abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6734a0cb85cSEd Tanous if (address != nullptr) 6744a0cb85cSEd Tanous { 6752c70f800SEd Tanous ipv4Address.address = *address; 6764a0cb85cSEd Tanous } 6774a0cb85cSEd Tanous } 6784a0cb85cSEd Tanous else if (property.first == "Origin") 6794a0cb85cSEd Tanous { 6804a0cb85cSEd Tanous const std::string* origin = 681abf2add6SEd Tanous std::get_if<std::string>(&property.second); 6824a0cb85cSEd Tanous if (origin != nullptr) 6834a0cb85cSEd Tanous { 6842c70f800SEd Tanous ipv4Address.origin = 6854a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 6864a0cb85cSEd Tanous true); 6874a0cb85cSEd Tanous } 6884a0cb85cSEd Tanous } 6894a0cb85cSEd Tanous else if (property.first == "PrefixLength") 6904a0cb85cSEd Tanous { 6914a0cb85cSEd Tanous const uint8_t* mask = 692abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 6934a0cb85cSEd Tanous if (mask != nullptr) 6944a0cb85cSEd Tanous { 6954a0cb85cSEd Tanous // convert it to the string 6962c70f800SEd Tanous ipv4Address.netmask = getNetmask(*mask); 6974a0cb85cSEd Tanous } 6984a0cb85cSEd Tanous } 699889ff694SAsmitha Karunanithi else if (property.first == "Type" || 700889ff694SAsmitha Karunanithi property.first == "Gateway") 701889ff694SAsmitha Karunanithi { 702889ff694SAsmitha Karunanithi // Type & Gateway is not used 703889ff694SAsmitha Karunanithi } 7044a0cb85cSEd Tanous else 7054a0cb85cSEd Tanous { 70662598e31SEd Tanous BMCWEB_LOG_ERROR( 70762598e31SEd Tanous "Got extra property: {} on the {} object", 70862598e31SEd Tanous property.first, objpath.first.str); 7094a0cb85cSEd Tanous } 7104a0cb85cSEd Tanous } 7114a0cb85cSEd Tanous // Check if given address is local, or global 7122c70f800SEd Tanous ipv4Address.linktype = 71311ba3979SEd Tanous ipv4Address.address.starts_with("169.254.") 71418659d10SJohnathan Mantey ? LinkType::Local 71518659d10SJohnathan Mantey : LinkType::Global; 7164a0cb85cSEd Tanous } 7174a0cb85cSEd Tanous } 7184a0cb85cSEd Tanous } 7194a0cb85cSEd Tanous } 7204a0cb85cSEd Tanous } 721588c3f0dSKowalski, Kamil 722588c3f0dSKowalski, Kamil /** 723743eb1c0SJohnathan Mantey * @brief Modifies the default gateway assigned to the NIC 724743eb1c0SJohnathan Mantey * 725743eb1c0SJohnathan Mantey * @param[in] ifaceId Id of network interface whose default gateway is to be 726743eb1c0SJohnathan Mantey * changed 727743eb1c0SJohnathan Mantey * @param[in] gateway The new gateway value. Assigning an empty string 728743eb1c0SJohnathan Mantey * causes the gateway to be deleted 729743eb1c0SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 730743eb1c0SJohnathan Mantey * 731743eb1c0SJohnathan Mantey * @return None 732743eb1c0SJohnathan Mantey */ 733743eb1c0SJohnathan Mantey inline void updateIPv4DefaultGateway( 734743eb1c0SJohnathan Mantey const std::string& ifaceId, const std::string& gateway, 735743eb1c0SJohnathan Mantey const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 736743eb1c0SJohnathan Mantey { 737743eb1c0SJohnathan Mantey setDbusProperty( 738e93abac6SGinu George asyncResp, "Gateway", "xyz.openbmc_project.Network", 739743eb1c0SJohnathan Mantey sdbusplus::message::object_path("/xyz/openbmc_project/network") / 740743eb1c0SJohnathan Mantey ifaceId, 741743eb1c0SJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway", 742e93abac6SGinu George gateway); 743743eb1c0SJohnathan Mantey } 744743eb1c0SJohnathan Mantey 745743eb1c0SJohnathan Mantey /** 746743eb1c0SJohnathan Mantey * @brief Deletes given static IP address for the interface 747179db1d7SKowalski, Kamil * 748179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 749179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 750179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 751179db1d7SKowalski, Kamil * 752179db1d7SKowalski, Kamil * @return None 753179db1d7SKowalski, Kamil */ 7549c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId, 7559c5e585cSRavi Teja const std::string& ipHash, 7568d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7571abe55efSEd Tanous { 758177612aaSEd Tanous dbus::utility::async_method_call( 759177612aaSEd Tanous asyncResp, 7605e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec) { 7611abe55efSEd Tanous if (ec) 7621abe55efSEd Tanous { 763a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7641abe55efSEd Tanous } 765179db1d7SKowalski, Kamil }, 766179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 7679c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + ipHash, 768179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 769179db1d7SKowalski, Kamil } 770179db1d7SKowalski, Kamil 771179db1d7SKowalski, Kamil /** 77201784826SJohnathan Mantey * @brief Creates a static IPv4 entry 773179db1d7SKowalski, Kamil * 77401784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 77501784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 77601784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 77701784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 778179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 779179db1d7SKowalski, Kamil * 780179db1d7SKowalski, Kamil * @return None 781179db1d7SKowalski, Kamil */ 782cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength, 783cb13a392SEd Tanous const std::string& gateway, const std::string& address, 7848d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 7851abe55efSEd Tanous { 786bd79bce8SPatrick Williams auto createIpHandler = 787bd79bce8SPatrick Williams [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) { 7881abe55efSEd Tanous if (ec) 7891abe55efSEd Tanous { 790a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7919010ec2eSRavi Teja return; 792179db1d7SKowalski, Kamil } 7939010ec2eSRavi Teja }; 7949010ec2eSRavi Teja 795177612aaSEd Tanous dbus::utility::async_method_call( 796177612aaSEd Tanous asyncResp, std::move(createIpHandler), "xyz.openbmc_project.Network", 797179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 798179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 79901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 800179db1d7SKowalski, Kamil gateway); 801179db1d7SKowalski, Kamil } 802e48c0fc5SRavi Teja 803e48c0fc5SRavi Teja /** 804743eb1c0SJohnathan Mantey * @brief Deletes the IP entry for this interface and creates a replacement 805743eb1c0SJohnathan Mantey * static entry 80601784826SJohnathan Mantey * 80701784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 80801784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 809743eb1c0SJohnathan Mantey * @param[in] prefixLength Prefix syntax for the subnet mask 810743eb1c0SJohnathan Mantey * @param[in] address Address to assign to this interface 811743eb1c0SJohnathan Mantey * @param[in] numStaticAddrs Count of IPv4 static addresses 81201784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 81301784826SJohnathan Mantey * 81401784826SJohnathan Mantey * @return None 81501784826SJohnathan Mantey */ 8169c5e585cSRavi Teja 8179c5e585cSRavi Teja inline void deleteAndCreateIPAddress( 8189c5e585cSRavi Teja IpVersion version, const std::string& ifaceId, const std::string& id, 8198d1b46d7Szhanghch05 uint8_t prefixLength, const std::string& address, 8209c5e585cSRavi Teja const std::string& gateway, 8218d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 82201784826SJohnathan Mantey { 823177612aaSEd Tanous dbus::utility::async_method_call( 824177612aaSEd Tanous asyncResp, 8259c5e585cSRavi Teja [asyncResp, version, ifaceId, address, prefixLength, 8269c5e585cSRavi Teja gateway](const boost::system::error_code& ec) { 82701784826SJohnathan Mantey if (ec) 82801784826SJohnathan Mantey { 82901784826SJohnathan Mantey messages::internalError(asyncResp->res); 83001784826SJohnathan Mantey } 8319c5e585cSRavi Teja std::string protocol = "xyz.openbmc_project.Network.IP.Protocol."; 8329c5e585cSRavi Teja protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6"; 833177612aaSEd Tanous dbus::utility::async_method_call( 834177612aaSEd Tanous asyncResp, 8355e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec2) { 83623a21a1cSEd Tanous if (ec2) 83701784826SJohnathan Mantey { 83801784826SJohnathan Mantey messages::internalError(asyncResp->res); 83901784826SJohnathan Mantey } 84001784826SJohnathan Mantey }, 84101784826SJohnathan Mantey "xyz.openbmc_project.Network", 84201784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 843bd79bce8SPatrick Williams "xyz.openbmc_project.Network.IP.Create", "IP", protocol, 844bd79bce8SPatrick Williams address, prefixLength, gateway); 84501784826SJohnathan Mantey }, 84601784826SJohnathan Mantey "xyz.openbmc_project.Network", 8479c5e585cSRavi Teja "/xyz/openbmc_project/network/" + ifaceId + id, 84801784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 84901784826SJohnathan Mantey } 85001784826SJohnathan Mantey 851ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData( 852ce73d5c8SSunitha Harish const std::string& ethifaceId, 853ce73d5c8SSunitha Harish const dbus::utility::ManagedObjectType& dbusData, 854ce73d5c8SSunitha Harish std::vector<StaticGatewayData>& staticGatewayConfig) 855ce73d5c8SSunitha Harish { 856ce73d5c8SSunitha Harish std::string staticGatewayPathStart("/xyz/openbmc_project/network/"); 857ce73d5c8SSunitha Harish staticGatewayPathStart += ethifaceId; 858ce73d5c8SSunitha Harish 859ce73d5c8SSunitha Harish for (const auto& objpath : dbusData) 860ce73d5c8SSunitha Harish { 861ce73d5c8SSunitha Harish if (!std::string_view(objpath.first.str) 862ce73d5c8SSunitha Harish .starts_with(staticGatewayPathStart)) 863ce73d5c8SSunitha Harish { 864ce73d5c8SSunitha Harish continue; 865ce73d5c8SSunitha Harish } 866ce73d5c8SSunitha Harish for (const auto& interface : objpath.second) 867ce73d5c8SSunitha Harish { 868ce73d5c8SSunitha Harish if (interface.first != "xyz.openbmc_project.Network.StaticGateway") 869ce73d5c8SSunitha Harish { 870ce73d5c8SSunitha Harish continue; 871ce73d5c8SSunitha Harish } 872ce73d5c8SSunitha Harish StaticGatewayData& staticGateway = 873ce73d5c8SSunitha Harish staticGatewayConfig.emplace_back(); 874ce73d5c8SSunitha Harish staticGateway.id = objpath.first.filename(); 875ce73d5c8SSunitha Harish 876ce73d5c8SSunitha Harish bool success = sdbusplus::unpackPropertiesNoThrow( 877ce73d5c8SSunitha Harish redfish::dbus_utils::UnpackErrorPrinter(), interface.second, 878ab0d4390SRavi Teja "Gateway", staticGateway.gateway, "ProtocolType", 879ce73d5c8SSunitha Harish staticGateway.protocol); 880ce73d5c8SSunitha Harish if (!success) 881ce73d5c8SSunitha Harish { 882ce73d5c8SSunitha Harish return false; 883ce73d5c8SSunitha Harish } 884ce73d5c8SSunitha Harish } 885ce73d5c8SSunitha Harish } 886ce73d5c8SSunitha Harish return true; 887ce73d5c8SSunitha Harish } 888ce73d5c8SSunitha Harish 88901784826SJohnathan Mantey /** 890e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 891e48c0fc5SRavi Teja * 892e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 893e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 894e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 895e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 896e48c0fc5SRavi Teja * 897e48c0fc5SRavi Teja * @return None 898e48c0fc5SRavi Teja */ 89901784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength, 90001784826SJohnathan Mantey const std::string& address, 9018d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 902e48c0fc5SRavi Teja { 903ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 904ce73d5c8SSunitha Harish path /= ifaceId; 905ce73d5c8SSunitha Harish 906bd79bce8SPatrick Williams auto createIpHandler = 907bd79bce8SPatrick Williams [asyncResp, address](const boost::system::error_code& ec) { 908e48c0fc5SRavi Teja if (ec) 909e48c0fc5SRavi Teja { 910fc23ef8aSNitin Kumar Kotania if (ec == boost::system::errc::io_error) 911fc23ef8aSNitin Kumar Kotania { 912fc23ef8aSNitin Kumar Kotania messages::propertyValueFormatError(asyncResp->res, address, 913fc23ef8aSNitin Kumar Kotania "Address"); 914fc23ef8aSNitin Kumar Kotania } 915fc23ef8aSNitin Kumar Kotania else 916fc23ef8aSNitin Kumar Kotania { 917e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 918e48c0fc5SRavi Teja } 919fc23ef8aSNitin Kumar Kotania } 920e48c0fc5SRavi Teja }; 921ce73d5c8SSunitha Harish // Passing null for gateway, as per redfish spec IPv6StaticAddresses 922ce73d5c8SSunitha Harish // object does not have associated gateway property 923177612aaSEd Tanous dbus::utility::async_method_call( 924177612aaSEd Tanous asyncResp, std::move(createIpHandler), "xyz.openbmc_project.Network", 925177612aaSEd Tanous path, "xyz.openbmc_project.Network.IP.Create", "IP", 926e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 927e48c0fc5SRavi Teja ""); 928e48c0fc5SRavi Teja } 929e48c0fc5SRavi Teja 930179db1d7SKowalski, Kamil /** 931ce73d5c8SSunitha Harish * @brief Deletes given IPv6 Static Gateway 932ce73d5c8SSunitha Harish * 933ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be deleted 934ce73d5c8SSunitha Harish * @param[in] ipHash DBus Hash id of IP that should be deleted 935ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 936ce73d5c8SSunitha Harish * 937ce73d5c8SSunitha Harish * @return None 938ce73d5c8SSunitha Harish */ 939504af5a0SPatrick Williams inline void deleteIPv6Gateway( 940504af5a0SPatrick Williams std::string_view ifaceId, std::string_view gatewayId, 941ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 942ce73d5c8SSunitha Harish { 943ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 944739b27b2SRavi Teja path /= ifaceId; 945ce73d5c8SSunitha Harish path /= gatewayId; 946177612aaSEd Tanous dbus::utility::async_method_call( 947177612aaSEd Tanous asyncResp, 948ce73d5c8SSunitha Harish [asyncResp](const boost::system::error_code& ec) { 949ce73d5c8SSunitha Harish if (ec) 950ce73d5c8SSunitha Harish { 951ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 952ce73d5c8SSunitha Harish } 953ce73d5c8SSunitha Harish }, 954ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 955ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 956ce73d5c8SSunitha Harish } 957ce73d5c8SSunitha Harish 958ce73d5c8SSunitha Harish /** 959ce73d5c8SSunitha Harish * @brief Creates IPv6 static default gateway with given data 960ce73d5c8SSunitha Harish * 961ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose IP should be added 962ce73d5c8SSunitha Harish * @param[in] gateway Gateway address that needs to be added 963ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 964ce73d5c8SSunitha Harish * 965ce73d5c8SSunitha Harish * @return None 966ce73d5c8SSunitha Harish */ 967ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway( 968cf91c8c4SAsmitha Karunanithi std::string_view ifaceId, const std::string& gateway, 969ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 970ce73d5c8SSunitha Harish { 971ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 972ce73d5c8SSunitha Harish path /= ifaceId; 973ce73d5c8SSunitha Harish auto createIpHandler = [asyncResp](const boost::system::error_code& ec) { 974ce73d5c8SSunitha Harish if (ec) 975ce73d5c8SSunitha Harish { 976ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 977ce73d5c8SSunitha Harish } 978ce73d5c8SSunitha Harish }; 979177612aaSEd Tanous dbus::utility::async_method_call( 980177612aaSEd Tanous asyncResp, std::move(createIpHandler), "xyz.openbmc_project.Network", 981177612aaSEd Tanous path, "xyz.openbmc_project.Network.StaticGateway.Create", 982177612aaSEd Tanous "StaticGateway", gateway, 983177612aaSEd Tanous "xyz.openbmc_project.Network.IP.Protocol.IPv6"); 984ce73d5c8SSunitha Harish } 985ce73d5c8SSunitha Harish 986ce73d5c8SSunitha Harish /** 987ce73d5c8SSunitha Harish * @brief Deletes the IPv6 default gateway entry for this interface and 988ce73d5c8SSunitha Harish * creates a replacement IPv6 default gateway entry 989ce73d5c8SSunitha Harish * 990ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface upon which to create the IPv6 991ce73d5c8SSunitha Harish * entry 992ce73d5c8SSunitha Harish * @param[in] gateway IPv6 gateway to assign to this interface 993ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 994ce73d5c8SSunitha Harish * 995ce73d5c8SSunitha Harish * @return None 996ce73d5c8SSunitha Harish */ 997ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway( 998ce73d5c8SSunitha Harish std::string_view ifaceId, std::string_view gatewayId, 999cf91c8c4SAsmitha Karunanithi const std::string& gateway, 1000ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1001ce73d5c8SSunitha Harish { 1002ce73d5c8SSunitha Harish sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1003739b27b2SRavi Teja path /= ifaceId; 1004ce73d5c8SSunitha Harish path /= gatewayId; 1005177612aaSEd Tanous dbus::utility::async_method_call( 1006177612aaSEd Tanous asyncResp, 1007ab0d4390SRavi Teja [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) { 1008ce73d5c8SSunitha Harish if (ec) 1009ce73d5c8SSunitha Harish { 1010ce73d5c8SSunitha Harish messages::internalError(asyncResp->res); 1011ce73d5c8SSunitha Harish return; 1012ce73d5c8SSunitha Harish } 1013ab0d4390SRavi Teja createIPv6DefaultGateway(ifaceId, gateway, asyncResp); 1014ce73d5c8SSunitha Harish }, 1015ce73d5c8SSunitha Harish "xyz.openbmc_project.Network", path, 1016ce73d5c8SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 1017ce73d5c8SSunitha Harish } 1018ce73d5c8SSunitha Harish 1019ce73d5c8SSunitha Harish /** 1020ce73d5c8SSunitha Harish * @brief Sets IPv6 default gateway with given data 1021ce73d5c8SSunitha Harish * 1022ce73d5c8SSunitha Harish * @param[in] ifaceId Id of interface whose gateway should be added 1023ce73d5c8SSunitha Harish * @param[in] input Contains address that needs to be added 1024ce73d5c8SSunitha Harish * @param[in] staticGatewayData Current static gateways in the system 1025ce73d5c8SSunitha Harish * @param[io] asyncResp Response object that will be returned to client 1026ce73d5c8SSunitha Harish * 1027ce73d5c8SSunitha Harish * @return None 1028ce73d5c8SSunitha Harish */ 1029ce73d5c8SSunitha Harish 1030ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway( 10313dfed536SEd Tanous const std::string& ifaceId, 10323dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 1033ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& staticGatewayData, 1034ce73d5c8SSunitha Harish const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1035ce73d5c8SSunitha Harish { 1036ce73d5c8SSunitha Harish size_t entryIdx = 1; 1037ce73d5c8SSunitha Harish std::vector<StaticGatewayData>::const_iterator staticGatewayEntry = 1038ce73d5c8SSunitha Harish staticGatewayData.begin(); 1039ce73d5c8SSunitha Harish 10403dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 10413dfed536SEd Tanous input) 1042ce73d5c8SSunitha Harish { 1043ce73d5c8SSunitha Harish // find the next gateway entry 1044ce73d5c8SSunitha Harish while (staticGatewayEntry != staticGatewayData.end()) 1045ce73d5c8SSunitha Harish { 1046ce73d5c8SSunitha Harish if (staticGatewayEntry->protocol == 1047ce73d5c8SSunitha Harish "xyz.openbmc_project.Network.IP.Protocol.IPv6") 1048ce73d5c8SSunitha Harish { 1049ce73d5c8SSunitha Harish break; 1050ce73d5c8SSunitha Harish } 1051ce73d5c8SSunitha Harish staticGatewayEntry++; 1052ce73d5c8SSunitha Harish } 1053bd79bce8SPatrick Williams std::string pathString = 1054bd79bce8SPatrick Williams "IPv6StaticDefaultGateways/" + std::to_string(entryIdx); 10553dfed536SEd Tanous nlohmann::json::object_t* obj = 10563dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 10573dfed536SEd Tanous if (obj == nullptr) 1058ce73d5c8SSunitha Harish { 1059ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1060ce73d5c8SSunitha Harish { 1061ce73d5c8SSunitha Harish messages::resourceCannotBeDeleted(asyncResp->res); 1062ce73d5c8SSunitha Harish return; 1063ce73d5c8SSunitha Harish } 1064739b27b2SRavi Teja deleteIPv6Gateway(ifaceId, staticGatewayEntry->id, asyncResp); 1065ce73d5c8SSunitha Harish return; 1066ce73d5c8SSunitha Harish } 10673dfed536SEd Tanous if (obj->empty()) 1068ce73d5c8SSunitha Harish { 1069ce73d5c8SSunitha Harish // Do nothing, but make sure the entry exists. 1070ce73d5c8SSunitha Harish if (staticGatewayEntry == staticGatewayData.end()) 1071ce73d5c8SSunitha Harish { 10723dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 1073ce73d5c8SSunitha Harish pathString); 1074ce73d5c8SSunitha Harish return; 1075ce73d5c8SSunitha Harish } 1076ce73d5c8SSunitha Harish } 1077ce73d5c8SSunitha Harish std::optional<std::string> address; 1078ce73d5c8SSunitha Harish 1079ab0d4390SRavi Teja if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", 1080ab0d4390SRavi Teja address)) 1081ce73d5c8SSunitha Harish { 1082ce73d5c8SSunitha Harish return; 1083ce73d5c8SSunitha Harish } 1084ce73d5c8SSunitha Harish const std::string* addr = nullptr; 1085ce73d5c8SSunitha Harish if (address) 1086ce73d5c8SSunitha Harish { 1087ce73d5c8SSunitha Harish addr = &(*address); 1088ce73d5c8SSunitha Harish } 1089ce73d5c8SSunitha Harish else if (staticGatewayEntry != staticGatewayData.end()) 1090ce73d5c8SSunitha Harish { 1091ce73d5c8SSunitha Harish addr = &(staticGatewayEntry->gateway); 1092ce73d5c8SSunitha Harish } 1093ce73d5c8SSunitha Harish else 1094ce73d5c8SSunitha Harish { 1095ce73d5c8SSunitha Harish messages::propertyMissing(asyncResp->res, pathString + "/Address"); 1096ce73d5c8SSunitha Harish return; 1097ce73d5c8SSunitha Harish } 1098ce73d5c8SSunitha Harish if (staticGatewayEntry != staticGatewayData.end()) 1099ce73d5c8SSunitha Harish { 1100ce73d5c8SSunitha Harish deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id, 1101ab0d4390SRavi Teja *addr, asyncResp); 1102ce73d5c8SSunitha Harish staticGatewayEntry++; 1103ce73d5c8SSunitha Harish } 1104ce73d5c8SSunitha Harish else 1105ce73d5c8SSunitha Harish { 1106ab0d4390SRavi Teja createIPv6DefaultGateway(ifaceId, *addr, asyncResp); 1107ce73d5c8SSunitha Harish } 1108ce73d5c8SSunitha Harish entryIdx++; 1109ce73d5c8SSunitha Harish } 1110ce73d5c8SSunitha Harish } 1111ce73d5c8SSunitha Harish 1112ce73d5c8SSunitha Harish /** 1113179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 1114179db1d7SKowalski, Kamil * Object 1115179db1d7SKowalski, Kamil * from EntityManager Network Manager 11164a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 1117179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 1118179db1d7SKowalski, Kamil * into JSON 1119179db1d7SKowalski, Kamil */ 1120179db1d7SKowalski, Kamil template <typename CallbackFunc> 112181ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId, 11221abe55efSEd Tanous CallbackFunc&& callback) 11231abe55efSEd Tanous { 1124f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1125f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1126f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 1127f94c4ecfSEd Tanous [ethifaceId{std::string{ethifaceId}}, 11288cb2c024SEd Tanous callback = std::forward<CallbackFunc>(callback)]( 11298b24275dSEd Tanous const boost::system::error_code& ec, 11303dfed536SEd Tanous const dbus::utility::ManagedObjectType& resp) mutable { 113155c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 113277179532SEd Tanous std::vector<IPv4AddressData> ipv4Data; 113377179532SEd Tanous std::vector<IPv6AddressData> ipv6Data; 1134ce73d5c8SSunitha Harish std::vector<StaticGatewayData> ipv6GatewayData; 1135179db1d7SKowalski, Kamil 11368b24275dSEd Tanous if (ec) 11371abe55efSEd Tanous { 1138ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1139179db1d7SKowalski, Kamil return; 1140179db1d7SKowalski, Kamil } 1141179db1d7SKowalski, Kamil 1142bd79bce8SPatrick Williams bool found = 1143bd79bce8SPatrick Williams extractEthernetInterfaceData(ethifaceId, resp, ethData); 11444c9afe43SEd Tanous if (!found) 11454c9afe43SEd Tanous { 1146ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 11474c9afe43SEd Tanous return; 11484c9afe43SEd Tanous } 11494c9afe43SEd Tanous 11502c70f800SEd Tanous extractIPData(ethifaceId, resp, ipv4Data); 1151179db1d7SKowalski, Kamil // Fix global GW 11521abe55efSEd Tanous for (IPv4AddressData& ipv4 : ipv4Data) 11531abe55efSEd Tanous { 1154c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 1155c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 11569010ec2eSRavi Teja (ipv4.origin == "DHCP") || (ipv4.origin == "Static")) 11571abe55efSEd Tanous { 115882695a5bSJiaqing Zhao ipv4.gateway = ethData.defaultGateway; 1159179db1d7SKowalski, Kamil } 1160179db1d7SKowalski, Kamil } 1161179db1d7SKowalski, Kamil 11622c70f800SEd Tanous extractIPV6Data(ethifaceId, resp, ipv6Data); 1163bd79bce8SPatrick Williams if (!extractIPv6DefaultGatewayData(ethifaceId, resp, 1164bd79bce8SPatrick Williams ipv6GatewayData)) 1165ce73d5c8SSunitha Harish { 1166ce73d5c8SSunitha Harish callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1167ce73d5c8SSunitha Harish } 11684e0453b1SGunnar Mills // Finally make a callback with useful data 1169ce73d5c8SSunitha Harish callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData); 1170f5892d0dSGeorge Liu }); 1171271584abSEd Tanous } 1172179db1d7SKowalski, Kamil 1173179db1d7SKowalski, Kamil /** 11749391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 11759391bb9cSRapkiewicz, Pawel * Manager 11761abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 11771abe55efSEd Tanous * into JSON. 11789391bb9cSRapkiewicz, Pawel */ 11799391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 11801abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback) 11811abe55efSEd Tanous { 1182f5892d0dSGeorge Liu sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1183f5892d0dSGeorge Liu dbus::utility::getManagedObjects( 1184f5892d0dSGeorge Liu "xyz.openbmc_project.Network", path, 11858cb2c024SEd Tanous [callback = std::forward<CallbackFunc>(callback)]( 11868b24275dSEd Tanous const boost::system::error_code& ec, 1187f5892d0dSGeorge Liu const dbus::utility::ManagedObjectType& resp) { 11881abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 11891abe55efSEd Tanous // ethernet interfaces 119077179532SEd Tanous std::vector<std::string> ifaceList; 11912c70f800SEd Tanous ifaceList.reserve(resp.size()); 11928b24275dSEd Tanous if (ec) 11931abe55efSEd Tanous { 11942c70f800SEd Tanous callback(false, ifaceList); 11959391bb9cSRapkiewicz, Pawel return; 11969391bb9cSRapkiewicz, Pawel } 11979391bb9cSRapkiewicz, Pawel 11989391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 11994a0cb85cSEd Tanous for (const auto& objpath : resp) 12001abe55efSEd Tanous { 12019391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 12024a0cb85cSEd Tanous for (const auto& interface : objpath.second) 12031abe55efSEd Tanous { 12041abe55efSEd Tanous // If interface is 12054a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 12064a0cb85cSEd Tanous // what we're looking for. 12079391bb9cSRapkiewicz, Pawel if (interface.first == 12081abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 12091abe55efSEd Tanous { 12102dfd18efSEd Tanous std::string ifaceId = objpath.first.filename(); 12112dfd18efSEd Tanous if (ifaceId.empty()) 12121abe55efSEd Tanous { 12132dfd18efSEd Tanous continue; 12149391bb9cSRapkiewicz, Pawel } 12152dfd18efSEd Tanous // and put it into output vector. 121677179532SEd Tanous ifaceList.emplace_back(ifaceId); 12179391bb9cSRapkiewicz, Pawel } 12189391bb9cSRapkiewicz, Pawel } 12199391bb9cSRapkiewicz, Pawel } 12202c5875a2SEd Tanous 12213544d2a7SEd Tanous std::ranges::sort(ifaceList, AlphanumLess<std::string>()); 12222c5875a2SEd Tanous 1223a434f2bdSEd Tanous // Finally make a callback with useful data 12242c70f800SEd Tanous callback(true, ifaceList); 1225f5892d0dSGeorge Liu }); 1226271584abSEd Tanous } 12279391bb9cSRapkiewicz, Pawel 1228504af5a0SPatrick Williams inline void handleHostnamePatch( 1229504af5a0SPatrick Williams const std::string& hostname, 12308d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 12311abe55efSEd Tanous { 1232ab6554f1SJoshi-Mansi // SHOULD handle host names of up to 255 characters(RFC 1123) 1233ab6554f1SJoshi-Mansi if (hostname.length() > 255) 1234ab6554f1SJoshi-Mansi { 1235ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, hostname, 1236ab6554f1SJoshi-Mansi "HostName"); 1237ab6554f1SJoshi-Mansi return; 1238ab6554f1SJoshi-Mansi } 1239d02aad39SEd Tanous setDbusProperty( 1240e93abac6SGinu George asyncResp, "HostName", "xyz.openbmc_project.Network", 1241d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network/config"), 1242d02aad39SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1243e93abac6SGinu George hostname); 1244588c3f0dSKowalski, Kamil } 1245588c3f0dSKowalski, Kamil 1246504af5a0SPatrick Williams inline void handleMTUSizePatch( 1247504af5a0SPatrick Williams const std::string& ifaceId, const size_t mtuSize, 124835fb5311STejas Patil const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 124935fb5311STejas Patil { 1250d02aad39SEd Tanous sdbusplus::message::object_path objPath("/xyz/openbmc_project/network"); 1251d02aad39SEd Tanous objPath /= ifaceId; 1252e93abac6SGinu George setDbusProperty(asyncResp, "MTUSize", "xyz.openbmc_project.Network", 1253e93abac6SGinu George objPath, "xyz.openbmc_project.Network.EthernetInterface", 1254e93abac6SGinu George "MTU", mtuSize); 125535fb5311STejas Patil } 125635fb5311STejas Patil 1257bd79bce8SPatrick Williams inline void handleDomainnamePatch( 1258bd79bce8SPatrick Williams const std::string& ifaceId, const std::string& domainname, 12598d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1260ab6554f1SJoshi-Mansi { 1261ab6554f1SJoshi-Mansi std::vector<std::string> vectorDomainname = {domainname}; 1262d02aad39SEd Tanous setDbusProperty( 1263e93abac6SGinu George asyncResp, "FQDN", "xyz.openbmc_project.Network", 1264d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1265d02aad39SEd Tanous ifaceId, 1266e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", "DomainName", 1267d02aad39SEd Tanous vectorDomainname); 1268ab6554f1SJoshi-Mansi } 1269ab6554f1SJoshi-Mansi 12704f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname) 1271bf648f77SEd Tanous { 1272bf648f77SEd Tanous // A valid host name can never have the dotted-decimal form (RFC 1123) 12733544d2a7SEd Tanous if (std::ranges::all_of(hostname, ::isdigit)) 1274bf648f77SEd Tanous { 1275bf648f77SEd Tanous return false; 1276bf648f77SEd Tanous } 1277bf648f77SEd Tanous // Each label(hostname/subdomains) within a valid FQDN 1278bf648f77SEd Tanous // MUST handle host names of up to 63 characters (RFC 1123) 1279bf648f77SEd Tanous // labels cannot start or end with hyphens (RFC 952) 1280bf648f77SEd Tanous // labels can start with numbers (RFC 1123) 12814b242749SEd Tanous const static std::regex pattern( 1282bf648f77SEd Tanous "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$"); 1283bf648f77SEd Tanous 1284bf648f77SEd Tanous return std::regex_match(hostname, pattern); 1285bf648f77SEd Tanous } 1286bf648f77SEd Tanous 12874f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname) 1288bf648f77SEd Tanous { 1289bf648f77SEd Tanous // Can have multiple subdomains 1290bf648f77SEd Tanous // Top Level Domain's min length is 2 character 12914b242749SEd Tanous const static std::regex pattern( 12920fda0f12SGeorge Liu "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$"); 1293bf648f77SEd Tanous 1294bf648f77SEd Tanous return std::regex_match(domainname, pattern); 1295bf648f77SEd Tanous } 1296bf648f77SEd Tanous 12974f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn, 12988d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1299ab6554f1SJoshi-Mansi { 1300ab6554f1SJoshi-Mansi // Total length of FQDN must not exceed 255 characters(RFC 1035) 1301ab6554f1SJoshi-Mansi if (fqdn.length() > 255) 1302ab6554f1SJoshi-Mansi { 1303ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1304ab6554f1SJoshi-Mansi return; 1305ab6554f1SJoshi-Mansi } 1306ab6554f1SJoshi-Mansi 1307ab6554f1SJoshi-Mansi size_t pos = fqdn.find('.'); 1308ab6554f1SJoshi-Mansi if (pos == std::string::npos) 1309ab6554f1SJoshi-Mansi { 1310ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1311ab6554f1SJoshi-Mansi return; 1312ab6554f1SJoshi-Mansi } 1313ab6554f1SJoshi-Mansi 1314ab6554f1SJoshi-Mansi std::string hostname; 1315ab6554f1SJoshi-Mansi std::string domainname; 1316ab6554f1SJoshi-Mansi domainname = (fqdn).substr(pos + 1); 1317ab6554f1SJoshi-Mansi hostname = (fqdn).substr(0, pos); 1318ab6554f1SJoshi-Mansi 1319ab6554f1SJoshi-Mansi if (!isHostnameValid(hostname) || !isDomainnameValid(domainname)) 1320ab6554f1SJoshi-Mansi { 1321ab6554f1SJoshi-Mansi messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN"); 1322ab6554f1SJoshi-Mansi return; 1323ab6554f1SJoshi-Mansi } 1324ab6554f1SJoshi-Mansi 1325ab6554f1SJoshi-Mansi handleHostnamePatch(hostname, asyncResp); 1326ab6554f1SJoshi-Mansi handleDomainnamePatch(ifaceId, domainname, asyncResp); 1327ab6554f1SJoshi-Mansi } 1328ab6554f1SJoshi-Mansi 1329bd79bce8SPatrick Williams inline void handleMACAddressPatch( 1330bd79bce8SPatrick Williams const std::string& ifaceId, const std::string& macAddress, 13318d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1332d577665bSRatan Gupta { 1333d02aad39SEd Tanous setDbusProperty( 1334e93abac6SGinu George asyncResp, "MACAddress", "xyz.openbmc_project.Network", 1335d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1336d02aad39SEd Tanous ifaceId, 1337e93abac6SGinu George "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress); 1338d577665bSRatan Gupta } 1339286b9118SJohnathan Mantey 13404f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId, 13414f48d5f6SEd Tanous const std::string& propertyName, const bool v4Value, 13424f48d5f6SEd Tanous const bool v6Value, 13438d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1344da131a9aSJennifer Lee { 13452c70f800SEd Tanous const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value); 1346d02aad39SEd Tanous setDbusProperty( 1347e93abac6SGinu George asyncResp, "DHCPv4", "xyz.openbmc_project.Network", 1348d02aad39SEd Tanous sdbusplus::message::object_path("/xyz/openbmc_project/network") / 1349d02aad39SEd Tanous ifaceId, 1350e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp); 1351eeedda23SJohnathan Mantey } 1352eeedda23SJohnathan Mantey 1353e4588158SJishnu CM enum class NetworkType 1354e4588158SJishnu CM { 1355e4588158SJishnu CM dhcp4, 1356e4588158SJishnu CM dhcp6 1357e4588158SJishnu CM }; 1358e4588158SJishnu CM 1359e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value, 1360e4588158SJishnu CM const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1361e4588158SJishnu CM const std::string& ethifaceId, NetworkType type) 1362da131a9aSJennifer Lee { 136362598e31SEd Tanous BMCWEB_LOG_DEBUG("{} = {}", propertyName, value); 13641847f2a0SAsmitha Karunanithi std::string redfishPropertyName; 1365e4588158SJishnu CM sdbusplus::message::object_path path("/xyz/openbmc_project/network/"); 1366e4588158SJishnu CM path /= ethifaceId; 1367e4588158SJishnu CM 1368e4588158SJishnu CM if (type == NetworkType::dhcp4) 1369e4588158SJishnu CM { 1370e4588158SJishnu CM path /= "dhcp4"; 13711847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv4"; 1372e4588158SJishnu CM } 1373e4588158SJishnu CM else 1374e4588158SJishnu CM { 1375e4588158SJishnu CM path /= "dhcp6"; 13761847f2a0SAsmitha Karunanithi redfishPropertyName = "DHCPv6"; 1377e4588158SJishnu CM } 1378e4588158SJishnu CM 1379e93abac6SGinu George setDbusProperty( 1380e93abac6SGinu George asyncResp, redfishPropertyName, "xyz.openbmc_project.Network", path, 1381e93abac6SGinu George "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value); 1382da131a9aSJennifer Lee } 1383d577665bSRatan Gupta 1384b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch( 1385b10d8db0SRavi Teja const std::string& ifaceId, bool ipv6AutoConfigEnabled, 1386b10d8db0SRavi Teja const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1387b10d8db0SRavi Teja { 1388b10d8db0SRavi Teja sdbusplus::message::object_path path("/xyz/openbmc_project/network"); 1389b10d8db0SRavi Teja path /= ifaceId; 1390e93abac6SGinu George setDbusProperty(asyncResp, 13911847f2a0SAsmitha Karunanithi "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 1392e93abac6SGinu George "xyz.openbmc_project.Network", path, 1393e93abac6SGinu George "xyz.openbmc_project.Network.EthernetInterface", 1394e93abac6SGinu George "IPv6AcceptRA", ipv6AutoConfigEnabled); 1395b10d8db0SRavi Teja } 1396b10d8db0SRavi Teja 1397bd79bce8SPatrick Williams inline void handleDHCPPatch( 1398bd79bce8SPatrick Williams const std::string& ifaceId, const EthernetInterfaceData& ethData, 1399bd79bce8SPatrick Williams const DHCPParameters& v4dhcpParms, const DHCPParameters& v6dhcpParms, 14008d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1401da131a9aSJennifer Lee { 140282695a5bSJiaqing Zhao bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 140382695a5bSJiaqing Zhao bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false); 1404da131a9aSJennifer Lee 1405743eb1c0SJohnathan Mantey if (ipv4Active) 1406743eb1c0SJohnathan Mantey { 1407743eb1c0SJohnathan Mantey updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1408743eb1c0SJohnathan Mantey } 14091f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 14101f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 14111f8c7b5dSJohnathan Mantey 14121f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 14131f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1414da131a9aSJennifer Lee { 1415b10d8db0SRavi Teja if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") && 14161f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 14171f8c7b5dSJohnathan Mantey { 1418bf648f77SEd Tanous messages::propertyValueFormatError(asyncResp->res, 1419bf648f77SEd Tanous *v6dhcpParms.dhcpv6OperatingMode, 14201f8c7b5dSJohnathan Mantey "OperatingMode"); 1421da131a9aSJennifer Lee return; 1422da131a9aSJennifer Lee } 1423b10d8db0SRavi Teja nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled"); 14241f8c7b5dSJohnathan Mantey } 14251f8c7b5dSJohnathan Mantey else 1426da131a9aSJennifer Lee { 14271f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 14281f8c7b5dSJohnathan Mantey } 14291f8c7b5dSJohnathan Mantey 1430e4588158SJishnu CM bool nextDNSv4 = ethData.dnsv4Enabled; 1431e4588158SJishnu CM bool nextDNSv6 = ethData.dnsv6Enabled; 1432e4588158SJishnu CM if (v4dhcpParms.useDnsServers) 14331f8c7b5dSJohnathan Mantey { 1434e4588158SJishnu CM nextDNSv4 = *v4dhcpParms.useDnsServers; 14351f8c7b5dSJohnathan Mantey } 1436e4588158SJishnu CM if (v6dhcpParms.useDnsServers) 14371f8c7b5dSJohnathan Mantey { 1438e4588158SJishnu CM nextDNSv6 = *v6dhcpParms.useDnsServers; 14391f8c7b5dSJohnathan Mantey } 14401f8c7b5dSJohnathan Mantey 1441e4588158SJishnu CM bool nextNTPv4 = ethData.ntpv4Enabled; 1442e4588158SJishnu CM bool nextNTPv6 = ethData.ntpv6Enabled; 1443e4588158SJishnu CM if (v4dhcpParms.useNtpServers) 14441f8c7b5dSJohnathan Mantey { 1445e4588158SJishnu CM nextNTPv4 = *v4dhcpParms.useNtpServers; 14461f8c7b5dSJohnathan Mantey } 1447e4588158SJishnu CM if (v6dhcpParms.useNtpServers) 14481f8c7b5dSJohnathan Mantey { 1449e4588158SJishnu CM nextNTPv6 = *v6dhcpParms.useNtpServers; 14501f8c7b5dSJohnathan Mantey } 14511f8c7b5dSJohnathan Mantey 145291c441ecSRavi Teja bool nextUsev4Domain = ethData.domainv4Enabled; 145391c441ecSRavi Teja bool nextUsev6Domain = ethData.domainv6Enabled; 1454e4588158SJishnu CM if (v4dhcpParms.useDomainName) 14551f8c7b5dSJohnathan Mantey { 1456e4588158SJishnu CM nextUsev4Domain = *v4dhcpParms.useDomainName; 14571f8c7b5dSJohnathan Mantey } 1458e4588158SJishnu CM if (v6dhcpParms.useDomainName) 14591f8c7b5dSJohnathan Mantey { 1460e4588158SJishnu CM nextUsev6Domain = *v6dhcpParms.useDomainName; 14611f8c7b5dSJohnathan Mantey } 14621f8c7b5dSJohnathan Mantey 146362598e31SEd Tanous BMCWEB_LOG_DEBUG("set DHCPEnabled..."); 14641f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 14651f8c7b5dSJohnathan Mantey asyncResp); 146662598e31SEd Tanous BMCWEB_LOG_DEBUG("set DNSEnabled..."); 1467e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId, 1468e4588158SJishnu CM NetworkType::dhcp4); 146962598e31SEd Tanous BMCWEB_LOG_DEBUG("set NTPEnabled..."); 1470e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId, 1471e4588158SJishnu CM NetworkType::dhcp4); 147291c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled..."); 147391c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId, 1474e4588158SJishnu CM NetworkType::dhcp4); 1475e4588158SJishnu CM BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6..."); 1476e4588158SJishnu CM setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId, 1477e4588158SJishnu CM NetworkType::dhcp6); 1478e4588158SJishnu CM BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6..."); 1479e4588158SJishnu CM setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId, 1480e4588158SJishnu CM NetworkType::dhcp6); 148191c441ecSRavi Teja BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6..."); 148291c441ecSRavi Teja setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId, 1483e4588158SJishnu CM NetworkType::dhcp6); 1484da131a9aSJennifer Lee } 148501784826SJohnathan Mantey 148677179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry( 148777179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& head, 148877179532SEd Tanous const std::vector<IPv4AddressData>::const_iterator& end) 148901784826SJohnathan Mantey { 149017a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv4AddressData& value) { 149117a897dfSManojkiran Eda return value.origin == "Static"; 149217a897dfSManojkiran Eda }); 149301784826SJohnathan Mantey } 149401784826SJohnathan Mantey 149577179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry( 149677179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& head, 149777179532SEd Tanous const std::vector<IPv6AddressData>::const_iterator& end) 149801784826SJohnathan Mantey { 149917a897dfSManojkiran Eda return std::find_if(head, end, [](const IPv6AddressData& value) { 150017a897dfSManojkiran Eda return value.origin == "Static"; 150117a897dfSManojkiran Eda }); 150201784826SJohnathan Mantey } 150301784826SJohnathan Mantey 15046e1a52faSEd Tanous enum class AddrChange 15051abe55efSEd Tanous { 15066e1a52faSEd Tanous Noop, 15076e1a52faSEd Tanous Delete, 15086e1a52faSEd Tanous Update, 15096e1a52faSEd Tanous }; 15106e1a52faSEd Tanous 15116e1a52faSEd Tanous // Struct representing a dbus change 15126e1a52faSEd Tanous struct AddressPatch 15136e1a52faSEd Tanous { 15146e1a52faSEd Tanous std::string address; 15156e1a52faSEd Tanous std::string gateway; 15166e1a52faSEd Tanous uint8_t prefixLength = 0; 15176e1a52faSEd Tanous std::string existingDbusId; 15186e1a52faSEd Tanous AddrChange operation = AddrChange::Noop; 15196e1a52faSEd Tanous }; 15206e1a52faSEd Tanous 15216e1a52faSEd Tanous inline bool parseAddresses( 15226e1a52faSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 15236e1a52faSEd Tanous const std::vector<IPv4AddressData>& ipv4Data, crow::Response& res, 15246e1a52faSEd Tanous std::vector<AddressPatch>& addressesOut, std::string& gatewayOut) 15256e1a52faSEd Tanous { 152677179532SEd Tanous std::vector<IPv4AddressData>::const_iterator nicIpEntry = 15272c70f800SEd Tanous getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend()); 152801784826SJohnathan Mantey 15296e1a52faSEd Tanous std::string lastGatewayPath; 15306e1a52faSEd Tanous size_t entryIdx = 0; 15313dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 15323dfed536SEd Tanous input) 15331abe55efSEd Tanous { 1534bd79bce8SPatrick Williams std::string pathString = 15356e1a52faSEd Tanous std::format("IPv4StaticAddresses/{}", entryIdx); 15366e1a52faSEd Tanous AddressPatch& thisAddress = addressesOut.emplace_back(); 15373dfed536SEd Tanous nlohmann::json::object_t* obj = 15383dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 1539743eb1c0SJohnathan Mantey if (nicIpEntry != ipv4Data.cend()) 1540743eb1c0SJohnathan Mantey { 15416e1a52faSEd Tanous thisAddress.existingDbusId = nicIpEntry->id; 1542743eb1c0SJohnathan Mantey } 1543743eb1c0SJohnathan Mantey 15446e1a52faSEd Tanous if (obj == nullptr) 15456e1a52faSEd Tanous { 15466e1a52faSEd Tanous if (thisAddress.existingDbusId.empty()) 15476e1a52faSEd Tanous { 15486e1a52faSEd Tanous // Received a DELETE action on an entry not assigned to the NIC 15496e1a52faSEd Tanous messages::resourceCannotBeDeleted(res); 15506e1a52faSEd Tanous return false; 15516e1a52faSEd Tanous } 15526e1a52faSEd Tanous thisAddress.operation = AddrChange::Delete; 15536e1a52faSEd Tanous } 15546e1a52faSEd Tanous else 1555f476acbfSRatan Gupta { 1556537174c4SEd Tanous std::optional<std::string> address; 1557537174c4SEd Tanous std::optional<std::string> gateway; 15586e1a52faSEd Tanous std::optional<std::string> subnetMask; 15596e1a52faSEd Tanous if (!obj->empty()) 15606e1a52faSEd Tanous { 1561afc474aeSMyung Bae if (!json_util::readJsonObject( // 15626e1a52faSEd Tanous *obj, res, // 1563afc474aeSMyung Bae "Address", address, // 1564afc474aeSMyung Bae "Gateway", gateway, // 1565afc474aeSMyung Bae "SubnetMask", subnetMask // 1566afc474aeSMyung Bae )) 1567537174c4SEd Tanous { 15686e1a52faSEd Tanous messages::propertyValueFormatError(res, *obj, pathString); 15696e1a52faSEd Tanous return false; 1570179db1d7SKowalski, Kamil } 15716e1a52faSEd Tanous } 157201784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 157301784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 157401784826SJohnathan Mantey // current state of the interface. Merge existing state into the 157501784826SJohnathan Mantey // current request. 1576537174c4SEd Tanous if (address) 15771abe55efSEd Tanous { 1578e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*address)) 157901784826SJohnathan Mantey { 15806e1a52faSEd Tanous messages::propertyValueFormatError(res, *address, 1581bf648f77SEd Tanous pathString + "/Address"); 15826e1a52faSEd Tanous return false; 158301784826SJohnathan Mantey } 15846e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 15856e1a52faSEd Tanous thisAddress.address = *address; 158601784826SJohnathan Mantey } 15876e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 158801784826SJohnathan Mantey { 15896e1a52faSEd Tanous messages::propertyMissing(res, pathString + "/Address"); 15906e1a52faSEd Tanous return false; 159101784826SJohnathan Mantey } 159201784826SJohnathan Mantey else 159301784826SJohnathan Mantey { 15946e1a52faSEd Tanous thisAddress.address = nicIpEntry->address; 15954a0cb85cSEd Tanous } 15964a0cb85cSEd Tanous 1597537174c4SEd Tanous if (subnetMask) 15984a0cb85cSEd Tanous { 15996e1a52faSEd Tanous uint8_t prefixLength = 0; 1600033f1e4dSEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask, 1601033f1e4dSEd Tanous &prefixLength)) 16024a0cb85cSEd Tanous { 1603f12894f8SJason M. Bills messages::propertyValueFormatError( 16046e1a52faSEd Tanous res, *subnetMask, pathString + "/SubnetMask"); 16056e1a52faSEd Tanous return false; 16064a0cb85cSEd Tanous } 16076e1a52faSEd Tanous thisAddress.prefixLength = prefixLength; 16086e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 16094a0cb85cSEd Tanous } 16106e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 16114a0cb85cSEd Tanous { 16126e1a52faSEd Tanous messages::propertyMissing(res, pathString + "/SubnetMask"); 16136e1a52faSEd Tanous return false; 16144a0cb85cSEd Tanous } 16151abe55efSEd Tanous else 16161abe55efSEd Tanous { 16176e1a52faSEd Tanous uint8_t prefixLength = 0; 16186e1a52faSEd Tanous // Ignore return code. It came from internal, it's it's invalid 16196e1a52faSEd Tanous // nothing we can do 16206e1a52faSEd Tanous ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask, 16216e1a52faSEd Tanous &prefixLength); 162201784826SJohnathan Mantey 16236e1a52faSEd Tanous thisAddress.prefixLength = prefixLength; 16246e1a52faSEd Tanous } 162501784826SJohnathan Mantey if (gateway) 162601784826SJohnathan Mantey { 1627e01d0c36SEd Tanous if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway)) 162801784826SJohnathan Mantey { 16296e1a52faSEd Tanous messages::propertyValueFormatError(res, *gateway, 1630bf648f77SEd Tanous pathString + "/Gateway"); 16316e1a52faSEd Tanous return false; 163201784826SJohnathan Mantey } 16336e1a52faSEd Tanous thisAddress.operation = AddrChange::Update; 16346e1a52faSEd Tanous thisAddress.gateway = *gateway; 163501784826SJohnathan Mantey } 16366e1a52faSEd Tanous else if (thisAddress.existingDbusId.empty()) 163701784826SJohnathan Mantey { 16386e1a52faSEd Tanous // Default to null gateway 16396e1a52faSEd Tanous gateway = ""; 164001784826SJohnathan Mantey } 164101784826SJohnathan Mantey else 16421abe55efSEd Tanous { 16436e1a52faSEd Tanous thisAddress.gateway = nicIpEntry->gateway; 16444a0cb85cSEd Tanous } 16454a0cb85cSEd Tanous 16466e1a52faSEd Tanous // Changing gateway from existing 16476e1a52faSEd Tanous if (!thisAddress.gateway.empty() && 16486e1a52faSEd Tanous thisAddress.gateway != "0.0.0.0") 1649743eb1c0SJohnathan Mantey { 16506e1a52faSEd Tanous if (!gatewayOut.empty() && gatewayOut != thisAddress.gateway) 1651743eb1c0SJohnathan Mantey { 1652743eb1c0SJohnathan Mantey // A NIC can only have a single active gateway value. 1653743eb1c0SJohnathan Mantey // If any gateway in the array of static addresses 1654743eb1c0SJohnathan Mantey // mismatch the PATCH is in error. 1655743eb1c0SJohnathan Mantey std::string arg1 = pathString + "/Gateway"; 16566e1a52faSEd Tanous std::string arg2 = lastGatewayPath + "/Gateway"; 16576e1a52faSEd Tanous messages::propertyValueConflict(res, arg1, arg2); 16586e1a52faSEd Tanous return false; 16596e1a52faSEd Tanous } 16606e1a52faSEd Tanous gatewayOut = thisAddress.gateway; 16616e1a52faSEd Tanous lastGatewayPath = pathString; 1662743eb1c0SJohnathan Mantey } 1663743eb1c0SJohnathan Mantey } 1664948c0b1bSEd Tanous if (nicIpEntry != ipv4Data.end()) 1665948c0b1bSEd Tanous { 16666e1a52faSEd Tanous nicIpEntry++; 16676e1a52faSEd Tanous nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend()); 1668948c0b1bSEd Tanous } 16696e1a52faSEd Tanous entryIdx++; 1670743eb1c0SJohnathan Mantey } 1671743eb1c0SJohnathan Mantey 16726e1a52faSEd Tanous // Delete the remaining IPs 16736e1a52faSEd Tanous while (nicIpEntry != ipv4Data.cend()) 16741abe55efSEd Tanous { 16756e1a52faSEd Tanous AddressPatch& thisAddress = addressesOut.emplace_back(); 16766e1a52faSEd Tanous thisAddress.operation = AddrChange::Delete; 16776e1a52faSEd Tanous thisAddress.existingDbusId = nicIpEntry->id; 16786e1a52faSEd Tanous nicIpEntry++; 16796e1a52faSEd Tanous nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend()); 1680588c3f0dSKowalski, Kamil } 16816e1a52faSEd Tanous 16826e1a52faSEd Tanous return true; 16834a0cb85cSEd Tanous } 16846e1a52faSEd Tanous 16856e1a52faSEd Tanous inline void handleIPv4StaticPatch( 16866e1a52faSEd Tanous const std::string& ifaceId, 16876e1a52faSEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 16886e1a52faSEd Tanous const EthernetInterfaceData& ethData, 16896e1a52faSEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 16906e1a52faSEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 169101784826SJohnathan Mantey { 16926e1a52faSEd Tanous std::vector<AddressPatch> addresses; 16936e1a52faSEd Tanous std::string gatewayOut; 16946e1a52faSEd Tanous if (!parseAddresses(input, ipv4Data, asyncResp->res, addresses, gatewayOut)) 169501784826SJohnathan Mantey { 1696743eb1c0SJohnathan Mantey return; 1697743eb1c0SJohnathan Mantey } 16986e1a52faSEd Tanous 16996e1a52faSEd Tanous // If we're setting the gateway to something new, delete the 17006e1a52faSEd Tanous // existing so we won't conflict 17016e1a52faSEd Tanous if (!ethData.defaultGateway.empty() && ethData.defaultGateway != gatewayOut) 17026e1a52faSEd Tanous { 17036e1a52faSEd Tanous updateIPv4DefaultGateway(ifaceId, "", asyncResp); 1704743eb1c0SJohnathan Mantey } 17056e1a52faSEd Tanous 17066e1a52faSEd Tanous for (const AddressPatch& address : addresses) 17076e1a52faSEd Tanous { 17086e1a52faSEd Tanous switch (address.operation) 17096e1a52faSEd Tanous { 17106e1a52faSEd Tanous case AddrChange::Delete: 17116e1a52faSEd Tanous { 17126e1a52faSEd Tanous BMCWEB_LOG_ERROR("Deleting id {} on interface {}", 17136e1a52faSEd Tanous address.existingDbusId, ifaceId); 17146e1a52faSEd Tanous deleteIPAddress(ifaceId, address.existingDbusId, asyncResp); 17156e1a52faSEd Tanous } 17166e1a52faSEd Tanous break; 17176e1a52faSEd Tanous case AddrChange::Update: 17186e1a52faSEd Tanous { 17196e1a52faSEd Tanous // Update is a delete then a recreate 17206e1a52faSEd Tanous // Only need to update if there is an existing ip at this index 17216e1a52faSEd Tanous if (!address.existingDbusId.empty()) 17226e1a52faSEd Tanous { 17236e1a52faSEd Tanous BMCWEB_LOG_ERROR("Deleting id {} on interface {}", 17246e1a52faSEd Tanous address.existingDbusId, ifaceId); 17256e1a52faSEd Tanous deleteAndCreateIPAddress( 17266e1a52faSEd Tanous IpVersion::IpV4, ifaceId, address.existingDbusId, 17276e1a52faSEd Tanous address.prefixLength, address.address, address.gateway, 17286e1a52faSEd Tanous asyncResp); 17296e1a52faSEd Tanous } 17306e1a52faSEd Tanous else 17316e1a52faSEd Tanous { 17326e1a52faSEd Tanous // Otherwise, just create a new one 17336e1a52faSEd Tanous BMCWEB_LOG_ERROR( 17346e1a52faSEd Tanous "creating ip {} prefix {} gateway {} on interface {}", 17356e1a52faSEd Tanous address.address, address.prefixLength, address.gateway, 17366e1a52faSEd Tanous ifaceId); 17376e1a52faSEd Tanous createIPv4(ifaceId, address.prefixLength, address.gateway, 17386e1a52faSEd Tanous address.address, asyncResp); 17396e1a52faSEd Tanous } 17406e1a52faSEd Tanous } 17416e1a52faSEd Tanous break; 17426e1a52faSEd Tanous default: 17436e1a52faSEd Tanous { 17446e1a52faSEd Tanous // Leave alone 17456e1a52faSEd Tanous } 17466e1a52faSEd Tanous break; 17476e1a52faSEd Tanous } 17486e1a52faSEd Tanous } 17496e1a52faSEd Tanous 17506e1a52faSEd Tanous // now update to the new gateway. 17516e1a52faSEd Tanous // Default gateway is already empty, so no need to update if we're clearing 17526e1a52faSEd Tanous if (!gatewayOut.empty() && ethData.defaultGateway != gatewayOut) 17536e1a52faSEd Tanous { 17546e1a52faSEd Tanous updateIPv4DefaultGateway(ifaceId, gatewayOut, asyncResp); 175501784826SJohnathan Mantey } 17564a0cb85cSEd Tanous } 17574a0cb85cSEd Tanous 17584f48d5f6SEd Tanous inline void handleStaticNameServersPatch( 1759f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string& ifaceId, 1760f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string>& updatedStaticNameServers, 17618d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1762f85837bfSRAJESWARAN THILLAIGOVINDAN { 17631847f2a0SAsmitha Karunanithi setDbusProperty( 1764e93abac6SGinu George asyncResp, "StaticNameServers", "xyz.openbmc_project.Network", 17651847f2a0SAsmitha Karunanithi sdbusplus::message::object_path("/xyz/openbmc_project/network") / 17661847f2a0SAsmitha Karunanithi ifaceId, 17679ae226faSGeorge Liu "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers", 1768e93abac6SGinu George updatedStaticNameServers); 1769f85837bfSRAJESWARAN THILLAIGOVINDAN } 1770f85837bfSRAJESWARAN THILLAIGOVINDAN 17714f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch( 17723dfed536SEd Tanous const std::string& ifaceId, 17733dfed536SEd Tanous std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input, 177477179532SEd Tanous const std::vector<IPv6AddressData>& ipv6Data, 17758d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1776e48c0fc5SRavi Teja { 1777271584abSEd Tanous size_t entryIdx = 1; 177877179532SEd Tanous std::vector<IPv6AddressData>::const_iterator nicIpEntry = 17792c70f800SEd Tanous getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend()); 17803dfed536SEd Tanous for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson : 17813dfed536SEd Tanous input) 1782e48c0fc5SRavi Teja { 1783bd79bce8SPatrick Williams std::string pathString = 1784bd79bce8SPatrick Williams "IPv6StaticAddresses/" + std::to_string(entryIdx); 17853dfed536SEd Tanous nlohmann::json::object_t* obj = 17863dfed536SEd Tanous std::get_if<nlohmann::json::object_t>(&thisJson); 17873dfed536SEd Tanous if (obj != nullptr && !obj->empty()) 1788e48c0fc5SRavi Teja { 1789e48c0fc5SRavi Teja std::optional<std::string> address; 1790e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 17913dfed536SEd Tanous nlohmann::json::object_t thisJsonCopy = *obj; 1792afc474aeSMyung Bae if (!json_util::readJsonObject( // 1793afc474aeSMyung Bae thisJsonCopy, asyncResp->res, // 1794afc474aeSMyung Bae "Address", address, // 1795afc474aeSMyung Bae "PrefixLength", prefixLength // 1796afc474aeSMyung Bae )) 1797e48c0fc5SRavi Teja { 17983dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, thisJsonCopy, 179971f52d96SEd Tanous pathString); 1800e48c0fc5SRavi Teja return; 1801e48c0fc5SRavi Teja } 1802e48c0fc5SRavi Teja 180301784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 180401784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 180501784826SJohnathan Mantey // current state of the interface. Merge existing state into the 180601784826SJohnathan Mantey // current request. 1807d547d8d2SEd Tanous if (!address) 1808e48c0fc5SRavi Teja { 1809d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 181001784826SJohnathan Mantey { 181101784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 181201784826SJohnathan Mantey pathString + "/Address"); 181301784826SJohnathan Mantey return; 1814e48c0fc5SRavi Teja } 1815d547d8d2SEd Tanous address = nicIpEntry->address; 1816d547d8d2SEd Tanous } 1817e48c0fc5SRavi Teja 1818d547d8d2SEd Tanous if (!prefixLength) 1819e48c0fc5SRavi Teja { 1820d547d8d2SEd Tanous if (nicIpEntry == ipv6Data.end()) 1821e48c0fc5SRavi Teja { 1822e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1823e48c0fc5SRavi Teja pathString + "/PrefixLength"); 182401784826SJohnathan Mantey return; 1825e48c0fc5SRavi Teja } 1826d547d8d2SEd Tanous prefixLength = nicIpEntry->prefixLength; 1827d547d8d2SEd Tanous } 1828e48c0fc5SRavi Teja 182985ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.end()) 1830e48c0fc5SRavi Teja { 18319c5e585cSRavi Teja deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId, 1832d547d8d2SEd Tanous nicIpEntry->id, *prefixLength, 1833d547d8d2SEd Tanous *address, "", asyncResp); 1834bd79bce8SPatrick Williams nicIpEntry = 1835bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend()); 183601784826SJohnathan Mantey } 183701784826SJohnathan Mantey else 183801784826SJohnathan Mantey { 1839d547d8d2SEd Tanous createIPv6(ifaceId, *prefixLength, *address, asyncResp); 1840e48c0fc5SRavi Teja } 1841e48c0fc5SRavi Teja entryIdx++; 1842e48c0fc5SRavi Teja } 184301784826SJohnathan Mantey else 184401784826SJohnathan Mantey { 184585ffe86aSJiaqing Zhao if (nicIpEntry == ipv6Data.end()) 184601784826SJohnathan Mantey { 184701784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 184801784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 184901784826SJohnathan Mantey // in error, so bail out. 18503dfed536SEd Tanous if (obj == nullptr) 185101784826SJohnathan Mantey { 185201784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 185301784826SJohnathan Mantey return; 185401784826SJohnathan Mantey } 18553dfed536SEd Tanous messages::propertyValueFormatError(asyncResp->res, *obj, 185671f52d96SEd Tanous pathString); 185701784826SJohnathan Mantey return; 185801784826SJohnathan Mantey } 185901784826SJohnathan Mantey 18603dfed536SEd Tanous if (obj == nullptr) 186101784826SJohnathan Mantey { 18629c5e585cSRavi Teja deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp); 186301784826SJohnathan Mantey } 186485ffe86aSJiaqing Zhao if (nicIpEntry != ipv6Data.cend()) 186501784826SJohnathan Mantey { 1866bd79bce8SPatrick Williams nicIpEntry = 1867bd79bce8SPatrick Williams getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend()); 186801784826SJohnathan Mantey } 186901784826SJohnathan Mantey entryIdx++; 187001784826SJohnathan Mantey } 187101784826SJohnathan Mantey } 1872e48c0fc5SRavi Teja } 1873e48c0fc5SRavi Teja 18747857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId) 18757857cb8dSJiaqing Zhao { 18767857cb8dSJiaqing Zhao std::size_t pos = ifaceId.find('_'); 18777857cb8dSJiaqing Zhao return ifaceId.substr(0, pos); 18787857cb8dSJiaqing Zhao } 18797857cb8dSJiaqing Zhao 1880bd79bce8SPatrick Williams inline void parseInterfaceData( 1881bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1882bd79bce8SPatrick Williams const std::string& ifaceId, const EthernetInterfaceData& ethData, 188377179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 1884ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 1885ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) 18864a0cb85cSEd Tanous { 18872c70f800SEd Tanous nlohmann::json& jsonResponse = asyncResp->res.jsonValue; 188881ce609eSEd Tanous jsonResponse["Id"] = ifaceId; 1889253f11b8SEd Tanous jsonResponse["@odata.id"] = 1890253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 1891253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId); 18922c70f800SEd Tanous jsonResponse["InterfaceEnabled"] = ethData.nicEnabled; 1893eeedda23SJohnathan Mantey 1894eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1895eeedda23SJohnathan Mantey { 1896539d8c6bSEd Tanous jsonResponse["LinkStatus"] = 1897539d8c6bSEd Tanous ethData.linkUp ? ethernet_interface::LinkStatus::LinkUp 1898539d8c6bSEd Tanous : ethernet_interface::LinkStatus::LinkDown; 1899539d8c6bSEd Tanous jsonResponse["Status"]["State"] = resource::State::Enabled; 1900029573d4SEd Tanous } 1901029573d4SEd Tanous else 1902029573d4SEd Tanous { 1903539d8c6bSEd Tanous jsonResponse["LinkStatus"] = ethernet_interface::LinkStatus::NoLink; 1904539d8c6bSEd Tanous jsonResponse["Status"]["State"] = resource::State::Disabled; 1905029573d4SEd Tanous } 1906aa05fb27SJohnathan Mantey 19072c70f800SEd Tanous jsonResponse["SpeedMbps"] = ethData.speed; 190835fb5311STejas Patil jsonResponse["MTUSize"] = ethData.mtuSize; 19094652c640SAsmitha Karunanithi if (ethData.macAddress) 19104652c640SAsmitha Karunanithi { 19114652c640SAsmitha Karunanithi jsonResponse["MACAddress"] = *ethData.macAddress; 19124652c640SAsmitha Karunanithi } 19132c70f800SEd Tanous jsonResponse["DHCPv4"]["DHCPEnabled"] = 191482695a5bSJiaqing Zhao translateDhcpEnabledToBool(ethData.dhcpEnabled, true); 1915e4588158SJishnu CM jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled; 1916e4588158SJishnu CM jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled; 1917de9ad764SRavi Teja jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled; 19182c70f800SEd Tanous jsonResponse["DHCPv6"]["OperatingMode"] = 1919bd79bce8SPatrick Williams translateDhcpEnabledToBool(ethData.dhcpEnabled, false) 1920bd79bce8SPatrick Williams ? "Enabled" 19211f8c7b5dSJohnathan Mantey : "Disabled"; 1922e4588158SJishnu CM jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled; 1923e4588158SJishnu CM jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled; 1924de9ad764SRavi Teja jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled; 1925b10d8db0SRavi Teja jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] = 1926b10d8db0SRavi Teja ethData.ipv6AcceptRa; 19272a133282Smanojkiraneda 192882695a5bSJiaqing Zhao if (!ethData.hostName.empty()) 19294a0cb85cSEd Tanous { 193082695a5bSJiaqing Zhao jsonResponse["HostName"] = ethData.hostName; 1931ab6554f1SJoshi-Mansi 1932ab6554f1SJoshi-Mansi // When domain name is empty then it means, that it is a network 1933ab6554f1SJoshi-Mansi // without domain names, and the host name itself must be treated as 1934ab6554f1SJoshi-Mansi // FQDN 193582695a5bSJiaqing Zhao std::string fqdn = ethData.hostName; 1936d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1937d24bfc7aSJennifer Lee { 19382c70f800SEd Tanous fqdn += "." + ethData.domainnames[0]; 1939d24bfc7aSJennifer Lee } 19402c70f800SEd Tanous jsonResponse["FQDN"] = fqdn; 19414a0cb85cSEd Tanous } 19424a0cb85cSEd Tanous 19437857cb8dSJiaqing Zhao if (ethData.vlanId) 19447857cb8dSJiaqing Zhao { 1945539d8c6bSEd Tanous jsonResponse["EthernetInterfaceType"] = 1946539d8c6bSEd Tanous ethernet_interface::EthernetDeviceType::Virtual; 19477857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANEnable"] = true; 19487857cb8dSJiaqing Zhao jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId; 19497857cb8dSJiaqing Zhao jsonResponse["VLAN"]["Tagged"] = true; 19507857cb8dSJiaqing Zhao 19517857cb8dSJiaqing Zhao nlohmann::json::array_t relatedInterfaces; 19527857cb8dSJiaqing Zhao nlohmann::json& parentInterface = relatedInterfaces.emplace_back(); 19537857cb8dSJiaqing Zhao parentInterface["@odata.id"] = 1954253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces", 1955253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, 19567857cb8dSJiaqing Zhao extractParentInterfaceName(ifaceId)); 19577857cb8dSJiaqing Zhao jsonResponse["Links"]["RelatedInterfaces"] = 19587857cb8dSJiaqing Zhao std::move(relatedInterfaces); 19597857cb8dSJiaqing Zhao } 19607857cb8dSJiaqing Zhao else 19617857cb8dSJiaqing Zhao { 1962539d8c6bSEd Tanous jsonResponse["EthernetInterfaceType"] = 1963539d8c6bSEd Tanous ethernet_interface::EthernetDeviceType::Physical; 19647857cb8dSJiaqing Zhao } 19657857cb8dSJiaqing Zhao 19662c70f800SEd Tanous jsonResponse["NameServers"] = ethData.nameServers; 19672c70f800SEd Tanous jsonResponse["StaticNameServers"] = ethData.staticNameServers; 19684a0cb85cSEd Tanous 19692c70f800SEd Tanous nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"]; 19702c70f800SEd Tanous nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"]; 19712c70f800SEd Tanous ipv4Array = nlohmann::json::array(); 19722c70f800SEd Tanous ipv4StaticArray = nlohmann::json::array(); 19739eb808c1SEd Tanous for (const auto& ipv4Config : ipv4Data) 19744a0cb85cSEd Tanous { 19752c70f800SEd Tanous std::string gatewayStr = ipv4Config.gateway; 1976fa5053a6SGunnar Mills if (gatewayStr.empty()) 1977fa5053a6SGunnar Mills { 1978fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1979fa5053a6SGunnar Mills } 19801476687dSEd Tanous nlohmann::json::object_t ipv4; 19811476687dSEd Tanous ipv4["AddressOrigin"] = ipv4Config.origin; 19821476687dSEd Tanous ipv4["SubnetMask"] = ipv4Config.netmask; 19831476687dSEd Tanous ipv4["Address"] = ipv4Config.address; 19841476687dSEd Tanous ipv4["Gateway"] = gatewayStr; 1985fa5053a6SGunnar Mills 19862c70f800SEd Tanous if (ipv4Config.origin == "Static") 1987d1d50814SRavi Teja { 19881476687dSEd Tanous ipv4StaticArray.push_back(ipv4); 1989d1d50814SRavi Teja } 19901476687dSEd Tanous 1991b2ba3072SPatrick Williams ipv4Array.emplace_back(std::move(ipv4)); 199201784826SJohnathan Mantey } 1993d1d50814SRavi Teja 199482695a5bSJiaqing Zhao std::string ipv6GatewayStr = ethData.ipv6DefaultGateway; 19957ea79e5eSRavi Teja if (ipv6GatewayStr.empty()) 19967ea79e5eSRavi Teja { 19977ea79e5eSRavi Teja ipv6GatewayStr = "0:0:0:0:0:0:0:0"; 19987ea79e5eSRavi Teja } 19997ea79e5eSRavi Teja 20007ea79e5eSRavi Teja jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr; 2001e48c0fc5SRavi Teja 2002ce73d5c8SSunitha Harish nlohmann::json::array_t ipv6StaticGatewayArray; 2003ce73d5c8SSunitha Harish for (const auto& ipv6GatewayConfig : ipv6GatewayData) 2004ce73d5c8SSunitha Harish { 2005ce73d5c8SSunitha Harish nlohmann::json::object_t ipv6Gateway; 2006ce73d5c8SSunitha Harish ipv6Gateway["Address"] = ipv6GatewayConfig.gateway; 2007ce73d5c8SSunitha Harish ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway)); 2008ce73d5c8SSunitha Harish } 2009ce73d5c8SSunitha Harish jsonResponse["IPv6StaticDefaultGateways"] = 2010ce73d5c8SSunitha Harish std::move(ipv6StaticGatewayArray); 2011ce73d5c8SSunitha Harish 20122c70f800SEd Tanous nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"]; 20132c70f800SEd Tanous nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"]; 20142c70f800SEd Tanous ipv6Array = nlohmann::json::array(); 20152c70f800SEd Tanous ipv6StaticArray = nlohmann::json::array(); 20167f2e23e9SJohnathan Mantey nlohmann::json& ipv6AddrPolicyTable = 20172c70f800SEd Tanous jsonResponse["IPv6AddressPolicyTable"]; 20187f2e23e9SJohnathan Mantey ipv6AddrPolicyTable = nlohmann::json::array(); 20199eb808c1SEd Tanous for (const auto& ipv6Config : ipv6Data) 2020e48c0fc5SRavi Teja { 20211476687dSEd Tanous nlohmann::json::object_t ipv6; 20221476687dSEd Tanous ipv6["Address"] = ipv6Config.address; 20231476687dSEd Tanous ipv6["PrefixLength"] = ipv6Config.prefixLength; 20241476687dSEd Tanous ipv6["AddressOrigin"] = ipv6Config.origin; 2025f8361275SSunitha Harish 2026b2ba3072SPatrick Williams ipv6Array.emplace_back(std::move(ipv6)); 20272c70f800SEd Tanous if (ipv6Config.origin == "Static") 2028e48c0fc5SRavi Teja { 20291476687dSEd Tanous nlohmann::json::object_t ipv6Static; 20301476687dSEd Tanous ipv6Static["Address"] = ipv6Config.address; 20311476687dSEd Tanous ipv6Static["PrefixLength"] = ipv6Config.prefixLength; 2032b2ba3072SPatrick Williams ipv6StaticArray.emplace_back(std::move(ipv6Static)); 203301784826SJohnathan Mantey } 2034e48c0fc5SRavi Teja } 2035588c3f0dSKowalski, Kamil } 2036588c3f0dSKowalski, Kamil 2037e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2038e7caf250SJiaqing Zhao const std::string& ifaceId, 2039e7caf250SJiaqing Zhao const boost::system::error_code& ec, 2040e7caf250SJiaqing Zhao const sdbusplus::message_t& m) 2041e7caf250SJiaqing Zhao { 2042e7caf250SJiaqing Zhao if (!ec) 2043e7caf250SJiaqing Zhao { 2044e7caf250SJiaqing Zhao return; 2045e7caf250SJiaqing Zhao } 2046e7caf250SJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2047e7caf250SJiaqing Zhao if (dbusError == nullptr) 2048e7caf250SJiaqing Zhao { 2049e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2050e7caf250SJiaqing Zhao return; 2051e7caf250SJiaqing Zhao } 205262598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2053e7caf250SJiaqing Zhao 2054e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") == 2055e7caf250SJiaqing Zhao dbusError->name) 2056e7caf250SJiaqing Zhao { 2057e7caf250SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "EthernetInterface", 2058e7caf250SJiaqing Zhao ifaceId); 2059e7caf250SJiaqing Zhao return; 2060e7caf250SJiaqing Zhao } 2061e7caf250SJiaqing Zhao if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") == 2062e7caf250SJiaqing Zhao dbusError->name) 2063e7caf250SJiaqing Zhao { 2064e7caf250SJiaqing Zhao messages::resourceCannotBeDeleted(asyncResp->res); 2065e7caf250SJiaqing Zhao return; 2066e7caf250SJiaqing Zhao } 2067e7caf250SJiaqing Zhao messages::internalError(asyncResp->res); 2068e7caf250SJiaqing Zhao } 2069e7caf250SJiaqing Zhao 2070bd79bce8SPatrick Williams inline void afterVlanCreate( 2071bd79bce8SPatrick Williams const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2072bd79bce8SPatrick Williams const std::string& parentInterfaceUri, const std::string& vlanInterface, 2073bd79bce8SPatrick Williams const boost::system::error_code& ec, const sdbusplus::message_t& m 2074b5ca3fdcSJiaqing Zhao 2075b5ca3fdcSJiaqing Zhao ) 2076b5ca3fdcSJiaqing Zhao { 2077b5ca3fdcSJiaqing Zhao if (ec) 2078b5ca3fdcSJiaqing Zhao { 2079b5ca3fdcSJiaqing Zhao const sd_bus_error* dbusError = m.get_error(); 2080b5ca3fdcSJiaqing Zhao if (dbusError == nullptr) 2081b5ca3fdcSJiaqing Zhao { 2082b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2083b5ca3fdcSJiaqing Zhao return; 2084b5ca3fdcSJiaqing Zhao } 208562598e31SEd Tanous BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name); 2086b5ca3fdcSJiaqing Zhao 2087b5ca3fdcSJiaqing Zhao if (std::string_view( 2088b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.ResourceNotFound") == 2089b5ca3fdcSJiaqing Zhao dbusError->name) 2090b5ca3fdcSJiaqing Zhao { 2091b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2092b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2093b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2094b5ca3fdcSJiaqing Zhao return; 2095b5ca3fdcSJiaqing Zhao } 2096b5ca3fdcSJiaqing Zhao if (std::string_view( 2097b5ca3fdcSJiaqing Zhao "xyz.openbmc_project.Common.Error.InvalidArgument") == 2098b5ca3fdcSJiaqing Zhao dbusError->name) 2099b5ca3fdcSJiaqing Zhao { 2100b5ca3fdcSJiaqing Zhao messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface", 2101b5ca3fdcSJiaqing Zhao "Id", vlanInterface); 2102b5ca3fdcSJiaqing Zhao return; 2103b5ca3fdcSJiaqing Zhao } 2104b5ca3fdcSJiaqing Zhao messages::internalError(asyncResp->res); 2105b5ca3fdcSJiaqing Zhao return; 2106b5ca3fdcSJiaqing Zhao } 2107b5ca3fdcSJiaqing Zhao 2108253f11b8SEd Tanous const boost::urls::url vlanInterfaceUri = 2109253f11b8SEd Tanous boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2110253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface); 2111b5ca3fdcSJiaqing Zhao asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer()); 2112b5ca3fdcSJiaqing Zhao } 2113b5ca3fdcSJiaqing Zhao 2114bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app) 2115bf648f77SEd Tanous { 2116253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2117ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterfaceCollection) 21181476687dSEd Tanous .methods(boost::beast::http::verb::get)( 21191476687dSEd Tanous [&app](const crow::Request& req, 2120253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2121253f11b8SEd Tanous const std::string& managerId) { 21223ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 212345ca1b86SEd Tanous { 212445ca1b86SEd Tanous return; 212545ca1b86SEd Tanous } 212645ca1b86SEd Tanous 2127253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2128253f11b8SEd Tanous { 2129bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2130bd79bce8SPatrick Williams managerId); 2131253f11b8SEd Tanous return; 2132253f11b8SEd Tanous } 2133253f11b8SEd Tanous 2134bf648f77SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 2135bf648f77SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 2136bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 2137bd79bce8SPatrick Williams "/redfish/v1/Managers/{}/EthernetInterfaces", 2138253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2139bf648f77SEd Tanous asyncResp->res.jsonValue["Name"] = 2140bf648f77SEd Tanous "Ethernet Network Interface Collection"; 2141bf648f77SEd Tanous asyncResp->res.jsonValue["Description"] = 2142bf648f77SEd Tanous "Collection of EthernetInterfaces for this Manager"; 2143bf648f77SEd Tanous 2144bf648f77SEd Tanous // Get eth interface list, and call the below callback for JSON 2145bf648f77SEd Tanous // preparation 2146002d39b4SEd Tanous getEthernetIfaceList( 214777179532SEd Tanous [asyncResp](const bool& success, 214877179532SEd Tanous const std::vector<std::string>& ifaceList) { 2149bf648f77SEd Tanous if (!success) 21501abe55efSEd Tanous { 2151f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21529391bb9cSRapkiewicz, Pawel return; 21539391bb9cSRapkiewicz, Pawel } 21549391bb9cSRapkiewicz, Pawel 2155bd79bce8SPatrick Williams nlohmann::json& ifaceArray = 2156bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members"]; 2157bf648f77SEd Tanous ifaceArray = nlohmann::json::array(); 2158bf648f77SEd Tanous for (const std::string& ifaceItem : ifaceList) 2159bf648f77SEd Tanous { 21601476687dSEd Tanous nlohmann::json::object_t iface; 2161ef4c65b7SEd Tanous iface["@odata.id"] = boost::urls::format( 2162253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces/{}", 2163253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem); 21647857cb8dSJiaqing Zhao ifaceArray.push_back(std::move(iface)); 2165bf648f77SEd Tanous } 2166bf648f77SEd Tanous 2167bd79bce8SPatrick Williams asyncResp->res.jsonValue["Members@odata.count"] = 2168bd79bce8SPatrick Williams ifaceArray.size(); 2169bd79bce8SPatrick Williams asyncResp->res.jsonValue["@odata.id"] = 2170bd79bce8SPatrick Williams boost::urls::format( 2171253f11b8SEd Tanous "/redfish/v1/Managers/{}/EthernetInterfaces", 2172253f11b8SEd Tanous BMCWEB_REDFISH_MANAGER_URI_NAME); 2173bf648f77SEd Tanous }); 2174bf648f77SEd Tanous }); 2175bf648f77SEd Tanous 2176253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/") 2177b5ca3fdcSJiaqing Zhao .privileges(redfish::privileges::postEthernetInterfaceCollection) 2178b5ca3fdcSJiaqing Zhao .methods(boost::beast::http::verb::post)( 2179b5ca3fdcSJiaqing Zhao [&app](const crow::Request& req, 2180253f11b8SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2181253f11b8SEd Tanous const std::string& managerId) { 2182b5ca3fdcSJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2183b5ca3fdcSJiaqing Zhao { 2184b5ca3fdcSJiaqing Zhao return; 2185b5ca3fdcSJiaqing Zhao } 2186b5ca3fdcSJiaqing Zhao 2187253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2188253f11b8SEd Tanous { 2189bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2190bd79bce8SPatrick Williams managerId); 2191253f11b8SEd Tanous return; 2192253f11b8SEd Tanous } 2193253f11b8SEd Tanous 2194b5ca3fdcSJiaqing Zhao bool vlanEnable = false; 2195b5ca3fdcSJiaqing Zhao uint32_t vlanId = 0; 21963dfed536SEd Tanous std::vector<nlohmann::json::object_t> relatedInterfaces; 2197b5ca3fdcSJiaqing Zhao 2198afc474aeSMyung Bae if (!json_util::readJsonPatch( // 2199afc474aeSMyung Bae req, asyncResp->res, // 2200afc474aeSMyung Bae "Links/RelatedInterfaces", relatedInterfaces, // 2201afc474aeSMyung Bae "VLAN/VLANEnable", vlanEnable, // 2202afc474aeSMyung Bae "VLAN/VLANId", vlanId // 2203afc474aeSMyung Bae )) 2204b5ca3fdcSJiaqing Zhao { 2205b5ca3fdcSJiaqing Zhao return; 2206b5ca3fdcSJiaqing Zhao } 2207b5ca3fdcSJiaqing Zhao 2208b5ca3fdcSJiaqing Zhao if (relatedInterfaces.size() != 1) 2209b5ca3fdcSJiaqing Zhao { 2210b5ca3fdcSJiaqing Zhao messages::arraySizeTooLong(asyncResp->res, 2211b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces", 2212b5ca3fdcSJiaqing Zhao relatedInterfaces.size()); 2213b5ca3fdcSJiaqing Zhao return; 2214b5ca3fdcSJiaqing Zhao } 2215b5ca3fdcSJiaqing Zhao 2216b5ca3fdcSJiaqing Zhao std::string parentInterfaceUri; 2217bd79bce8SPatrick Williams if (!json_util::readJsonObject(relatedInterfaces[0], 2218bd79bce8SPatrick Williams asyncResp->res, "@odata.id", 2219bd79bce8SPatrick Williams parentInterfaceUri)) 2220b5ca3fdcSJiaqing Zhao { 2221bd79bce8SPatrick Williams messages::propertyMissing( 2222bd79bce8SPatrick Williams asyncResp->res, "Links/RelatedInterfaces/0/@odata.id"); 2223b5ca3fdcSJiaqing Zhao return; 2224b5ca3fdcSJiaqing Zhao } 222562598e31SEd Tanous BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri); 2226b5ca3fdcSJiaqing Zhao 22276fd29553SEd Tanous boost::system::result<boost::urls::url_view> parsedUri = 2228b5ca3fdcSJiaqing Zhao boost::urls::parse_relative_ref(parentInterfaceUri); 2229b5ca3fdcSJiaqing Zhao if (!parsedUri) 2230b5ca3fdcSJiaqing Zhao { 2231b5ca3fdcSJiaqing Zhao messages::propertyValueFormatError( 2232b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2233b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2234b5ca3fdcSJiaqing Zhao return; 2235b5ca3fdcSJiaqing Zhao } 2236b5ca3fdcSJiaqing Zhao 2237b5ca3fdcSJiaqing Zhao std::string parentInterface; 2238b5ca3fdcSJiaqing Zhao if (!crow::utility::readUrlSegments( 2239b5ca3fdcSJiaqing Zhao *parsedUri, "redfish", "v1", "Managers", "bmc", 2240b5ca3fdcSJiaqing Zhao "EthernetInterfaces", std::ref(parentInterface))) 2241b5ca3fdcSJiaqing Zhao { 2242b5ca3fdcSJiaqing Zhao messages::propertyValueNotInList( 2243b5ca3fdcSJiaqing Zhao asyncResp->res, parentInterfaceUri, 2244b5ca3fdcSJiaqing Zhao "Links/RelatedInterfaces/0/@odata.id"); 2245b5ca3fdcSJiaqing Zhao return; 2246b5ca3fdcSJiaqing Zhao } 2247b5ca3fdcSJiaqing Zhao 2248b5ca3fdcSJiaqing Zhao if (!vlanEnable) 2249b5ca3fdcSJiaqing Zhao { 2250b5ca3fdcSJiaqing Zhao // In OpenBMC implementation, VLANEnable cannot be false on 2251b5ca3fdcSJiaqing Zhao // create 2252bd79bce8SPatrick Williams messages::propertyValueIncorrect( 2253bd79bce8SPatrick Williams asyncResp->res, "VLAN/VLANEnable", "false"); 2254b5ca3fdcSJiaqing Zhao return; 2255b5ca3fdcSJiaqing Zhao } 2256b5ca3fdcSJiaqing Zhao 2257bd79bce8SPatrick Williams std::string vlanInterface = 2258bd79bce8SPatrick Williams parentInterface + "_" + std::to_string(vlanId); 2259177612aaSEd Tanous dbus::utility::async_method_call( 2260177612aaSEd Tanous asyncResp, 2261b5ca3fdcSJiaqing Zhao [asyncResp, parentInterfaceUri, 2262b5ca3fdcSJiaqing Zhao vlanInterface](const boost::system::error_code& ec, 2263b5ca3fdcSJiaqing Zhao const sdbusplus::message_t& m) { 2264bd79bce8SPatrick Williams afterVlanCreate(asyncResp, parentInterfaceUri, 2265bd79bce8SPatrick Williams vlanInterface, ec, m); 2266b5ca3fdcSJiaqing Zhao }, 2267bd79bce8SPatrick Williams "xyz.openbmc_project.Network", 2268bd79bce8SPatrick Williams "/xyz/openbmc_project/network", 2269bd79bce8SPatrick Williams "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 2270bd79bce8SPatrick Williams parentInterface, vlanId); 2271b5ca3fdcSJiaqing Zhao }); 2272b5ca3fdcSJiaqing Zhao 2273253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2274ed398213SEd Tanous .privileges(redfish::privileges::getEthernetInterface) 2275bf648f77SEd Tanous .methods(boost::beast::http::verb::get)( 227645ca1b86SEd Tanous [&app](const crow::Request& req, 2277bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2278253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 22793ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 228045ca1b86SEd Tanous { 228145ca1b86SEd Tanous return; 228245ca1b86SEd Tanous } 2283253f11b8SEd Tanous 2284253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2285253f11b8SEd Tanous { 2286bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2287bd79bce8SPatrick Williams managerId); 2288253f11b8SEd Tanous return; 2289253f11b8SEd Tanous } 2290253f11b8SEd Tanous 22914a0cb85cSEd Tanous getEthernetIfaceData( 2292bf648f77SEd Tanous ifaceId, 2293bd79bce8SPatrick Williams [asyncResp, ifaceId]( 2294bd79bce8SPatrick Williams const bool& success, 2295bd79bce8SPatrick Williams const EthernetInterfaceData& ethData, 229677179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2297ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2298ce73d5c8SSunitha Harish const std::vector<StaticGatewayData>& ipv6GatewayData) { 22994a0cb85cSEd Tanous if (!success) 23001abe55efSEd Tanous { 2301bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2302bf648f77SEd Tanous // existing object, and other errors 2303bd79bce8SPatrick Williams messages::resourceNotFound( 2304bd79bce8SPatrick Williams asyncResp->res, "EthernetInterface", ifaceId); 23054a0cb85cSEd Tanous return; 23069391bb9cSRapkiewicz, Pawel } 23074c9afe43SEd Tanous 23080f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 230993bbc953SJiaqing Zhao "#EthernetInterface.v1_9_0.EthernetInterface"; 2310bd79bce8SPatrick Williams asyncResp->res.jsonValue["Name"] = 2311bd79bce8SPatrick Williams "Manager Ethernet Interface"; 23120f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 23130f74e643SEd Tanous "Management Network Interface"; 23140f74e643SEd Tanous 2315bd79bce8SPatrick Williams parseInterfaceData(asyncResp, ifaceId, ethData, 2316bd79bce8SPatrick Williams ipv4Data, ipv6Data, ipv6GatewayData); 23179391bb9cSRapkiewicz, Pawel }); 2318bf648f77SEd Tanous }); 23199391bb9cSRapkiewicz, Pawel 2320253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2321ed398213SEd Tanous .privileges(redfish::privileges::patchEthernetInterface) 2322bf648f77SEd Tanous .methods(boost::beast::http::verb::patch)( 232345ca1b86SEd Tanous [&app](const crow::Request& req, 2324bf648f77SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2325253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 23263ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 232745ca1b86SEd Tanous { 232845ca1b86SEd Tanous return; 232945ca1b86SEd Tanous } 2330253f11b8SEd Tanous 2331253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2332253f11b8SEd Tanous { 2333bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2334bd79bce8SPatrick Williams managerId); 2335253f11b8SEd Tanous return; 2336253f11b8SEd Tanous } 2337253f11b8SEd Tanous 2338bc0bd6e0SEd Tanous std::optional<std::string> hostname; 2339ab6554f1SJoshi-Mansi std::optional<std::string> fqdn; 2340d577665bSRatan Gupta std::optional<std::string> macAddress; 23419a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 2342bd79bce8SPatrick Williams std::optional<std::vector< 2343bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23443dfed536SEd Tanous ipv4StaticAddresses; 2345bd79bce8SPatrick Williams std::optional<std::vector< 2346bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23473dfed536SEd Tanous ipv6StaticAddresses; 2348bd79bce8SPatrick Williams std::optional<std::vector< 2349bd79bce8SPatrick Williams std::variant<nlohmann::json::object_t, std::nullptr_t>>> 23503dfed536SEd Tanous ipv6StaticDefaultGateways; 2351f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 2352b10d8db0SRavi Teja std::optional<bool> ipv6AutoConfigEnabled; 2353eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 235435fb5311STejas Patil std::optional<size_t> mtuSize; 23551f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 23561f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 2357afc474aeSMyung Bae 2358afc474aeSMyung Bae if (!json_util::readJsonPatch( // 2359afc474aeSMyung Bae req, asyncResp->res, // 2360afc474aeSMyung Bae "DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled, // 2361afc474aeSMyung Bae "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers, // 2362afc474aeSMyung Bae "DHCPv4/UseDomainName", v4dhcpParms.useDomainName, // 2363afc474aeSMyung Bae "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers, // 2364afc474aeSMyung Bae "DHCPv6/OperatingMode", 2365afc474aeSMyung Bae v6dhcpParms.dhcpv6OperatingMode, // 2366afc474aeSMyung Bae "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers, // 2367afc474aeSMyung Bae "DHCPv6/UseDomainName", v6dhcpParms.useDomainName, // 2368afc474aeSMyung Bae "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers, // 2369afc474aeSMyung Bae "FQDN", fqdn, // 2370afc474aeSMyung Bae "HostName", hostname, // 2371afc474aeSMyung Bae "InterfaceEnabled", interfaceEnabled, // 2372afc474aeSMyung Bae "IPv4StaticAddresses", ipv4StaticAddresses, // 2373afc474aeSMyung Bae "IPv6DefaultGateway", ipv6DefaultGateway, // 2374afc474aeSMyung Bae "IPv6StaticAddresses", ipv6StaticAddresses, // 2375afc474aeSMyung Bae "IPv6StaticDefaultGateways", 2376afc474aeSMyung Bae ipv6StaticDefaultGateways, // 2377afc474aeSMyung Bae "InterfaceEnabled", interfaceEnabled, // 2378afc474aeSMyung Bae "MACAddress", macAddress, // 2379afc474aeSMyung Bae "MTUSize", mtuSize, // 2380afc474aeSMyung Bae "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", 2381afc474aeSMyung Bae ipv6AutoConfigEnabled, // 2382afc474aeSMyung Bae "StaticNameServers", staticNameServers // 2383afc474aeSMyung Bae )) 23841abe55efSEd Tanous { 2385588c3f0dSKowalski, Kamil return; 2386588c3f0dSKowalski, Kamil } 2387da131a9aSJennifer Lee 2388bf648f77SEd Tanous // Get single eth interface data, and call the below callback 2389bf648f77SEd Tanous // for JSON preparation 23904a0cb85cSEd Tanous getEthernetIfaceData( 23912c70f800SEd Tanous ifaceId, 2392bf648f77SEd Tanous [asyncResp, ifaceId, hostname = std::move(hostname), 2393ab6554f1SJoshi-Mansi fqdn = std::move(fqdn), macAddress = std::move(macAddress), 2394d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 23959a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 2396e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 2397bd79bce8SPatrick Williams ipv6StaticDefaultGateway = 2398bd79bce8SPatrick Williams std::move(ipv6StaticDefaultGateways), 23993dfed536SEd Tanous staticNameServers = std::move(staticNameServers), mtuSize, 2400bd79bce8SPatrick Williams ipv6AutoConfigEnabled, 2401bd79bce8SPatrick Williams v4dhcpParms = std::move(v4dhcpParms), 2402f23b7296SEd Tanous v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled]( 2403bd79bce8SPatrick Williams const bool success, 2404bd79bce8SPatrick Williams const EthernetInterfaceData& ethData, 240577179532SEd Tanous const std::vector<IPv4AddressData>& ipv4Data, 2406ce73d5c8SSunitha Harish const std::vector<IPv6AddressData>& ipv6Data, 2407bd79bce8SPatrick Williams const std::vector<StaticGatewayData>& 2408bd79bce8SPatrick Williams ipv6GatewayData) mutable { 24091abe55efSEd Tanous if (!success) 24101abe55efSEd Tanous { 2411588c3f0dSKowalski, Kamil // ... otherwise return error 2412bf648f77SEd Tanous // TODO(Pawel)consider distinguish between non 2413bf648f77SEd Tanous // existing object, and other errors 2414bd79bce8SPatrick Williams messages::resourceNotFound( 2415bd79bce8SPatrick Williams asyncResp->res, "EthernetInterface", ifaceId); 2416588c3f0dSKowalski, Kamil return; 2417588c3f0dSKowalski, Kamil } 2418588c3f0dSKowalski, Kamil 2419bd79bce8SPatrick Williams handleDHCPPatch(ifaceId, ethData, v4dhcpParms, 2420bd79bce8SPatrick Williams v6dhcpParms, asyncResp); 24211f8c7b5dSJohnathan Mantey 24220627a2c7SEd Tanous if (hostname) 24231abe55efSEd Tanous { 24240627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 24251abe55efSEd Tanous } 24260627a2c7SEd Tanous 2427b10d8db0SRavi Teja if (ipv6AutoConfigEnabled) 2428b10d8db0SRavi Teja { 2429bd79bce8SPatrick Williams handleSLAACAutoConfigPatch( 2430bd79bce8SPatrick Williams ifaceId, *ipv6AutoConfigEnabled, asyncResp); 2431b10d8db0SRavi Teja } 2432b10d8db0SRavi Teja 2433ab6554f1SJoshi-Mansi if (fqdn) 2434ab6554f1SJoshi-Mansi { 24352c70f800SEd Tanous handleFqdnPatch(ifaceId, *fqdn, asyncResp); 2436ab6554f1SJoshi-Mansi } 2437ab6554f1SJoshi-Mansi 2438d577665bSRatan Gupta if (macAddress) 2439d577665bSRatan Gupta { 2440bd79bce8SPatrick Williams handleMACAddressPatch(ifaceId, *macAddress, 2441bd79bce8SPatrick Williams asyncResp); 2442d577665bSRatan Gupta } 2443d577665bSRatan Gupta 2444*05d84e47SChandra Harkude if (ipv4StaticAddresses) 2445*05d84e47SChandra Harkude { 2446*05d84e47SChandra Harkude handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, 2447*05d84e47SChandra Harkude ethData, ipv4Data, asyncResp); 2448*05d84e47SChandra Harkude } 2449*05d84e47SChandra Harkude 2450f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 2451f85837bfSRAJESWARAN THILLAIGOVINDAN { 2452bd79bce8SPatrick Williams handleStaticNameServersPatch( 2453bd79bce8SPatrick Williams ifaceId, *staticNameServers, asyncResp); 2454f85837bfSRAJESWARAN THILLAIGOVINDAN } 24559a6fc6feSRavi Teja 24569a6fc6feSRavi Teja if (ipv6DefaultGateway) 24579a6fc6feSRavi Teja { 24589a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 24599a6fc6feSRavi Teja "IPv6DefaultGateway"); 24609a6fc6feSRavi Teja } 2461e48c0fc5SRavi Teja 2462e48c0fc5SRavi Teja if (ipv6StaticAddresses) 2463e48c0fc5SRavi Teja { 2464bd79bce8SPatrick Williams handleIPv6StaticAddressesPatch(ifaceId, 2465bd79bce8SPatrick Williams *ipv6StaticAddresses, 2466ddd70dcaSEd Tanous ipv6Data, asyncResp); 2467e48c0fc5SRavi Teja } 2468eeedda23SJohnathan Mantey 2469ce73d5c8SSunitha Harish if (ipv6StaticDefaultGateway) 2470ce73d5c8SSunitha Harish { 2471bd79bce8SPatrick Williams handleIPv6DefaultGateway( 2472bd79bce8SPatrick Williams ifaceId, *ipv6StaticDefaultGateway, 2473ce73d5c8SSunitha Harish ipv6GatewayData, asyncResp); 2474ce73d5c8SSunitha Harish } 2475ce73d5c8SSunitha Harish 2476eeedda23SJohnathan Mantey if (interfaceEnabled) 2477eeedda23SJohnathan Mantey { 2478bd79bce8SPatrick Williams setDbusProperty( 2479bd79bce8SPatrick Williams asyncResp, "InterfaceEnabled", 2480e93abac6SGinu George "xyz.openbmc_project.Network", 2481d02aad39SEd Tanous sdbusplus::message::object_path( 2482d02aad39SEd Tanous "/xyz/openbmc_project/network") / 2483d02aad39SEd Tanous ifaceId, 2484d02aad39SEd Tanous "xyz.openbmc_project.Network.EthernetInterface", 2485e93abac6SGinu George "NICEnabled", *interfaceEnabled); 2486eeedda23SJohnathan Mantey } 248735fb5311STejas Patil 248835fb5311STejas Patil if (mtuSize) 248935fb5311STejas Patil { 249035fb5311STejas Patil handleMTUSizePatch(ifaceId, *mtuSize, asyncResp); 249135fb5311STejas Patil } 2492588c3f0dSKowalski, Kamil }); 2493bf648f77SEd Tanous }); 2494e7caf250SJiaqing Zhao 2495253f11b8SEd Tanous BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/") 2496e7caf250SJiaqing Zhao .privileges(redfish::privileges::deleteEthernetInterface) 2497e7caf250SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 2498e7caf250SJiaqing Zhao [&app](const crow::Request& req, 2499e7caf250SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 2500253f11b8SEd Tanous const std::string& managerId, const std::string& ifaceId) { 2501e7caf250SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 2502e7caf250SJiaqing Zhao { 2503e7caf250SJiaqing Zhao return; 2504e7caf250SJiaqing Zhao } 2505e7caf250SJiaqing Zhao 2506253f11b8SEd Tanous if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME) 2507253f11b8SEd Tanous { 2508bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Manager", 2509bd79bce8SPatrick Williams managerId); 2510253f11b8SEd Tanous return; 2511253f11b8SEd Tanous } 2512253f11b8SEd Tanous 2513177612aaSEd Tanous dbus::utility::async_method_call( 2514177612aaSEd Tanous asyncResp, 2515e7caf250SJiaqing Zhao [asyncResp, ifaceId](const boost::system::error_code& ec, 2516e7caf250SJiaqing Zhao const sdbusplus::message_t& m) { 2517e7caf250SJiaqing Zhao afterDelete(asyncResp, ifaceId, ec, m); 2518e7caf250SJiaqing Zhao }, 2519e7caf250SJiaqing Zhao "xyz.openbmc_project.Network", 2520e7caf250SJiaqing Zhao std::string("/xyz/openbmc_project/network/") + ifaceId, 2521e7caf250SJiaqing Zhao "xyz.openbmc_project.Object.Delete", "Delete"); 2522e7caf250SJiaqing Zhao }); 25234a0cb85cSEd Tanous } 2524bf648f77SEd Tanous 25259391bb9cSRapkiewicz, Pawel } // namespace redfish 2526