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 29901784826SJohnathan Mantey inline void 30001784826SJohnathan Mantey extractIPV6Data(const std::string ðiface_id, 30101784826SJohnathan Mantey const GetManagedObjects &dbus_data, 30201784826SJohnathan 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> 323*271584abSEd Tanous it = ipv6_config.insert(IPv6AddressData{}); 324e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 325*271584abSEd Tanous ipv6_address.id = 326*271584abSEd Tanous objpath.first.str.substr(ipv6PathStart.size()); 327e48c0fc5SRavi Teja for (auto &property : interface.second) 328e48c0fc5SRavi Teja { 329e48c0fc5SRavi Teja if (property.first == "Address") 330e48c0fc5SRavi Teja { 331e48c0fc5SRavi Teja const std::string *address = 332e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 333e48c0fc5SRavi Teja if (address != nullptr) 334e48c0fc5SRavi Teja { 335e48c0fc5SRavi Teja ipv6_address.address = *address; 336e48c0fc5SRavi Teja } 337e48c0fc5SRavi Teja } 338e48c0fc5SRavi Teja else if (property.first == "Origin") 339e48c0fc5SRavi Teja { 340e48c0fc5SRavi Teja const std::string *origin = 341e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 342e48c0fc5SRavi Teja if (origin != nullptr) 343e48c0fc5SRavi Teja { 344e48c0fc5SRavi Teja ipv6_address.origin = 345e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 346e48c0fc5SRavi Teja false); 347e48c0fc5SRavi Teja } 348e48c0fc5SRavi Teja } 349e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 350e48c0fc5SRavi Teja { 351e48c0fc5SRavi Teja const uint8_t *prefix = 352e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 353e48c0fc5SRavi Teja if (prefix != nullptr) 354e48c0fc5SRavi Teja { 355e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 356e48c0fc5SRavi Teja } 357e48c0fc5SRavi Teja } 358e48c0fc5SRavi Teja else 359e48c0fc5SRavi Teja { 360e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 361e48c0fc5SRavi Teja << "Got extra property: " << property.first 362e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 363e48c0fc5SRavi Teja } 364e48c0fc5SRavi Teja } 365e48c0fc5SRavi Teja } 366e48c0fc5SRavi Teja } 367e48c0fc5SRavi Teja } 368e48c0fc5SRavi Teja } 369e48c0fc5SRavi Teja } 370e48c0fc5SRavi Teja 3714a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 37201784826SJohnathan Mantey inline void 37301784826SJohnathan Mantey extractIPData(const std::string ðiface_id, 37401784826SJohnathan Mantey const GetManagedObjects &dbus_data, 37501784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData> &ipv4_config) 3764a0cb85cSEd Tanous { 3774a0cb85cSEd Tanous const std::string ipv4PathStart = 3784a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 3794a0cb85cSEd Tanous 3804a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 3814a0cb85cSEd Tanous // single ethernet interface, loop over all of them 3824a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 3834a0cb85cSEd Tanous { 3844a0cb85cSEd Tanous // Check if proper pattern for object path appears 3854a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 3864a0cb85cSEd Tanous { 3874a0cb85cSEd Tanous for (auto &interface : objpath.second) 3884a0cb85cSEd Tanous { 3894a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 3904a0cb85cSEd Tanous { 3914a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 3924a0cb85cSEd Tanous // appropriate 3934a0cb85cSEd Tanous std::pair< 3944a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 3954a0cb85cSEd Tanous bool> 396*271584abSEd Tanous it = ipv4_config.insert(IPv4AddressData{}); 3974a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 398*271584abSEd Tanous ipv4_address.id = 399*271584abSEd Tanous objpath.first.str.substr(ipv4PathStart.size()); 4004a0cb85cSEd Tanous for (auto &property : interface.second) 4014a0cb85cSEd Tanous { 4024a0cb85cSEd Tanous if (property.first == "Address") 4034a0cb85cSEd Tanous { 4044a0cb85cSEd Tanous const std::string *address = 405abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4064a0cb85cSEd Tanous if (address != nullptr) 4074a0cb85cSEd Tanous { 4084a0cb85cSEd Tanous ipv4_address.address = *address; 4094a0cb85cSEd Tanous } 4104a0cb85cSEd Tanous } 4114a0cb85cSEd Tanous else if (property.first == "Gateway") 4124a0cb85cSEd Tanous { 4134a0cb85cSEd Tanous const std::string *gateway = 414abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4154a0cb85cSEd Tanous if (gateway != nullptr) 4164a0cb85cSEd Tanous { 4174a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 4184a0cb85cSEd Tanous } 4194a0cb85cSEd Tanous } 4204a0cb85cSEd Tanous else if (property.first == "Origin") 4214a0cb85cSEd Tanous { 4224a0cb85cSEd Tanous const std::string *origin = 423abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4244a0cb85cSEd Tanous if (origin != nullptr) 4254a0cb85cSEd Tanous { 4264a0cb85cSEd Tanous ipv4_address.origin = 4274a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 4284a0cb85cSEd Tanous true); 4294a0cb85cSEd Tanous } 4304a0cb85cSEd Tanous } 4314a0cb85cSEd Tanous else if (property.first == "PrefixLength") 4324a0cb85cSEd Tanous { 4334a0cb85cSEd Tanous const uint8_t *mask = 434abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 4354a0cb85cSEd Tanous if (mask != nullptr) 4364a0cb85cSEd Tanous { 4374a0cb85cSEd Tanous // convert it to the string 4384a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 4394a0cb85cSEd Tanous } 4404a0cb85cSEd Tanous } 4414a0cb85cSEd Tanous else 4424a0cb85cSEd Tanous { 4434a0cb85cSEd Tanous BMCWEB_LOG_ERROR 4444a0cb85cSEd Tanous << "Got extra property: " << property.first 4454a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 4464a0cb85cSEd Tanous } 4474a0cb85cSEd Tanous } 4484a0cb85cSEd Tanous // Check if given address is local, or global 4494a0cb85cSEd Tanous ipv4_address.linktype = 4504a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 45118659d10SJohnathan Mantey ? LinkType::Local 45218659d10SJohnathan Mantey : LinkType::Global; 4534a0cb85cSEd Tanous } 4544a0cb85cSEd Tanous } 4554a0cb85cSEd Tanous } 4564a0cb85cSEd Tanous } 4574a0cb85cSEd Tanous } 458588c3f0dSKowalski, Kamil 459588c3f0dSKowalski, Kamil /** 460588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 461588c3f0dSKowalski, Kamil * 462588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 463588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 464588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 465588c3f0dSKowalski, Kamil * 466588c3f0dSKowalski, Kamil * @return None. 467588c3f0dSKowalski, Kamil */ 468588c3f0dSKowalski, Kamil template <typename CallbackFunc> 4694a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 4701abe55efSEd Tanous CallbackFunc &&callback) 4711abe55efSEd Tanous { 47255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 473588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 474588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 475588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 476588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 477abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 4784a0cb85cSEd Tanous } 479588c3f0dSKowalski, Kamil 480588c3f0dSKowalski, Kamil /** 481179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 482179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 483179db1d7SKowalski, Kamil * bit count for Subnet Mask. 484179db1d7SKowalski, Kamil * 485179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 486179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 487179db1d7SKowalski, Kamil * 488179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 489179db1d7SKowalski, Kamil */ 4904a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 4911abe55efSEd Tanous uint8_t *bits = nullptr) 4921abe55efSEd Tanous { 493179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 494179db1d7SKowalski, Kamil 495179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 496179db1d7SKowalski, Kamil 4974a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 4981abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 4991abe55efSEd Tanous { 500179db1d7SKowalski, Kamil return false; 501179db1d7SKowalski, Kamil } 502179db1d7SKowalski, Kamil 5031abe55efSEd Tanous if (bits != nullptr) 5041abe55efSEd Tanous { 505179db1d7SKowalski, Kamil *bits = 0; 506179db1d7SKowalski, Kamil } 507179db1d7SKowalski, Kamil 508179db1d7SKowalski, Kamil char *endPtr; 509179db1d7SKowalski, Kamil long previousValue = 255; 510179db1d7SKowalski, Kamil bool firstZeroInByteHit; 5111abe55efSEd Tanous for (const std::string &byte : bytesInMask) 5121abe55efSEd Tanous { 5131abe55efSEd Tanous if (byte.empty()) 5141abe55efSEd Tanous { 5151db9ca37SKowalski, Kamil return false; 5161db9ca37SKowalski, Kamil } 5171db9ca37SKowalski, Kamil 518179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 5191db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 520179db1d7SKowalski, Kamil 5214a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 5224a0cb85cSEd Tanous // is not 100% number 5231abe55efSEd Tanous if (*endPtr != '\0') 5241abe55efSEd Tanous { 525179db1d7SKowalski, Kamil return false; 526179db1d7SKowalski, Kamil } 527179db1d7SKowalski, Kamil 528179db1d7SKowalski, Kamil // Value should be contained in byte 5291abe55efSEd Tanous if (value < 0 || value > 255) 5301abe55efSEd Tanous { 531179db1d7SKowalski, Kamil return false; 532179db1d7SKowalski, Kamil } 533179db1d7SKowalski, Kamil 5341abe55efSEd Tanous if (bits != nullptr) 5351abe55efSEd Tanous { 536179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 5371abe55efSEd Tanous if (previousValue != 255 && value != 0) 5381abe55efSEd Tanous { 539179db1d7SKowalski, Kamil return false; 540179db1d7SKowalski, Kamil } 541179db1d7SKowalski, Kamil 542179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 543179db1d7SKowalski, Kamil firstZeroInByteHit = false; 544179db1d7SKowalski, Kamil 545179db1d7SKowalski, Kamil // Count bits 5461abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 5471abe55efSEd Tanous { 5481abe55efSEd Tanous if (value & (1 << bitIdx)) 5491abe55efSEd Tanous { 5501abe55efSEd Tanous if (firstZeroInByteHit) 5511abe55efSEd Tanous { 552179db1d7SKowalski, Kamil // Continuity not preserved 553179db1d7SKowalski, Kamil return false; 5541abe55efSEd Tanous } 5551abe55efSEd Tanous else 5561abe55efSEd Tanous { 557179db1d7SKowalski, Kamil (*bits)++; 558179db1d7SKowalski, Kamil } 5591abe55efSEd Tanous } 5601abe55efSEd Tanous else 5611abe55efSEd Tanous { 562179db1d7SKowalski, Kamil firstZeroInByteHit = true; 563179db1d7SKowalski, Kamil } 564179db1d7SKowalski, Kamil } 565179db1d7SKowalski, Kamil } 566179db1d7SKowalski, Kamil 567179db1d7SKowalski, Kamil previousValue = value; 568179db1d7SKowalski, Kamil } 569179db1d7SKowalski, Kamil 570179db1d7SKowalski, Kamil return true; 571179db1d7SKowalski, Kamil } 572179db1d7SKowalski, Kamil 573179db1d7SKowalski, Kamil /** 57401784826SJohnathan Mantey * @brief Deletes given IPv4 interface 575179db1d7SKowalski, Kamil * 576179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 577179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 578179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 579179db1d7SKowalski, Kamil * 580179db1d7SKowalski, Kamil * @return None 581179db1d7SKowalski, Kamil */ 5824a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 5834a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 5841abe55efSEd Tanous { 58555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 586286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 5871abe55efSEd Tanous if (ec) 5881abe55efSEd Tanous { 589a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 5901abe55efSEd Tanous } 591179db1d7SKowalski, Kamil }, 592179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 593179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 594179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 595179db1d7SKowalski, Kamil } 596179db1d7SKowalski, Kamil 597179db1d7SKowalski, Kamil /** 59801784826SJohnathan Mantey * @brief Creates a static IPv4 entry 599179db1d7SKowalski, Kamil * 60001784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 60101784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 60201784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 60301784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 604179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 605179db1d7SKowalski, Kamil * 606179db1d7SKowalski, Kamil * @return None 607179db1d7SKowalski, Kamil */ 608b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 60901784826SJohnathan Mantey uint8_t prefixLength, const std::string &gateway, 610b01bf299SEd Tanous const std::string &address, 6114a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6121abe55efSEd Tanous { 61301784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 61401784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 6151abe55efSEd Tanous if (ec) 6161abe55efSEd Tanous { 617a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 618179db1d7SKowalski, Kamil } 61901784826SJohnathan Mantey }, 62001784826SJohnathan Mantey "xyz.openbmc_project.Network", 621179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 622179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 62301784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 624179db1d7SKowalski, Kamil gateway); 625179db1d7SKowalski, Kamil } 626e48c0fc5SRavi Teja 627e48c0fc5SRavi Teja /** 62801784826SJohnathan Mantey * @brief Deletes the IPv4 entry for this interface and creates a replacement 62901784826SJohnathan Mantey * static IPv4 entry 63001784826SJohnathan Mantey * 63101784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 63201784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 63301784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 63401784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 63501784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 63601784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 63701784826SJohnathan Mantey * 63801784826SJohnathan Mantey * @return None 63901784826SJohnathan Mantey */ 64001784826SJohnathan Mantey inline void deleteAndCreateIPv4(const std::string &ifaceId, 64101784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 64201784826SJohnathan Mantey const std::string &gateway, 64301784826SJohnathan Mantey const std::string &address, 64401784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 64501784826SJohnathan Mantey { 64601784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 64701784826SJohnathan Mantey [asyncResp, ifaceId, address, prefixLength, 64801784826SJohnathan Mantey gateway](const boost::system::error_code ec) { 64901784826SJohnathan Mantey if (ec) 65001784826SJohnathan Mantey { 65101784826SJohnathan Mantey messages::internalError(asyncResp->res); 65201784826SJohnathan Mantey } 65301784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 65401784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 65501784826SJohnathan Mantey if (ec) 65601784826SJohnathan Mantey { 65701784826SJohnathan Mantey messages::internalError(asyncResp->res); 65801784826SJohnathan Mantey } 65901784826SJohnathan Mantey }, 66001784826SJohnathan Mantey "xyz.openbmc_project.Network", 66101784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 66201784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 66301784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, 66401784826SJohnathan Mantey prefixLength, gateway); 66501784826SJohnathan Mantey }, 66601784826SJohnathan Mantey "xyz.openbmc_project.Network", 66701784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + id, 66801784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 66901784826SJohnathan Mantey } 67001784826SJohnathan Mantey 67101784826SJohnathan Mantey /** 672e48c0fc5SRavi Teja * @brief Deletes given IPv6 673e48c0fc5SRavi Teja * 674e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 675e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 676e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 677e48c0fc5SRavi Teja * 678e48c0fc5SRavi Teja * @return None 679e48c0fc5SRavi Teja */ 680e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 681e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 682e48c0fc5SRavi Teja { 683e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 684286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 685e48c0fc5SRavi Teja if (ec) 686e48c0fc5SRavi Teja { 687e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 688e48c0fc5SRavi Teja } 689e48c0fc5SRavi Teja }, 690e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 691e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 692e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 693e48c0fc5SRavi Teja } 694e48c0fc5SRavi Teja 695e48c0fc5SRavi Teja /** 69601784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 69701784826SJohnathan Mantey * static IPv6 entry 69801784826SJohnathan Mantey * 69901784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 70001784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 70101784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 70201784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 70301784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 70401784826SJohnathan Mantey * 70501784826SJohnathan Mantey * @return None 70601784826SJohnathan Mantey */ 70701784826SJohnathan Mantey inline void deleteAndCreateIPv6(const std::string &ifaceId, 70801784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 70901784826SJohnathan Mantey const std::string &address, 71001784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 71101784826SJohnathan Mantey { 71201784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 71301784826SJohnathan Mantey [asyncResp, ifaceId, address, 71401784826SJohnathan Mantey prefixLength](const boost::system::error_code ec) { 71501784826SJohnathan Mantey if (ec) 71601784826SJohnathan Mantey { 71701784826SJohnathan Mantey messages::internalError(asyncResp->res); 71801784826SJohnathan Mantey } 71901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 72001784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 72101784826SJohnathan Mantey if (ec) 72201784826SJohnathan Mantey { 72301784826SJohnathan Mantey messages::internalError(asyncResp->res); 72401784826SJohnathan Mantey } 72501784826SJohnathan Mantey }, 72601784826SJohnathan Mantey "xyz.openbmc_project.Network", 72701784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 72801784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 72901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, 73001784826SJohnathan Mantey prefixLength, ""); 73101784826SJohnathan Mantey }, 73201784826SJohnathan Mantey "xyz.openbmc_project.Network", 73301784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + id, 73401784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 73501784826SJohnathan Mantey } 73601784826SJohnathan Mantey 73701784826SJohnathan Mantey /** 738e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 739e48c0fc5SRavi Teja * 740e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 741e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 742e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 743e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 744e48c0fc5SRavi Teja * 745e48c0fc5SRavi Teja * @return None 746e48c0fc5SRavi Teja */ 74701784826SJohnathan Mantey inline void createIPv6(const std::string &ifaceId, uint8_t prefixLength, 74801784826SJohnathan Mantey const std::string &address, 749e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 750e48c0fc5SRavi Teja { 751e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 752e48c0fc5SRavi Teja if (ec) 753e48c0fc5SRavi Teja { 754e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 755e48c0fc5SRavi Teja } 756e48c0fc5SRavi Teja }; 757e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 758e48c0fc5SRavi Teja // does not have assosiated gateway property 759e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 760e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 761e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 762e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 763e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 764e48c0fc5SRavi Teja ""); 765e48c0fc5SRavi Teja } 766e48c0fc5SRavi Teja 7672a133282Smanojkiraneda using GetAllPropertiesType = 7682a133282Smanojkiraneda boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>; 7692a133282Smanojkiraneda 7702a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) 7712a133282Smanojkiraneda { 7722a133282Smanojkiraneda auto getConfig = [asyncResp](const boost::system::error_code error_code, 7732a133282Smanojkiraneda const GetAllPropertiesType &dbus_data) { 7742a133282Smanojkiraneda if (error_code) 7752a133282Smanojkiraneda { 7762a133282Smanojkiraneda BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code; 7772a133282Smanojkiraneda messages::internalError(asyncResp->res); 7782a133282Smanojkiraneda return; 7792a133282Smanojkiraneda } 780fda13ad2SSunitha Harish nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; 7812a133282Smanojkiraneda for (const auto &property : dbus_data) 7822a133282Smanojkiraneda { 7832a133282Smanojkiraneda auto value = 7842a133282Smanojkiraneda sdbusplus::message::variant_ns::get_if<bool>(&property.second); 7852a133282Smanojkiraneda 7862a133282Smanojkiraneda if (value == nullptr) 7872a133282Smanojkiraneda { 7882a133282Smanojkiraneda continue; 7892a133282Smanojkiraneda } 7902a133282Smanojkiraneda if (property.first == "DNSEnabled") 7912a133282Smanojkiraneda { 7922a133282Smanojkiraneda DHCPConfigTypeJson["UseDNSServers"] = *value; 7932a133282Smanojkiraneda } 7942a133282Smanojkiraneda else if (property.first == "HostNameEnabled") 7952a133282Smanojkiraneda { 7962a133282Smanojkiraneda DHCPConfigTypeJson["UseDomainName"] = *value; 7972a133282Smanojkiraneda } 7982a133282Smanojkiraneda else if (property.first == "NTPEnabled") 7992a133282Smanojkiraneda { 8002a133282Smanojkiraneda DHCPConfigTypeJson["UseNTPServers"] = *value; 8012a133282Smanojkiraneda } 8022a133282Smanojkiraneda } 8032a133282Smanojkiraneda }; 8042a133282Smanojkiraneda crow::connections::systemBus->async_method_call( 8052a133282Smanojkiraneda std::move(getConfig), "xyz.openbmc_project.Network", 8062a133282Smanojkiraneda "/xyz/openbmc_project/network/config/dhcp", 8072a133282Smanojkiraneda "org.freedesktop.DBus.Properties", "GetAll", 8082a133282Smanojkiraneda "xyz.openbmc_project.Network.DHCPConfiguration"); 8092a133282Smanojkiraneda } 810179db1d7SKowalski, Kamil 811179db1d7SKowalski, Kamil /** 812179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 813179db1d7SKowalski, Kamil * Object 814179db1d7SKowalski, Kamil * from EntityManager Network Manager 8154a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 816179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 817179db1d7SKowalski, Kamil * into JSON 818179db1d7SKowalski, Kamil */ 819179db1d7SKowalski, Kamil template <typename CallbackFunc> 8204a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8211abe55efSEd Tanous CallbackFunc &&callback) 8221abe55efSEd Tanous { 82355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8244a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8251abe55efSEd Tanous const boost::system::error_code error_code, 8264a0cb85cSEd Tanous const GetManagedObjects &resp) { 82755c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8284a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 829e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 830179db1d7SKowalski, Kamil 8311abe55efSEd Tanous if (error_code) 8321abe55efSEd Tanous { 83301784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 834179db1d7SKowalski, Kamil return; 835179db1d7SKowalski, Kamil } 836179db1d7SKowalski, Kamil 8374c9afe43SEd Tanous bool found = 8384a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 8394c9afe43SEd Tanous if (!found) 8404c9afe43SEd Tanous { 84101784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 8424c9afe43SEd Tanous return; 8434c9afe43SEd Tanous } 8444c9afe43SEd Tanous 84501784826SJohnathan Mantey extractIPData(ethiface_id, resp, ipv4Data); 846179db1d7SKowalski, Kamil // Fix global GW 8471abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 8481abe55efSEd Tanous { 849c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 850c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 851c619141bSRavi Teja (ipv4.origin == "DHCP")) 8521abe55efSEd Tanous { 8534a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 854179db1d7SKowalski, Kamil } 855179db1d7SKowalski, Kamil } 856179db1d7SKowalski, Kamil 85701784826SJohnathan Mantey extractIPV6Data(ethiface_id, resp, ipv6Data); 8584a0cb85cSEd Tanous // Finally make a callback with usefull data 85901784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 860179db1d7SKowalski, Kamil }, 861179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 862179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 863*271584abSEd Tanous } 864179db1d7SKowalski, Kamil 865179db1d7SKowalski, Kamil /** 8669391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8679391bb9cSRapkiewicz, Pawel * Manager 8681abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8691abe55efSEd Tanous * into JSON. 8709391bb9cSRapkiewicz, Pawel */ 8719391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8721abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 8731abe55efSEd Tanous { 87455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8754a0cb85cSEd Tanous [callback{std::move(callback)}]( 8769391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 8774a0cb85cSEd Tanous GetManagedObjects &resp) { 8781abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8791abe55efSEd Tanous // ethernet interfaces 8804c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 8814a0cb85cSEd Tanous iface_list.reserve(resp.size()); 8821abe55efSEd Tanous if (error_code) 8831abe55efSEd Tanous { 8844a0cb85cSEd Tanous callback(false, iface_list); 8859391bb9cSRapkiewicz, Pawel return; 8869391bb9cSRapkiewicz, Pawel } 8879391bb9cSRapkiewicz, Pawel 8889391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8894a0cb85cSEd Tanous for (const auto &objpath : resp) 8901abe55efSEd Tanous { 8919391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 8924a0cb85cSEd Tanous for (const auto &interface : objpath.second) 8931abe55efSEd Tanous { 8941abe55efSEd Tanous // If interface is 8954a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 8964a0cb85cSEd Tanous // what we're looking for. 8979391bb9cSRapkiewicz, Pawel if (interface.first == 8981abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 8991abe55efSEd Tanous { 9004a0cb85cSEd Tanous // Cut out everyting until last "/", ... 9014a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9024a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9034a0cb85cSEd Tanous if (last_pos != std::string::npos) 9041abe55efSEd Tanous { 9059391bb9cSRapkiewicz, Pawel // and put it into output vector. 9064c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9079391bb9cSRapkiewicz, Pawel } 9089391bb9cSRapkiewicz, Pawel } 9099391bb9cSRapkiewicz, Pawel } 9109391bb9cSRapkiewicz, Pawel } 911a434f2bdSEd Tanous // Finally make a callback with useful data 9124a0cb85cSEd Tanous callback(true, iface_list); 9139391bb9cSRapkiewicz, Pawel }, 914aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 915aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 916*271584abSEd Tanous } 9179391bb9cSRapkiewicz, Pawel 9189391bb9cSRapkiewicz, Pawel /** 9199391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9209391bb9cSRapkiewicz, Pawel */ 9211abe55efSEd Tanous class EthernetCollection : public Node 9221abe55efSEd Tanous { 9239391bb9cSRapkiewicz, Pawel public: 9244a0cb85cSEd Tanous template <typename CrowApp> 9251abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9264a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9271abe55efSEd Tanous { 928588c3f0dSKowalski, Kamil entityPrivileges = { 929588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 930e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 931e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 932e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 933e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 934e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9359391bb9cSRapkiewicz, Pawel } 9369391bb9cSRapkiewicz, Pawel 9379391bb9cSRapkiewicz, Pawel private: 9389391bb9cSRapkiewicz, Pawel /** 9399391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 9409391bb9cSRapkiewicz, Pawel */ 94155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 9421abe55efSEd Tanous const std::vector<std::string> ¶ms) override 9431abe55efSEd Tanous { 9440f74e643SEd Tanous res.jsonValue["@odata.type"] = 9450f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9460f74e643SEd Tanous res.jsonValue["@odata.context"] = 9470f74e643SEd Tanous "/redfish/v1/" 9480f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9490f74e643SEd Tanous res.jsonValue["@odata.id"] = 9500f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9510f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 9520f74e643SEd Tanous res.jsonValue["Description"] = 9530f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 9544c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 9554a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 9561abe55efSEd Tanous // preparation 957f12894f8SJason M. Bills getEthernetIfaceList( 9584c9afe43SEd Tanous [asyncResp]( 9594c9afe43SEd Tanous const bool &success, 9604c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 9614a0cb85cSEd Tanous if (!success) 9621abe55efSEd Tanous { 9634c9afe43SEd Tanous messages::internalError(asyncResp->res); 9644a0cb85cSEd Tanous return; 9654a0cb85cSEd Tanous } 9664a0cb85cSEd Tanous 9674c9afe43SEd Tanous nlohmann::json &iface_array = 9684c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 9694a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 970fda13ad2SSunitha Harish std::string tag = "_"; 9714a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 9721abe55efSEd Tanous { 973fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 974fda13ad2SSunitha Harish if (found == std::string::npos) 975fda13ad2SSunitha Harish { 9764a0cb85cSEd Tanous iface_array.push_back( 9774a0cb85cSEd Tanous {{"@odata.id", 9784a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 9794a0cb85cSEd Tanous iface_item}}); 9809391bb9cSRapkiewicz, Pawel } 981fda13ad2SSunitha Harish } 9824a0cb85cSEd Tanous 9834c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 9844c9afe43SEd Tanous iface_array.size(); 9854c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9864a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9879391bb9cSRapkiewicz, Pawel }); 9889391bb9cSRapkiewicz, Pawel } 9899391bb9cSRapkiewicz, Pawel }; 9909391bb9cSRapkiewicz, Pawel 9919391bb9cSRapkiewicz, Pawel /** 9929391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 9939391bb9cSRapkiewicz, Pawel */ 9941abe55efSEd Tanous class EthernetInterface : public Node 9951abe55efSEd Tanous { 9969391bb9cSRapkiewicz, Pawel public: 9979391bb9cSRapkiewicz, Pawel /* 9989391bb9cSRapkiewicz, Pawel * Default Constructor 9999391bb9cSRapkiewicz, Pawel */ 10004a0cb85cSEd Tanous template <typename CrowApp> 10011abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10024a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10031abe55efSEd Tanous std::string()) 10041abe55efSEd Tanous { 1005588c3f0dSKowalski, Kamil entityPrivileges = { 1006588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1007e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1008e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1009e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1010e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1011e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10129391bb9cSRapkiewicz, Pawel } 10139391bb9cSRapkiewicz, Pawel 1014e439f0f8SKowalski, Kamil private: 1015bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10164a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10171abe55efSEd Tanous { 1018bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1019bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1020bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10214a0cb85cSEd Tanous if (ec) 10224a0cb85cSEd Tanous { 1023a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10241abe55efSEd Tanous } 1025bc0bd6e0SEd Tanous }, 1026bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1027bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1028bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1029bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1030abf2add6SEd Tanous std::variant<std::string>(hostname)); 1031588c3f0dSKowalski, Kamil } 1032588c3f0dSKowalski, Kamil 1033d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1034d577665bSRatan Gupta const std::string &macAddress, 1035d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1036d577665bSRatan Gupta { 1037d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1038d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1039d577665bSRatan Gupta if (ec) 1040d577665bSRatan Gupta { 1041d577665bSRatan Gupta messages::internalError(asyncResp->res); 1042d577665bSRatan Gupta return; 1043d577665bSRatan Gupta } 1044d577665bSRatan Gupta }, 1045d577665bSRatan Gupta "xyz.openbmc_project.Network", 1046d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1047d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1048d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1049d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1050d577665bSRatan Gupta } 1051286b9118SJohnathan Mantey 1052da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1053da131a9aSJennifer Lee const std::string &propertyName, const bool &value, 1054da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1055da131a9aSJennifer Lee { 1056da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1057da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1058da131a9aSJennifer Lee if (ec) 1059da131a9aSJennifer Lee { 1060da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1061da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1062da131a9aSJennifer Lee return; 1063da131a9aSJennifer Lee } 1064da131a9aSJennifer Lee }, 1065da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1066da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1067da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1068da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1069da131a9aSJennifer Lee std::variant<bool>{value}); 1070da131a9aSJennifer Lee } 1071da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1072da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1073da131a9aSJennifer Lee { 1074da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1075da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1076da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1077da131a9aSJennifer Lee if (ec) 1078da131a9aSJennifer Lee { 1079da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1080da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1081da131a9aSJennifer Lee return; 1082da131a9aSJennifer Lee } 1083da131a9aSJennifer Lee }, 1084da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1085da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1086da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1087da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1088da131a9aSJennifer Lee std::variant<bool>{value}); 1089da131a9aSJennifer Lee } 1090d577665bSRatan Gupta 1091da131a9aSJennifer Lee void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input, 1092da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1093da131a9aSJennifer Lee { 1094da131a9aSJennifer Lee std::optional<bool> dhcpEnabled; 1095da131a9aSJennifer Lee std::optional<bool> useDNSServers; 1096da131a9aSJennifer Lee std::optional<bool> useDomainName; 1097da131a9aSJennifer Lee std::optional<bool> useNTPServers; 1098da131a9aSJennifer Lee 1099da131a9aSJennifer Lee if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled", 1100da131a9aSJennifer Lee dhcpEnabled, "UseDNSServers", useDNSServers, 1101da131a9aSJennifer Lee "UseDomainName", useDomainName, 1102da131a9aSJennifer Lee "UseNTPServers", useNTPServers)) 1103da131a9aSJennifer Lee { 1104da131a9aSJennifer Lee return; 1105da131a9aSJennifer Lee } 1106da131a9aSJennifer Lee 1107da131a9aSJennifer Lee if (dhcpEnabled) 1108da131a9aSJennifer Lee { 1109da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1110da131a9aSJennifer Lee setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp); 1111da131a9aSJennifer Lee } 1112da131a9aSJennifer Lee 1113da131a9aSJennifer Lee if (useDNSServers) 1114da131a9aSJennifer Lee { 1115da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1116da131a9aSJennifer Lee setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp); 1117da131a9aSJennifer Lee } 1118da131a9aSJennifer Lee 1119da131a9aSJennifer Lee if (useDomainName) 1120da131a9aSJennifer Lee { 1121da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1122da131a9aSJennifer Lee setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp); 1123da131a9aSJennifer Lee } 1124da131a9aSJennifer Lee 1125da131a9aSJennifer Lee if (useNTPServers) 1126da131a9aSJennifer Lee { 1127da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1128da131a9aSJennifer Lee setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp); 1129da131a9aSJennifer Lee } 1130da131a9aSJennifer Lee } 113101784826SJohnathan Mantey 113201784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator 113301784826SJohnathan Mantey GetNextStaticIPEntry( 113401784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator head, 113501784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator end) 113601784826SJohnathan Mantey { 113701784826SJohnathan Mantey for (; head != end; head++) 113801784826SJohnathan Mantey { 113901784826SJohnathan Mantey if (head->origin == "Static") 114001784826SJohnathan Mantey { 114101784826SJohnathan Mantey return head; 114201784826SJohnathan Mantey } 114301784826SJohnathan Mantey } 114401784826SJohnathan Mantey return end; 114501784826SJohnathan Mantey } 114601784826SJohnathan Mantey 114701784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator 114801784826SJohnathan Mantey GetNextStaticIPEntry( 114901784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator head, 115001784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator end) 115101784826SJohnathan Mantey { 115201784826SJohnathan Mantey for (; head != end; head++) 115301784826SJohnathan Mantey { 115401784826SJohnathan Mantey if (head->origin == "Static") 115501784826SJohnathan Mantey { 115601784826SJohnathan Mantey return head; 115701784826SJohnathan Mantey } 115801784826SJohnathan Mantey } 115901784826SJohnathan Mantey return end; 116001784826SJohnathan Mantey } 116101784826SJohnathan Mantey 1162d1d50814SRavi Teja void handleIPv4StaticPatch( 1163f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 116401784826SJohnathan Mantey const boost::container::flat_set<IPv4AddressData> &ipv4Data, 11654a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 11661abe55efSEd Tanous { 116701784826SJohnathan Mantey if ((!input.is_array()) || input.empty()) 1168f476acbfSRatan Gupta { 1169f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1170d1d50814SRavi Teja "IPv4StaticAddresses"); 1171f476acbfSRatan Gupta return; 1172f476acbfSRatan Gupta } 1173f476acbfSRatan Gupta 1174*271584abSEd Tanous unsigned entryIdx = 1; 117501784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 117601784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 117701784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 117801784826SJohnathan Mantey // into the NIC. 117901784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator NICIPentry = 118001784826SJohnathan Mantey GetNextStaticIPEntry(ipv4Data.cbegin(), ipv4Data.cend()); 118101784826SJohnathan Mantey 1182537174c4SEd Tanous for (nlohmann::json &thisJson : input) 11831abe55efSEd Tanous { 11844a0cb85cSEd Tanous std::string pathString = 1185d1d50814SRavi Teja "IPv4StaticAddresses/" + std::to_string(entryIdx); 1186179db1d7SKowalski, Kamil 118701784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1188f476acbfSRatan Gupta { 1189537174c4SEd Tanous std::optional<std::string> address; 1190537174c4SEd Tanous std::optional<std::string> subnetMask; 1191537174c4SEd Tanous std::optional<std::string> gateway; 1192537174c4SEd Tanous 1193537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 11947e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 11957e27d832SJohnathan Mantey "Gateway", gateway)) 1196537174c4SEd Tanous { 119701784826SJohnathan Mantey messages::propertyValueFormatError( 119801784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1199537174c4SEd Tanous return; 1200179db1d7SKowalski, Kamil } 1201179db1d7SKowalski, Kamil 120201784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 120301784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 120401784826SJohnathan Mantey // current state of the interface. Merge existing state into the 120501784826SJohnathan Mantey // current request. 1206*271584abSEd Tanous const std::string *addr = nullptr; 1207*271584abSEd Tanous const std::string *gw = nullptr; 120801784826SJohnathan Mantey uint8_t prefixLength = 0; 120901784826SJohnathan Mantey bool errorInEntry = false; 1210537174c4SEd Tanous if (address) 12111abe55efSEd Tanous { 121201784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*address)) 12131abe55efSEd Tanous { 121401784826SJohnathan Mantey addr = &(*address); 12154a0cb85cSEd Tanous } 121601784826SJohnathan Mantey else 121701784826SJohnathan Mantey { 121801784826SJohnathan Mantey messages::propertyValueFormatError( 121901784826SJohnathan Mantey asyncResp->res, *address, pathString + "/Address"); 122001784826SJohnathan Mantey errorInEntry = true; 122101784826SJohnathan Mantey } 122201784826SJohnathan Mantey } 122301784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 122401784826SJohnathan Mantey { 122501784826SJohnathan Mantey addr = &(NICIPentry->address); 122601784826SJohnathan Mantey } 122701784826SJohnathan Mantey else 122801784826SJohnathan Mantey { 122901784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 123001784826SJohnathan Mantey pathString + "/Address"); 123101784826SJohnathan Mantey errorInEntry = true; 12324a0cb85cSEd Tanous } 12334a0cb85cSEd Tanous 1234537174c4SEd Tanous if (subnetMask) 12354a0cb85cSEd Tanous { 1236537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 12374a0cb85cSEd Tanous { 1238f12894f8SJason M. Bills messages::propertyValueFormatError( 1239537174c4SEd Tanous asyncResp->res, *subnetMask, 12404a0cb85cSEd Tanous pathString + "/SubnetMask"); 124101784826SJohnathan Mantey errorInEntry = true; 12424a0cb85cSEd Tanous } 12434a0cb85cSEd Tanous } 124401784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 12454a0cb85cSEd Tanous { 124601784826SJohnathan Mantey if (!ipv4VerifyIpAndGetBitcount(NICIPentry->netmask, 124701784826SJohnathan Mantey &prefixLength)) 12484a0cb85cSEd Tanous { 124901784826SJohnathan Mantey messages::propertyValueFormatError( 125001784826SJohnathan Mantey asyncResp->res, NICIPentry->netmask, 125101784826SJohnathan Mantey pathString + "/SubnetMask"); 125201784826SJohnathan Mantey errorInEntry = true; 12534a0cb85cSEd Tanous } 12544a0cb85cSEd Tanous } 12551abe55efSEd Tanous else 12561abe55efSEd Tanous { 125701784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 125801784826SJohnathan Mantey pathString + "/SubnetMask"); 125901784826SJohnathan Mantey errorInEntry = true; 126001784826SJohnathan Mantey } 126101784826SJohnathan Mantey 126201784826SJohnathan Mantey if (gateway) 126301784826SJohnathan Mantey { 126401784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*gateway)) 126501784826SJohnathan Mantey { 126601784826SJohnathan Mantey gw = &(*gateway); 126701784826SJohnathan Mantey } 126801784826SJohnathan Mantey else 126901784826SJohnathan Mantey { 127001784826SJohnathan Mantey messages::propertyValueFormatError( 127101784826SJohnathan Mantey asyncResp->res, *gateway, pathString + "/Gateway"); 127201784826SJohnathan Mantey errorInEntry = true; 127301784826SJohnathan Mantey } 127401784826SJohnathan Mantey } 127501784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 127601784826SJohnathan Mantey { 127701784826SJohnathan Mantey gw = &NICIPentry->gateway; 127801784826SJohnathan Mantey } 127901784826SJohnathan Mantey else 12801abe55efSEd Tanous { 1281a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 12824a0cb85cSEd Tanous pathString + "/Gateway"); 128301784826SJohnathan Mantey errorInEntry = true; 12844a0cb85cSEd Tanous } 12854a0cb85cSEd Tanous 128601784826SJohnathan Mantey if (errorInEntry) 12871abe55efSEd Tanous { 128801784826SJohnathan Mantey return; 12894a0cb85cSEd Tanous } 12904a0cb85cSEd Tanous 129101784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 12921abe55efSEd Tanous { 1293*271584abSEd Tanous if (gw != nullptr || addr != nullptr) 1294*271584abSEd Tanous { 1295*271584abSEd Tanous // Shouldn't be possible based on errorInEntry, but 1296*271584abSEd Tanous // it flags -wmaybe-uninitialized in the compiler, 1297*271584abSEd Tanous // so defend against that 1298*271584abSEd Tanous return; 1299*271584abSEd Tanous } 130001784826SJohnathan Mantey deleteAndCreateIPv4(ifaceId, NICIPentry->id, prefixLength, 130101784826SJohnathan Mantey *gw, *addr, asyncResp); 130201784826SJohnathan Mantey NICIPentry = 130301784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 1304588c3f0dSKowalski, Kamil } 130501784826SJohnathan Mantey else 130601784826SJohnathan Mantey { 130701784826SJohnathan Mantey createIPv4(ifaceId, entryIdx, prefixLength, *gateway, 130801784826SJohnathan Mantey *address, asyncResp); 13094a0cb85cSEd Tanous } 13104a0cb85cSEd Tanous entryIdx++; 13114a0cb85cSEd Tanous } 131201784826SJohnathan Mantey else 131301784826SJohnathan Mantey { 131401784826SJohnathan Mantey if (NICIPentry == ipv4Data.cend()) 131501784826SJohnathan Mantey { 131601784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 131701784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 131801784826SJohnathan Mantey // in error, so bail out. 131901784826SJohnathan Mantey if (thisJson.is_null()) 132001784826SJohnathan Mantey { 132101784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 132201784826SJohnathan Mantey return; 132301784826SJohnathan Mantey } 132401784826SJohnathan Mantey else 132501784826SJohnathan Mantey { 132601784826SJohnathan Mantey messages::propertyValueFormatError( 132701784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 132801784826SJohnathan Mantey return; 132901784826SJohnathan Mantey } 133001784826SJohnathan Mantey } 133101784826SJohnathan Mantey 133201784826SJohnathan Mantey if (thisJson.is_null()) 133301784826SJohnathan Mantey { 133401784826SJohnathan Mantey deleteIPv4(ifaceId, NICIPentry->id, asyncResp); 133501784826SJohnathan Mantey } 133601784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 133701784826SJohnathan Mantey { 133801784826SJohnathan Mantey NICIPentry = 133901784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 134001784826SJohnathan Mantey } 134101784826SJohnathan Mantey entryIdx++; 134201784826SJohnathan Mantey } 134301784826SJohnathan Mantey } 13444a0cb85cSEd Tanous } 13454a0cb85cSEd Tanous 1346f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1347f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1348f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1349f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1350f85837bfSRAJESWARAN THILLAIGOVINDAN { 1351f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1352286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1353f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1354f85837bfSRAJESWARAN THILLAIGOVINDAN { 1355f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1356f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1357f85837bfSRAJESWARAN THILLAIGOVINDAN } 1358f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1359f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1360f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1361f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1362f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1363f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1364f85837bfSRAJESWARAN THILLAIGOVINDAN } 1365f85837bfSRAJESWARAN THILLAIGOVINDAN 1366e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1367e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 136801784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1369e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1370e48c0fc5SRavi Teja { 137101784826SJohnathan Mantey if (!input.is_array() || input.empty()) 1372e48c0fc5SRavi Teja { 1373e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1374e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1375e48c0fc5SRavi Teja return; 1376e48c0fc5SRavi Teja } 1377*271584abSEd Tanous size_t entryIdx = 1; 137801784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator NICIPentry = 137901784826SJohnathan Mantey GetNextStaticIPEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1380e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1381e48c0fc5SRavi Teja { 1382e48c0fc5SRavi Teja std::string pathString = 1383e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1384e48c0fc5SRavi Teja 138501784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1386e48c0fc5SRavi Teja { 1387e48c0fc5SRavi Teja std::optional<std::string> address; 1388e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1389e48c0fc5SRavi Teja 1390e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1391e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1392e48c0fc5SRavi Teja { 139301784826SJohnathan Mantey messages::propertyValueFormatError( 139401784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1395e48c0fc5SRavi Teja return; 1396e48c0fc5SRavi Teja } 1397e48c0fc5SRavi Teja 139801784826SJohnathan Mantey const std::string *addr; 139901784826SJohnathan Mantey uint8_t prefix; 140001784826SJohnathan Mantey 140101784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 140201784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 140301784826SJohnathan Mantey // current state of the interface. Merge existing state into the 140401784826SJohnathan Mantey // current request. 1405e48c0fc5SRavi Teja if (address) 1406e48c0fc5SRavi Teja { 140701784826SJohnathan Mantey addr = &(*address); 1408e48c0fc5SRavi Teja } 140901784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 141001784826SJohnathan Mantey { 141101784826SJohnathan Mantey addr = &(NICIPentry->address); 141201784826SJohnathan Mantey } 141301784826SJohnathan Mantey else 141401784826SJohnathan Mantey { 141501784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 141601784826SJohnathan Mantey pathString + "/Address"); 141701784826SJohnathan Mantey return; 1418e48c0fc5SRavi Teja } 1419e48c0fc5SRavi Teja 1420e48c0fc5SRavi Teja if (prefixLength) 1421e48c0fc5SRavi Teja { 142201784826SJohnathan Mantey prefix = *prefixLength; 142301784826SJohnathan Mantey } 142401784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 1425e48c0fc5SRavi Teja { 142601784826SJohnathan Mantey prefix = NICIPentry->prefixLength; 1427e48c0fc5SRavi Teja } 1428e48c0fc5SRavi Teja else 1429e48c0fc5SRavi Teja { 1430e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1431e48c0fc5SRavi Teja pathString + "/PrefixLength"); 143201784826SJohnathan Mantey return; 1433e48c0fc5SRavi Teja } 1434e48c0fc5SRavi Teja 143501784826SJohnathan Mantey if (NICIPentry != ipv6Data.end()) 1436e48c0fc5SRavi Teja { 143701784826SJohnathan Mantey deleteAndCreateIPv6(ifaceId, NICIPentry->id, prefix, *addr, 1438e48c0fc5SRavi Teja asyncResp); 143901784826SJohnathan Mantey NICIPentry = 144001784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 144101784826SJohnathan Mantey } 144201784826SJohnathan Mantey else 144301784826SJohnathan Mantey { 144401784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1445e48c0fc5SRavi Teja } 1446e48c0fc5SRavi Teja entryIdx++; 1447e48c0fc5SRavi Teja } 144801784826SJohnathan Mantey else 144901784826SJohnathan Mantey { 145001784826SJohnathan Mantey if (NICIPentry == ipv6Data.end()) 145101784826SJohnathan Mantey { 145201784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 145301784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 145401784826SJohnathan Mantey // in error, so bail out. 145501784826SJohnathan Mantey if (thisJson.is_null()) 145601784826SJohnathan Mantey { 145701784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 145801784826SJohnathan Mantey return; 145901784826SJohnathan Mantey } 146001784826SJohnathan Mantey else 146101784826SJohnathan Mantey { 146201784826SJohnathan Mantey messages::propertyValueFormatError( 146301784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 146401784826SJohnathan Mantey return; 146501784826SJohnathan Mantey } 146601784826SJohnathan Mantey } 146701784826SJohnathan Mantey 146801784826SJohnathan Mantey if (thisJson.is_null()) 146901784826SJohnathan Mantey { 147001784826SJohnathan Mantey deleteIPv6(ifaceId, NICIPentry->id, asyncResp); 147101784826SJohnathan Mantey } 147201784826SJohnathan Mantey if (NICIPentry != ipv6Data.cend()) 147301784826SJohnathan Mantey { 147401784826SJohnathan Mantey NICIPentry = 147501784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 147601784826SJohnathan Mantey } 147701784826SJohnathan Mantey entryIdx++; 147801784826SJohnathan Mantey } 147901784826SJohnathan Mantey } 1480e48c0fc5SRavi Teja } 1481e48c0fc5SRavi Teja 14820f74e643SEd Tanous void parseInterfaceData( 14830f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 14840f74e643SEd Tanous const EthernetInterfaceData ðData, 1485e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 148601784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 14874a0cb85cSEd Tanous { 14884a0cb85cSEd Tanous json_response["Id"] = iface_id; 14894a0cb85cSEd Tanous json_response["@odata.id"] = 14904a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1491029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1492029573d4SEd Tanous if (ethData.speed == 0) 1493029573d4SEd Tanous { 1494029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1495029573d4SEd Tanous json_response["Status"] = { 1496029573d4SEd Tanous {"Health", "OK"}, 1497029573d4SEd Tanous {"State", "Disabled"}, 1498029573d4SEd Tanous }; 1499029573d4SEd Tanous } 1500029573d4SEd Tanous else 1501029573d4SEd Tanous { 1502029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1503029573d4SEd Tanous json_response["Status"] = { 1504029573d4SEd Tanous {"Health", "OK"}, 1505029573d4SEd Tanous {"State", "Enabled"}, 1506029573d4SEd Tanous }; 1507029573d4SEd Tanous } 15084a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 15094a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1510fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 15112a133282Smanojkiraneda 15124a0cb85cSEd Tanous if (!ethData.hostname.empty()) 15134a0cb85cSEd Tanous { 15144a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 1515d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1516d24bfc7aSJennifer Lee { 1517d24bfc7aSJennifer Lee json_response["FQDN"] = 1518d24bfc7aSJennifer Lee ethData.hostname + "." + ethData.domainnames[0]; 1519d24bfc7aSJennifer Lee } 15204a0cb85cSEd Tanous } 15214a0cb85cSEd Tanous 1522fda13ad2SSunitha Harish json_response["VLANs"] = { 1523fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1524fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1525fda13ad2SSunitha Harish 1526029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 152795f8646eSManojkiran Eda 152895f8646eSManojkiran Eda if (!ethData.DHCPEnabled) 152995f8646eSManojkiran Eda { 1530f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 153195f8646eSManojkiran Eda } 153295f8646eSManojkiran Eda else 153395f8646eSManojkiran Eda { 1534f1a3caeeSManojkiran Eda json_response["StaticNameServers"] = nlohmann::json::array(); 153595f8646eSManojkiran Eda } 15364a0cb85cSEd Tanous 15374a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 153801784826SJohnathan Mantey nlohmann::json &ipv4_static_array = 153901784826SJohnathan Mantey json_response["IPv4StaticAddresses"]; 15404a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 154101784826SJohnathan Mantey ipv4_static_array = nlohmann::json::array(); 15424a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 15434a0cb85cSEd Tanous { 1544fa5053a6SGunnar Mills 1545fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1546fa5053a6SGunnar Mills if (gatewayStr.empty()) 1547fa5053a6SGunnar Mills { 1548fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1549fa5053a6SGunnar Mills } 1550fa5053a6SGunnar Mills 15514a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 15524a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1553029573d4SEd Tanous {"Address", ipv4_config.address}, 1554fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 155501784826SJohnathan Mantey if (ipv4_config.origin == "Static") 1556d1d50814SRavi Teja { 1557d1d50814SRavi Teja ipv4_static_array.push_back( 155801784826SJohnathan Mantey {{"AddressOrigin", ipv4_config.origin}, 155901784826SJohnathan Mantey {"SubnetMask", ipv4_config.netmask}, 156001784826SJohnathan Mantey {"Address", ipv4_config.address}, 1561d1d50814SRavi Teja {"Gateway", gatewayStr}}); 1562d1d50814SRavi Teja } 156301784826SJohnathan Mantey } 1564d1d50814SRavi Teja 15659a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1566e48c0fc5SRavi Teja 1567e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 156801784826SJohnathan Mantey nlohmann::json &ipv6_static_array = 156901784826SJohnathan Mantey json_response["IPv6StaticAddresses"]; 1570e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 157101784826SJohnathan Mantey ipv6_static_array = nlohmann::json::array(); 1572e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1573e48c0fc5SRavi Teja { 1574e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1575e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1576e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 157701784826SJohnathan Mantey if (ipv6_config.origin == "Static") 1578e48c0fc5SRavi Teja { 1579e48c0fc5SRavi Teja ipv6_static_array.push_back( 158001784826SJohnathan Mantey {{"Address", ipv6_config.address}, 158101784826SJohnathan Mantey {"PrefixLength", ipv6_config.prefixLength}, 158201784826SJohnathan Mantey {"AddressOrigin", ipv6_config.origin}}); 158301784826SJohnathan Mantey } 1584e48c0fc5SRavi Teja } 1585588c3f0dSKowalski, Kamil } 1586588c3f0dSKowalski, Kamil 15879391bb9cSRapkiewicz, Pawel /** 15889391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 15899391bb9cSRapkiewicz, Pawel */ 159055c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 15911abe55efSEd Tanous const std::vector<std::string> ¶ms) override 15921abe55efSEd Tanous { 15934a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 15941abe55efSEd Tanous if (params.size() != 1) 15951abe55efSEd Tanous { 1596f12894f8SJason M. Bills messages::internalError(asyncResp->res); 15979391bb9cSRapkiewicz, Pawel return; 15989391bb9cSRapkiewicz, Pawel } 15999391bb9cSRapkiewicz, Pawel 16004a0cb85cSEd Tanous getEthernetIfaceData( 16014a0cb85cSEd Tanous params[0], 16024a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 16034a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1604e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 160501784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 16064a0cb85cSEd Tanous if (!success) 16071abe55efSEd Tanous { 16081abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16091abe55efSEd Tanous // object, and other errors 1610f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1611f12894f8SJason M. Bills "EthernetInterface", iface_id); 16124a0cb85cSEd Tanous return; 16139391bb9cSRapkiewicz, Pawel } 16144c9afe43SEd Tanous 16154c9afe43SEd Tanous // because this has no dependence on the interface at this 16164c9afe43SEd Tanous // point, it needs to be done after we know the interface 16174c9afe43SEd Tanous // exists, not before. 16184c9afe43SEd Tanous getDHCPConfigData(asyncResp); 16194c9afe43SEd Tanous 16200f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1621fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 16220f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 162301784826SJohnathan Mantey "/redfish/v1/" 162401784826SJohnathan Mantey "$metadata#EthernetInterface.EthernetInterface"; 16250f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 16260f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 16270f74e643SEd Tanous "Management Network Interface"; 16280f74e643SEd Tanous 16290f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 163001784826SJohnathan Mantey ipv4Data, ipv6Data); 16319391bb9cSRapkiewicz, Pawel }); 16329391bb9cSRapkiewicz, Pawel } 16339391bb9cSRapkiewicz, Pawel 163455c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 16351abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16361abe55efSEd Tanous { 16374a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16381abe55efSEd Tanous if (params.size() != 1) 16391abe55efSEd Tanous { 1640f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1641588c3f0dSKowalski, Kamil return; 1642588c3f0dSKowalski, Kamil } 1643588c3f0dSKowalski, Kamil 16444a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1645588c3f0dSKowalski, Kamil 1646bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1647d577665bSRatan Gupta std::optional<std::string> macAddress; 16489a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1649d1d50814SRavi Teja std::optional<nlohmann::json> ipv4StaticAddresses; 1650e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1651f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 1652da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 16530627a2c7SEd Tanous 165401784826SJohnathan Mantey if (!json_util::readJson(req, res, "HostName", hostname, 165501784826SJohnathan Mantey "IPv4StaticAddresses", ipv4StaticAddresses, 165601784826SJohnathan Mantey "MACAddress", macAddress, "StaticNameServers", 165701784826SJohnathan Mantey staticNameServers, "IPv6DefaultGateway", 165801784826SJohnathan Mantey ipv6DefaultGateway, "IPv6StaticAddresses", 165901784826SJohnathan Mantey ipv6StaticAddresses, "DHCPv4", dhcpv4)) 16601abe55efSEd Tanous { 1661588c3f0dSKowalski, Kamil return; 1662588c3f0dSKowalski, Kamil } 1663f15aad37SRatan Gupta 1664da131a9aSJennifer Lee if (dhcpv4) 1665da131a9aSJennifer Lee { 1666da131a9aSJennifer Lee handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp); 1667da131a9aSJennifer Lee } 1668da131a9aSJennifer Lee 166901784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 167001784826SJohnathan Mantey // JSON preparation 16714a0cb85cSEd Tanous getEthernetIfaceData( 16724a0cb85cSEd Tanous iface_id, 1673fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1674fda13ad2SSunitha Harish macAddress = std::move(macAddress), 1675d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 16769a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1677e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 167801784826SJohnathan Mantey staticNameServers = std::move(staticNameServers)]( 16794a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1680e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 168101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 16821abe55efSEd Tanous if (!success) 16831abe55efSEd Tanous { 1684588c3f0dSKowalski, Kamil // ... otherwise return error 16851abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16861abe55efSEd Tanous // object, and other errors 1687fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1688fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1689588c3f0dSKowalski, Kamil return; 1690588c3f0dSKowalski, Kamil } 1691588c3f0dSKowalski, Kamil 16920627a2c7SEd Tanous if (hostname) 16931abe55efSEd Tanous { 16940627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 16951abe55efSEd Tanous } 16960627a2c7SEd Tanous 1697d577665bSRatan Gupta if (macAddress) 1698d577665bSRatan Gupta { 1699d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1700d577665bSRatan Gupta } 1701d577665bSRatan Gupta 1702d1d50814SRavi Teja if (ipv4StaticAddresses) 1703d1d50814SRavi Teja { 1704537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 170501784826SJohnathan Mantey // above is returning a const value, not a non-const 170601784826SJohnathan Mantey // value. This doesn't really work for us, as we need to 170701784826SJohnathan Mantey // be able to efficiently move out the intermedia 170801784826SJohnathan Mantey // nlohmann::json objects. This makes a copy of the 170901784826SJohnathan Mantey // structure, and operates on that, but could be done 171001784826SJohnathan Mantey // more efficiently 1711d1d50814SRavi Teja nlohmann::json ipv4Static = std::move(*ipv4StaticAddresses); 171201784826SJohnathan Mantey handleIPv4StaticPatch(iface_id, ipv4Static, ipv4Data, 1713d1d50814SRavi Teja asyncResp); 17141abe55efSEd Tanous } 17150627a2c7SEd Tanous 1716f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1717f85837bfSRAJESWARAN THILLAIGOVINDAN { 1718f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1719f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1720f85837bfSRAJESWARAN THILLAIGOVINDAN } 17219a6fc6feSRavi Teja 17229a6fc6feSRavi Teja if (ipv6DefaultGateway) 17239a6fc6feSRavi Teja { 17249a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 17259a6fc6feSRavi Teja "IPv6DefaultGateway"); 17269a6fc6feSRavi Teja } 1727e48c0fc5SRavi Teja 1728e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1729e48c0fc5SRavi Teja { 1730e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1731e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 173201784826SJohnathan Mantey ipv6Data, asyncResp); 1733e48c0fc5SRavi Teja } 1734588c3f0dSKowalski, Kamil }); 1735588c3f0dSKowalski, Kamil } 17369391bb9cSRapkiewicz, Pawel }; 17379391bb9cSRapkiewicz, Pawel 1738e439f0f8SKowalski, Kamil /** 17394a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 17404a0cb85cSEd Tanous * Schema 1741e439f0f8SKowalski, Kamil */ 17421abe55efSEd Tanous class VlanNetworkInterface : public Node 17431abe55efSEd Tanous { 1744e439f0f8SKowalski, Kamil public: 1745e439f0f8SKowalski, Kamil /* 1746e439f0f8SKowalski, Kamil * Default Constructor 1747e439f0f8SKowalski, Kamil */ 1748e439f0f8SKowalski, Kamil template <typename CrowApp> 17491abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 17504a0cb85cSEd Tanous Node(app, 17510f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 17521abe55efSEd Tanous std::string(), std::string()) 17531abe55efSEd Tanous { 1754e439f0f8SKowalski, Kamil entityPrivileges = { 1755e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1756e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1757e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1758e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1759e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1760e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1761e439f0f8SKowalski, Kamil } 1762e439f0f8SKowalski, Kamil 1763e439f0f8SKowalski, Kamil private: 17640f74e643SEd Tanous void parseInterfaceData( 17650f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 17660f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1767e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 176801784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 17691abe55efSEd Tanous { 1770e439f0f8SKowalski, Kamil // Fill out obvious data... 17714a0cb85cSEd Tanous json_response["Id"] = iface_id; 17724a0cb85cSEd Tanous json_response["@odata.id"] = 17734a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 17744a0cb85cSEd Tanous "/VLANs/" + iface_id; 1775e439f0f8SKowalski, Kamil 17764a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1777fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 17784a0cb85cSEd Tanous { 1779fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 17804a0cb85cSEd Tanous } 1781e439f0f8SKowalski, Kamil } 1782e439f0f8SKowalski, Kamil 1783fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 17841abe55efSEd Tanous { 17851abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 17861abe55efSEd Tanous { 1787927a505aSKowalski, Kamil return false; 17881abe55efSEd Tanous } 17891abe55efSEd Tanous else 17901abe55efSEd Tanous { 1791927a505aSKowalski, Kamil return true; 1792927a505aSKowalski, Kamil } 1793927a505aSKowalski, Kamil } 1794927a505aSKowalski, Kamil 1795e439f0f8SKowalski, Kamil /** 1796e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1797e439f0f8SKowalski, Kamil */ 179855c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 17991abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18001abe55efSEd Tanous { 18014a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18024a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1803e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1804e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1805e439f0f8SKowalski, Kamil // impossible. 18061abe55efSEd Tanous if (params.size() != 2) 18071abe55efSEd Tanous { 1808f12894f8SJason M. Bills messages::internalError(res); 1809e439f0f8SKowalski, Kamil res.end(); 1810e439f0f8SKowalski, Kamil return; 1811e439f0f8SKowalski, Kamil } 1812e439f0f8SKowalski, Kamil 18134a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 18144a0cb85cSEd Tanous const std::string &iface_id = params[1]; 18150f74e643SEd Tanous res.jsonValue["@odata.type"] = 18160f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 18170f74e643SEd Tanous res.jsonValue["@odata.context"] = 181801784826SJohnathan Mantey "/redfish/v1/" 181901784826SJohnathan Mantey "$metadata#VLanNetworkInterface.VLanNetworkInterface"; 18200f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1821e439f0f8SKowalski, Kamil 1822fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 18231abe55efSEd Tanous { 1824a434f2bdSEd Tanous return; 1825a434f2bdSEd Tanous } 1826a434f2bdSEd Tanous 182701784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 182801784826SJohnathan Mantey // JSON preparation 18294a0cb85cSEd Tanous getEthernetIfaceData( 1830fda13ad2SSunitha Harish params[1], 1831fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1832fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 18334a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1834e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 183501784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 1836fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 18371abe55efSEd Tanous { 18380f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 18390f74e643SEd Tanous parent_iface_id, iface_id, ethData, 184001784826SJohnathan Mantey ipv4Data, ipv6Data); 18411abe55efSEd Tanous } 18421abe55efSEd Tanous else 18431abe55efSEd Tanous { 1844e439f0f8SKowalski, Kamil // ... otherwise return error 18451abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18461abe55efSEd Tanous // object, and other errors 1847f12894f8SJason M. Bills messages::resourceNotFound( 1848f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1849e439f0f8SKowalski, Kamil } 1850e439f0f8SKowalski, Kamil }); 1851e439f0f8SKowalski, Kamil } 1852e439f0f8SKowalski, Kamil 185355c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 18541abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18551abe55efSEd Tanous { 18564a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18571abe55efSEd Tanous if (params.size() != 2) 18581abe55efSEd Tanous { 1859f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1860e439f0f8SKowalski, Kamil return; 1861e439f0f8SKowalski, Kamil } 1862e439f0f8SKowalski, Kamil 1863d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 186455c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1865927a505aSKowalski, Kamil 1866fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 18671abe55efSEd Tanous { 1868fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1869fda13ad2SSunitha Harish ifaceId); 1870927a505aSKowalski, Kamil return; 1871927a505aSKowalski, Kamil } 1872927a505aSKowalski, Kamil 18730627a2c7SEd Tanous bool vlanEnable = false; 18740627a2c7SEd Tanous uint64_t vlanId = 0; 18750627a2c7SEd Tanous 18760627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 18770627a2c7SEd Tanous vlanId)) 18781abe55efSEd Tanous { 1879927a505aSKowalski, Kamil return; 1880927a505aSKowalski, Kamil } 1881927a505aSKowalski, Kamil 188201784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 188301784826SJohnathan Mantey // JSON preparation 1884e48c0fc5SRavi Teja getEthernetIfaceData( 1885e48c0fc5SRavi Teja params[1], 1886*271584abSEd Tanous [asyncResp, parentIfaceId{std::string(params[0])}, 1887e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 1888e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 1889e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 189001784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 189108244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 189208244d02SSunitha Harish { 189308244d02SSunitha Harish auto callback = 189408244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 189508244d02SSunitha Harish if (ec) 189608244d02SSunitha Harish { 189708244d02SSunitha Harish messages::internalError(asyncResp->res); 189808244d02SSunitha Harish } 189908244d02SSunitha Harish }; 190008244d02SSunitha Harish 190108244d02SSunitha Harish if (vlanEnable == true) 190208244d02SSunitha Harish { 190308244d02SSunitha Harish crow::connections::systemBus->async_method_call( 190408244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 190508244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 190608244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 190708244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 190808244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 190908244d02SSunitha Harish } 191008244d02SSunitha Harish else 191108244d02SSunitha Harish { 1912e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 1913e48c0fc5SRavi Teja "vlan interface"; 191408244d02SSunitha Harish crow::connections::systemBus->async_method_call( 191508244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 1916e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 1917e48c0fc5SRavi Teja ifaceId, 191808244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 191908244d02SSunitha Harish } 192008244d02SSunitha Harish } 192108244d02SSunitha Harish else 19221abe55efSEd Tanous { 19231abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 19241abe55efSEd Tanous // object, and other errors 1925e48c0fc5SRavi Teja messages::resourceNotFound( 1926e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 1927927a505aSKowalski, Kamil return; 1928927a505aSKowalski, Kamil } 1929927a505aSKowalski, Kamil }); 1930e439f0f8SKowalski, Kamil } 1931e439f0f8SKowalski, Kamil 193255c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 19331abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19341abe55efSEd Tanous { 19354a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19361abe55efSEd Tanous if (params.size() != 2) 19371abe55efSEd Tanous { 1938f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1939e439f0f8SKowalski, Kamil return; 1940e439f0f8SKowalski, Kamil } 1941e439f0f8SKowalski, Kamil 1942d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 194355c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1944927a505aSKowalski, Kamil 1945fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19461abe55efSEd Tanous { 1947fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1948fda13ad2SSunitha Harish ifaceId); 1949927a505aSKowalski, Kamil return; 1950927a505aSKowalski, Kamil } 1951927a505aSKowalski, Kamil 195201784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 195301784826SJohnathan Mantey // JSON preparation 1954f12894f8SJason M. Bills getEthernetIfaceData( 1955fda13ad2SSunitha Harish params[1], 1956*271584abSEd Tanous [asyncResp, parentIfaceId{std::string(params[0])}, 1957fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 1958f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 1959e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 196001784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 1961fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 19621abe55efSEd Tanous { 1963f12894f8SJason M. Bills auto callback = 1964f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 19651abe55efSEd Tanous if (ec) 19661abe55efSEd Tanous { 1967f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1968927a505aSKowalski, Kamil } 19694a0cb85cSEd Tanous }; 19704a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 19714a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 19724a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 19734a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 19741abe55efSEd Tanous } 19751abe55efSEd Tanous else 19761abe55efSEd Tanous { 1977927a505aSKowalski, Kamil // ... otherwise return error 1978f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 1979f12894f8SJason M. Bills // object, and other errors 1980f12894f8SJason M. Bills messages::resourceNotFound( 1981f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 1982927a505aSKowalski, Kamil } 1983927a505aSKowalski, Kamil }); 1984e439f0f8SKowalski, Kamil } 1985e439f0f8SKowalski, Kamil }; 1986e439f0f8SKowalski, Kamil 1987e439f0f8SKowalski, Kamil /** 1988e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 1989e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 1990e439f0f8SKowalski, Kamil */ 19911abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 19921abe55efSEd Tanous { 1993e439f0f8SKowalski, Kamil public: 1994e439f0f8SKowalski, Kamil template <typename CrowApp> 19951abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 19964a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 19974a0cb85cSEd Tanous std::string()) 19981abe55efSEd Tanous { 1999e439f0f8SKowalski, Kamil entityPrivileges = { 2000e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 2001e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2002e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2003e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2004e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2005e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2006e439f0f8SKowalski, Kamil } 2007e439f0f8SKowalski, Kamil 2008e439f0f8SKowalski, Kamil private: 2009e439f0f8SKowalski, Kamil /** 2010e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2011e439f0f8SKowalski, Kamil */ 201255c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 20131abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20141abe55efSEd Tanous { 20154a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20161abe55efSEd Tanous if (params.size() != 1) 20171abe55efSEd Tanous { 2018e439f0f8SKowalski, Kamil // This means there is a problem with the router 2019f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2020e439f0f8SKowalski, Kamil return; 2021e439f0f8SKowalski, Kamil } 2022e439f0f8SKowalski, Kamil 20234a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2024e439f0f8SKowalski, Kamil 20254a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 20261abe55efSEd Tanous // preparation 2027f12894f8SJason M. Bills getEthernetIfaceList( 202843b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 20291abe55efSEd Tanous const bool &success, 20304c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 20314a0cb85cSEd Tanous if (!success) 20321abe55efSEd Tanous { 2033f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20344a0cb85cSEd Tanous return; 20351abe55efSEd Tanous } 20364c9afe43SEd Tanous 20374c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 20384c9afe43SEd Tanous { 20394c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 20404c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 20414c9afe43SEd Tanous rootInterfaceName); 20424c9afe43SEd Tanous return; 20434c9afe43SEd Tanous } 20444c9afe43SEd Tanous 20450f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 20460f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 20470f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 20480f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 20490f74e643SEd Tanous "/redfish/v1/$metadata" 20500f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 20510f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 20520f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 20530f74e643SEd Tanous "VLAN Network Interface Collection"; 20544a0cb85cSEd Tanous 20554a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 20564a0cb85cSEd Tanous 20574a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 20581abe55efSEd Tanous { 20594a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 20604a0cb85cSEd Tanous { 20614a0cb85cSEd Tanous iface_array.push_back( 20624a0cb85cSEd Tanous {{"@odata.id", 20634a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 20644a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2065e439f0f8SKowalski, Kamil } 2066e439f0f8SKowalski, Kamil } 2067e439f0f8SKowalski, Kamil 20684a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 20694a0cb85cSEd Tanous iface_array.size(); 20704a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 20714a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 20724a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 20734a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2074e439f0f8SKowalski, Kamil }); 2075e439f0f8SKowalski, Kamil } 2076e439f0f8SKowalski, Kamil 207755c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 20781abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20791abe55efSEd Tanous { 20804a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20811abe55efSEd Tanous if (params.size() != 1) 20821abe55efSEd Tanous { 2083f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2084e439f0f8SKowalski, Kamil return; 2085e439f0f8SKowalski, Kamil } 2086fda13ad2SSunitha Harish bool vlanEnable = false; 20870627a2c7SEd Tanous uint32_t vlanId = 0; 2088fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2089fda13ad2SSunitha Harish vlanEnable)) 20901abe55efSEd Tanous { 20914a0cb85cSEd Tanous return; 2092e439f0f8SKowalski, Kamil } 2093fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2094fda13ad2SSunitha Harish if (!vlanId) 2095fda13ad2SSunitha Harish { 2096fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2097fda13ad2SSunitha Harish } 2098fda13ad2SSunitha Harish if (!vlanEnable) 2099fda13ad2SSunitha Harish { 2100fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2101fda13ad2SSunitha Harish } 2102*271584abSEd Tanous if (static_cast<bool>(vlanId) ^ vlanEnable) 2103fda13ad2SSunitha Harish { 2104fda13ad2SSunitha Harish return; 2105fda13ad2SSunitha Harish } 2106fda13ad2SSunitha Harish 21074a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 21084a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 21091abe55efSEd Tanous if (ec) 21101abe55efSEd Tanous { 21114a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 21124a0cb85cSEd Tanous // phosphor-network responses 2113f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21144a0cb85cSEd Tanous return; 21151abe55efSEd Tanous } 2116f12894f8SJason M. Bills messages::created(asyncResp->res); 2117e439f0f8SKowalski, Kamil }; 21184a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21194a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21204a0cb85cSEd Tanous "/xyz/openbmc_project/network", 21214a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 21220627a2c7SEd Tanous rootInterfaceName, vlanId); 21234a0cb85cSEd Tanous } 21244a0cb85cSEd Tanous }; 21259391bb9cSRapkiewicz, Pawel } // namespace redfish 2126