19391bb9cSRapkiewicz, Pawel /* 29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 39391bb9cSRapkiewicz, Pawel // 49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License. 69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at 79391bb9cSRapkiewicz, Pawel // 89391bb9cSRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 99391bb9cSRapkiewicz, Pawel // 109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and 149391bb9cSRapkiewicz, Pawel // limitations under the License. 159391bb9cSRapkiewicz, Pawel */ 169391bb9cSRapkiewicz, Pawel #pragma once 179391bb9cSRapkiewicz, Pawel 181abe55efSEd Tanous #include <boost/container/flat_map.hpp> 194a0cb85cSEd Tanous #include <boost/container/flat_set.hpp> 20179db1d7SKowalski, Kamil #include <dbus_singleton.hpp> 21588c3f0dSKowalski, Kamil #include <error_messages.hpp> 22179db1d7SKowalski, Kamil #include <node.hpp> 23a24526dcSEd Tanous #include <optional> 24588c3f0dSKowalski, Kamil #include <utils/json_utils.hpp> 25abf2add6SEd Tanous #include <variant> 269391bb9cSRapkiewicz, Pawel 271abe55efSEd Tanous namespace redfish 281abe55efSEd Tanous { 299391bb9cSRapkiewicz, Pawel 309391bb9cSRapkiewicz, Pawel /** 319391bb9cSRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 329391bb9cSRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 339391bb9cSRapkiewicz, Pawel */ 34aa2e59c1SEd Tanous using PropertiesMapType = boost::container::flat_map< 35abf2add6SEd Tanous std::string, std::variant<std::string, bool, uint8_t, int16_t, uint16_t, 36aa2e59c1SEd Tanous int32_t, uint32_t, int64_t, uint64_t, double>>; 379391bb9cSRapkiewicz, Pawel 384a0cb85cSEd Tanous using GetManagedObjects = std::vector<std::pair< 39aa2e59c1SEd Tanous sdbusplus::message::object_path, 404a0cb85cSEd Tanous std::vector<std::pair< 41aa2e59c1SEd Tanous std::string, 42aa2e59c1SEd Tanous boost::container::flat_map< 43029573d4SEd Tanous std::string, sdbusplus::message::variant< 44029573d4SEd Tanous std::string, bool, uint8_t, int16_t, uint16_t, 45029573d4SEd Tanous int32_t, uint32_t, int64_t, uint64_t, double, 46029573d4SEd Tanous std::vector<std::string>>>>>>>; 474a0cb85cSEd Tanous 484a0cb85cSEd Tanous enum class LinkType 494a0cb85cSEd Tanous { 504a0cb85cSEd Tanous Local, 514a0cb85cSEd Tanous Global 524a0cb85cSEd Tanous }; 539391bb9cSRapkiewicz, Pawel 549391bb9cSRapkiewicz, Pawel /** 559391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 569391bb9cSRapkiewicz, Pawel */ 571abe55efSEd Tanous struct IPv4AddressData 581abe55efSEd Tanous { 59179db1d7SKowalski, Kamil std::string id; 604a0cb85cSEd Tanous std::string address; 614a0cb85cSEd Tanous std::string domain; 624a0cb85cSEd Tanous std::string gateway; 639391bb9cSRapkiewicz, Pawel std::string netmask; 649391bb9cSRapkiewicz, Pawel std::string origin; 654a0cb85cSEd Tanous LinkType linktype; 664a0cb85cSEd Tanous 671abe55efSEd Tanous bool operator<(const IPv4AddressData &obj) const 681abe55efSEd Tanous { 694a0cb85cSEd Tanous return id < obj.id; 701abe55efSEd Tanous } 719391bb9cSRapkiewicz, Pawel }; 729391bb9cSRapkiewicz, Pawel 739391bb9cSRapkiewicz, Pawel /** 74e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 75e48c0fc5SRavi Teja */ 76e48c0fc5SRavi Teja struct IPv6AddressData 77e48c0fc5SRavi Teja { 78e48c0fc5SRavi Teja std::string id; 79e48c0fc5SRavi Teja std::string address; 80e48c0fc5SRavi Teja std::string origin; 81e48c0fc5SRavi Teja uint8_t prefixLength; 82e48c0fc5SRavi Teja 83e48c0fc5SRavi Teja bool operator<(const IPv6AddressData &obj) const 84e48c0fc5SRavi Teja { 85e48c0fc5SRavi Teja return id < obj.id; 86e48c0fc5SRavi Teja } 87e48c0fc5SRavi Teja }; 88e48c0fc5SRavi Teja /** 899391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 909391bb9cSRapkiewicz, Pawel * available from DBus 919391bb9cSRapkiewicz, Pawel */ 921abe55efSEd Tanous struct EthernetInterfaceData 931abe55efSEd Tanous { 944a0cb85cSEd Tanous uint32_t speed; 954a0cb85cSEd Tanous bool auto_neg; 96*1f8c7b5dSJohnathan Mantey bool DNSEnabled; 97*1f8c7b5dSJohnathan Mantey bool NTPEnabled; 98*1f8c7b5dSJohnathan Mantey bool HostNameEnabled; 99*1f8c7b5dSJohnathan Mantey bool SendHostNameEnabled; 100*1f8c7b5dSJohnathan Mantey std::string DHCPEnabled; 101*1f8c7b5dSJohnathan Mantey std::string operatingMode; 1024a0cb85cSEd Tanous std::string hostname; 1034a0cb85cSEd Tanous std::string default_gateway; 1049a6fc6feSRavi Teja std::string ipv6_default_gateway; 1054a0cb85cSEd Tanous std::string mac_address; 106fda13ad2SSunitha Harish std::vector<std::uint32_t> vlan_id; 107029573d4SEd Tanous std::vector<std::string> nameservers; 108d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1099391bb9cSRapkiewicz, Pawel }; 1109391bb9cSRapkiewicz, Pawel 111*1f8c7b5dSJohnathan Mantey struct DHCPParameters 112*1f8c7b5dSJohnathan Mantey { 113*1f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 114*1f8c7b5dSJohnathan Mantey std::optional<bool> useDNSServers; 115*1f8c7b5dSJohnathan Mantey std::optional<bool> useNTPServers; 116*1f8c7b5dSJohnathan Mantey std::optional<bool> useUseDomainName; 117*1f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 118*1f8c7b5dSJohnathan Mantey }; 119*1f8c7b5dSJohnathan Mantey 1209391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1219391bb9cSRapkiewicz, Pawel // into full dot notation 1221abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1231abe55efSEd Tanous { 1249391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1259391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1269391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1279391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1289391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1299391bb9cSRapkiewicz, Pawel return netmask; 1309391bb9cSRapkiewicz, Pawel } 1319391bb9cSRapkiewicz, Pawel 132*1f8c7b5dSJohnathan Mantey inline bool translateDHCPEnabledToBool(const std::string &inputDHCP, 133*1f8c7b5dSJohnathan Mantey bool isIPv4) 134*1f8c7b5dSJohnathan Mantey { 135*1f8c7b5dSJohnathan Mantey if (isIPv4) 136*1f8c7b5dSJohnathan Mantey { 137*1f8c7b5dSJohnathan Mantey return ( 138*1f8c7b5dSJohnathan Mantey (inputDHCP == 139*1f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 140*1f8c7b5dSJohnathan Mantey (inputDHCP == 141*1f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 142*1f8c7b5dSJohnathan Mantey } 143*1f8c7b5dSJohnathan Mantey return ((inputDHCP == 144*1f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 145*1f8c7b5dSJohnathan Mantey (inputDHCP == 146*1f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 147*1f8c7b5dSJohnathan Mantey } 148*1f8c7b5dSJohnathan Mantey 149*1f8c7b5dSJohnathan Mantey inline std::string GetDHCPEnabledEnumeration(bool isIPv4, bool isIPv6) 150*1f8c7b5dSJohnathan Mantey { 151*1f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 152*1f8c7b5dSJohnathan Mantey { 153*1f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 154*1f8c7b5dSJohnathan Mantey } 155*1f8c7b5dSJohnathan Mantey else if (isIPv4) 156*1f8c7b5dSJohnathan Mantey { 157*1f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 158*1f8c7b5dSJohnathan Mantey } 159*1f8c7b5dSJohnathan Mantey else if (isIPv6) 160*1f8c7b5dSJohnathan Mantey { 161*1f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 162*1f8c7b5dSJohnathan Mantey } 163*1f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 164*1f8c7b5dSJohnathan Mantey } 165*1f8c7b5dSJohnathan Mantey 1664a0cb85cSEd Tanous inline std::string 1674a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string &inputOrigin, 1684a0cb85cSEd Tanous bool isIPv4) 1691abe55efSEd Tanous { 1704a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1711abe55efSEd Tanous { 1724a0cb85cSEd Tanous return "Static"; 1739391bb9cSRapkiewicz, Pawel } 1744a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1751abe55efSEd Tanous { 1764a0cb85cSEd Tanous if (isIPv4) 1771abe55efSEd Tanous { 1784a0cb85cSEd Tanous return "IPv4LinkLocal"; 1791abe55efSEd Tanous } 1801abe55efSEd Tanous else 1811abe55efSEd Tanous { 1824a0cb85cSEd Tanous return "LinkLocal"; 1839391bb9cSRapkiewicz, Pawel } 1849391bb9cSRapkiewicz, Pawel } 1854a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1861abe55efSEd Tanous { 1874a0cb85cSEd Tanous if (isIPv4) 1884a0cb85cSEd Tanous { 1894a0cb85cSEd Tanous return "DHCP"; 1904a0cb85cSEd Tanous } 1914a0cb85cSEd Tanous else 1924a0cb85cSEd Tanous { 1934a0cb85cSEd Tanous return "DHCPv6"; 1944a0cb85cSEd Tanous } 1954a0cb85cSEd Tanous } 1964a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1974a0cb85cSEd Tanous { 1984a0cb85cSEd Tanous return "SLAAC"; 1994a0cb85cSEd Tanous } 2004a0cb85cSEd Tanous return ""; 2014a0cb85cSEd Tanous } 2024a0cb85cSEd Tanous 2034c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string ðiface_id, 2044a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 2054a0cb85cSEd Tanous EthernetInterfaceData ðData) 2064a0cb85cSEd Tanous { 2074c9afe43SEd Tanous bool idFound = false; 2084a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 2094a0cb85cSEd Tanous { 2104a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 2114a0cb85cSEd Tanous { 212029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 213029573d4SEd Tanous { 2144c9afe43SEd Tanous idFound = true; 2154a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2164a0cb85cSEd Tanous { 2174a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2184a0cb85cSEd Tanous { 2194a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2204a0cb85cSEd Tanous { 2214a0cb85cSEd Tanous const std::string *mac = 222abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2234a0cb85cSEd Tanous if (mac != nullptr) 2244a0cb85cSEd Tanous { 2254a0cb85cSEd Tanous ethData.mac_address = *mac; 2264a0cb85cSEd Tanous } 2274a0cb85cSEd Tanous } 2284a0cb85cSEd Tanous } 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2314a0cb85cSEd Tanous { 2324a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2334a0cb85cSEd Tanous { 2344a0cb85cSEd Tanous if (propertyPair.first == "Id") 2354a0cb85cSEd Tanous { 2361b6b96c5SEd Tanous const uint32_t *id = 237abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2384a0cb85cSEd Tanous if (id != nullptr) 2394a0cb85cSEd Tanous { 240fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 2414a0cb85cSEd Tanous } 2424a0cb85cSEd Tanous } 2434a0cb85cSEd Tanous } 2444a0cb85cSEd Tanous } 2454a0cb85cSEd Tanous else if (ifacePair.first == 2464a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2474a0cb85cSEd Tanous { 2484a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2494a0cb85cSEd Tanous { 2504a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2514a0cb85cSEd Tanous { 2524a0cb85cSEd Tanous const bool *auto_neg = 253abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2544a0cb85cSEd Tanous if (auto_neg != nullptr) 2554a0cb85cSEd Tanous { 2564a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2574a0cb85cSEd Tanous } 2584a0cb85cSEd Tanous } 2594a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2604a0cb85cSEd Tanous { 2614a0cb85cSEd Tanous const uint32_t *speed = 262abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2634a0cb85cSEd Tanous if (speed != nullptr) 2644a0cb85cSEd Tanous { 2654a0cb85cSEd Tanous ethData.speed = *speed; 2664a0cb85cSEd Tanous } 2674a0cb85cSEd Tanous } 268f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 269029573d4SEd Tanous { 270029573d4SEd Tanous const std::vector<std::string> *nameservers = 271029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 272029573d4SEd Tanous std::vector<std::string>>( 273029573d4SEd Tanous &propertyPair.second); 274029573d4SEd Tanous if (nameservers != nullptr) 275029573d4SEd Tanous { 276029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2774a0cb85cSEd Tanous } 2784a0cb85cSEd Tanous } 2792a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 2802a133282Smanojkiraneda { 281*1f8c7b5dSJohnathan Mantey const std::string *DHCPEnabled = 282*1f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 2832a133282Smanojkiraneda if (DHCPEnabled != nullptr) 2842a133282Smanojkiraneda { 2852a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 2862a133282Smanojkiraneda } 2872a133282Smanojkiraneda } 288d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 289d24bfc7aSJennifer Lee { 290d24bfc7aSJennifer Lee const std::vector<std::string> *domainNames = 291d24bfc7aSJennifer Lee sdbusplus::message::variant_ns::get_if< 292d24bfc7aSJennifer Lee std::vector<std::string>>( 293d24bfc7aSJennifer Lee &propertyPair.second); 294d24bfc7aSJennifer Lee if (domainNames != nullptr) 295d24bfc7aSJennifer Lee { 296d24bfc7aSJennifer Lee ethData.domainnames = std::move(*domainNames); 297d24bfc7aSJennifer Lee } 298d24bfc7aSJennifer Lee } 299029573d4SEd Tanous } 300029573d4SEd Tanous } 301029573d4SEd Tanous } 302*1f8c7b5dSJohnathan Mantey 303*1f8c7b5dSJohnathan Mantey if (objpath.first == "/xyz/openbmc_project/network/config/dhcp") 304*1f8c7b5dSJohnathan Mantey { 305*1f8c7b5dSJohnathan Mantey if (ifacePair.first == 306*1f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 307*1f8c7b5dSJohnathan Mantey { 308*1f8c7b5dSJohnathan Mantey for (const auto &propertyPair : ifacePair.second) 309*1f8c7b5dSJohnathan Mantey { 310*1f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 311*1f8c7b5dSJohnathan Mantey { 312*1f8c7b5dSJohnathan Mantey const bool *DNSEnabled = 313*1f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 314*1f8c7b5dSJohnathan Mantey if (DNSEnabled != nullptr) 315*1f8c7b5dSJohnathan Mantey { 316*1f8c7b5dSJohnathan Mantey ethData.DNSEnabled = *DNSEnabled; 317*1f8c7b5dSJohnathan Mantey } 318*1f8c7b5dSJohnathan Mantey } 319*1f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 320*1f8c7b5dSJohnathan Mantey { 321*1f8c7b5dSJohnathan Mantey const bool *NTPEnabled = 322*1f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 323*1f8c7b5dSJohnathan Mantey if (NTPEnabled != nullptr) 324*1f8c7b5dSJohnathan Mantey { 325*1f8c7b5dSJohnathan Mantey ethData.NTPEnabled = *NTPEnabled; 326*1f8c7b5dSJohnathan Mantey } 327*1f8c7b5dSJohnathan Mantey } 328*1f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 329*1f8c7b5dSJohnathan Mantey { 330*1f8c7b5dSJohnathan Mantey const bool *HostNameEnabled = 331*1f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 332*1f8c7b5dSJohnathan Mantey if (HostNameEnabled != nullptr) 333*1f8c7b5dSJohnathan Mantey { 334*1f8c7b5dSJohnathan Mantey ethData.HostNameEnabled = *HostNameEnabled; 335*1f8c7b5dSJohnathan Mantey } 336*1f8c7b5dSJohnathan Mantey } 337*1f8c7b5dSJohnathan Mantey else if (propertyPair.first == "SendHostNameEnabled") 338*1f8c7b5dSJohnathan Mantey { 339*1f8c7b5dSJohnathan Mantey const bool *SendHostNameEnabled = 340*1f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 341*1f8c7b5dSJohnathan Mantey if (SendHostNameEnabled != nullptr) 342*1f8c7b5dSJohnathan Mantey { 343*1f8c7b5dSJohnathan Mantey ethData.SendHostNameEnabled = 344*1f8c7b5dSJohnathan Mantey *SendHostNameEnabled; 345*1f8c7b5dSJohnathan Mantey } 346*1f8c7b5dSJohnathan Mantey } 347*1f8c7b5dSJohnathan Mantey } 348*1f8c7b5dSJohnathan Mantey } 349*1f8c7b5dSJohnathan Mantey } 350029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 351029573d4SEd Tanous // to check eth number 352029573d4SEd Tanous if (ifacePair.first == 3534a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 3544a0cb85cSEd Tanous { 3554a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 3564a0cb85cSEd Tanous { 3574a0cb85cSEd Tanous if (propertyPair.first == "HostName") 3584a0cb85cSEd Tanous { 3594a0cb85cSEd Tanous const std::string *hostname = 360029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 361029573d4SEd Tanous &propertyPair.second); 3624a0cb85cSEd Tanous if (hostname != nullptr) 3634a0cb85cSEd Tanous { 3644a0cb85cSEd Tanous ethData.hostname = *hostname; 3654a0cb85cSEd Tanous } 3664a0cb85cSEd Tanous } 3674a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 3684a0cb85cSEd Tanous { 3694a0cb85cSEd Tanous const std::string *defaultGateway = 370029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 371029573d4SEd Tanous &propertyPair.second); 3724a0cb85cSEd Tanous if (defaultGateway != nullptr) 3734a0cb85cSEd Tanous { 3744a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 3754a0cb85cSEd Tanous } 3764a0cb85cSEd Tanous } 3779a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3789a6fc6feSRavi Teja { 3799a6fc6feSRavi Teja const std::string *defaultGateway6 = 3809a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 3819a6fc6feSRavi Teja &propertyPair.second); 3829a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 3839a6fc6feSRavi Teja { 3849a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 3859a6fc6feSRavi Teja } 3869a6fc6feSRavi Teja } 3874a0cb85cSEd Tanous } 3884a0cb85cSEd Tanous } 3894a0cb85cSEd Tanous } 3904a0cb85cSEd Tanous } 3914c9afe43SEd Tanous return idFound; 3924a0cb85cSEd Tanous } 3934a0cb85cSEd Tanous 394e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 39501784826SJohnathan Mantey inline void 39601784826SJohnathan Mantey extractIPV6Data(const std::string ðiface_id, 39701784826SJohnathan Mantey const GetManagedObjects &dbus_data, 39801784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData> &ipv6_config) 399e48c0fc5SRavi Teja { 400e48c0fc5SRavi Teja const std::string ipv6PathStart = 401e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/"; 402e48c0fc5SRavi Teja 403e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 404e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 405e48c0fc5SRavi Teja for (const auto &objpath : dbus_data) 406e48c0fc5SRavi Teja { 407e48c0fc5SRavi Teja // Check if proper pattern for object path appears 408e48c0fc5SRavi Teja if (boost::starts_with(objpath.first.str, ipv6PathStart)) 409e48c0fc5SRavi Teja { 410e48c0fc5SRavi Teja for (auto &interface : objpath.second) 411e48c0fc5SRavi Teja { 412e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 413e48c0fc5SRavi Teja { 414e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 415e48c0fc5SRavi Teja // appropriate 416e48c0fc5SRavi Teja std::pair< 417e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::iterator, 418e48c0fc5SRavi Teja bool> 419271584abSEd Tanous it = ipv6_config.insert(IPv6AddressData{}); 420e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 421271584abSEd Tanous ipv6_address.id = 422271584abSEd Tanous objpath.first.str.substr(ipv6PathStart.size()); 423e48c0fc5SRavi Teja for (auto &property : interface.second) 424e48c0fc5SRavi Teja { 425e48c0fc5SRavi Teja if (property.first == "Address") 426e48c0fc5SRavi Teja { 427e48c0fc5SRavi Teja const std::string *address = 428e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 429e48c0fc5SRavi Teja if (address != nullptr) 430e48c0fc5SRavi Teja { 431e48c0fc5SRavi Teja ipv6_address.address = *address; 432e48c0fc5SRavi Teja } 433e48c0fc5SRavi Teja } 434e48c0fc5SRavi Teja else if (property.first == "Origin") 435e48c0fc5SRavi Teja { 436e48c0fc5SRavi Teja const std::string *origin = 437e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 438e48c0fc5SRavi Teja if (origin != nullptr) 439e48c0fc5SRavi Teja { 440e48c0fc5SRavi Teja ipv6_address.origin = 441e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 442e48c0fc5SRavi Teja false); 443e48c0fc5SRavi Teja } 444e48c0fc5SRavi Teja } 445e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 446e48c0fc5SRavi Teja { 447e48c0fc5SRavi Teja const uint8_t *prefix = 448e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 449e48c0fc5SRavi Teja if (prefix != nullptr) 450e48c0fc5SRavi Teja { 451e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 452e48c0fc5SRavi Teja } 453e48c0fc5SRavi Teja } 454e48c0fc5SRavi Teja else 455e48c0fc5SRavi Teja { 456e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 457e48c0fc5SRavi Teja << "Got extra property: " << property.first 458e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 459e48c0fc5SRavi Teja } 460e48c0fc5SRavi Teja } 461e48c0fc5SRavi Teja } 462e48c0fc5SRavi Teja } 463e48c0fc5SRavi Teja } 464e48c0fc5SRavi Teja } 465e48c0fc5SRavi Teja } 466e48c0fc5SRavi Teja 4674a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 46801784826SJohnathan Mantey inline void 46901784826SJohnathan Mantey extractIPData(const std::string ðiface_id, 47001784826SJohnathan Mantey const GetManagedObjects &dbus_data, 47101784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData> &ipv4_config) 4724a0cb85cSEd Tanous { 4734a0cb85cSEd Tanous const std::string ipv4PathStart = 4744a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 4754a0cb85cSEd Tanous 4764a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 4774a0cb85cSEd Tanous // single ethernet interface, loop over all of them 4784a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 4794a0cb85cSEd Tanous { 4804a0cb85cSEd Tanous // Check if proper pattern for object path appears 4814a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 4824a0cb85cSEd Tanous { 4834a0cb85cSEd Tanous for (auto &interface : objpath.second) 4844a0cb85cSEd Tanous { 4854a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 4864a0cb85cSEd Tanous { 4874a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 4884a0cb85cSEd Tanous // appropriate 4894a0cb85cSEd Tanous std::pair< 4904a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 4914a0cb85cSEd Tanous bool> 492271584abSEd Tanous it = ipv4_config.insert(IPv4AddressData{}); 4934a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 494271584abSEd Tanous ipv4_address.id = 495271584abSEd Tanous objpath.first.str.substr(ipv4PathStart.size()); 4964a0cb85cSEd Tanous for (auto &property : interface.second) 4974a0cb85cSEd Tanous { 4984a0cb85cSEd Tanous if (property.first == "Address") 4994a0cb85cSEd Tanous { 5004a0cb85cSEd Tanous const std::string *address = 501abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5024a0cb85cSEd Tanous if (address != nullptr) 5034a0cb85cSEd Tanous { 5044a0cb85cSEd Tanous ipv4_address.address = *address; 5054a0cb85cSEd Tanous } 5064a0cb85cSEd Tanous } 5074a0cb85cSEd Tanous else if (property.first == "Gateway") 5084a0cb85cSEd Tanous { 5094a0cb85cSEd Tanous const std::string *gateway = 510abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5114a0cb85cSEd Tanous if (gateway != nullptr) 5124a0cb85cSEd Tanous { 5134a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 5144a0cb85cSEd Tanous } 5154a0cb85cSEd Tanous } 5164a0cb85cSEd Tanous else if (property.first == "Origin") 5174a0cb85cSEd Tanous { 5184a0cb85cSEd Tanous const std::string *origin = 519abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5204a0cb85cSEd Tanous if (origin != nullptr) 5214a0cb85cSEd Tanous { 5224a0cb85cSEd Tanous ipv4_address.origin = 5234a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 5244a0cb85cSEd Tanous true); 5254a0cb85cSEd Tanous } 5264a0cb85cSEd Tanous } 5274a0cb85cSEd Tanous else if (property.first == "PrefixLength") 5284a0cb85cSEd Tanous { 5294a0cb85cSEd Tanous const uint8_t *mask = 530abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 5314a0cb85cSEd Tanous if (mask != nullptr) 5324a0cb85cSEd Tanous { 5334a0cb85cSEd Tanous // convert it to the string 5344a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 5354a0cb85cSEd Tanous } 5364a0cb85cSEd Tanous } 5374a0cb85cSEd Tanous else 5384a0cb85cSEd Tanous { 5394a0cb85cSEd Tanous BMCWEB_LOG_ERROR 5404a0cb85cSEd Tanous << "Got extra property: " << property.first 5414a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 5424a0cb85cSEd Tanous } 5434a0cb85cSEd Tanous } 5444a0cb85cSEd Tanous // Check if given address is local, or global 5454a0cb85cSEd Tanous ipv4_address.linktype = 5464a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 54718659d10SJohnathan Mantey ? LinkType::Local 54818659d10SJohnathan Mantey : LinkType::Global; 5494a0cb85cSEd Tanous } 5504a0cb85cSEd Tanous } 5514a0cb85cSEd Tanous } 5524a0cb85cSEd Tanous } 5534a0cb85cSEd Tanous } 554588c3f0dSKowalski, Kamil 555588c3f0dSKowalski, Kamil /** 556588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 557588c3f0dSKowalski, Kamil * 558588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 559588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 560588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 561588c3f0dSKowalski, Kamil * 562588c3f0dSKowalski, Kamil * @return None. 563588c3f0dSKowalski, Kamil */ 564588c3f0dSKowalski, Kamil template <typename CallbackFunc> 5654a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 5661abe55efSEd Tanous CallbackFunc &&callback) 5671abe55efSEd Tanous { 56855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 569588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 570588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 571588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 572588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 573abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 5744a0cb85cSEd Tanous } 575588c3f0dSKowalski, Kamil 576588c3f0dSKowalski, Kamil /** 577179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 578179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 579179db1d7SKowalski, Kamil * bit count for Subnet Mask. 580179db1d7SKowalski, Kamil * 581179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 582179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 583179db1d7SKowalski, Kamil * 584179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 585179db1d7SKowalski, Kamil */ 5864a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 5871abe55efSEd Tanous uint8_t *bits = nullptr) 5881abe55efSEd Tanous { 589179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 590179db1d7SKowalski, Kamil 591179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 592179db1d7SKowalski, Kamil 5934a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 5941abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 5951abe55efSEd Tanous { 596179db1d7SKowalski, Kamil return false; 597179db1d7SKowalski, Kamil } 598179db1d7SKowalski, Kamil 5991abe55efSEd Tanous if (bits != nullptr) 6001abe55efSEd Tanous { 601179db1d7SKowalski, Kamil *bits = 0; 602179db1d7SKowalski, Kamil } 603179db1d7SKowalski, Kamil 604179db1d7SKowalski, Kamil char *endPtr; 605179db1d7SKowalski, Kamil long previousValue = 255; 606179db1d7SKowalski, Kamil bool firstZeroInByteHit; 6071abe55efSEd Tanous for (const std::string &byte : bytesInMask) 6081abe55efSEd Tanous { 6091abe55efSEd Tanous if (byte.empty()) 6101abe55efSEd Tanous { 6111db9ca37SKowalski, Kamil return false; 6121db9ca37SKowalski, Kamil } 6131db9ca37SKowalski, Kamil 614179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 6151db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 616179db1d7SKowalski, Kamil 6174a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 6184a0cb85cSEd Tanous // is not 100% number 6191abe55efSEd Tanous if (*endPtr != '\0') 6201abe55efSEd Tanous { 621179db1d7SKowalski, Kamil return false; 622179db1d7SKowalski, Kamil } 623179db1d7SKowalski, Kamil 624179db1d7SKowalski, Kamil // Value should be contained in byte 6251abe55efSEd Tanous if (value < 0 || value > 255) 6261abe55efSEd Tanous { 627179db1d7SKowalski, Kamil return false; 628179db1d7SKowalski, Kamil } 629179db1d7SKowalski, Kamil 6301abe55efSEd Tanous if (bits != nullptr) 6311abe55efSEd Tanous { 632179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 6331abe55efSEd Tanous if (previousValue != 255 && value != 0) 6341abe55efSEd Tanous { 635179db1d7SKowalski, Kamil return false; 636179db1d7SKowalski, Kamil } 637179db1d7SKowalski, Kamil 638179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 639179db1d7SKowalski, Kamil firstZeroInByteHit = false; 640179db1d7SKowalski, Kamil 641179db1d7SKowalski, Kamil // Count bits 6421abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 6431abe55efSEd Tanous { 6441abe55efSEd Tanous if (value & (1 << bitIdx)) 6451abe55efSEd Tanous { 6461abe55efSEd Tanous if (firstZeroInByteHit) 6471abe55efSEd Tanous { 648179db1d7SKowalski, Kamil // Continuity not preserved 649179db1d7SKowalski, Kamil return false; 6501abe55efSEd Tanous } 6511abe55efSEd Tanous else 6521abe55efSEd Tanous { 653179db1d7SKowalski, Kamil (*bits)++; 654179db1d7SKowalski, Kamil } 6551abe55efSEd Tanous } 6561abe55efSEd Tanous else 6571abe55efSEd Tanous { 658179db1d7SKowalski, Kamil firstZeroInByteHit = true; 659179db1d7SKowalski, Kamil } 660179db1d7SKowalski, Kamil } 661179db1d7SKowalski, Kamil } 662179db1d7SKowalski, Kamil 663179db1d7SKowalski, Kamil previousValue = value; 664179db1d7SKowalski, Kamil } 665179db1d7SKowalski, Kamil 666179db1d7SKowalski, Kamil return true; 667179db1d7SKowalski, Kamil } 668179db1d7SKowalski, Kamil 669179db1d7SKowalski, Kamil /** 67001784826SJohnathan Mantey * @brief Deletes given IPv4 interface 671179db1d7SKowalski, Kamil * 672179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 673179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 674179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 675179db1d7SKowalski, Kamil * 676179db1d7SKowalski, Kamil * @return None 677179db1d7SKowalski, Kamil */ 6784a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 6794a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 6801abe55efSEd Tanous { 68155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 682286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 6831abe55efSEd Tanous if (ec) 6841abe55efSEd Tanous { 685a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6861abe55efSEd Tanous } 687179db1d7SKowalski, Kamil }, 688179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 689179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 690179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 691179db1d7SKowalski, Kamil } 692179db1d7SKowalski, Kamil 693179db1d7SKowalski, Kamil /** 69401784826SJohnathan Mantey * @brief Creates a static IPv4 entry 695179db1d7SKowalski, Kamil * 69601784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 69701784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 69801784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 69901784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 700179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 701179db1d7SKowalski, Kamil * 702179db1d7SKowalski, Kamil * @return None 703179db1d7SKowalski, Kamil */ 704b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 70501784826SJohnathan Mantey uint8_t prefixLength, const std::string &gateway, 706b01bf299SEd Tanous const std::string &address, 7074a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 7081abe55efSEd Tanous { 70901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 71001784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 7111abe55efSEd Tanous if (ec) 7121abe55efSEd Tanous { 713a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 714179db1d7SKowalski, Kamil } 71501784826SJohnathan Mantey }, 71601784826SJohnathan Mantey "xyz.openbmc_project.Network", 717179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 718179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 71901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 720179db1d7SKowalski, Kamil gateway); 721179db1d7SKowalski, Kamil } 722e48c0fc5SRavi Teja 723e48c0fc5SRavi Teja /** 72401784826SJohnathan Mantey * @brief Deletes the IPv4 entry for this interface and creates a replacement 72501784826SJohnathan Mantey * static IPv4 entry 72601784826SJohnathan Mantey * 72701784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 72801784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 72901784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 73001784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 73101784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 73201784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 73301784826SJohnathan Mantey * 73401784826SJohnathan Mantey * @return None 73501784826SJohnathan Mantey */ 73601784826SJohnathan Mantey inline void deleteAndCreateIPv4(const std::string &ifaceId, 73701784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 73801784826SJohnathan Mantey const std::string &gateway, 73901784826SJohnathan Mantey const std::string &address, 74001784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 74101784826SJohnathan Mantey { 74201784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 74301784826SJohnathan Mantey [asyncResp, ifaceId, address, prefixLength, 74401784826SJohnathan Mantey gateway](const boost::system::error_code ec) { 74501784826SJohnathan Mantey if (ec) 74601784826SJohnathan Mantey { 74701784826SJohnathan Mantey messages::internalError(asyncResp->res); 74801784826SJohnathan Mantey } 74901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 75001784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 75101784826SJohnathan Mantey if (ec) 75201784826SJohnathan Mantey { 75301784826SJohnathan Mantey messages::internalError(asyncResp->res); 75401784826SJohnathan Mantey } 75501784826SJohnathan Mantey }, 75601784826SJohnathan Mantey "xyz.openbmc_project.Network", 75701784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 75801784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 75901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, 76001784826SJohnathan Mantey prefixLength, gateway); 76101784826SJohnathan Mantey }, 76201784826SJohnathan Mantey "xyz.openbmc_project.Network", 76301784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + id, 76401784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 76501784826SJohnathan Mantey } 76601784826SJohnathan Mantey 76701784826SJohnathan Mantey /** 768e48c0fc5SRavi Teja * @brief Deletes given IPv6 769e48c0fc5SRavi Teja * 770e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 771e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 772e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 773e48c0fc5SRavi Teja * 774e48c0fc5SRavi Teja * @return None 775e48c0fc5SRavi Teja */ 776e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 777e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 778e48c0fc5SRavi Teja { 779e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 780286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 781e48c0fc5SRavi Teja if (ec) 782e48c0fc5SRavi Teja { 783e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 784e48c0fc5SRavi Teja } 785e48c0fc5SRavi Teja }, 786e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 787e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 788e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 789e48c0fc5SRavi Teja } 790e48c0fc5SRavi Teja 791e48c0fc5SRavi Teja /** 79201784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 79301784826SJohnathan Mantey * static IPv6 entry 79401784826SJohnathan Mantey * 79501784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 79601784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 79701784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 79801784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 79901784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 80001784826SJohnathan Mantey * 80101784826SJohnathan Mantey * @return None 80201784826SJohnathan Mantey */ 80301784826SJohnathan Mantey inline void deleteAndCreateIPv6(const std::string &ifaceId, 80401784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 80501784826SJohnathan Mantey const std::string &address, 80601784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 80701784826SJohnathan Mantey { 80801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 80901784826SJohnathan Mantey [asyncResp, ifaceId, address, 81001784826SJohnathan Mantey prefixLength](const boost::system::error_code ec) { 81101784826SJohnathan Mantey if (ec) 81201784826SJohnathan Mantey { 81301784826SJohnathan Mantey messages::internalError(asyncResp->res); 81401784826SJohnathan Mantey } 81501784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 81601784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 81701784826SJohnathan Mantey if (ec) 81801784826SJohnathan Mantey { 81901784826SJohnathan Mantey messages::internalError(asyncResp->res); 82001784826SJohnathan Mantey } 82101784826SJohnathan Mantey }, 82201784826SJohnathan Mantey "xyz.openbmc_project.Network", 82301784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 82401784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 82501784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, 82601784826SJohnathan Mantey prefixLength, ""); 82701784826SJohnathan Mantey }, 82801784826SJohnathan Mantey "xyz.openbmc_project.Network", 82901784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + id, 83001784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 83101784826SJohnathan Mantey } 83201784826SJohnathan Mantey 83301784826SJohnathan Mantey /** 834e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 835e48c0fc5SRavi Teja * 836e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 837e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 838e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 839e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 840e48c0fc5SRavi Teja * 841e48c0fc5SRavi Teja * @return None 842e48c0fc5SRavi Teja */ 84301784826SJohnathan Mantey inline void createIPv6(const std::string &ifaceId, uint8_t prefixLength, 84401784826SJohnathan Mantey const std::string &address, 845e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 846e48c0fc5SRavi Teja { 847e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 848e48c0fc5SRavi Teja if (ec) 849e48c0fc5SRavi Teja { 850e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 851e48c0fc5SRavi Teja } 852e48c0fc5SRavi Teja }; 853e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 854e48c0fc5SRavi Teja // does not have assosiated gateway property 855e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 856e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 857e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 858e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 859e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 860e48c0fc5SRavi Teja ""); 861e48c0fc5SRavi Teja } 862e48c0fc5SRavi Teja 863179db1d7SKowalski, Kamil /** 864179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 865179db1d7SKowalski, Kamil * Object 866179db1d7SKowalski, Kamil * from EntityManager Network Manager 8674a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 868179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 869179db1d7SKowalski, Kamil * into JSON 870179db1d7SKowalski, Kamil */ 871179db1d7SKowalski, Kamil template <typename CallbackFunc> 8724a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8731abe55efSEd Tanous CallbackFunc &&callback) 8741abe55efSEd Tanous { 87555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8764a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8771abe55efSEd Tanous const boost::system::error_code error_code, 8784a0cb85cSEd Tanous const GetManagedObjects &resp) { 87955c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8804a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 881e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 882179db1d7SKowalski, Kamil 8831abe55efSEd Tanous if (error_code) 8841abe55efSEd Tanous { 88501784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 886179db1d7SKowalski, Kamil return; 887179db1d7SKowalski, Kamil } 888179db1d7SKowalski, Kamil 8894c9afe43SEd Tanous bool found = 8904a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 8914c9afe43SEd Tanous if (!found) 8924c9afe43SEd Tanous { 89301784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 8944c9afe43SEd Tanous return; 8954c9afe43SEd Tanous } 8964c9afe43SEd Tanous 89701784826SJohnathan Mantey extractIPData(ethiface_id, resp, ipv4Data); 898179db1d7SKowalski, Kamil // Fix global GW 8991abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 9001abe55efSEd Tanous { 901c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 902c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 903c619141bSRavi Teja (ipv4.origin == "DHCP")) 9041abe55efSEd Tanous { 9054a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 906179db1d7SKowalski, Kamil } 907179db1d7SKowalski, Kamil } 908179db1d7SKowalski, Kamil 90901784826SJohnathan Mantey extractIPV6Data(ethiface_id, resp, ipv6Data); 9104a0cb85cSEd Tanous // Finally make a callback with usefull data 91101784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 912179db1d7SKowalski, Kamil }, 913179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 914179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 915271584abSEd Tanous } 916179db1d7SKowalski, Kamil 917179db1d7SKowalski, Kamil /** 9189391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 9199391bb9cSRapkiewicz, Pawel * Manager 9201abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 9211abe55efSEd Tanous * into JSON. 9229391bb9cSRapkiewicz, Pawel */ 9239391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 9241abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 9251abe55efSEd Tanous { 92655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 9274a0cb85cSEd Tanous [callback{std::move(callback)}]( 9289391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 9294a0cb85cSEd Tanous GetManagedObjects &resp) { 9301abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 9311abe55efSEd Tanous // ethernet interfaces 9324c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 9334a0cb85cSEd Tanous iface_list.reserve(resp.size()); 9341abe55efSEd Tanous if (error_code) 9351abe55efSEd Tanous { 9364a0cb85cSEd Tanous callback(false, iface_list); 9379391bb9cSRapkiewicz, Pawel return; 9389391bb9cSRapkiewicz, Pawel } 9399391bb9cSRapkiewicz, Pawel 9409391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 9414a0cb85cSEd Tanous for (const auto &objpath : resp) 9421abe55efSEd Tanous { 9439391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 9444a0cb85cSEd Tanous for (const auto &interface : objpath.second) 9451abe55efSEd Tanous { 9461abe55efSEd Tanous // If interface is 9474a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9484a0cb85cSEd Tanous // what we're looking for. 9499391bb9cSRapkiewicz, Pawel if (interface.first == 9501abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9511abe55efSEd Tanous { 9524a0cb85cSEd Tanous // Cut out everyting until last "/", ... 9534a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9544a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9554a0cb85cSEd Tanous if (last_pos != std::string::npos) 9561abe55efSEd Tanous { 9579391bb9cSRapkiewicz, Pawel // and put it into output vector. 9584c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9599391bb9cSRapkiewicz, Pawel } 9609391bb9cSRapkiewicz, Pawel } 9619391bb9cSRapkiewicz, Pawel } 9629391bb9cSRapkiewicz, Pawel } 963a434f2bdSEd Tanous // Finally make a callback with useful data 9644a0cb85cSEd Tanous callback(true, iface_list); 9659391bb9cSRapkiewicz, Pawel }, 966aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 967aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 968271584abSEd Tanous } 9699391bb9cSRapkiewicz, Pawel 9709391bb9cSRapkiewicz, Pawel /** 9719391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9729391bb9cSRapkiewicz, Pawel */ 9731abe55efSEd Tanous class EthernetCollection : public Node 9741abe55efSEd Tanous { 9759391bb9cSRapkiewicz, Pawel public: 9764a0cb85cSEd Tanous template <typename CrowApp> 9771abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9784a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9791abe55efSEd Tanous { 980588c3f0dSKowalski, Kamil entityPrivileges = { 981588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 982e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 983e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 984e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 985e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 986e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9879391bb9cSRapkiewicz, Pawel } 9889391bb9cSRapkiewicz, Pawel 9899391bb9cSRapkiewicz, Pawel private: 9909391bb9cSRapkiewicz, Pawel /** 9919391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 9929391bb9cSRapkiewicz, Pawel */ 99355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 9941abe55efSEd Tanous const std::vector<std::string> ¶ms) override 9951abe55efSEd Tanous { 9960f74e643SEd Tanous res.jsonValue["@odata.type"] = 9970f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9980f74e643SEd Tanous res.jsonValue["@odata.context"] = 9990f74e643SEd Tanous "/redfish/v1/" 10000f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 10010f74e643SEd Tanous res.jsonValue["@odata.id"] = 10020f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 10030f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 10040f74e643SEd Tanous res.jsonValue["Description"] = 10050f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 10064c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 10074a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 10081abe55efSEd Tanous // preparation 1009f12894f8SJason M. Bills getEthernetIfaceList( 10104c9afe43SEd Tanous [asyncResp]( 10114c9afe43SEd Tanous const bool &success, 10124c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 10134a0cb85cSEd Tanous if (!success) 10141abe55efSEd Tanous { 10154c9afe43SEd Tanous messages::internalError(asyncResp->res); 10164a0cb85cSEd Tanous return; 10174a0cb85cSEd Tanous } 10184a0cb85cSEd Tanous 10194c9afe43SEd Tanous nlohmann::json &iface_array = 10204c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 10214a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 1022fda13ad2SSunitha Harish std::string tag = "_"; 10234a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 10241abe55efSEd Tanous { 1025fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 1026fda13ad2SSunitha Harish if (found == std::string::npos) 1027fda13ad2SSunitha Harish { 10284a0cb85cSEd Tanous iface_array.push_back( 10294a0cb85cSEd Tanous {{"@odata.id", 10304a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 10314a0cb85cSEd Tanous iface_item}}); 10329391bb9cSRapkiewicz, Pawel } 1033fda13ad2SSunitha Harish } 10344a0cb85cSEd Tanous 10354c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 10364c9afe43SEd Tanous iface_array.size(); 10374c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10384a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 10399391bb9cSRapkiewicz, Pawel }); 10409391bb9cSRapkiewicz, Pawel } 10419391bb9cSRapkiewicz, Pawel }; 10429391bb9cSRapkiewicz, Pawel 10439391bb9cSRapkiewicz, Pawel /** 10449391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 10459391bb9cSRapkiewicz, Pawel */ 10461abe55efSEd Tanous class EthernetInterface : public Node 10471abe55efSEd Tanous { 10489391bb9cSRapkiewicz, Pawel public: 10499391bb9cSRapkiewicz, Pawel /* 10509391bb9cSRapkiewicz, Pawel * Default Constructor 10519391bb9cSRapkiewicz, Pawel */ 10524a0cb85cSEd Tanous template <typename CrowApp> 10531abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10544a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10551abe55efSEd Tanous std::string()) 10561abe55efSEd Tanous { 1057588c3f0dSKowalski, Kamil entityPrivileges = { 1058588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1059e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1060e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1061e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1062e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1063e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10649391bb9cSRapkiewicz, Pawel } 10659391bb9cSRapkiewicz, Pawel 1066e439f0f8SKowalski, Kamil private: 1067bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10684a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10691abe55efSEd Tanous { 1070bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1071bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1072bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10734a0cb85cSEd Tanous if (ec) 10744a0cb85cSEd Tanous { 1075a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10761abe55efSEd Tanous } 1077bc0bd6e0SEd Tanous }, 1078bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1079bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1080bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1081bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1082abf2add6SEd Tanous std::variant<std::string>(hostname)); 1083588c3f0dSKowalski, Kamil } 1084588c3f0dSKowalski, Kamil 1085d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1086d577665bSRatan Gupta const std::string &macAddress, 1087d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1088d577665bSRatan Gupta { 1089d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1090d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1091d577665bSRatan Gupta if (ec) 1092d577665bSRatan Gupta { 1093d577665bSRatan Gupta messages::internalError(asyncResp->res); 1094d577665bSRatan Gupta return; 1095d577665bSRatan Gupta } 1096d577665bSRatan Gupta }, 1097d577665bSRatan Gupta "xyz.openbmc_project.Network", 1098d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1099d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1100d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1101d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1102d577665bSRatan Gupta } 1103286b9118SJohnathan Mantey 1104da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1105*1f8c7b5dSJohnathan Mantey const std::string &propertyName, const bool v4Value, 1106*1f8c7b5dSJohnathan Mantey const bool v6Value, 1107da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1108da131a9aSJennifer Lee { 1109*1f8c7b5dSJohnathan Mantey const std::string dhcp = GetDHCPEnabledEnumeration(v4Value, v6Value); 1110da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1111da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1112da131a9aSJennifer Lee if (ec) 1113da131a9aSJennifer Lee { 1114da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1115da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1116da131a9aSJennifer Lee return; 1117da131a9aSJennifer Lee } 1118da131a9aSJennifer Lee }, 1119da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1120da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1121da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1122da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1123*1f8c7b5dSJohnathan Mantey std::variant<std::string>{dhcp}); 1124da131a9aSJennifer Lee } 1125*1f8c7b5dSJohnathan Mantey 1126da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1127da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1128da131a9aSJennifer Lee { 1129da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1130da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1131da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1132da131a9aSJennifer Lee if (ec) 1133da131a9aSJennifer Lee { 1134da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1135da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1136da131a9aSJennifer Lee return; 1137da131a9aSJennifer Lee } 1138da131a9aSJennifer Lee }, 1139da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1140da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1141da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1142da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1143da131a9aSJennifer Lee std::variant<bool>{value}); 1144da131a9aSJennifer Lee } 1145d577665bSRatan Gupta 1146*1f8c7b5dSJohnathan Mantey void handleDHCPPatch(const std::string &ifaceId, 1147*1f8c7b5dSJohnathan Mantey const EthernetInterfaceData ðData, 1148*1f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms, DHCPParameters v6dhcpParms, 1149da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1150da131a9aSJennifer Lee { 1151*1f8c7b5dSJohnathan Mantey bool ipv4Active = translateDHCPEnabledToBool(ethData.DHCPEnabled, true); 1152*1f8c7b5dSJohnathan Mantey bool ipv6Active = 1153*1f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, false); 1154da131a9aSJennifer Lee 1155*1f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 1156*1f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 1157*1f8c7b5dSJohnathan Mantey 1158*1f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 1159*1f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1160da131a9aSJennifer Lee { 1161*1f8c7b5dSJohnathan Mantey if ((*v6dhcpParms.dhcpv6OperatingMode != "Stateful") && 1162*1f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Stateless") && 1163*1f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 1164*1f8c7b5dSJohnathan Mantey { 1165*1f8c7b5dSJohnathan Mantey messages::propertyValueFormatError( 1166*1f8c7b5dSJohnathan Mantey asyncResp->res, *v6dhcpParms.dhcpv6OperatingMode, 1167*1f8c7b5dSJohnathan Mantey "OperatingMode"); 1168da131a9aSJennifer Lee return; 1169da131a9aSJennifer Lee } 1170*1f8c7b5dSJohnathan Mantey nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Stateful"); 1171*1f8c7b5dSJohnathan Mantey } 1172*1f8c7b5dSJohnathan Mantey else 1173da131a9aSJennifer Lee { 1174*1f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 1175*1f8c7b5dSJohnathan Mantey } 1176*1f8c7b5dSJohnathan Mantey 1177*1f8c7b5dSJohnathan Mantey bool nextDNS{}; 1178*1f8c7b5dSJohnathan Mantey if (v4dhcpParms.useDNSServers && v6dhcpParms.useDNSServers) 1179*1f8c7b5dSJohnathan Mantey { 1180*1f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useDNSServers != *v6dhcpParms.useDNSServers) 1181*1f8c7b5dSJohnathan Mantey { 1182*1f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 1183*1f8c7b5dSJohnathan Mantey return; 1184*1f8c7b5dSJohnathan Mantey } 1185*1f8c7b5dSJohnathan Mantey nextDNS = *v4dhcpParms.useDNSServers; 1186*1f8c7b5dSJohnathan Mantey } 1187*1f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useDNSServers) 1188*1f8c7b5dSJohnathan Mantey { 1189*1f8c7b5dSJohnathan Mantey nextDNS = *v4dhcpParms.useDNSServers; 1190*1f8c7b5dSJohnathan Mantey } 1191*1f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useDNSServers) 1192*1f8c7b5dSJohnathan Mantey { 1193*1f8c7b5dSJohnathan Mantey nextDNS = *v6dhcpParms.useDNSServers; 1194*1f8c7b5dSJohnathan Mantey } 1195*1f8c7b5dSJohnathan Mantey else 1196*1f8c7b5dSJohnathan Mantey { 1197*1f8c7b5dSJohnathan Mantey nextDNS = ethData.DNSEnabled; 1198*1f8c7b5dSJohnathan Mantey } 1199*1f8c7b5dSJohnathan Mantey 1200*1f8c7b5dSJohnathan Mantey bool nextNTP{}; 1201*1f8c7b5dSJohnathan Mantey if (v4dhcpParms.useNTPServers && v6dhcpParms.useNTPServers) 1202*1f8c7b5dSJohnathan Mantey { 1203*1f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useNTPServers != *v6dhcpParms.useNTPServers) 1204*1f8c7b5dSJohnathan Mantey { 1205*1f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 1206*1f8c7b5dSJohnathan Mantey return; 1207*1f8c7b5dSJohnathan Mantey } 1208*1f8c7b5dSJohnathan Mantey nextNTP = *v4dhcpParms.useNTPServers; 1209*1f8c7b5dSJohnathan Mantey } 1210*1f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useNTPServers) 1211*1f8c7b5dSJohnathan Mantey { 1212*1f8c7b5dSJohnathan Mantey nextNTP = *v4dhcpParms.useNTPServers; 1213*1f8c7b5dSJohnathan Mantey } 1214*1f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useNTPServers) 1215*1f8c7b5dSJohnathan Mantey { 1216*1f8c7b5dSJohnathan Mantey nextNTP = *v6dhcpParms.useNTPServers; 1217*1f8c7b5dSJohnathan Mantey } 1218*1f8c7b5dSJohnathan Mantey else 1219*1f8c7b5dSJohnathan Mantey { 1220*1f8c7b5dSJohnathan Mantey nextNTP = ethData.NTPEnabled; 1221*1f8c7b5dSJohnathan Mantey } 1222*1f8c7b5dSJohnathan Mantey 1223*1f8c7b5dSJohnathan Mantey bool nextUseDomain{}; 1224*1f8c7b5dSJohnathan Mantey if (v4dhcpParms.useUseDomainName && v6dhcpParms.useUseDomainName) 1225*1f8c7b5dSJohnathan Mantey { 1226*1f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useUseDomainName != *v6dhcpParms.useUseDomainName) 1227*1f8c7b5dSJohnathan Mantey { 1228*1f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 1229*1f8c7b5dSJohnathan Mantey return; 1230*1f8c7b5dSJohnathan Mantey } 1231*1f8c7b5dSJohnathan Mantey nextUseDomain = *v4dhcpParms.useUseDomainName; 1232*1f8c7b5dSJohnathan Mantey } 1233*1f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useUseDomainName) 1234*1f8c7b5dSJohnathan Mantey { 1235*1f8c7b5dSJohnathan Mantey nextUseDomain = *v4dhcpParms.useUseDomainName; 1236*1f8c7b5dSJohnathan Mantey } 1237*1f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useUseDomainName) 1238*1f8c7b5dSJohnathan Mantey { 1239*1f8c7b5dSJohnathan Mantey nextUseDomain = *v6dhcpParms.useUseDomainName; 1240*1f8c7b5dSJohnathan Mantey } 1241*1f8c7b5dSJohnathan Mantey else 1242*1f8c7b5dSJohnathan Mantey { 1243*1f8c7b5dSJohnathan Mantey nextUseDomain = ethData.HostNameEnabled; 1244*1f8c7b5dSJohnathan Mantey } 1245*1f8c7b5dSJohnathan Mantey 1246da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1247*1f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 1248*1f8c7b5dSJohnathan Mantey asyncResp); 1249da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1250*1f8c7b5dSJohnathan Mantey setDHCPv4Config("DNSEnabled", nextDNS, asyncResp); 1251da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1252*1f8c7b5dSJohnathan Mantey setDHCPv4Config("NTPEnabled", nextNTP, asyncResp); 1253*1f8c7b5dSJohnathan Mantey BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1254*1f8c7b5dSJohnathan Mantey setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp); 1255da131a9aSJennifer Lee } 125601784826SJohnathan Mantey 125701784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator 125801784826SJohnathan Mantey GetNextStaticIPEntry( 125901784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator head, 126001784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator end) 126101784826SJohnathan Mantey { 126201784826SJohnathan Mantey for (; head != end; head++) 126301784826SJohnathan Mantey { 126401784826SJohnathan Mantey if (head->origin == "Static") 126501784826SJohnathan Mantey { 126601784826SJohnathan Mantey return head; 126701784826SJohnathan Mantey } 126801784826SJohnathan Mantey } 126901784826SJohnathan Mantey return end; 127001784826SJohnathan Mantey } 127101784826SJohnathan Mantey 127201784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator 127301784826SJohnathan Mantey GetNextStaticIPEntry( 127401784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator head, 127501784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator end) 127601784826SJohnathan Mantey { 127701784826SJohnathan Mantey for (; head != end; head++) 127801784826SJohnathan Mantey { 127901784826SJohnathan Mantey if (head->origin == "Static") 128001784826SJohnathan Mantey { 128101784826SJohnathan Mantey return head; 128201784826SJohnathan Mantey } 128301784826SJohnathan Mantey } 128401784826SJohnathan Mantey return end; 128501784826SJohnathan Mantey } 128601784826SJohnathan Mantey 1287d1d50814SRavi Teja void handleIPv4StaticPatch( 1288f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 128901784826SJohnathan Mantey const boost::container::flat_set<IPv4AddressData> &ipv4Data, 12904a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 12911abe55efSEd Tanous { 129201784826SJohnathan Mantey if ((!input.is_array()) || input.empty()) 1293f476acbfSRatan Gupta { 1294f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1295d1d50814SRavi Teja "IPv4StaticAddresses"); 1296f476acbfSRatan Gupta return; 1297f476acbfSRatan Gupta } 1298f476acbfSRatan Gupta 1299271584abSEd Tanous unsigned entryIdx = 1; 130001784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 130101784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 130201784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 130301784826SJohnathan Mantey // into the NIC. 130401784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator NICIPentry = 130501784826SJohnathan Mantey GetNextStaticIPEntry(ipv4Data.cbegin(), ipv4Data.cend()); 130601784826SJohnathan Mantey 1307537174c4SEd Tanous for (nlohmann::json &thisJson : input) 13081abe55efSEd Tanous { 13094a0cb85cSEd Tanous std::string pathString = 1310d1d50814SRavi Teja "IPv4StaticAddresses/" + std::to_string(entryIdx); 1311179db1d7SKowalski, Kamil 131201784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1313f476acbfSRatan Gupta { 1314537174c4SEd Tanous std::optional<std::string> address; 1315537174c4SEd Tanous std::optional<std::string> subnetMask; 1316537174c4SEd Tanous std::optional<std::string> gateway; 1317537174c4SEd Tanous 1318537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 13197e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 13207e27d832SJohnathan Mantey "Gateway", gateway)) 1321537174c4SEd Tanous { 132201784826SJohnathan Mantey messages::propertyValueFormatError( 132301784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1324537174c4SEd Tanous return; 1325179db1d7SKowalski, Kamil } 1326179db1d7SKowalski, Kamil 132701784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 132801784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 132901784826SJohnathan Mantey // current state of the interface. Merge existing state into the 133001784826SJohnathan Mantey // current request. 1331271584abSEd Tanous const std::string *addr = nullptr; 1332271584abSEd Tanous const std::string *gw = nullptr; 133301784826SJohnathan Mantey uint8_t prefixLength = 0; 133401784826SJohnathan Mantey bool errorInEntry = false; 1335537174c4SEd Tanous if (address) 13361abe55efSEd Tanous { 133701784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*address)) 13381abe55efSEd Tanous { 133901784826SJohnathan Mantey addr = &(*address); 13404a0cb85cSEd Tanous } 134101784826SJohnathan Mantey else 134201784826SJohnathan Mantey { 134301784826SJohnathan Mantey messages::propertyValueFormatError( 134401784826SJohnathan Mantey asyncResp->res, *address, pathString + "/Address"); 134501784826SJohnathan Mantey errorInEntry = true; 134601784826SJohnathan Mantey } 134701784826SJohnathan Mantey } 134801784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 134901784826SJohnathan Mantey { 135001784826SJohnathan Mantey addr = &(NICIPentry->address); 135101784826SJohnathan Mantey } 135201784826SJohnathan Mantey else 135301784826SJohnathan Mantey { 135401784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 135501784826SJohnathan Mantey pathString + "/Address"); 135601784826SJohnathan Mantey errorInEntry = true; 13574a0cb85cSEd Tanous } 13584a0cb85cSEd Tanous 1359537174c4SEd Tanous if (subnetMask) 13604a0cb85cSEd Tanous { 1361537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 13624a0cb85cSEd Tanous { 1363f12894f8SJason M. Bills messages::propertyValueFormatError( 1364537174c4SEd Tanous asyncResp->res, *subnetMask, 13654a0cb85cSEd Tanous pathString + "/SubnetMask"); 136601784826SJohnathan Mantey errorInEntry = true; 13674a0cb85cSEd Tanous } 13684a0cb85cSEd Tanous } 136901784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 13704a0cb85cSEd Tanous { 137101784826SJohnathan Mantey if (!ipv4VerifyIpAndGetBitcount(NICIPentry->netmask, 137201784826SJohnathan Mantey &prefixLength)) 13734a0cb85cSEd Tanous { 137401784826SJohnathan Mantey messages::propertyValueFormatError( 137501784826SJohnathan Mantey asyncResp->res, NICIPentry->netmask, 137601784826SJohnathan Mantey pathString + "/SubnetMask"); 137701784826SJohnathan Mantey errorInEntry = true; 13784a0cb85cSEd Tanous } 13794a0cb85cSEd Tanous } 13801abe55efSEd Tanous else 13811abe55efSEd Tanous { 138201784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 138301784826SJohnathan Mantey pathString + "/SubnetMask"); 138401784826SJohnathan Mantey errorInEntry = true; 138501784826SJohnathan Mantey } 138601784826SJohnathan Mantey 138701784826SJohnathan Mantey if (gateway) 138801784826SJohnathan Mantey { 138901784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*gateway)) 139001784826SJohnathan Mantey { 139101784826SJohnathan Mantey gw = &(*gateway); 139201784826SJohnathan Mantey } 139301784826SJohnathan Mantey else 139401784826SJohnathan Mantey { 139501784826SJohnathan Mantey messages::propertyValueFormatError( 139601784826SJohnathan Mantey asyncResp->res, *gateway, pathString + "/Gateway"); 139701784826SJohnathan Mantey errorInEntry = true; 139801784826SJohnathan Mantey } 139901784826SJohnathan Mantey } 140001784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 140101784826SJohnathan Mantey { 140201784826SJohnathan Mantey gw = &NICIPentry->gateway; 140301784826SJohnathan Mantey } 140401784826SJohnathan Mantey else 14051abe55efSEd Tanous { 1406a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 14074a0cb85cSEd Tanous pathString + "/Gateway"); 140801784826SJohnathan Mantey errorInEntry = true; 14094a0cb85cSEd Tanous } 14104a0cb85cSEd Tanous 141101784826SJohnathan Mantey if (errorInEntry) 14121abe55efSEd Tanous { 141301784826SJohnathan Mantey return; 14144a0cb85cSEd Tanous } 14154a0cb85cSEd Tanous 141601784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 14171abe55efSEd Tanous { 1418271584abSEd Tanous if (gw != nullptr || addr != nullptr) 1419271584abSEd Tanous { 1420271584abSEd Tanous // Shouldn't be possible based on errorInEntry, but 1421271584abSEd Tanous // it flags -wmaybe-uninitialized in the compiler, 1422271584abSEd Tanous // so defend against that 1423271584abSEd Tanous return; 1424271584abSEd Tanous } 142501784826SJohnathan Mantey deleteAndCreateIPv4(ifaceId, NICIPentry->id, prefixLength, 142601784826SJohnathan Mantey *gw, *addr, asyncResp); 142701784826SJohnathan Mantey NICIPentry = 142801784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 1429588c3f0dSKowalski, Kamil } 143001784826SJohnathan Mantey else 143101784826SJohnathan Mantey { 143201784826SJohnathan Mantey createIPv4(ifaceId, entryIdx, prefixLength, *gateway, 143301784826SJohnathan Mantey *address, asyncResp); 14344a0cb85cSEd Tanous } 14354a0cb85cSEd Tanous entryIdx++; 14364a0cb85cSEd Tanous } 143701784826SJohnathan Mantey else 143801784826SJohnathan Mantey { 143901784826SJohnathan Mantey if (NICIPentry == ipv4Data.cend()) 144001784826SJohnathan Mantey { 144101784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 144201784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 144301784826SJohnathan Mantey // in error, so bail out. 144401784826SJohnathan Mantey if (thisJson.is_null()) 144501784826SJohnathan Mantey { 144601784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 144701784826SJohnathan Mantey return; 144801784826SJohnathan Mantey } 144901784826SJohnathan Mantey else 145001784826SJohnathan Mantey { 145101784826SJohnathan Mantey messages::propertyValueFormatError( 145201784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 145301784826SJohnathan Mantey return; 145401784826SJohnathan Mantey } 145501784826SJohnathan Mantey } 145601784826SJohnathan Mantey 145701784826SJohnathan Mantey if (thisJson.is_null()) 145801784826SJohnathan Mantey { 145901784826SJohnathan Mantey deleteIPv4(ifaceId, NICIPentry->id, asyncResp); 146001784826SJohnathan Mantey } 146101784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 146201784826SJohnathan Mantey { 146301784826SJohnathan Mantey NICIPentry = 146401784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 146501784826SJohnathan Mantey } 146601784826SJohnathan Mantey entryIdx++; 146701784826SJohnathan Mantey } 146801784826SJohnathan Mantey } 14694a0cb85cSEd Tanous } 14704a0cb85cSEd Tanous 1471f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1472f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1473f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1474f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1475f85837bfSRAJESWARAN THILLAIGOVINDAN { 1476f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1477286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1478f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1479f85837bfSRAJESWARAN THILLAIGOVINDAN { 1480f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1481f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1482f85837bfSRAJESWARAN THILLAIGOVINDAN } 1483f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1484f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1485f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1486f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1487f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1488f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1489f85837bfSRAJESWARAN THILLAIGOVINDAN } 1490f85837bfSRAJESWARAN THILLAIGOVINDAN 1491e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1492e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 149301784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1494e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1495e48c0fc5SRavi Teja { 149601784826SJohnathan Mantey if (!input.is_array() || input.empty()) 1497e48c0fc5SRavi Teja { 1498e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1499e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1500e48c0fc5SRavi Teja return; 1501e48c0fc5SRavi Teja } 1502271584abSEd Tanous size_t entryIdx = 1; 150301784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator NICIPentry = 150401784826SJohnathan Mantey GetNextStaticIPEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1505e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1506e48c0fc5SRavi Teja { 1507e48c0fc5SRavi Teja std::string pathString = 1508e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1509e48c0fc5SRavi Teja 151001784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1511e48c0fc5SRavi Teja { 1512e48c0fc5SRavi Teja std::optional<std::string> address; 1513e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1514e48c0fc5SRavi Teja 1515e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1516e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1517e48c0fc5SRavi Teja { 151801784826SJohnathan Mantey messages::propertyValueFormatError( 151901784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1520e48c0fc5SRavi Teja return; 1521e48c0fc5SRavi Teja } 1522e48c0fc5SRavi Teja 152301784826SJohnathan Mantey const std::string *addr; 152401784826SJohnathan Mantey uint8_t prefix; 152501784826SJohnathan Mantey 152601784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 152701784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 152801784826SJohnathan Mantey // current state of the interface. Merge existing state into the 152901784826SJohnathan Mantey // current request. 1530e48c0fc5SRavi Teja if (address) 1531e48c0fc5SRavi Teja { 153201784826SJohnathan Mantey addr = &(*address); 1533e48c0fc5SRavi Teja } 153401784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 153501784826SJohnathan Mantey { 153601784826SJohnathan Mantey addr = &(NICIPentry->address); 153701784826SJohnathan Mantey } 153801784826SJohnathan Mantey else 153901784826SJohnathan Mantey { 154001784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 154101784826SJohnathan Mantey pathString + "/Address"); 154201784826SJohnathan Mantey return; 1543e48c0fc5SRavi Teja } 1544e48c0fc5SRavi Teja 1545e48c0fc5SRavi Teja if (prefixLength) 1546e48c0fc5SRavi Teja { 154701784826SJohnathan Mantey prefix = *prefixLength; 154801784826SJohnathan Mantey } 154901784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 1550e48c0fc5SRavi Teja { 155101784826SJohnathan Mantey prefix = NICIPentry->prefixLength; 1552e48c0fc5SRavi Teja } 1553e48c0fc5SRavi Teja else 1554e48c0fc5SRavi Teja { 1555e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1556e48c0fc5SRavi Teja pathString + "/PrefixLength"); 155701784826SJohnathan Mantey return; 1558e48c0fc5SRavi Teja } 1559e48c0fc5SRavi Teja 156001784826SJohnathan Mantey if (NICIPentry != ipv6Data.end()) 1561e48c0fc5SRavi Teja { 156201784826SJohnathan Mantey deleteAndCreateIPv6(ifaceId, NICIPentry->id, prefix, *addr, 1563e48c0fc5SRavi Teja asyncResp); 156401784826SJohnathan Mantey NICIPentry = 156501784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 156601784826SJohnathan Mantey } 156701784826SJohnathan Mantey else 156801784826SJohnathan Mantey { 156901784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1570e48c0fc5SRavi Teja } 1571e48c0fc5SRavi Teja entryIdx++; 1572e48c0fc5SRavi Teja } 157301784826SJohnathan Mantey else 157401784826SJohnathan Mantey { 157501784826SJohnathan Mantey if (NICIPentry == ipv6Data.end()) 157601784826SJohnathan Mantey { 157701784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 157801784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 157901784826SJohnathan Mantey // in error, so bail out. 158001784826SJohnathan Mantey if (thisJson.is_null()) 158101784826SJohnathan Mantey { 158201784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 158301784826SJohnathan Mantey return; 158401784826SJohnathan Mantey } 158501784826SJohnathan Mantey else 158601784826SJohnathan Mantey { 158701784826SJohnathan Mantey messages::propertyValueFormatError( 158801784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 158901784826SJohnathan Mantey return; 159001784826SJohnathan Mantey } 159101784826SJohnathan Mantey } 159201784826SJohnathan Mantey 159301784826SJohnathan Mantey if (thisJson.is_null()) 159401784826SJohnathan Mantey { 159501784826SJohnathan Mantey deleteIPv6(ifaceId, NICIPentry->id, asyncResp); 159601784826SJohnathan Mantey } 159701784826SJohnathan Mantey if (NICIPentry != ipv6Data.cend()) 159801784826SJohnathan Mantey { 159901784826SJohnathan Mantey NICIPentry = 160001784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 160101784826SJohnathan Mantey } 160201784826SJohnathan Mantey entryIdx++; 160301784826SJohnathan Mantey } 160401784826SJohnathan Mantey } 1605e48c0fc5SRavi Teja } 1606e48c0fc5SRavi Teja 16070f74e643SEd Tanous void parseInterfaceData( 16080f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 16090f74e643SEd Tanous const EthernetInterfaceData ðData, 1610e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 161101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 16124a0cb85cSEd Tanous { 16134a0cb85cSEd Tanous json_response["Id"] = iface_id; 16144a0cb85cSEd Tanous json_response["@odata.id"] = 16154a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1616029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1617029573d4SEd Tanous if (ethData.speed == 0) 1618029573d4SEd Tanous { 1619029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1620029573d4SEd Tanous json_response["Status"] = { 1621029573d4SEd Tanous {"Health", "OK"}, 1622029573d4SEd Tanous {"State", "Disabled"}, 1623029573d4SEd Tanous }; 1624029573d4SEd Tanous } 1625029573d4SEd Tanous else 1626029573d4SEd Tanous { 1627029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1628029573d4SEd Tanous json_response["Status"] = { 1629029573d4SEd Tanous {"Health", "OK"}, 1630029573d4SEd Tanous {"State", "Enabled"}, 1631029573d4SEd Tanous }; 1632029573d4SEd Tanous } 16334a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 16344a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1635*1f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["DHCPEnabled"] = 1636*1f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, true); 1637*1f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseNTPServers"] = ethData.NTPEnabled; 1638*1f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseDNSServers"] = ethData.DNSEnabled; 1639*1f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseDomainName"] = ethData.HostNameEnabled; 1640*1f8c7b5dSJohnathan Mantey 1641*1f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["OperatingMode"] = 1642*1f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, false) ? "Stateful" 1643*1f8c7b5dSJohnathan Mantey : "Disabled"; 1644*1f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseNTPServers"] = ethData.NTPEnabled; 1645*1f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseDNSServers"] = ethData.DNSEnabled; 1646*1f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseDomainName"] = ethData.HostNameEnabled; 16472a133282Smanojkiraneda 16484a0cb85cSEd Tanous if (!ethData.hostname.empty()) 16494a0cb85cSEd Tanous { 16504a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 1651d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1652d24bfc7aSJennifer Lee { 1653d24bfc7aSJennifer Lee json_response["FQDN"] = 1654d24bfc7aSJennifer Lee ethData.hostname + "." + ethData.domainnames[0]; 1655d24bfc7aSJennifer Lee } 16564a0cb85cSEd Tanous } 16574a0cb85cSEd Tanous 1658fda13ad2SSunitha Harish json_response["VLANs"] = { 1659fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1660fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1661fda13ad2SSunitha Harish 1662*1f8c7b5dSJohnathan Mantey if (translateDHCPEnabledToBool(ethData.DHCPEnabled, true) && 1663*1f8c7b5dSJohnathan Mantey ethData.DNSEnabled) 166495f8646eSManojkiran Eda { 1665*1f8c7b5dSJohnathan Mantey json_response["StaticNameServers"] = nlohmann::json::array(); 166695f8646eSManojkiran Eda } 166795f8646eSManojkiran Eda else 166895f8646eSManojkiran Eda { 1669*1f8c7b5dSJohnathan Mantey json_response["StaticNameServers"] = ethData.nameservers; 167095f8646eSManojkiran Eda } 16714a0cb85cSEd Tanous 16724a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 167301784826SJohnathan Mantey nlohmann::json &ipv4_static_array = 167401784826SJohnathan Mantey json_response["IPv4StaticAddresses"]; 16754a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 167601784826SJohnathan Mantey ipv4_static_array = nlohmann::json::array(); 16774a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 16784a0cb85cSEd Tanous { 1679fa5053a6SGunnar Mills 1680fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1681fa5053a6SGunnar Mills if (gatewayStr.empty()) 1682fa5053a6SGunnar Mills { 1683fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1684fa5053a6SGunnar Mills } 1685fa5053a6SGunnar Mills 16864a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 16874a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1688029573d4SEd Tanous {"Address", ipv4_config.address}, 1689fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 169001784826SJohnathan Mantey if (ipv4_config.origin == "Static") 1691d1d50814SRavi Teja { 1692d1d50814SRavi Teja ipv4_static_array.push_back( 169301784826SJohnathan Mantey {{"AddressOrigin", ipv4_config.origin}, 169401784826SJohnathan Mantey {"SubnetMask", ipv4_config.netmask}, 169501784826SJohnathan Mantey {"Address", ipv4_config.address}, 1696d1d50814SRavi Teja {"Gateway", gatewayStr}}); 1697d1d50814SRavi Teja } 169801784826SJohnathan Mantey } 1699d1d50814SRavi Teja 17009a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1701e48c0fc5SRavi Teja 1702e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 170301784826SJohnathan Mantey nlohmann::json &ipv6_static_array = 170401784826SJohnathan Mantey json_response["IPv6StaticAddresses"]; 1705e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 170601784826SJohnathan Mantey ipv6_static_array = nlohmann::json::array(); 1707e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1708e48c0fc5SRavi Teja { 1709e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1710e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1711e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 171201784826SJohnathan Mantey if (ipv6_config.origin == "Static") 1713e48c0fc5SRavi Teja { 1714e48c0fc5SRavi Teja ipv6_static_array.push_back( 171501784826SJohnathan Mantey {{"Address", ipv6_config.address}, 171601784826SJohnathan Mantey {"PrefixLength", ipv6_config.prefixLength}, 171701784826SJohnathan Mantey {"AddressOrigin", ipv6_config.origin}}); 171801784826SJohnathan Mantey } 1719e48c0fc5SRavi Teja } 1720588c3f0dSKowalski, Kamil } 1721588c3f0dSKowalski, Kamil 17229391bb9cSRapkiewicz, Pawel /** 17239391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 17249391bb9cSRapkiewicz, Pawel */ 172555c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 17261abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17271abe55efSEd Tanous { 17284a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17291abe55efSEd Tanous if (params.size() != 1) 17301abe55efSEd Tanous { 1731f12894f8SJason M. Bills messages::internalError(asyncResp->res); 17329391bb9cSRapkiewicz, Pawel return; 17339391bb9cSRapkiewicz, Pawel } 17349391bb9cSRapkiewicz, Pawel 17354a0cb85cSEd Tanous getEthernetIfaceData( 17364a0cb85cSEd Tanous params[0], 17374a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 17384a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1739e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 174001784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 17414a0cb85cSEd Tanous if (!success) 17421abe55efSEd Tanous { 17431abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 17441abe55efSEd Tanous // object, and other errors 1745f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1746f12894f8SJason M. Bills "EthernetInterface", iface_id); 17474a0cb85cSEd Tanous return; 17489391bb9cSRapkiewicz, Pawel } 17494c9afe43SEd Tanous 17500f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1751fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 17520f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 175301784826SJohnathan Mantey "/redfish/v1/" 175401784826SJohnathan Mantey "$metadata#EthernetInterface.EthernetInterface"; 17550f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 17560f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 17570f74e643SEd Tanous "Management Network Interface"; 17580f74e643SEd Tanous 17590f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 176001784826SJohnathan Mantey ipv4Data, ipv6Data); 17619391bb9cSRapkiewicz, Pawel }); 17629391bb9cSRapkiewicz, Pawel } 17639391bb9cSRapkiewicz, Pawel 176455c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 17651abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17661abe55efSEd Tanous { 17674a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17681abe55efSEd Tanous if (params.size() != 1) 17691abe55efSEd Tanous { 1770f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1771588c3f0dSKowalski, Kamil return; 1772588c3f0dSKowalski, Kamil } 1773588c3f0dSKowalski, Kamil 17744a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1775588c3f0dSKowalski, Kamil 1776bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1777d577665bSRatan Gupta std::optional<std::string> macAddress; 17789a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1779d1d50814SRavi Teja std::optional<nlohmann::json> ipv4StaticAddresses; 1780e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1781f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 1782da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 1783*1f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 1784*1f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 1785*1f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 17860627a2c7SEd Tanous 1787*1f8c7b5dSJohnathan Mantey if (!json_util::readJson( 1788*1f8c7b5dSJohnathan Mantey req, res, "HostName", hostname, "IPv4StaticAddresses", 1789*1f8c7b5dSJohnathan Mantey ipv4StaticAddresses, "MACAddress", macAddress, 1790*1f8c7b5dSJohnathan Mantey "StaticNameServers", staticNameServers, "IPv6DefaultGateway", 1791*1f8c7b5dSJohnathan Mantey ipv6DefaultGateway, "IPv6StaticAddresses", ipv6StaticAddresses, 1792*1f8c7b5dSJohnathan Mantey "DHCPv4", dhcpv4, "DHCPv6", dhcpv6)) 17931abe55efSEd Tanous { 1794588c3f0dSKowalski, Kamil return; 1795588c3f0dSKowalski, Kamil } 1796da131a9aSJennifer Lee if (dhcpv4) 1797da131a9aSJennifer Lee { 1798*1f8c7b5dSJohnathan Mantey if (!json_util::readJson(*dhcpv4, res, "DHCPEnabled", 1799*1f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 1800*1f8c7b5dSJohnathan Mantey v4dhcpParms.useDNSServers, "UseNTPServers", 1801*1f8c7b5dSJohnathan Mantey v4dhcpParms.useNTPServers, "UseDomainName", 1802*1f8c7b5dSJohnathan Mantey v4dhcpParms.useUseDomainName)) 1803*1f8c7b5dSJohnathan Mantey { 1804*1f8c7b5dSJohnathan Mantey return; 1805*1f8c7b5dSJohnathan Mantey } 1806*1f8c7b5dSJohnathan Mantey } 1807*1f8c7b5dSJohnathan Mantey 1808*1f8c7b5dSJohnathan Mantey if (dhcpv6) 1809*1f8c7b5dSJohnathan Mantey { 1810*1f8c7b5dSJohnathan Mantey if (!json_util::readJson(*dhcpv6, res, "OperatingMode", 1811*1f8c7b5dSJohnathan Mantey v6dhcpParms.dhcpv6OperatingMode, 1812*1f8c7b5dSJohnathan Mantey "UseDNSServers", v6dhcpParms.useDNSServers, 1813*1f8c7b5dSJohnathan Mantey "UseNTPServers", v6dhcpParms.useNTPServers, 1814*1f8c7b5dSJohnathan Mantey "UseDomainName", 1815*1f8c7b5dSJohnathan Mantey v6dhcpParms.useUseDomainName)) 1816*1f8c7b5dSJohnathan Mantey { 1817*1f8c7b5dSJohnathan Mantey return; 1818*1f8c7b5dSJohnathan Mantey } 1819da131a9aSJennifer Lee } 1820da131a9aSJennifer Lee 182101784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 182201784826SJohnathan Mantey // JSON preparation 18234a0cb85cSEd Tanous getEthernetIfaceData( 18244a0cb85cSEd Tanous iface_id, 1825fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1826fda13ad2SSunitha Harish macAddress = std::move(macAddress), 1827d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 18289a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1829e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 1830*1f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 1831*1f8c7b5dSJohnathan Mantey dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), 1832*1f8c7b5dSJohnathan Mantey v4dhcpParms = std::move(v4dhcpParms), 1833*1f8c7b5dSJohnathan Mantey v6dhcpParms = std::move(v6dhcpParms)]( 18344a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1835e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 183601784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 18371abe55efSEd Tanous if (!success) 18381abe55efSEd Tanous { 1839588c3f0dSKowalski, Kamil // ... otherwise return error 18401abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18411abe55efSEd Tanous // object, and other errors 1842fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1843fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1844588c3f0dSKowalski, Kamil return; 1845588c3f0dSKowalski, Kamil } 1846588c3f0dSKowalski, Kamil 1847*1f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 1848*1f8c7b5dSJohnathan Mantey { 1849*1f8c7b5dSJohnathan Mantey handleDHCPPatch(iface_id, ethData, std::move(v4dhcpParms), 1850*1f8c7b5dSJohnathan Mantey std::move(v6dhcpParms), asyncResp); 1851*1f8c7b5dSJohnathan Mantey } 1852*1f8c7b5dSJohnathan Mantey 18530627a2c7SEd Tanous if (hostname) 18541abe55efSEd Tanous { 18550627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 18561abe55efSEd Tanous } 18570627a2c7SEd Tanous 1858d577665bSRatan Gupta if (macAddress) 1859d577665bSRatan Gupta { 1860d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1861d577665bSRatan Gupta } 1862d577665bSRatan Gupta 1863d1d50814SRavi Teja if (ipv4StaticAddresses) 1864d1d50814SRavi Teja { 1865537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 186601784826SJohnathan Mantey // above is returning a const value, not a non-const 186701784826SJohnathan Mantey // value. This doesn't really work for us, as we need to 186801784826SJohnathan Mantey // be able to efficiently move out the intermedia 186901784826SJohnathan Mantey // nlohmann::json objects. This makes a copy of the 187001784826SJohnathan Mantey // structure, and operates on that, but could be done 187101784826SJohnathan Mantey // more efficiently 1872d1d50814SRavi Teja nlohmann::json ipv4Static = std::move(*ipv4StaticAddresses); 187301784826SJohnathan Mantey handleIPv4StaticPatch(iface_id, ipv4Static, ipv4Data, 1874d1d50814SRavi Teja asyncResp); 18751abe55efSEd Tanous } 18760627a2c7SEd Tanous 1877f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1878f85837bfSRAJESWARAN THILLAIGOVINDAN { 1879f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1880f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1881f85837bfSRAJESWARAN THILLAIGOVINDAN } 18829a6fc6feSRavi Teja 18839a6fc6feSRavi Teja if (ipv6DefaultGateway) 18849a6fc6feSRavi Teja { 18859a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 18869a6fc6feSRavi Teja "IPv6DefaultGateway"); 18879a6fc6feSRavi Teja } 1888e48c0fc5SRavi Teja 1889e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1890e48c0fc5SRavi Teja { 1891e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1892e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 189301784826SJohnathan Mantey ipv6Data, asyncResp); 1894e48c0fc5SRavi Teja } 1895588c3f0dSKowalski, Kamil }); 1896588c3f0dSKowalski, Kamil } 18979391bb9cSRapkiewicz, Pawel }; 18989391bb9cSRapkiewicz, Pawel 1899e439f0f8SKowalski, Kamil /** 19004a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 19014a0cb85cSEd Tanous * Schema 1902e439f0f8SKowalski, Kamil */ 19031abe55efSEd Tanous class VlanNetworkInterface : public Node 19041abe55efSEd Tanous { 1905e439f0f8SKowalski, Kamil public: 1906e439f0f8SKowalski, Kamil /* 1907e439f0f8SKowalski, Kamil * Default Constructor 1908e439f0f8SKowalski, Kamil */ 1909e439f0f8SKowalski, Kamil template <typename CrowApp> 19101abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 19114a0cb85cSEd Tanous Node(app, 19120f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 19131abe55efSEd Tanous std::string(), std::string()) 19141abe55efSEd Tanous { 1915e439f0f8SKowalski, Kamil entityPrivileges = { 1916e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1917e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1918e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1919e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1920e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1921e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1922e439f0f8SKowalski, Kamil } 1923e439f0f8SKowalski, Kamil 1924e439f0f8SKowalski, Kamil private: 19250f74e643SEd Tanous void parseInterfaceData( 19260f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 19270f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1928e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 192901784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 19301abe55efSEd Tanous { 1931e439f0f8SKowalski, Kamil // Fill out obvious data... 19324a0cb85cSEd Tanous json_response["Id"] = iface_id; 19334a0cb85cSEd Tanous json_response["@odata.id"] = 19344a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 19354a0cb85cSEd Tanous "/VLANs/" + iface_id; 1936e439f0f8SKowalski, Kamil 19374a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1938fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 19394a0cb85cSEd Tanous { 1940fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 19414a0cb85cSEd Tanous } 1942e439f0f8SKowalski, Kamil } 1943e439f0f8SKowalski, Kamil 1944fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 19451abe55efSEd Tanous { 19461abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 19471abe55efSEd Tanous { 1948927a505aSKowalski, Kamil return false; 19491abe55efSEd Tanous } 19501abe55efSEd Tanous else 19511abe55efSEd Tanous { 1952927a505aSKowalski, Kamil return true; 1953927a505aSKowalski, Kamil } 1954927a505aSKowalski, Kamil } 1955927a505aSKowalski, Kamil 1956e439f0f8SKowalski, Kamil /** 1957e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1958e439f0f8SKowalski, Kamil */ 195955c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 19601abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19611abe55efSEd Tanous { 19624a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19634a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1964e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1965e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1966e439f0f8SKowalski, Kamil // impossible. 19671abe55efSEd Tanous if (params.size() != 2) 19681abe55efSEd Tanous { 1969f12894f8SJason M. Bills messages::internalError(res); 1970e439f0f8SKowalski, Kamil res.end(); 1971e439f0f8SKowalski, Kamil return; 1972e439f0f8SKowalski, Kamil } 1973e439f0f8SKowalski, Kamil 19744a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 19754a0cb85cSEd Tanous const std::string &iface_id = params[1]; 19760f74e643SEd Tanous res.jsonValue["@odata.type"] = 19770f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 19780f74e643SEd Tanous res.jsonValue["@odata.context"] = 197901784826SJohnathan Mantey "/redfish/v1/" 198001784826SJohnathan Mantey "$metadata#VLanNetworkInterface.VLanNetworkInterface"; 19810f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1982e439f0f8SKowalski, Kamil 1983fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 19841abe55efSEd Tanous { 1985a434f2bdSEd Tanous return; 1986a434f2bdSEd Tanous } 1987a434f2bdSEd Tanous 198801784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 198901784826SJohnathan Mantey // JSON preparation 19904a0cb85cSEd Tanous getEthernetIfaceData( 1991fda13ad2SSunitha Harish params[1], 1992fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1993fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 19944a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1995e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 199601784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 1997fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 19981abe55efSEd Tanous { 19990f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 20000f74e643SEd Tanous parent_iface_id, iface_id, ethData, 200101784826SJohnathan Mantey ipv4Data, ipv6Data); 20021abe55efSEd Tanous } 20031abe55efSEd Tanous else 20041abe55efSEd Tanous { 2005e439f0f8SKowalski, Kamil // ... otherwise return error 20061abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 20071abe55efSEd Tanous // object, and other errors 2008f12894f8SJason M. Bills messages::resourceNotFound( 2009f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 2010e439f0f8SKowalski, Kamil } 2011e439f0f8SKowalski, Kamil }); 2012e439f0f8SKowalski, Kamil } 2013e439f0f8SKowalski, Kamil 201455c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 20151abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20161abe55efSEd Tanous { 20174a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20181abe55efSEd Tanous if (params.size() != 2) 20191abe55efSEd Tanous { 2020f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2021e439f0f8SKowalski, Kamil return; 2022e439f0f8SKowalski, Kamil } 2023e439f0f8SKowalski, Kamil 2024d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 202555c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2026927a505aSKowalski, Kamil 2027fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 20281abe55efSEd Tanous { 2029fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2030fda13ad2SSunitha Harish ifaceId); 2031927a505aSKowalski, Kamil return; 2032927a505aSKowalski, Kamil } 2033927a505aSKowalski, Kamil 20340627a2c7SEd Tanous bool vlanEnable = false; 20350627a2c7SEd Tanous uint64_t vlanId = 0; 20360627a2c7SEd Tanous 20370627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 20380627a2c7SEd Tanous vlanId)) 20391abe55efSEd Tanous { 2040927a505aSKowalski, Kamil return; 2041927a505aSKowalski, Kamil } 2042927a505aSKowalski, Kamil 204301784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 204401784826SJohnathan Mantey // JSON preparation 2045e48c0fc5SRavi Teja getEthernetIfaceData( 2046e48c0fc5SRavi Teja params[1], 2047271584abSEd Tanous [asyncResp, parentIfaceId{std::string(params[0])}, 2048e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 2049e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 2050e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 205101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 205208244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 205308244d02SSunitha Harish { 205408244d02SSunitha Harish auto callback = 205508244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 205608244d02SSunitha Harish if (ec) 205708244d02SSunitha Harish { 205808244d02SSunitha Harish messages::internalError(asyncResp->res); 205908244d02SSunitha Harish } 206008244d02SSunitha Harish }; 206108244d02SSunitha Harish 206208244d02SSunitha Harish if (vlanEnable == true) 206308244d02SSunitha Harish { 206408244d02SSunitha Harish crow::connections::systemBus->async_method_call( 206508244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 206608244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 206708244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 206808244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 206908244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 207008244d02SSunitha Harish } 207108244d02SSunitha Harish else 207208244d02SSunitha Harish { 2073e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 2074e48c0fc5SRavi Teja "vlan interface"; 207508244d02SSunitha Harish crow::connections::systemBus->async_method_call( 207608244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 2077e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 2078e48c0fc5SRavi Teja ifaceId, 207908244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 208008244d02SSunitha Harish } 208108244d02SSunitha Harish } 208208244d02SSunitha Harish else 20831abe55efSEd Tanous { 20841abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 20851abe55efSEd Tanous // object, and other errors 2086e48c0fc5SRavi Teja messages::resourceNotFound( 2087e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 2088927a505aSKowalski, Kamil return; 2089927a505aSKowalski, Kamil } 2090927a505aSKowalski, Kamil }); 2091e439f0f8SKowalski, Kamil } 2092e439f0f8SKowalski, Kamil 209355c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 20941abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20951abe55efSEd Tanous { 20964a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20971abe55efSEd Tanous if (params.size() != 2) 20981abe55efSEd Tanous { 2099f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2100e439f0f8SKowalski, Kamil return; 2101e439f0f8SKowalski, Kamil } 2102e439f0f8SKowalski, Kamil 2103d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 210455c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2105927a505aSKowalski, Kamil 2106fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 21071abe55efSEd Tanous { 2108fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2109fda13ad2SSunitha Harish ifaceId); 2110927a505aSKowalski, Kamil return; 2111927a505aSKowalski, Kamil } 2112927a505aSKowalski, Kamil 211301784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 211401784826SJohnathan Mantey // JSON preparation 2115f12894f8SJason M. Bills getEthernetIfaceData( 2116fda13ad2SSunitha Harish params[1], 2117271584abSEd Tanous [asyncResp, parentIfaceId{std::string(params[0])}, 2118fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 2119f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 2120e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 212101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 2122fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 21231abe55efSEd Tanous { 2124f12894f8SJason M. Bills auto callback = 2125f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 21261abe55efSEd Tanous if (ec) 21271abe55efSEd Tanous { 2128f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2129927a505aSKowalski, Kamil } 21304a0cb85cSEd Tanous }; 21314a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21324a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21334a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 21344a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 21351abe55efSEd Tanous } 21361abe55efSEd Tanous else 21371abe55efSEd Tanous { 2138927a505aSKowalski, Kamil // ... otherwise return error 2139f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 2140f12894f8SJason M. Bills // object, and other errors 2141f12894f8SJason M. Bills messages::resourceNotFound( 2142f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 2143927a505aSKowalski, Kamil } 2144927a505aSKowalski, Kamil }); 2145e439f0f8SKowalski, Kamil } 2146e439f0f8SKowalski, Kamil }; 2147e439f0f8SKowalski, Kamil 2148e439f0f8SKowalski, Kamil /** 2149e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 2150e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 2151e439f0f8SKowalski, Kamil */ 21521abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 21531abe55efSEd Tanous { 2154e439f0f8SKowalski, Kamil public: 2155e439f0f8SKowalski, Kamil template <typename CrowApp> 21561abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 21574a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 21584a0cb85cSEd Tanous std::string()) 21591abe55efSEd Tanous { 2160e439f0f8SKowalski, Kamil entityPrivileges = { 2161e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 2162e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2163e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2164e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2165e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2166e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2167e439f0f8SKowalski, Kamil } 2168e439f0f8SKowalski, Kamil 2169e439f0f8SKowalski, Kamil private: 2170e439f0f8SKowalski, Kamil /** 2171e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2172e439f0f8SKowalski, Kamil */ 217355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 21741abe55efSEd Tanous const std::vector<std::string> ¶ms) override 21751abe55efSEd Tanous { 21764a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 21771abe55efSEd Tanous if (params.size() != 1) 21781abe55efSEd Tanous { 2179e439f0f8SKowalski, Kamil // This means there is a problem with the router 2180f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2181e439f0f8SKowalski, Kamil return; 2182e439f0f8SKowalski, Kamil } 2183e439f0f8SKowalski, Kamil 21844a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2185e439f0f8SKowalski, Kamil 21864a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 21871abe55efSEd Tanous // preparation 2188f12894f8SJason M. Bills getEthernetIfaceList( 218943b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 21901abe55efSEd Tanous const bool &success, 21914c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 21924a0cb85cSEd Tanous if (!success) 21931abe55efSEd Tanous { 2194f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21954a0cb85cSEd Tanous return; 21961abe55efSEd Tanous } 21974c9afe43SEd Tanous 21984c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 21994c9afe43SEd Tanous { 22004c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 22014c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 22024c9afe43SEd Tanous rootInterfaceName); 22034c9afe43SEd Tanous return; 22044c9afe43SEd Tanous } 22054c9afe43SEd Tanous 22060f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 22070f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 22080f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 22090f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 22100f74e643SEd Tanous "/redfish/v1/$metadata" 22110f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 22120f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 22130f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 22140f74e643SEd Tanous "VLAN Network Interface Collection"; 22154a0cb85cSEd Tanous 22164a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 22174a0cb85cSEd Tanous 22184a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 22191abe55efSEd Tanous { 22204a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 22214a0cb85cSEd Tanous { 22224a0cb85cSEd Tanous iface_array.push_back( 22234a0cb85cSEd Tanous {{"@odata.id", 22244a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 22254a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2226e439f0f8SKowalski, Kamil } 2227e439f0f8SKowalski, Kamil } 2228e439f0f8SKowalski, Kamil 22294a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 22304a0cb85cSEd Tanous iface_array.size(); 22314a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 22324a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 22334a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 22344a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2235e439f0f8SKowalski, Kamil }); 2236e439f0f8SKowalski, Kamil } 2237e439f0f8SKowalski, Kamil 223855c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 22391abe55efSEd Tanous const std::vector<std::string> ¶ms) override 22401abe55efSEd Tanous { 22414a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 22421abe55efSEd Tanous if (params.size() != 1) 22431abe55efSEd Tanous { 2244f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2245e439f0f8SKowalski, Kamil return; 2246e439f0f8SKowalski, Kamil } 2247fda13ad2SSunitha Harish bool vlanEnable = false; 22480627a2c7SEd Tanous uint32_t vlanId = 0; 2249fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2250fda13ad2SSunitha Harish vlanEnable)) 22511abe55efSEd Tanous { 22524a0cb85cSEd Tanous return; 2253e439f0f8SKowalski, Kamil } 2254fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2255fda13ad2SSunitha Harish if (!vlanId) 2256fda13ad2SSunitha Harish { 2257fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2258fda13ad2SSunitha Harish } 2259fda13ad2SSunitha Harish if (!vlanEnable) 2260fda13ad2SSunitha Harish { 2261fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2262fda13ad2SSunitha Harish } 2263271584abSEd Tanous if (static_cast<bool>(vlanId) ^ vlanEnable) 2264fda13ad2SSunitha Harish { 2265fda13ad2SSunitha Harish return; 2266fda13ad2SSunitha Harish } 2267fda13ad2SSunitha Harish 22684a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 22694a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 22701abe55efSEd Tanous if (ec) 22711abe55efSEd Tanous { 22724a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 22734a0cb85cSEd Tanous // phosphor-network responses 2274f12894f8SJason M. Bills messages::internalError(asyncResp->res); 22754a0cb85cSEd Tanous return; 22761abe55efSEd Tanous } 2277f12894f8SJason M. Bills messages::created(asyncResp->res); 2278e439f0f8SKowalski, Kamil }; 22794a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 22804a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 22814a0cb85cSEd Tanous "/xyz/openbmc_project/network", 22824a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 22830627a2c7SEd Tanous rootInterfaceName, vlanId); 22844a0cb85cSEd Tanous } 22854a0cb85cSEd Tanous }; 22869391bb9cSRapkiewicz, Pawel } // namespace redfish 2287