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; 962a133282Smanojkiraneda bool DHCPEnabled; 974a0cb85cSEd Tanous std::string hostname; 984a0cb85cSEd Tanous std::string default_gateway; 999a6fc6feSRavi Teja std::string ipv6_default_gateway; 1004a0cb85cSEd Tanous std::string mac_address; 101fda13ad2SSunitha Harish std::vector<std::uint32_t> vlan_id; 102029573d4SEd Tanous std::vector<std::string> nameservers; 103d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1049391bb9cSRapkiewicz, Pawel }; 1059391bb9cSRapkiewicz, Pawel 1069391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1079391bb9cSRapkiewicz, Pawel // into full dot notation 1081abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1091abe55efSEd Tanous { 1109391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1119391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1129391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1139391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1149391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1159391bb9cSRapkiewicz, Pawel return netmask; 1169391bb9cSRapkiewicz, Pawel } 1179391bb9cSRapkiewicz, Pawel 1184a0cb85cSEd Tanous inline std::string 1194a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string &inputOrigin, 1204a0cb85cSEd Tanous bool isIPv4) 1211abe55efSEd Tanous { 1224a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1231abe55efSEd Tanous { 1244a0cb85cSEd Tanous return "Static"; 1259391bb9cSRapkiewicz, Pawel } 1264a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1271abe55efSEd Tanous { 1284a0cb85cSEd Tanous if (isIPv4) 1291abe55efSEd Tanous { 1304a0cb85cSEd Tanous return "IPv4LinkLocal"; 1311abe55efSEd Tanous } 1321abe55efSEd Tanous else 1331abe55efSEd Tanous { 1344a0cb85cSEd Tanous return "LinkLocal"; 1359391bb9cSRapkiewicz, Pawel } 1369391bb9cSRapkiewicz, Pawel } 1374a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1381abe55efSEd Tanous { 1394a0cb85cSEd Tanous if (isIPv4) 1404a0cb85cSEd Tanous { 1414a0cb85cSEd Tanous return "DHCP"; 1424a0cb85cSEd Tanous } 1434a0cb85cSEd Tanous else 1444a0cb85cSEd Tanous { 1454a0cb85cSEd Tanous return "DHCPv6"; 1464a0cb85cSEd Tanous } 1474a0cb85cSEd Tanous } 1484a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1494a0cb85cSEd Tanous { 1504a0cb85cSEd Tanous return "SLAAC"; 1514a0cb85cSEd Tanous } 1524a0cb85cSEd Tanous return ""; 1534a0cb85cSEd Tanous } 1544a0cb85cSEd Tanous 1554c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string ðiface_id, 1564a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 1574a0cb85cSEd Tanous EthernetInterfaceData ðData) 1584a0cb85cSEd Tanous { 1594c9afe43SEd Tanous bool idFound = false; 1604a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 1614a0cb85cSEd Tanous { 1624a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 1634a0cb85cSEd Tanous { 164029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 165029573d4SEd Tanous { 1664c9afe43SEd Tanous idFound = true; 1674a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 1684a0cb85cSEd Tanous { 1694a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1704a0cb85cSEd Tanous { 1714a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 1724a0cb85cSEd Tanous { 1734a0cb85cSEd Tanous const std::string *mac = 174abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 1754a0cb85cSEd Tanous if (mac != nullptr) 1764a0cb85cSEd Tanous { 1774a0cb85cSEd Tanous ethData.mac_address = *mac; 1784a0cb85cSEd Tanous } 1794a0cb85cSEd Tanous } 1804a0cb85cSEd Tanous } 1814a0cb85cSEd Tanous } 1824a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 1834a0cb85cSEd Tanous { 1844a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1854a0cb85cSEd Tanous { 1864a0cb85cSEd Tanous if (propertyPair.first == "Id") 1874a0cb85cSEd Tanous { 1881b6b96c5SEd Tanous const uint32_t *id = 189abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 1904a0cb85cSEd Tanous if (id != nullptr) 1914a0cb85cSEd Tanous { 192fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 1934a0cb85cSEd Tanous } 1944a0cb85cSEd Tanous } 1954a0cb85cSEd Tanous } 1964a0cb85cSEd Tanous } 1974a0cb85cSEd Tanous else if (ifacePair.first == 1984a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 1994a0cb85cSEd Tanous { 2004a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2014a0cb85cSEd Tanous { 2024a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2034a0cb85cSEd Tanous { 2044a0cb85cSEd Tanous const bool *auto_neg = 205abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2064a0cb85cSEd Tanous if (auto_neg != nullptr) 2074a0cb85cSEd Tanous { 2084a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2094a0cb85cSEd Tanous } 2104a0cb85cSEd Tanous } 2114a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2124a0cb85cSEd Tanous { 2134a0cb85cSEd Tanous const uint32_t *speed = 214abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2154a0cb85cSEd Tanous if (speed != nullptr) 2164a0cb85cSEd Tanous { 2174a0cb85cSEd Tanous ethData.speed = *speed; 2184a0cb85cSEd Tanous } 2194a0cb85cSEd Tanous } 220f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 221029573d4SEd Tanous { 222029573d4SEd Tanous const std::vector<std::string> *nameservers = 223029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 224029573d4SEd Tanous std::vector<std::string>>( 225029573d4SEd Tanous &propertyPair.second); 226029573d4SEd Tanous if (nameservers != nullptr) 227029573d4SEd Tanous { 228029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous } 2312a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 2322a133282Smanojkiraneda { 2332a133282Smanojkiraneda const bool *DHCPEnabled = 2342a133282Smanojkiraneda std::get_if<bool>(&propertyPair.second); 2352a133282Smanojkiraneda if (DHCPEnabled != nullptr) 2362a133282Smanojkiraneda { 2372a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 2382a133282Smanojkiraneda } 2392a133282Smanojkiraneda } 240d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 241d24bfc7aSJennifer Lee { 242d24bfc7aSJennifer Lee const std::vector<std::string> *domainNames = 243d24bfc7aSJennifer Lee sdbusplus::message::variant_ns::get_if< 244d24bfc7aSJennifer Lee std::vector<std::string>>( 245d24bfc7aSJennifer Lee &propertyPair.second); 246d24bfc7aSJennifer Lee if (domainNames != nullptr) 247d24bfc7aSJennifer Lee { 248d24bfc7aSJennifer Lee ethData.domainnames = std::move(*domainNames); 249d24bfc7aSJennifer Lee } 250d24bfc7aSJennifer Lee } 251029573d4SEd Tanous } 252029573d4SEd Tanous } 253029573d4SEd Tanous } 254029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 255029573d4SEd Tanous // to check eth number 256029573d4SEd Tanous if (ifacePair.first == 2574a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 2584a0cb85cSEd Tanous { 2594a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2604a0cb85cSEd Tanous { 2614a0cb85cSEd Tanous if (propertyPair.first == "HostName") 2624a0cb85cSEd Tanous { 2634a0cb85cSEd Tanous const std::string *hostname = 264029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 265029573d4SEd Tanous &propertyPair.second); 2664a0cb85cSEd Tanous if (hostname != nullptr) 2674a0cb85cSEd Tanous { 2684a0cb85cSEd Tanous ethData.hostname = *hostname; 2694a0cb85cSEd Tanous } 2704a0cb85cSEd Tanous } 2714a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 2724a0cb85cSEd Tanous { 2734a0cb85cSEd Tanous const std::string *defaultGateway = 274029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 275029573d4SEd Tanous &propertyPair.second); 2764a0cb85cSEd Tanous if (defaultGateway != nullptr) 2774a0cb85cSEd Tanous { 2784a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 2794a0cb85cSEd Tanous } 2804a0cb85cSEd Tanous } 2819a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 2829a6fc6feSRavi Teja { 2839a6fc6feSRavi Teja const std::string *defaultGateway6 = 2849a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 2859a6fc6feSRavi Teja &propertyPair.second); 2869a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 2879a6fc6feSRavi Teja { 2889a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 2899a6fc6feSRavi Teja } 2909a6fc6feSRavi Teja } 2914a0cb85cSEd Tanous } 2924a0cb85cSEd Tanous } 2934a0cb85cSEd Tanous } 2944a0cb85cSEd Tanous } 2954c9afe43SEd Tanous return idFound; 2964a0cb85cSEd Tanous } 2974a0cb85cSEd Tanous 298e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 299*01784826SJohnathan Mantey inline void 300*01784826SJohnathan Mantey extractIPV6Data(const std::string ðiface_id, 301*01784826SJohnathan Mantey const GetManagedObjects &dbus_data, 302*01784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData> &ipv6_config) 303e48c0fc5SRavi Teja { 304e48c0fc5SRavi Teja const std::string ipv6PathStart = 305e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/"; 306e48c0fc5SRavi Teja 307e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 308e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 309e48c0fc5SRavi Teja for (const auto &objpath : dbus_data) 310e48c0fc5SRavi Teja { 311e48c0fc5SRavi Teja // Check if proper pattern for object path appears 312e48c0fc5SRavi Teja if (boost::starts_with(objpath.first.str, ipv6PathStart)) 313e48c0fc5SRavi Teja { 314e48c0fc5SRavi Teja for (auto &interface : objpath.second) 315e48c0fc5SRavi Teja { 316e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 317e48c0fc5SRavi Teja { 318e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 319e48c0fc5SRavi Teja // appropriate 320e48c0fc5SRavi Teja std::pair< 321e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::iterator, 322e48c0fc5SRavi Teja bool> 323e48c0fc5SRavi Teja it = ipv6_config.insert( 324e48c0fc5SRavi Teja {objpath.first.str.substr(ipv6PathStart.size())}); 325e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 326e48c0fc5SRavi Teja for (auto &property : interface.second) 327e48c0fc5SRavi Teja { 328e48c0fc5SRavi Teja if (property.first == "Address") 329e48c0fc5SRavi Teja { 330e48c0fc5SRavi Teja const std::string *address = 331e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 332e48c0fc5SRavi Teja if (address != nullptr) 333e48c0fc5SRavi Teja { 334e48c0fc5SRavi Teja ipv6_address.address = *address; 335e48c0fc5SRavi Teja } 336e48c0fc5SRavi Teja } 337e48c0fc5SRavi Teja else if (property.first == "Origin") 338e48c0fc5SRavi Teja { 339e48c0fc5SRavi Teja const std::string *origin = 340e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 341e48c0fc5SRavi Teja if (origin != nullptr) 342e48c0fc5SRavi Teja { 343e48c0fc5SRavi Teja ipv6_address.origin = 344e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 345e48c0fc5SRavi Teja false); 346e48c0fc5SRavi Teja } 347e48c0fc5SRavi Teja } 348e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 349e48c0fc5SRavi Teja { 350e48c0fc5SRavi Teja const uint8_t *prefix = 351e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 352e48c0fc5SRavi Teja if (prefix != nullptr) 353e48c0fc5SRavi Teja { 354e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 355e48c0fc5SRavi Teja } 356e48c0fc5SRavi Teja } 357e48c0fc5SRavi Teja else 358e48c0fc5SRavi Teja { 359e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 360e48c0fc5SRavi Teja << "Got extra property: " << property.first 361e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 362e48c0fc5SRavi Teja } 363e48c0fc5SRavi Teja } 364e48c0fc5SRavi Teja } 365e48c0fc5SRavi Teja } 366e48c0fc5SRavi Teja } 367e48c0fc5SRavi Teja } 368e48c0fc5SRavi Teja } 369e48c0fc5SRavi Teja 3704a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 371*01784826SJohnathan Mantey inline void 372*01784826SJohnathan Mantey extractIPData(const std::string ðiface_id, 373*01784826SJohnathan Mantey const GetManagedObjects &dbus_data, 374*01784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData> &ipv4_config) 3754a0cb85cSEd Tanous { 3764a0cb85cSEd Tanous const std::string ipv4PathStart = 3774a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 3784a0cb85cSEd Tanous 3794a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 3804a0cb85cSEd Tanous // single ethernet interface, loop over all of them 3814a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 3824a0cb85cSEd Tanous { 3834a0cb85cSEd Tanous // Check if proper pattern for object path appears 3844a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 3854a0cb85cSEd Tanous { 3864a0cb85cSEd Tanous for (auto &interface : objpath.second) 3874a0cb85cSEd Tanous { 3884a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 3894a0cb85cSEd Tanous { 3904a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 3914a0cb85cSEd Tanous // appropriate 3924a0cb85cSEd Tanous std::pair< 3934a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 3944a0cb85cSEd Tanous bool> 3954a0cb85cSEd Tanous it = ipv4_config.insert( 396b01bf299SEd Tanous {objpath.first.str.substr(ipv4PathStart.size())}); 3974a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 3984a0cb85cSEd Tanous for (auto &property : interface.second) 3994a0cb85cSEd Tanous { 4004a0cb85cSEd Tanous if (property.first == "Address") 4014a0cb85cSEd Tanous { 4024a0cb85cSEd Tanous const std::string *address = 403abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4044a0cb85cSEd Tanous if (address != nullptr) 4054a0cb85cSEd Tanous { 4064a0cb85cSEd Tanous ipv4_address.address = *address; 4074a0cb85cSEd Tanous } 4084a0cb85cSEd Tanous } 4094a0cb85cSEd Tanous else if (property.first == "Gateway") 4104a0cb85cSEd Tanous { 4114a0cb85cSEd Tanous const std::string *gateway = 412abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4134a0cb85cSEd Tanous if (gateway != nullptr) 4144a0cb85cSEd Tanous { 4154a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 4164a0cb85cSEd Tanous } 4174a0cb85cSEd Tanous } 4184a0cb85cSEd Tanous else if (property.first == "Origin") 4194a0cb85cSEd Tanous { 4204a0cb85cSEd Tanous const std::string *origin = 421abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4224a0cb85cSEd Tanous if (origin != nullptr) 4234a0cb85cSEd Tanous { 4244a0cb85cSEd Tanous ipv4_address.origin = 4254a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 4264a0cb85cSEd Tanous true); 4274a0cb85cSEd Tanous } 4284a0cb85cSEd Tanous } 4294a0cb85cSEd Tanous else if (property.first == "PrefixLength") 4304a0cb85cSEd Tanous { 4314a0cb85cSEd Tanous const uint8_t *mask = 432abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 4334a0cb85cSEd Tanous if (mask != nullptr) 4344a0cb85cSEd Tanous { 4354a0cb85cSEd Tanous // convert it to the string 4364a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 4374a0cb85cSEd Tanous } 4384a0cb85cSEd Tanous } 4394a0cb85cSEd Tanous else 4404a0cb85cSEd Tanous { 4414a0cb85cSEd Tanous BMCWEB_LOG_ERROR 4424a0cb85cSEd Tanous << "Got extra property: " << property.first 4434a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 4444a0cb85cSEd Tanous } 4454a0cb85cSEd Tanous } 4464a0cb85cSEd Tanous // Check if given address is local, or global 4474a0cb85cSEd Tanous ipv4_address.linktype = 4484a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 44918659d10SJohnathan Mantey ? LinkType::Local 45018659d10SJohnathan Mantey : LinkType::Global; 4514a0cb85cSEd Tanous } 4524a0cb85cSEd Tanous } 4534a0cb85cSEd Tanous } 4544a0cb85cSEd Tanous } 4554a0cb85cSEd Tanous } 456588c3f0dSKowalski, Kamil 457588c3f0dSKowalski, Kamil /** 458588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 459588c3f0dSKowalski, Kamil * 460588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 461588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 462588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 463588c3f0dSKowalski, Kamil * 464588c3f0dSKowalski, Kamil * @return None. 465588c3f0dSKowalski, Kamil */ 466588c3f0dSKowalski, Kamil template <typename CallbackFunc> 4674a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 4681abe55efSEd Tanous CallbackFunc &&callback) 4691abe55efSEd Tanous { 47055c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 471588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 472588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 473588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 474588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 475abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 4764a0cb85cSEd Tanous } 477588c3f0dSKowalski, Kamil 478588c3f0dSKowalski, Kamil /** 479179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 480179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 481179db1d7SKowalski, Kamil * bit count for Subnet Mask. 482179db1d7SKowalski, Kamil * 483179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 484179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 485179db1d7SKowalski, Kamil * 486179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 487179db1d7SKowalski, Kamil */ 4884a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 4891abe55efSEd Tanous uint8_t *bits = nullptr) 4901abe55efSEd Tanous { 491179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 492179db1d7SKowalski, Kamil 493179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 494179db1d7SKowalski, Kamil 4954a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 4961abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 4971abe55efSEd Tanous { 498179db1d7SKowalski, Kamil return false; 499179db1d7SKowalski, Kamil } 500179db1d7SKowalski, Kamil 5011abe55efSEd Tanous if (bits != nullptr) 5021abe55efSEd Tanous { 503179db1d7SKowalski, Kamil *bits = 0; 504179db1d7SKowalski, Kamil } 505179db1d7SKowalski, Kamil 506179db1d7SKowalski, Kamil char *endPtr; 507179db1d7SKowalski, Kamil long previousValue = 255; 508179db1d7SKowalski, Kamil bool firstZeroInByteHit; 5091abe55efSEd Tanous for (const std::string &byte : bytesInMask) 5101abe55efSEd Tanous { 5111abe55efSEd Tanous if (byte.empty()) 5121abe55efSEd Tanous { 5131db9ca37SKowalski, Kamil return false; 5141db9ca37SKowalski, Kamil } 5151db9ca37SKowalski, Kamil 516179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 5171db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 518179db1d7SKowalski, Kamil 5194a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 5204a0cb85cSEd Tanous // is not 100% number 5211abe55efSEd Tanous if (*endPtr != '\0') 5221abe55efSEd Tanous { 523179db1d7SKowalski, Kamil return false; 524179db1d7SKowalski, Kamil } 525179db1d7SKowalski, Kamil 526179db1d7SKowalski, Kamil // Value should be contained in byte 5271abe55efSEd Tanous if (value < 0 || value > 255) 5281abe55efSEd Tanous { 529179db1d7SKowalski, Kamil return false; 530179db1d7SKowalski, Kamil } 531179db1d7SKowalski, Kamil 5321abe55efSEd Tanous if (bits != nullptr) 5331abe55efSEd Tanous { 534179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 5351abe55efSEd Tanous if (previousValue != 255 && value != 0) 5361abe55efSEd Tanous { 537179db1d7SKowalski, Kamil return false; 538179db1d7SKowalski, Kamil } 539179db1d7SKowalski, Kamil 540179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 541179db1d7SKowalski, Kamil firstZeroInByteHit = false; 542179db1d7SKowalski, Kamil 543179db1d7SKowalski, Kamil // Count bits 5441abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 5451abe55efSEd Tanous { 5461abe55efSEd Tanous if (value & (1 << bitIdx)) 5471abe55efSEd Tanous { 5481abe55efSEd Tanous if (firstZeroInByteHit) 5491abe55efSEd Tanous { 550179db1d7SKowalski, Kamil // Continuity not preserved 551179db1d7SKowalski, Kamil return false; 5521abe55efSEd Tanous } 5531abe55efSEd Tanous else 5541abe55efSEd Tanous { 555179db1d7SKowalski, Kamil (*bits)++; 556179db1d7SKowalski, Kamil } 5571abe55efSEd Tanous } 5581abe55efSEd Tanous else 5591abe55efSEd Tanous { 560179db1d7SKowalski, Kamil firstZeroInByteHit = true; 561179db1d7SKowalski, Kamil } 562179db1d7SKowalski, Kamil } 563179db1d7SKowalski, Kamil } 564179db1d7SKowalski, Kamil 565179db1d7SKowalski, Kamil previousValue = value; 566179db1d7SKowalski, Kamil } 567179db1d7SKowalski, Kamil 568179db1d7SKowalski, Kamil return true; 569179db1d7SKowalski, Kamil } 570179db1d7SKowalski, Kamil 571179db1d7SKowalski, Kamil /** 572*01784826SJohnathan Mantey * @brief Deletes given IPv4 interface 573179db1d7SKowalski, Kamil * 574179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 575179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 576179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 577179db1d7SKowalski, Kamil * 578179db1d7SKowalski, Kamil * @return None 579179db1d7SKowalski, Kamil */ 5804a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 5814a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 5821abe55efSEd Tanous { 58355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 584286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 5851abe55efSEd Tanous if (ec) 5861abe55efSEd Tanous { 587a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 5881abe55efSEd Tanous } 589179db1d7SKowalski, Kamil }, 590179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 591179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 592179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 593179db1d7SKowalski, Kamil } 594179db1d7SKowalski, Kamil 595179db1d7SKowalski, Kamil /** 596*01784826SJohnathan Mantey * @brief Creates a static IPv4 entry 597179db1d7SKowalski, Kamil * 598*01784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 599*01784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 600*01784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 601*01784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 602179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 603179db1d7SKowalski, Kamil * 604179db1d7SKowalski, Kamil * @return None 605179db1d7SKowalski, Kamil */ 606b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 607*01784826SJohnathan Mantey uint8_t prefixLength, const std::string &gateway, 608b01bf299SEd Tanous const std::string &address, 6094a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6101abe55efSEd Tanous { 611*01784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 612*01784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 6131abe55efSEd Tanous if (ec) 6141abe55efSEd Tanous { 615a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 616179db1d7SKowalski, Kamil } 617*01784826SJohnathan Mantey }, 618*01784826SJohnathan Mantey "xyz.openbmc_project.Network", 619179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 620179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 621*01784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 622179db1d7SKowalski, Kamil gateway); 623179db1d7SKowalski, Kamil } 624e48c0fc5SRavi Teja 625e48c0fc5SRavi Teja /** 626*01784826SJohnathan Mantey * @brief Deletes the IPv4 entry for this interface and creates a replacement 627*01784826SJohnathan Mantey * static IPv4 entry 628*01784826SJohnathan Mantey * 629*01784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 630*01784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 631*01784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 632*01784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 633*01784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 634*01784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 635*01784826SJohnathan Mantey * 636*01784826SJohnathan Mantey * @return None 637*01784826SJohnathan Mantey */ 638*01784826SJohnathan Mantey inline void deleteAndCreateIPv4(const std::string &ifaceId, 639*01784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 640*01784826SJohnathan Mantey const std::string &gateway, 641*01784826SJohnathan Mantey const std::string &address, 642*01784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 643*01784826SJohnathan Mantey { 644*01784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 645*01784826SJohnathan Mantey [asyncResp, ifaceId, address, prefixLength, 646*01784826SJohnathan Mantey gateway](const boost::system::error_code ec) { 647*01784826SJohnathan Mantey if (ec) 648*01784826SJohnathan Mantey { 649*01784826SJohnathan Mantey messages::internalError(asyncResp->res); 650*01784826SJohnathan Mantey } 651*01784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 652*01784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 653*01784826SJohnathan Mantey if (ec) 654*01784826SJohnathan Mantey { 655*01784826SJohnathan Mantey messages::internalError(asyncResp->res); 656*01784826SJohnathan Mantey } 657*01784826SJohnathan Mantey }, 658*01784826SJohnathan Mantey "xyz.openbmc_project.Network", 659*01784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 660*01784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 661*01784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, 662*01784826SJohnathan Mantey prefixLength, gateway); 663*01784826SJohnathan Mantey }, 664*01784826SJohnathan Mantey "xyz.openbmc_project.Network", 665*01784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + id, 666*01784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 667*01784826SJohnathan Mantey } 668*01784826SJohnathan Mantey 669*01784826SJohnathan Mantey /** 670e48c0fc5SRavi Teja * @brief Deletes given IPv6 671e48c0fc5SRavi Teja * 672e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 673e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 674e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 675e48c0fc5SRavi Teja * 676e48c0fc5SRavi Teja * @return None 677e48c0fc5SRavi Teja */ 678e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 679e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 680e48c0fc5SRavi Teja { 681e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 682286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 683e48c0fc5SRavi Teja if (ec) 684e48c0fc5SRavi Teja { 685e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 686e48c0fc5SRavi Teja } 687e48c0fc5SRavi Teja }, 688e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 689e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 690e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 691e48c0fc5SRavi Teja } 692e48c0fc5SRavi Teja 693e48c0fc5SRavi Teja /** 694*01784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 695*01784826SJohnathan Mantey * static IPv6 entry 696*01784826SJohnathan Mantey * 697*01784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 698*01784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 699*01784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 700*01784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 701*01784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 702*01784826SJohnathan Mantey * 703*01784826SJohnathan Mantey * @return None 704*01784826SJohnathan Mantey */ 705*01784826SJohnathan Mantey inline void deleteAndCreateIPv6(const std::string &ifaceId, 706*01784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 707*01784826SJohnathan Mantey const std::string &address, 708*01784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 709*01784826SJohnathan Mantey { 710*01784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 711*01784826SJohnathan Mantey [asyncResp, ifaceId, address, 712*01784826SJohnathan Mantey prefixLength](const boost::system::error_code ec) { 713*01784826SJohnathan Mantey if (ec) 714*01784826SJohnathan Mantey { 715*01784826SJohnathan Mantey messages::internalError(asyncResp->res); 716*01784826SJohnathan Mantey } 717*01784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 718*01784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 719*01784826SJohnathan Mantey if (ec) 720*01784826SJohnathan Mantey { 721*01784826SJohnathan Mantey messages::internalError(asyncResp->res); 722*01784826SJohnathan Mantey } 723*01784826SJohnathan Mantey }, 724*01784826SJohnathan Mantey "xyz.openbmc_project.Network", 725*01784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 726*01784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 727*01784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, 728*01784826SJohnathan Mantey prefixLength, ""); 729*01784826SJohnathan Mantey }, 730*01784826SJohnathan Mantey "xyz.openbmc_project.Network", 731*01784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + id, 732*01784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 733*01784826SJohnathan Mantey } 734*01784826SJohnathan Mantey 735*01784826SJohnathan Mantey /** 736e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 737e48c0fc5SRavi Teja * 738e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 739e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 740e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 741e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 742e48c0fc5SRavi Teja * 743e48c0fc5SRavi Teja * @return None 744e48c0fc5SRavi Teja */ 745*01784826SJohnathan Mantey inline void createIPv6(const std::string &ifaceId, uint8_t prefixLength, 746*01784826SJohnathan Mantey const std::string &address, 747e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 748e48c0fc5SRavi Teja { 749e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 750e48c0fc5SRavi Teja if (ec) 751e48c0fc5SRavi Teja { 752e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 753e48c0fc5SRavi Teja } 754e48c0fc5SRavi Teja }; 755e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 756e48c0fc5SRavi Teja // does not have assosiated gateway property 757e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 758e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 759e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 760e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 761e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 762e48c0fc5SRavi Teja ""); 763e48c0fc5SRavi Teja } 764e48c0fc5SRavi Teja 7652a133282Smanojkiraneda using GetAllPropertiesType = 7662a133282Smanojkiraneda boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>; 7672a133282Smanojkiraneda 7682a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) 7692a133282Smanojkiraneda { 7702a133282Smanojkiraneda auto getConfig = [asyncResp](const boost::system::error_code error_code, 7712a133282Smanojkiraneda const GetAllPropertiesType &dbus_data) { 7722a133282Smanojkiraneda if (error_code) 7732a133282Smanojkiraneda { 7742a133282Smanojkiraneda BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code; 7752a133282Smanojkiraneda messages::internalError(asyncResp->res); 7762a133282Smanojkiraneda return; 7772a133282Smanojkiraneda } 778fda13ad2SSunitha Harish nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; 7792a133282Smanojkiraneda for (const auto &property : dbus_data) 7802a133282Smanojkiraneda { 7812a133282Smanojkiraneda auto value = 7822a133282Smanojkiraneda sdbusplus::message::variant_ns::get_if<bool>(&property.second); 7832a133282Smanojkiraneda 7842a133282Smanojkiraneda if (value == nullptr) 7852a133282Smanojkiraneda { 7862a133282Smanojkiraneda continue; 7872a133282Smanojkiraneda } 7882a133282Smanojkiraneda if (property.first == "DNSEnabled") 7892a133282Smanojkiraneda { 7902a133282Smanojkiraneda DHCPConfigTypeJson["UseDNSServers"] = *value; 7912a133282Smanojkiraneda } 7922a133282Smanojkiraneda else if (property.first == "HostNameEnabled") 7932a133282Smanojkiraneda { 7942a133282Smanojkiraneda DHCPConfigTypeJson["UseDomainName"] = *value; 7952a133282Smanojkiraneda } 7962a133282Smanojkiraneda else if (property.first == "NTPEnabled") 7972a133282Smanojkiraneda { 7982a133282Smanojkiraneda DHCPConfigTypeJson["UseNTPServers"] = *value; 7992a133282Smanojkiraneda } 8002a133282Smanojkiraneda } 8012a133282Smanojkiraneda }; 8022a133282Smanojkiraneda crow::connections::systemBus->async_method_call( 8032a133282Smanojkiraneda std::move(getConfig), "xyz.openbmc_project.Network", 8042a133282Smanojkiraneda "/xyz/openbmc_project/network/config/dhcp", 8052a133282Smanojkiraneda "org.freedesktop.DBus.Properties", "GetAll", 8062a133282Smanojkiraneda "xyz.openbmc_project.Network.DHCPConfiguration"); 8072a133282Smanojkiraneda } 808179db1d7SKowalski, Kamil 809179db1d7SKowalski, Kamil /** 810179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 811179db1d7SKowalski, Kamil * Object 812179db1d7SKowalski, Kamil * from EntityManager Network Manager 8134a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 814179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 815179db1d7SKowalski, Kamil * into JSON 816179db1d7SKowalski, Kamil */ 817179db1d7SKowalski, Kamil template <typename CallbackFunc> 8184a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8191abe55efSEd Tanous CallbackFunc &&callback) 8201abe55efSEd Tanous { 82155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8224a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8231abe55efSEd Tanous const boost::system::error_code error_code, 8244a0cb85cSEd Tanous const GetManagedObjects &resp) { 82555c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8264a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 827e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 828179db1d7SKowalski, Kamil 8291abe55efSEd Tanous if (error_code) 8301abe55efSEd Tanous { 831*01784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 832179db1d7SKowalski, Kamil return; 833179db1d7SKowalski, Kamil } 834179db1d7SKowalski, Kamil 8354c9afe43SEd Tanous bool found = 8364a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 8374c9afe43SEd Tanous if (!found) 8384c9afe43SEd Tanous { 839*01784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 8404c9afe43SEd Tanous return; 8414c9afe43SEd Tanous } 8424c9afe43SEd Tanous 843*01784826SJohnathan Mantey extractIPData(ethiface_id, resp, ipv4Data); 844179db1d7SKowalski, Kamil // Fix global GW 8451abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 8461abe55efSEd Tanous { 847c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 848c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 849c619141bSRavi Teja (ipv4.origin == "DHCP")) 8501abe55efSEd Tanous { 8514a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 852179db1d7SKowalski, Kamil } 853179db1d7SKowalski, Kamil } 854179db1d7SKowalski, Kamil 855*01784826SJohnathan Mantey extractIPV6Data(ethiface_id, resp, ipv6Data); 8564a0cb85cSEd Tanous // Finally make a callback with usefull data 857*01784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 858179db1d7SKowalski, Kamil }, 859179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 860179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 861179db1d7SKowalski, Kamil }; 862179db1d7SKowalski, Kamil 863179db1d7SKowalski, Kamil /** 8649391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8659391bb9cSRapkiewicz, Pawel * Manager 8661abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8671abe55efSEd Tanous * into JSON. 8689391bb9cSRapkiewicz, Pawel */ 8699391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8701abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 8711abe55efSEd Tanous { 87255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8734a0cb85cSEd Tanous [callback{std::move(callback)}]( 8749391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 8754a0cb85cSEd Tanous GetManagedObjects &resp) { 8761abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8771abe55efSEd Tanous // ethernet interfaces 8784c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 8794a0cb85cSEd Tanous iface_list.reserve(resp.size()); 8801abe55efSEd Tanous if (error_code) 8811abe55efSEd Tanous { 8824a0cb85cSEd Tanous callback(false, iface_list); 8839391bb9cSRapkiewicz, Pawel return; 8849391bb9cSRapkiewicz, Pawel } 8859391bb9cSRapkiewicz, Pawel 8869391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8874a0cb85cSEd Tanous for (const auto &objpath : resp) 8881abe55efSEd Tanous { 8899391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 8904a0cb85cSEd Tanous for (const auto &interface : objpath.second) 8911abe55efSEd Tanous { 8921abe55efSEd Tanous // If interface is 8934a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 8944a0cb85cSEd Tanous // what we're looking for. 8959391bb9cSRapkiewicz, Pawel if (interface.first == 8961abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 8971abe55efSEd Tanous { 8984a0cb85cSEd Tanous // Cut out everyting until last "/", ... 8994a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9004a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9014a0cb85cSEd Tanous if (last_pos != std::string::npos) 9021abe55efSEd Tanous { 9039391bb9cSRapkiewicz, Pawel // and put it into output vector. 9044c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9059391bb9cSRapkiewicz, Pawel } 9069391bb9cSRapkiewicz, Pawel } 9079391bb9cSRapkiewicz, Pawel } 9089391bb9cSRapkiewicz, Pawel } 909a434f2bdSEd Tanous // Finally make a callback with useful data 9104a0cb85cSEd Tanous callback(true, iface_list); 9119391bb9cSRapkiewicz, Pawel }, 912aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 913aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 9149391bb9cSRapkiewicz, Pawel }; 9159391bb9cSRapkiewicz, Pawel 9169391bb9cSRapkiewicz, Pawel /** 9179391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9189391bb9cSRapkiewicz, Pawel */ 9191abe55efSEd Tanous class EthernetCollection : public Node 9201abe55efSEd Tanous { 9219391bb9cSRapkiewicz, Pawel public: 9224a0cb85cSEd Tanous template <typename CrowApp> 9231abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9244a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9251abe55efSEd Tanous { 926588c3f0dSKowalski, Kamil entityPrivileges = { 927588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 928e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 929e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 930e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 931e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 932e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9339391bb9cSRapkiewicz, Pawel } 9349391bb9cSRapkiewicz, Pawel 9359391bb9cSRapkiewicz, Pawel private: 9369391bb9cSRapkiewicz, Pawel /** 9379391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 9389391bb9cSRapkiewicz, Pawel */ 93955c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 9401abe55efSEd Tanous const std::vector<std::string> ¶ms) override 9411abe55efSEd Tanous { 9420f74e643SEd Tanous res.jsonValue["@odata.type"] = 9430f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9440f74e643SEd Tanous res.jsonValue["@odata.context"] = 9450f74e643SEd Tanous "/redfish/v1/" 9460f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9470f74e643SEd Tanous res.jsonValue["@odata.id"] = 9480f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9490f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 9500f74e643SEd Tanous res.jsonValue["Description"] = 9510f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 9524c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 9534a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 9541abe55efSEd Tanous // preparation 955f12894f8SJason M. Bills getEthernetIfaceList( 9564c9afe43SEd Tanous [asyncResp]( 9574c9afe43SEd Tanous const bool &success, 9584c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 9594a0cb85cSEd Tanous if (!success) 9601abe55efSEd Tanous { 9614c9afe43SEd Tanous messages::internalError(asyncResp->res); 9624a0cb85cSEd Tanous return; 9634a0cb85cSEd Tanous } 9644a0cb85cSEd Tanous 9654c9afe43SEd Tanous nlohmann::json &iface_array = 9664c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 9674a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 968fda13ad2SSunitha Harish std::string tag = "_"; 9694a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 9701abe55efSEd Tanous { 971fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 972fda13ad2SSunitha Harish if (found == std::string::npos) 973fda13ad2SSunitha Harish { 9744a0cb85cSEd Tanous iface_array.push_back( 9754a0cb85cSEd Tanous {{"@odata.id", 9764a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 9774a0cb85cSEd Tanous iface_item}}); 9789391bb9cSRapkiewicz, Pawel } 979fda13ad2SSunitha Harish } 9804a0cb85cSEd Tanous 9814c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 9824c9afe43SEd Tanous iface_array.size(); 9834c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9844a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9859391bb9cSRapkiewicz, Pawel }); 9869391bb9cSRapkiewicz, Pawel } 9879391bb9cSRapkiewicz, Pawel }; 9889391bb9cSRapkiewicz, Pawel 9899391bb9cSRapkiewicz, Pawel /** 9909391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 9919391bb9cSRapkiewicz, Pawel */ 9921abe55efSEd Tanous class EthernetInterface : public Node 9931abe55efSEd Tanous { 9949391bb9cSRapkiewicz, Pawel public: 9959391bb9cSRapkiewicz, Pawel /* 9969391bb9cSRapkiewicz, Pawel * Default Constructor 9979391bb9cSRapkiewicz, Pawel */ 9984a0cb85cSEd Tanous template <typename CrowApp> 9991abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10004a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10011abe55efSEd Tanous std::string()) 10021abe55efSEd Tanous { 1003588c3f0dSKowalski, Kamil entityPrivileges = { 1004588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1005e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1006e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1007e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1008e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1009e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10109391bb9cSRapkiewicz, Pawel } 10119391bb9cSRapkiewicz, Pawel 1012e439f0f8SKowalski, Kamil private: 1013bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10144a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10151abe55efSEd Tanous { 1016bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1017bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1018bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10194a0cb85cSEd Tanous if (ec) 10204a0cb85cSEd Tanous { 1021a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10221abe55efSEd Tanous } 1023bc0bd6e0SEd Tanous }, 1024bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1025bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1026bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1027bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1028abf2add6SEd Tanous std::variant<std::string>(hostname)); 1029588c3f0dSKowalski, Kamil } 1030588c3f0dSKowalski, Kamil 1031d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1032d577665bSRatan Gupta const std::string &macAddress, 1033d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1034d577665bSRatan Gupta { 1035d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1036d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1037d577665bSRatan Gupta if (ec) 1038d577665bSRatan Gupta { 1039d577665bSRatan Gupta messages::internalError(asyncResp->res); 1040d577665bSRatan Gupta return; 1041d577665bSRatan Gupta } 1042d577665bSRatan Gupta }, 1043d577665bSRatan Gupta "xyz.openbmc_project.Network", 1044d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1045d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1046d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1047d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1048d577665bSRatan Gupta } 1049286b9118SJohnathan Mantey 1050da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1051da131a9aSJennifer Lee const std::string &propertyName, const bool &value, 1052da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1053da131a9aSJennifer Lee { 1054da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1055da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1056da131a9aSJennifer Lee if (ec) 1057da131a9aSJennifer Lee { 1058da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1059da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1060da131a9aSJennifer Lee return; 1061da131a9aSJennifer Lee } 1062da131a9aSJennifer Lee }, 1063da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1064da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1065da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1066da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1067da131a9aSJennifer Lee std::variant<bool>{value}); 1068da131a9aSJennifer Lee } 1069da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1070da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1071da131a9aSJennifer Lee { 1072da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1073da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1074da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1075da131a9aSJennifer Lee if (ec) 1076da131a9aSJennifer Lee { 1077da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1078da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1079da131a9aSJennifer Lee return; 1080da131a9aSJennifer Lee } 1081da131a9aSJennifer Lee }, 1082da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1083da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1084da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1085da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1086da131a9aSJennifer Lee std::variant<bool>{value}); 1087da131a9aSJennifer Lee } 1088d577665bSRatan Gupta 1089da131a9aSJennifer Lee void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input, 1090da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1091da131a9aSJennifer Lee { 1092da131a9aSJennifer Lee std::optional<bool> dhcpEnabled; 1093da131a9aSJennifer Lee std::optional<bool> useDNSServers; 1094da131a9aSJennifer Lee std::optional<bool> useDomainName; 1095da131a9aSJennifer Lee std::optional<bool> useNTPServers; 1096da131a9aSJennifer Lee 1097da131a9aSJennifer Lee if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled", 1098da131a9aSJennifer Lee dhcpEnabled, "UseDNSServers", useDNSServers, 1099da131a9aSJennifer Lee "UseDomainName", useDomainName, 1100da131a9aSJennifer Lee "UseNTPServers", useNTPServers)) 1101da131a9aSJennifer Lee { 1102da131a9aSJennifer Lee return; 1103da131a9aSJennifer Lee } 1104da131a9aSJennifer Lee 1105da131a9aSJennifer Lee if (dhcpEnabled) 1106da131a9aSJennifer Lee { 1107da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1108da131a9aSJennifer Lee setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp); 1109da131a9aSJennifer Lee } 1110da131a9aSJennifer Lee 1111da131a9aSJennifer Lee if (useDNSServers) 1112da131a9aSJennifer Lee { 1113da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1114da131a9aSJennifer Lee setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp); 1115da131a9aSJennifer Lee } 1116da131a9aSJennifer Lee 1117da131a9aSJennifer Lee if (useDomainName) 1118da131a9aSJennifer Lee { 1119da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1120da131a9aSJennifer Lee setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp); 1121da131a9aSJennifer Lee } 1122da131a9aSJennifer Lee 1123da131a9aSJennifer Lee if (useNTPServers) 1124da131a9aSJennifer Lee { 1125da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1126da131a9aSJennifer Lee setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp); 1127da131a9aSJennifer Lee } 1128da131a9aSJennifer Lee } 1129*01784826SJohnathan Mantey 1130*01784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator 1131*01784826SJohnathan Mantey GetNextStaticIPEntry( 1132*01784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator head, 1133*01784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator end) 1134*01784826SJohnathan Mantey { 1135*01784826SJohnathan Mantey for (; head != end; head++) 1136*01784826SJohnathan Mantey { 1137*01784826SJohnathan Mantey if (head->origin == "Static") 1138*01784826SJohnathan Mantey { 1139*01784826SJohnathan Mantey return head; 1140*01784826SJohnathan Mantey } 1141*01784826SJohnathan Mantey } 1142*01784826SJohnathan Mantey return end; 1143*01784826SJohnathan Mantey } 1144*01784826SJohnathan Mantey 1145*01784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator 1146*01784826SJohnathan Mantey GetNextStaticIPEntry( 1147*01784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator head, 1148*01784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator end) 1149*01784826SJohnathan Mantey { 1150*01784826SJohnathan Mantey for (; head != end; head++) 1151*01784826SJohnathan Mantey { 1152*01784826SJohnathan Mantey if (head->origin == "Static") 1153*01784826SJohnathan Mantey { 1154*01784826SJohnathan Mantey return head; 1155*01784826SJohnathan Mantey } 1156*01784826SJohnathan Mantey } 1157*01784826SJohnathan Mantey return end; 1158*01784826SJohnathan Mantey } 1159*01784826SJohnathan Mantey 1160d1d50814SRavi Teja void handleIPv4StaticPatch( 1161f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 1162*01784826SJohnathan Mantey const boost::container::flat_set<IPv4AddressData> &ipv4Data, 11634a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 11641abe55efSEd Tanous { 1165*01784826SJohnathan Mantey if ((!input.is_array()) || input.empty()) 1166f476acbfSRatan Gupta { 1167f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1168d1d50814SRavi Teja "IPv4StaticAddresses"); 1169f476acbfSRatan Gupta return; 1170f476acbfSRatan Gupta } 1171f476acbfSRatan Gupta 1172*01784826SJohnathan Mantey int entryIdx = 1; 1173*01784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 1174*01784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 1175*01784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 1176*01784826SJohnathan Mantey // into the NIC. 1177*01784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator NICIPentry = 1178*01784826SJohnathan Mantey GetNextStaticIPEntry(ipv4Data.cbegin(), ipv4Data.cend()); 1179*01784826SJohnathan Mantey 1180537174c4SEd Tanous for (nlohmann::json &thisJson : input) 11811abe55efSEd Tanous { 11824a0cb85cSEd Tanous std::string pathString = 1183d1d50814SRavi Teja "IPv4StaticAddresses/" + std::to_string(entryIdx); 1184179db1d7SKowalski, Kamil 1185*01784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1186f476acbfSRatan Gupta { 1187537174c4SEd Tanous std::optional<std::string> address; 1188537174c4SEd Tanous std::optional<std::string> subnetMask; 1189537174c4SEd Tanous std::optional<std::string> gateway; 1190537174c4SEd Tanous 1191537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 11927e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 11937e27d832SJohnathan Mantey "Gateway", gateway)) 1194537174c4SEd Tanous { 1195*01784826SJohnathan Mantey messages::propertyValueFormatError( 1196*01784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1197537174c4SEd Tanous return; 1198179db1d7SKowalski, Kamil } 1199179db1d7SKowalski, Kamil 1200*01784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 1201*01784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 1202*01784826SJohnathan Mantey // current state of the interface. Merge existing state into the 1203*01784826SJohnathan Mantey // current request. 1204*01784826SJohnathan Mantey const std::string *addr; 1205*01784826SJohnathan Mantey const std::string *gw; 1206*01784826SJohnathan Mantey uint8_t prefixLength = 0; 1207*01784826SJohnathan Mantey bool errorInEntry = false; 1208537174c4SEd Tanous if (address) 12091abe55efSEd Tanous { 1210*01784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*address)) 12111abe55efSEd Tanous { 1212*01784826SJohnathan Mantey addr = &(*address); 12134a0cb85cSEd Tanous } 1214*01784826SJohnathan Mantey else 1215*01784826SJohnathan Mantey { 1216*01784826SJohnathan Mantey messages::propertyValueFormatError( 1217*01784826SJohnathan Mantey asyncResp->res, *address, pathString + "/Address"); 1218*01784826SJohnathan Mantey errorInEntry = true; 1219*01784826SJohnathan Mantey } 1220*01784826SJohnathan Mantey } 1221*01784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 1222*01784826SJohnathan Mantey { 1223*01784826SJohnathan Mantey addr = &(NICIPentry->address); 1224*01784826SJohnathan Mantey } 1225*01784826SJohnathan Mantey else 1226*01784826SJohnathan Mantey { 1227*01784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 1228*01784826SJohnathan Mantey pathString + "/Address"); 1229*01784826SJohnathan Mantey errorInEntry = true; 12304a0cb85cSEd Tanous } 12314a0cb85cSEd Tanous 1232537174c4SEd Tanous if (subnetMask) 12334a0cb85cSEd Tanous { 1234537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 12354a0cb85cSEd Tanous { 1236f12894f8SJason M. Bills messages::propertyValueFormatError( 1237537174c4SEd Tanous asyncResp->res, *subnetMask, 12384a0cb85cSEd Tanous pathString + "/SubnetMask"); 1239*01784826SJohnathan Mantey errorInEntry = true; 12404a0cb85cSEd Tanous } 12414a0cb85cSEd Tanous } 1242*01784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 12434a0cb85cSEd Tanous { 1244*01784826SJohnathan Mantey if (!ipv4VerifyIpAndGetBitcount(NICIPentry->netmask, 1245*01784826SJohnathan Mantey &prefixLength)) 12464a0cb85cSEd Tanous { 1247*01784826SJohnathan Mantey messages::propertyValueFormatError( 1248*01784826SJohnathan Mantey asyncResp->res, NICIPentry->netmask, 1249*01784826SJohnathan Mantey pathString + "/SubnetMask"); 1250*01784826SJohnathan Mantey errorInEntry = true; 12514a0cb85cSEd Tanous } 12524a0cb85cSEd Tanous } 12531abe55efSEd Tanous else 12541abe55efSEd Tanous { 1255*01784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 1256*01784826SJohnathan Mantey pathString + "/SubnetMask"); 1257*01784826SJohnathan Mantey errorInEntry = true; 1258*01784826SJohnathan Mantey } 1259*01784826SJohnathan Mantey 1260*01784826SJohnathan Mantey if (gateway) 1261*01784826SJohnathan Mantey { 1262*01784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*gateway)) 1263*01784826SJohnathan Mantey { 1264*01784826SJohnathan Mantey gw = &(*gateway); 1265*01784826SJohnathan Mantey } 1266*01784826SJohnathan Mantey else 1267*01784826SJohnathan Mantey { 1268*01784826SJohnathan Mantey messages::propertyValueFormatError( 1269*01784826SJohnathan Mantey asyncResp->res, *gateway, pathString + "/Gateway"); 1270*01784826SJohnathan Mantey errorInEntry = true; 1271*01784826SJohnathan Mantey } 1272*01784826SJohnathan Mantey } 1273*01784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 1274*01784826SJohnathan Mantey { 1275*01784826SJohnathan Mantey gw = &NICIPentry->gateway; 1276*01784826SJohnathan Mantey } 1277*01784826SJohnathan Mantey else 12781abe55efSEd Tanous { 1279a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 12804a0cb85cSEd Tanous pathString + "/Gateway"); 1281*01784826SJohnathan Mantey errorInEntry = true; 12824a0cb85cSEd Tanous } 12834a0cb85cSEd Tanous 1284*01784826SJohnathan Mantey if (errorInEntry) 12851abe55efSEd Tanous { 1286*01784826SJohnathan Mantey return; 12874a0cb85cSEd Tanous } 12884a0cb85cSEd Tanous 1289*01784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 12901abe55efSEd Tanous { 1291*01784826SJohnathan Mantey deleteAndCreateIPv4(ifaceId, NICIPentry->id, prefixLength, 1292*01784826SJohnathan Mantey *gw, *addr, asyncResp); 1293*01784826SJohnathan Mantey NICIPentry = 1294*01784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 1295588c3f0dSKowalski, Kamil } 1296*01784826SJohnathan Mantey else 1297*01784826SJohnathan Mantey { 1298*01784826SJohnathan Mantey createIPv4(ifaceId, entryIdx, prefixLength, *gateway, 1299*01784826SJohnathan Mantey *address, asyncResp); 13004a0cb85cSEd Tanous } 13014a0cb85cSEd Tanous entryIdx++; 13024a0cb85cSEd Tanous } 1303*01784826SJohnathan Mantey else 1304*01784826SJohnathan Mantey { 1305*01784826SJohnathan Mantey if (NICIPentry == ipv4Data.cend()) 1306*01784826SJohnathan Mantey { 1307*01784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 1308*01784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 1309*01784826SJohnathan Mantey // in error, so bail out. 1310*01784826SJohnathan Mantey if (thisJson.is_null()) 1311*01784826SJohnathan Mantey { 1312*01784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 1313*01784826SJohnathan Mantey return; 1314*01784826SJohnathan Mantey } 1315*01784826SJohnathan Mantey else 1316*01784826SJohnathan Mantey { 1317*01784826SJohnathan Mantey messages::propertyValueFormatError( 1318*01784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1319*01784826SJohnathan Mantey return; 1320*01784826SJohnathan Mantey } 1321*01784826SJohnathan Mantey } 1322*01784826SJohnathan Mantey 1323*01784826SJohnathan Mantey if (thisJson.is_null()) 1324*01784826SJohnathan Mantey { 1325*01784826SJohnathan Mantey deleteIPv4(ifaceId, NICIPentry->id, asyncResp); 1326*01784826SJohnathan Mantey } 1327*01784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 1328*01784826SJohnathan Mantey { 1329*01784826SJohnathan Mantey NICIPentry = 1330*01784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 1331*01784826SJohnathan Mantey } 1332*01784826SJohnathan Mantey entryIdx++; 1333*01784826SJohnathan Mantey } 1334*01784826SJohnathan Mantey } 13354a0cb85cSEd Tanous } 13364a0cb85cSEd Tanous 1337f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1338f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1339f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1340f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1341f85837bfSRAJESWARAN THILLAIGOVINDAN { 1342f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1343286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1344f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1345f85837bfSRAJESWARAN THILLAIGOVINDAN { 1346f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1347f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1348f85837bfSRAJESWARAN THILLAIGOVINDAN } 1349f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1350f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1351f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1352f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1353f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1354f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1355f85837bfSRAJESWARAN THILLAIGOVINDAN } 1356f85837bfSRAJESWARAN THILLAIGOVINDAN 1357e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1358e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 1359*01784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1360e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1361e48c0fc5SRavi Teja { 1362*01784826SJohnathan Mantey if (!input.is_array() || input.empty()) 1363e48c0fc5SRavi Teja { 1364e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1365e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1366e48c0fc5SRavi Teja return; 1367e48c0fc5SRavi Teja } 1368*01784826SJohnathan Mantey int entryIdx = 1; 1369*01784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator NICIPentry = 1370*01784826SJohnathan Mantey GetNextStaticIPEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1371e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1372e48c0fc5SRavi Teja { 1373e48c0fc5SRavi Teja std::string pathString = 1374e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1375e48c0fc5SRavi Teja 1376*01784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1377e48c0fc5SRavi Teja { 1378e48c0fc5SRavi Teja std::optional<std::string> address; 1379e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1380e48c0fc5SRavi Teja 1381e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1382e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1383e48c0fc5SRavi Teja { 1384*01784826SJohnathan Mantey messages::propertyValueFormatError( 1385*01784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1386e48c0fc5SRavi Teja return; 1387e48c0fc5SRavi Teja } 1388e48c0fc5SRavi Teja 1389*01784826SJohnathan Mantey const std::string *addr; 1390*01784826SJohnathan Mantey uint8_t prefix; 1391*01784826SJohnathan Mantey 1392*01784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 1393*01784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 1394*01784826SJohnathan Mantey // current state of the interface. Merge existing state into the 1395*01784826SJohnathan Mantey // current request. 1396e48c0fc5SRavi Teja if (address) 1397e48c0fc5SRavi Teja { 1398*01784826SJohnathan Mantey addr = &(*address); 1399e48c0fc5SRavi Teja } 1400*01784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 1401*01784826SJohnathan Mantey { 1402*01784826SJohnathan Mantey addr = &(NICIPentry->address); 1403*01784826SJohnathan Mantey } 1404*01784826SJohnathan Mantey else 1405*01784826SJohnathan Mantey { 1406*01784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 1407*01784826SJohnathan Mantey pathString + "/Address"); 1408*01784826SJohnathan Mantey return; 1409e48c0fc5SRavi Teja } 1410e48c0fc5SRavi Teja 1411e48c0fc5SRavi Teja if (prefixLength) 1412e48c0fc5SRavi Teja { 1413*01784826SJohnathan Mantey prefix = *prefixLength; 1414*01784826SJohnathan Mantey } 1415*01784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 1416e48c0fc5SRavi Teja { 1417*01784826SJohnathan Mantey prefix = NICIPentry->prefixLength; 1418e48c0fc5SRavi Teja } 1419e48c0fc5SRavi Teja else 1420e48c0fc5SRavi Teja { 1421e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1422e48c0fc5SRavi Teja pathString + "/PrefixLength"); 1423*01784826SJohnathan Mantey return; 1424e48c0fc5SRavi Teja } 1425e48c0fc5SRavi Teja 1426*01784826SJohnathan Mantey if (NICIPentry != ipv6Data.end()) 1427e48c0fc5SRavi Teja { 1428*01784826SJohnathan Mantey deleteAndCreateIPv6(ifaceId, NICIPentry->id, prefix, *addr, 1429e48c0fc5SRavi Teja asyncResp); 1430*01784826SJohnathan Mantey NICIPentry = 1431*01784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 1432*01784826SJohnathan Mantey } 1433*01784826SJohnathan Mantey else 1434*01784826SJohnathan Mantey { 1435*01784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1436e48c0fc5SRavi Teja } 1437e48c0fc5SRavi Teja entryIdx++; 1438e48c0fc5SRavi Teja } 1439*01784826SJohnathan Mantey else 1440*01784826SJohnathan Mantey { 1441*01784826SJohnathan Mantey if (NICIPentry == ipv6Data.end()) 1442*01784826SJohnathan Mantey { 1443*01784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 1444*01784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 1445*01784826SJohnathan Mantey // in error, so bail out. 1446*01784826SJohnathan Mantey if (thisJson.is_null()) 1447*01784826SJohnathan Mantey { 1448*01784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 1449*01784826SJohnathan Mantey return; 1450*01784826SJohnathan Mantey } 1451*01784826SJohnathan Mantey else 1452*01784826SJohnathan Mantey { 1453*01784826SJohnathan Mantey messages::propertyValueFormatError( 1454*01784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1455*01784826SJohnathan Mantey return; 1456*01784826SJohnathan Mantey } 1457*01784826SJohnathan Mantey } 1458*01784826SJohnathan Mantey 1459*01784826SJohnathan Mantey if (thisJson.is_null()) 1460*01784826SJohnathan Mantey { 1461*01784826SJohnathan Mantey deleteIPv6(ifaceId, NICIPentry->id, asyncResp); 1462*01784826SJohnathan Mantey } 1463*01784826SJohnathan Mantey if (NICIPentry != ipv6Data.cend()) 1464*01784826SJohnathan Mantey { 1465*01784826SJohnathan Mantey NICIPentry = 1466*01784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 1467*01784826SJohnathan Mantey } 1468*01784826SJohnathan Mantey entryIdx++; 1469*01784826SJohnathan Mantey } 1470*01784826SJohnathan Mantey } 1471e48c0fc5SRavi Teja } 1472e48c0fc5SRavi Teja 14730f74e643SEd Tanous void parseInterfaceData( 14740f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 14750f74e643SEd Tanous const EthernetInterfaceData ðData, 1476e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1477*01784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 14784a0cb85cSEd Tanous { 14794a0cb85cSEd Tanous json_response["Id"] = iface_id; 14804a0cb85cSEd Tanous json_response["@odata.id"] = 14814a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1482029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1483029573d4SEd Tanous if (ethData.speed == 0) 1484029573d4SEd Tanous { 1485029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1486029573d4SEd Tanous json_response["Status"] = { 1487029573d4SEd Tanous {"Health", "OK"}, 1488029573d4SEd Tanous {"State", "Disabled"}, 1489029573d4SEd Tanous }; 1490029573d4SEd Tanous } 1491029573d4SEd Tanous else 1492029573d4SEd Tanous { 1493029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1494029573d4SEd Tanous json_response["Status"] = { 1495029573d4SEd Tanous {"Health", "OK"}, 1496029573d4SEd Tanous {"State", "Enabled"}, 1497029573d4SEd Tanous }; 1498029573d4SEd Tanous } 14994a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 15004a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1501fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 15022a133282Smanojkiraneda 15034a0cb85cSEd Tanous if (!ethData.hostname.empty()) 15044a0cb85cSEd Tanous { 15054a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 1506d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1507d24bfc7aSJennifer Lee { 1508d24bfc7aSJennifer Lee json_response["FQDN"] = 1509d24bfc7aSJennifer Lee ethData.hostname + "." + ethData.domainnames[0]; 1510d24bfc7aSJennifer Lee } 15114a0cb85cSEd Tanous } 15124a0cb85cSEd Tanous 1513fda13ad2SSunitha Harish json_response["VLANs"] = { 1514fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1515fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1516fda13ad2SSunitha Harish 1517029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 151895f8646eSManojkiran Eda 151995f8646eSManojkiran Eda if (!ethData.DHCPEnabled) 152095f8646eSManojkiran Eda { 1521f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 152295f8646eSManojkiran Eda } 152395f8646eSManojkiran Eda else 152495f8646eSManojkiran Eda { 1525f1a3caeeSManojkiran Eda json_response["StaticNameServers"] = nlohmann::json::array(); 152695f8646eSManojkiran Eda } 15274a0cb85cSEd Tanous 15284a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 1529*01784826SJohnathan Mantey nlohmann::json &ipv4_static_array = 1530*01784826SJohnathan Mantey json_response["IPv4StaticAddresses"]; 15314a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 1532*01784826SJohnathan Mantey ipv4_static_array = nlohmann::json::array(); 15334a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 15344a0cb85cSEd Tanous { 1535fa5053a6SGunnar Mills 1536fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1537fa5053a6SGunnar Mills if (gatewayStr.empty()) 1538fa5053a6SGunnar Mills { 1539fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1540fa5053a6SGunnar Mills } 1541fa5053a6SGunnar Mills 15424a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 15434a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1544029573d4SEd Tanous {"Address", ipv4_config.address}, 1545fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 1546*01784826SJohnathan Mantey if (ipv4_config.origin == "Static") 1547d1d50814SRavi Teja { 1548d1d50814SRavi Teja ipv4_static_array.push_back( 1549*01784826SJohnathan Mantey {{"AddressOrigin", ipv4_config.origin}, 1550*01784826SJohnathan Mantey {"SubnetMask", ipv4_config.netmask}, 1551*01784826SJohnathan Mantey {"Address", ipv4_config.address}, 1552d1d50814SRavi Teja {"Gateway", gatewayStr}}); 1553d1d50814SRavi Teja } 1554*01784826SJohnathan Mantey } 1555d1d50814SRavi Teja 15569a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1557e48c0fc5SRavi Teja 1558e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 1559*01784826SJohnathan Mantey nlohmann::json &ipv6_static_array = 1560*01784826SJohnathan Mantey json_response["IPv6StaticAddresses"]; 1561e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 1562*01784826SJohnathan Mantey ipv6_static_array = nlohmann::json::array(); 1563e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1564e48c0fc5SRavi Teja { 1565e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1566e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1567e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 1568*01784826SJohnathan Mantey if (ipv6_config.origin == "Static") 1569e48c0fc5SRavi Teja { 1570e48c0fc5SRavi Teja ipv6_static_array.push_back( 1571*01784826SJohnathan Mantey {{"Address", ipv6_config.address}, 1572*01784826SJohnathan Mantey {"PrefixLength", ipv6_config.prefixLength}, 1573*01784826SJohnathan Mantey {"AddressOrigin", ipv6_config.origin}}); 1574*01784826SJohnathan Mantey } 1575e48c0fc5SRavi Teja } 1576588c3f0dSKowalski, Kamil } 1577588c3f0dSKowalski, Kamil 15789391bb9cSRapkiewicz, Pawel /** 15799391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 15809391bb9cSRapkiewicz, Pawel */ 158155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 15821abe55efSEd Tanous const std::vector<std::string> ¶ms) override 15831abe55efSEd Tanous { 15844a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 15851abe55efSEd Tanous if (params.size() != 1) 15861abe55efSEd Tanous { 1587f12894f8SJason M. Bills messages::internalError(asyncResp->res); 15889391bb9cSRapkiewicz, Pawel return; 15899391bb9cSRapkiewicz, Pawel } 15909391bb9cSRapkiewicz, Pawel 15914a0cb85cSEd Tanous getEthernetIfaceData( 15924a0cb85cSEd Tanous params[0], 15934a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 15944a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1595e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1596*01784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 15974a0cb85cSEd Tanous if (!success) 15981abe55efSEd Tanous { 15991abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16001abe55efSEd Tanous // object, and other errors 1601f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1602f12894f8SJason M. Bills "EthernetInterface", iface_id); 16034a0cb85cSEd Tanous return; 16049391bb9cSRapkiewicz, Pawel } 16054c9afe43SEd Tanous 16064c9afe43SEd Tanous // because this has no dependence on the interface at this 16074c9afe43SEd Tanous // point, it needs to be done after we know the interface 16084c9afe43SEd Tanous // exists, not before. 16094c9afe43SEd Tanous getDHCPConfigData(asyncResp); 16104c9afe43SEd Tanous 16110f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1612fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 16130f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 1614*01784826SJohnathan Mantey "/redfish/v1/" 1615*01784826SJohnathan Mantey "$metadata#EthernetInterface.EthernetInterface"; 16160f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 16170f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 16180f74e643SEd Tanous "Management Network Interface"; 16190f74e643SEd Tanous 16200f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1621*01784826SJohnathan Mantey ipv4Data, ipv6Data); 16229391bb9cSRapkiewicz, Pawel }); 16239391bb9cSRapkiewicz, Pawel } 16249391bb9cSRapkiewicz, Pawel 162555c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 16261abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16271abe55efSEd Tanous { 16284a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16291abe55efSEd Tanous if (params.size() != 1) 16301abe55efSEd Tanous { 1631f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1632588c3f0dSKowalski, Kamil return; 1633588c3f0dSKowalski, Kamil } 1634588c3f0dSKowalski, Kamil 16354a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1636588c3f0dSKowalski, Kamil 1637bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1638d577665bSRatan Gupta std::optional<std::string> macAddress; 16399a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1640d1d50814SRavi Teja std::optional<nlohmann::json> ipv4StaticAddresses; 1641e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1642f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 1643da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 16440627a2c7SEd Tanous 1645*01784826SJohnathan Mantey if (!json_util::readJson(req, res, "HostName", hostname, 1646*01784826SJohnathan Mantey "IPv4StaticAddresses", ipv4StaticAddresses, 1647*01784826SJohnathan Mantey "MACAddress", macAddress, "StaticNameServers", 1648*01784826SJohnathan Mantey staticNameServers, "IPv6DefaultGateway", 1649*01784826SJohnathan Mantey ipv6DefaultGateway, "IPv6StaticAddresses", 1650*01784826SJohnathan Mantey ipv6StaticAddresses, "DHCPv4", dhcpv4)) 16511abe55efSEd Tanous { 1652588c3f0dSKowalski, Kamil return; 1653588c3f0dSKowalski, Kamil } 1654f15aad37SRatan Gupta 1655da131a9aSJennifer Lee if (dhcpv4) 1656da131a9aSJennifer Lee { 1657da131a9aSJennifer Lee handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp); 1658da131a9aSJennifer Lee } 1659da131a9aSJennifer Lee 1660*01784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 1661*01784826SJohnathan Mantey // JSON preparation 16624a0cb85cSEd Tanous getEthernetIfaceData( 16634a0cb85cSEd Tanous iface_id, 1664fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1665fda13ad2SSunitha Harish macAddress = std::move(macAddress), 1666d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 16679a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1668e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 1669*01784826SJohnathan Mantey staticNameServers = std::move(staticNameServers)]( 16704a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1671e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1672*01784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 16731abe55efSEd Tanous if (!success) 16741abe55efSEd Tanous { 1675588c3f0dSKowalski, Kamil // ... otherwise return error 16761abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16771abe55efSEd Tanous // object, and other errors 1678fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1679fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1680588c3f0dSKowalski, Kamil return; 1681588c3f0dSKowalski, Kamil } 1682588c3f0dSKowalski, Kamil 16830627a2c7SEd Tanous if (hostname) 16841abe55efSEd Tanous { 16850627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 16861abe55efSEd Tanous } 16870627a2c7SEd Tanous 1688d577665bSRatan Gupta if (macAddress) 1689d577665bSRatan Gupta { 1690d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1691d577665bSRatan Gupta } 1692d577665bSRatan Gupta 1693d1d50814SRavi Teja if (ipv4StaticAddresses) 1694d1d50814SRavi Teja { 1695537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 1696*01784826SJohnathan Mantey // above is returning a const value, not a non-const 1697*01784826SJohnathan Mantey // value. This doesn't really work for us, as we need to 1698*01784826SJohnathan Mantey // be able to efficiently move out the intermedia 1699*01784826SJohnathan Mantey // nlohmann::json objects. This makes a copy of the 1700*01784826SJohnathan Mantey // structure, and operates on that, but could be done 1701*01784826SJohnathan Mantey // more efficiently 1702d1d50814SRavi Teja nlohmann::json ipv4Static = std::move(*ipv4StaticAddresses); 1703*01784826SJohnathan Mantey handleIPv4StaticPatch(iface_id, ipv4Static, ipv4Data, 1704d1d50814SRavi Teja asyncResp); 17051abe55efSEd Tanous } 17060627a2c7SEd Tanous 1707f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1708f85837bfSRAJESWARAN THILLAIGOVINDAN { 1709f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1710f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1711f85837bfSRAJESWARAN THILLAIGOVINDAN } 17129a6fc6feSRavi Teja 17139a6fc6feSRavi Teja if (ipv6DefaultGateway) 17149a6fc6feSRavi Teja { 17159a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 17169a6fc6feSRavi Teja "IPv6DefaultGateway"); 17179a6fc6feSRavi Teja } 1718e48c0fc5SRavi Teja 1719e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1720e48c0fc5SRavi Teja { 1721e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1722e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 1723*01784826SJohnathan Mantey ipv6Data, asyncResp); 1724e48c0fc5SRavi Teja } 1725588c3f0dSKowalski, Kamil }); 1726588c3f0dSKowalski, Kamil } 17279391bb9cSRapkiewicz, Pawel }; 17289391bb9cSRapkiewicz, Pawel 1729e439f0f8SKowalski, Kamil /** 17304a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 17314a0cb85cSEd Tanous * Schema 1732e439f0f8SKowalski, Kamil */ 17331abe55efSEd Tanous class VlanNetworkInterface : public Node 17341abe55efSEd Tanous { 1735e439f0f8SKowalski, Kamil public: 1736e439f0f8SKowalski, Kamil /* 1737e439f0f8SKowalski, Kamil * Default Constructor 1738e439f0f8SKowalski, Kamil */ 1739e439f0f8SKowalski, Kamil template <typename CrowApp> 17401abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 17414a0cb85cSEd Tanous Node(app, 17420f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 17431abe55efSEd Tanous std::string(), std::string()) 17441abe55efSEd Tanous { 1745e439f0f8SKowalski, Kamil entityPrivileges = { 1746e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1747e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1748e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1749e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1750e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1751e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1752e439f0f8SKowalski, Kamil } 1753e439f0f8SKowalski, Kamil 1754e439f0f8SKowalski, Kamil private: 17550f74e643SEd Tanous void parseInterfaceData( 17560f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 17570f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1758e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1759*01784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 17601abe55efSEd Tanous { 1761e439f0f8SKowalski, Kamil // Fill out obvious data... 17624a0cb85cSEd Tanous json_response["Id"] = iface_id; 17634a0cb85cSEd Tanous json_response["@odata.id"] = 17644a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 17654a0cb85cSEd Tanous "/VLANs/" + iface_id; 1766e439f0f8SKowalski, Kamil 17674a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1768fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 17694a0cb85cSEd Tanous { 1770fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 17714a0cb85cSEd Tanous } 1772e439f0f8SKowalski, Kamil } 1773e439f0f8SKowalski, Kamil 1774fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 17751abe55efSEd Tanous { 17761abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 17771abe55efSEd Tanous { 1778927a505aSKowalski, Kamil return false; 17791abe55efSEd Tanous } 17801abe55efSEd Tanous else 17811abe55efSEd Tanous { 1782927a505aSKowalski, Kamil return true; 1783927a505aSKowalski, Kamil } 1784927a505aSKowalski, Kamil } 1785927a505aSKowalski, Kamil 1786e439f0f8SKowalski, Kamil /** 1787e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1788e439f0f8SKowalski, Kamil */ 178955c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 17901abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17911abe55efSEd Tanous { 17924a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17934a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1794e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1795e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1796e439f0f8SKowalski, Kamil // impossible. 17971abe55efSEd Tanous if (params.size() != 2) 17981abe55efSEd Tanous { 1799f12894f8SJason M. Bills messages::internalError(res); 1800e439f0f8SKowalski, Kamil res.end(); 1801e439f0f8SKowalski, Kamil return; 1802e439f0f8SKowalski, Kamil } 1803e439f0f8SKowalski, Kamil 18044a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 18054a0cb85cSEd Tanous const std::string &iface_id = params[1]; 18060f74e643SEd Tanous res.jsonValue["@odata.type"] = 18070f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 18080f74e643SEd Tanous res.jsonValue["@odata.context"] = 1809*01784826SJohnathan Mantey "/redfish/v1/" 1810*01784826SJohnathan Mantey "$metadata#VLanNetworkInterface.VLanNetworkInterface"; 18110f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1812e439f0f8SKowalski, Kamil 1813fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 18141abe55efSEd Tanous { 1815a434f2bdSEd Tanous return; 1816a434f2bdSEd Tanous } 1817a434f2bdSEd Tanous 1818*01784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 1819*01784826SJohnathan Mantey // JSON preparation 18204a0cb85cSEd Tanous getEthernetIfaceData( 1821fda13ad2SSunitha Harish params[1], 1822fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1823fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 18244a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1825e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1826*01784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 1827fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 18281abe55efSEd Tanous { 18290f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 18300f74e643SEd Tanous parent_iface_id, iface_id, ethData, 1831*01784826SJohnathan Mantey ipv4Data, ipv6Data); 18321abe55efSEd Tanous } 18331abe55efSEd Tanous else 18341abe55efSEd Tanous { 1835e439f0f8SKowalski, Kamil // ... otherwise return error 18361abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18371abe55efSEd Tanous // object, and other errors 1838f12894f8SJason M. Bills messages::resourceNotFound( 1839f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1840e439f0f8SKowalski, Kamil } 1841e439f0f8SKowalski, Kamil }); 1842e439f0f8SKowalski, Kamil } 1843e439f0f8SKowalski, Kamil 184455c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 18451abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18461abe55efSEd Tanous { 18474a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18481abe55efSEd Tanous if (params.size() != 2) 18491abe55efSEd Tanous { 1850f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1851e439f0f8SKowalski, Kamil return; 1852e439f0f8SKowalski, Kamil } 1853e439f0f8SKowalski, Kamil 1854d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 185555c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1856927a505aSKowalski, Kamil 1857fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 18581abe55efSEd Tanous { 1859fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1860fda13ad2SSunitha Harish ifaceId); 1861927a505aSKowalski, Kamil return; 1862927a505aSKowalski, Kamil } 1863927a505aSKowalski, Kamil 18640627a2c7SEd Tanous bool vlanEnable = false; 18650627a2c7SEd Tanous uint64_t vlanId = 0; 18660627a2c7SEd Tanous 18670627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 18680627a2c7SEd Tanous vlanId)) 18691abe55efSEd Tanous { 1870927a505aSKowalski, Kamil return; 1871927a505aSKowalski, Kamil } 1872927a505aSKowalski, Kamil 1873*01784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 1874*01784826SJohnathan Mantey // JSON preparation 1875e48c0fc5SRavi Teja getEthernetIfaceData( 1876e48c0fc5SRavi Teja params[1], 1877e48c0fc5SRavi Teja [this, asyncResp, parentIfaceId{std::string(params[0])}, 1878e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 1879e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 1880e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1881*01784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 188208244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 188308244d02SSunitha Harish { 188408244d02SSunitha Harish auto callback = 188508244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 188608244d02SSunitha Harish if (ec) 188708244d02SSunitha Harish { 188808244d02SSunitha Harish messages::internalError(asyncResp->res); 188908244d02SSunitha Harish } 189008244d02SSunitha Harish }; 189108244d02SSunitha Harish 189208244d02SSunitha Harish if (vlanEnable == true) 189308244d02SSunitha Harish { 189408244d02SSunitha Harish crow::connections::systemBus->async_method_call( 189508244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 189608244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 189708244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 189808244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 189908244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 190008244d02SSunitha Harish } 190108244d02SSunitha Harish else 190208244d02SSunitha Harish { 1903e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 1904e48c0fc5SRavi Teja "vlan interface"; 190508244d02SSunitha Harish crow::connections::systemBus->async_method_call( 190608244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 1907e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 1908e48c0fc5SRavi Teja ifaceId, 190908244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 191008244d02SSunitha Harish } 191108244d02SSunitha Harish } 191208244d02SSunitha Harish else 19131abe55efSEd Tanous { 19141abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 19151abe55efSEd Tanous // object, and other errors 1916e48c0fc5SRavi Teja messages::resourceNotFound( 1917e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 1918927a505aSKowalski, Kamil return; 1919927a505aSKowalski, Kamil } 1920927a505aSKowalski, Kamil }); 1921e439f0f8SKowalski, Kamil } 1922e439f0f8SKowalski, Kamil 192355c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 19241abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19251abe55efSEd Tanous { 19264a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19271abe55efSEd Tanous if (params.size() != 2) 19281abe55efSEd Tanous { 1929f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1930e439f0f8SKowalski, Kamil return; 1931e439f0f8SKowalski, Kamil } 1932e439f0f8SKowalski, Kamil 1933d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 193455c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1935927a505aSKowalski, Kamil 1936fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19371abe55efSEd Tanous { 1938fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1939fda13ad2SSunitha Harish ifaceId); 1940927a505aSKowalski, Kamil return; 1941927a505aSKowalski, Kamil } 1942927a505aSKowalski, Kamil 1943*01784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 1944*01784826SJohnathan Mantey // JSON preparation 1945f12894f8SJason M. Bills getEthernetIfaceData( 1946fda13ad2SSunitha Harish params[1], 1947fda13ad2SSunitha Harish [this, asyncResp, parentIfaceId{std::string(params[0])}, 1948fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 1949f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 1950e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1951*01784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 1952fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 19531abe55efSEd Tanous { 1954f12894f8SJason M. Bills auto callback = 1955f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 19561abe55efSEd Tanous if (ec) 19571abe55efSEd Tanous { 1958f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1959927a505aSKowalski, Kamil } 19604a0cb85cSEd Tanous }; 19614a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 19624a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 19634a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 19644a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 19651abe55efSEd Tanous } 19661abe55efSEd Tanous else 19671abe55efSEd Tanous { 1968927a505aSKowalski, Kamil // ... otherwise return error 1969f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 1970f12894f8SJason M. Bills // object, and other errors 1971f12894f8SJason M. Bills messages::resourceNotFound( 1972f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 1973927a505aSKowalski, Kamil } 1974927a505aSKowalski, Kamil }); 1975e439f0f8SKowalski, Kamil } 1976e439f0f8SKowalski, Kamil }; 1977e439f0f8SKowalski, Kamil 1978e439f0f8SKowalski, Kamil /** 1979e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 1980e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 1981e439f0f8SKowalski, Kamil */ 19821abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 19831abe55efSEd Tanous { 1984e439f0f8SKowalski, Kamil public: 1985e439f0f8SKowalski, Kamil template <typename CrowApp> 19861abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 19874a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 19884a0cb85cSEd Tanous std::string()) 19891abe55efSEd Tanous { 1990e439f0f8SKowalski, Kamil entityPrivileges = { 1991e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1992e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1993e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1994e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1995e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1996e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1997e439f0f8SKowalski, Kamil } 1998e439f0f8SKowalski, Kamil 1999e439f0f8SKowalski, Kamil private: 2000e439f0f8SKowalski, Kamil /** 2001e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2002e439f0f8SKowalski, Kamil */ 200355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 20041abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20051abe55efSEd Tanous { 20064a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20071abe55efSEd Tanous if (params.size() != 1) 20081abe55efSEd Tanous { 2009e439f0f8SKowalski, Kamil // This means there is a problem with the router 2010f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2011e439f0f8SKowalski, Kamil return; 2012e439f0f8SKowalski, Kamil } 2013e439f0f8SKowalski, Kamil 20144a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2015e439f0f8SKowalski, Kamil 20164a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 20171abe55efSEd Tanous // preparation 2018f12894f8SJason M. Bills getEthernetIfaceList( 201943b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 20201abe55efSEd Tanous const bool &success, 20214c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 20224a0cb85cSEd Tanous if (!success) 20231abe55efSEd Tanous { 2024f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20254a0cb85cSEd Tanous return; 20261abe55efSEd Tanous } 20274c9afe43SEd Tanous 20284c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 20294c9afe43SEd Tanous { 20304c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 20314c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 20324c9afe43SEd Tanous rootInterfaceName); 20334c9afe43SEd Tanous return; 20344c9afe43SEd Tanous } 20354c9afe43SEd Tanous 20360f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 20370f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 20380f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 20390f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 20400f74e643SEd Tanous "/redfish/v1/$metadata" 20410f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 20420f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 20430f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 20440f74e643SEd Tanous "VLAN Network Interface Collection"; 20454a0cb85cSEd Tanous 20464a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 20474a0cb85cSEd Tanous 20484a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 20491abe55efSEd Tanous { 20504a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 20514a0cb85cSEd Tanous { 20524a0cb85cSEd Tanous iface_array.push_back( 20534a0cb85cSEd Tanous {{"@odata.id", 20544a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 20554a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2056e439f0f8SKowalski, Kamil } 2057e439f0f8SKowalski, Kamil } 2058e439f0f8SKowalski, Kamil 20594a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 20604a0cb85cSEd Tanous iface_array.size(); 20614a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 20624a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 20634a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 20644a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2065e439f0f8SKowalski, Kamil }); 2066e439f0f8SKowalski, Kamil } 2067e439f0f8SKowalski, Kamil 206855c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 20691abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20701abe55efSEd Tanous { 20714a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20721abe55efSEd Tanous if (params.size() != 1) 20731abe55efSEd Tanous { 2074f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2075e439f0f8SKowalski, Kamil return; 2076e439f0f8SKowalski, Kamil } 2077fda13ad2SSunitha Harish bool vlanEnable = false; 20780627a2c7SEd Tanous uint32_t vlanId = 0; 2079fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2080fda13ad2SSunitha Harish vlanEnable)) 20811abe55efSEd Tanous { 20824a0cb85cSEd Tanous return; 2083e439f0f8SKowalski, Kamil } 2084fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2085fda13ad2SSunitha Harish if (!vlanId) 2086fda13ad2SSunitha Harish { 2087fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2088fda13ad2SSunitha Harish } 2089fda13ad2SSunitha Harish if (!vlanEnable) 2090fda13ad2SSunitha Harish { 2091fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2092fda13ad2SSunitha Harish } 2093fda13ad2SSunitha Harish if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) 2094fda13ad2SSunitha Harish { 2095fda13ad2SSunitha Harish return; 2096fda13ad2SSunitha Harish } 2097fda13ad2SSunitha Harish 20984a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 20994a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 21001abe55efSEd Tanous if (ec) 21011abe55efSEd Tanous { 21024a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 21034a0cb85cSEd Tanous // phosphor-network responses 2104f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21054a0cb85cSEd Tanous return; 21061abe55efSEd Tanous } 2107f12894f8SJason M. Bills messages::created(asyncResp->res); 2108e439f0f8SKowalski, Kamil }; 21094a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21104a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21114a0cb85cSEd Tanous "/xyz/openbmc_project/network", 21124a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 21130627a2c7SEd Tanous rootInterfaceName, vlanId); 21144a0cb85cSEd Tanous } 21154a0cb85cSEd Tanous }; 21169391bb9cSRapkiewicz, Pawel } // namespace redfish 2117