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; 1039391bb9cSRapkiewicz, Pawel }; 1049391bb9cSRapkiewicz, Pawel 1059391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1069391bb9cSRapkiewicz, Pawel // into full dot notation 1071abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1081abe55efSEd Tanous { 1099391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1109391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1119391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1129391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1139391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1149391bb9cSRapkiewicz, Pawel return netmask; 1159391bb9cSRapkiewicz, Pawel } 1169391bb9cSRapkiewicz, Pawel 1174a0cb85cSEd Tanous inline std::string 1184a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string &inputOrigin, 1194a0cb85cSEd Tanous bool isIPv4) 1201abe55efSEd Tanous { 1214a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1221abe55efSEd Tanous { 1234a0cb85cSEd Tanous return "Static"; 1249391bb9cSRapkiewicz, Pawel } 1254a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1261abe55efSEd Tanous { 1274a0cb85cSEd Tanous if (isIPv4) 1281abe55efSEd Tanous { 1294a0cb85cSEd Tanous return "IPv4LinkLocal"; 1301abe55efSEd Tanous } 1311abe55efSEd Tanous else 1321abe55efSEd Tanous { 1334a0cb85cSEd Tanous return "LinkLocal"; 1349391bb9cSRapkiewicz, Pawel } 1359391bb9cSRapkiewicz, Pawel } 1364a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1371abe55efSEd Tanous { 1384a0cb85cSEd Tanous if (isIPv4) 1394a0cb85cSEd Tanous { 1404a0cb85cSEd Tanous return "DHCP"; 1414a0cb85cSEd Tanous } 1424a0cb85cSEd Tanous else 1434a0cb85cSEd Tanous { 1444a0cb85cSEd Tanous return "DHCPv6"; 1454a0cb85cSEd Tanous } 1464a0cb85cSEd Tanous } 1474a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1484a0cb85cSEd Tanous { 1494a0cb85cSEd Tanous return "SLAAC"; 1504a0cb85cSEd Tanous } 1514a0cb85cSEd Tanous return ""; 1524a0cb85cSEd Tanous } 1534a0cb85cSEd Tanous 1544c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string ðiface_id, 1554a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 1564a0cb85cSEd Tanous EthernetInterfaceData ðData) 1574a0cb85cSEd Tanous { 1584c9afe43SEd Tanous bool idFound = false; 1594a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 1604a0cb85cSEd Tanous { 1614a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 1624a0cb85cSEd Tanous { 163029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 164029573d4SEd Tanous { 1654c9afe43SEd Tanous idFound = true; 1664a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 1674a0cb85cSEd Tanous { 1684a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1694a0cb85cSEd Tanous { 1704a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 1714a0cb85cSEd Tanous { 1724a0cb85cSEd Tanous const std::string *mac = 173abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 1744a0cb85cSEd Tanous if (mac != nullptr) 1754a0cb85cSEd Tanous { 1764a0cb85cSEd Tanous ethData.mac_address = *mac; 1774a0cb85cSEd Tanous } 1784a0cb85cSEd Tanous } 1794a0cb85cSEd Tanous } 1804a0cb85cSEd Tanous } 1814a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 1824a0cb85cSEd Tanous { 1834a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1844a0cb85cSEd Tanous { 1854a0cb85cSEd Tanous if (propertyPair.first == "Id") 1864a0cb85cSEd Tanous { 1871b6b96c5SEd Tanous const uint32_t *id = 188abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 1894a0cb85cSEd Tanous if (id != nullptr) 1904a0cb85cSEd Tanous { 191fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 1924a0cb85cSEd Tanous } 1934a0cb85cSEd Tanous } 1944a0cb85cSEd Tanous } 1954a0cb85cSEd Tanous } 1964a0cb85cSEd Tanous else if (ifacePair.first == 1974a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 1984a0cb85cSEd Tanous { 1994a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2004a0cb85cSEd Tanous { 2014a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2024a0cb85cSEd Tanous { 2034a0cb85cSEd Tanous const bool *auto_neg = 204abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2054a0cb85cSEd Tanous if (auto_neg != nullptr) 2064a0cb85cSEd Tanous { 2074a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2084a0cb85cSEd Tanous } 2094a0cb85cSEd Tanous } 2104a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2114a0cb85cSEd Tanous { 2124a0cb85cSEd Tanous const uint32_t *speed = 213abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2144a0cb85cSEd Tanous if (speed != nullptr) 2154a0cb85cSEd Tanous { 2164a0cb85cSEd Tanous ethData.speed = *speed; 2174a0cb85cSEd Tanous } 2184a0cb85cSEd Tanous } 219f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 220029573d4SEd Tanous { 221029573d4SEd Tanous const std::vector<std::string> *nameservers = 222029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 223029573d4SEd Tanous std::vector<std::string>>( 224029573d4SEd Tanous &propertyPair.second); 225029573d4SEd Tanous if (nameservers != nullptr) 226029573d4SEd Tanous { 227029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2284a0cb85cSEd Tanous } 2294a0cb85cSEd Tanous } 2302a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 2312a133282Smanojkiraneda { 2322a133282Smanojkiraneda const bool *DHCPEnabled = 2332a133282Smanojkiraneda std::get_if<bool>(&propertyPair.second); 2342a133282Smanojkiraneda if (DHCPEnabled != nullptr) 2352a133282Smanojkiraneda { 2362a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 2372a133282Smanojkiraneda } 2382a133282Smanojkiraneda } 239029573d4SEd Tanous } 240029573d4SEd Tanous } 241029573d4SEd Tanous } 242029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 243029573d4SEd Tanous // to check eth number 244029573d4SEd Tanous if (ifacePair.first == 2454a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 2464a0cb85cSEd Tanous { 2474a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2484a0cb85cSEd Tanous { 2494a0cb85cSEd Tanous if (propertyPair.first == "HostName") 2504a0cb85cSEd Tanous { 2514a0cb85cSEd Tanous const std::string *hostname = 252029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 253029573d4SEd Tanous &propertyPair.second); 2544a0cb85cSEd Tanous if (hostname != nullptr) 2554a0cb85cSEd Tanous { 2564a0cb85cSEd Tanous ethData.hostname = *hostname; 2574a0cb85cSEd Tanous } 2584a0cb85cSEd Tanous } 2594a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 2604a0cb85cSEd Tanous { 2614a0cb85cSEd Tanous const std::string *defaultGateway = 262029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 263029573d4SEd Tanous &propertyPair.second); 2644a0cb85cSEd Tanous if (defaultGateway != nullptr) 2654a0cb85cSEd Tanous { 2664a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 2674a0cb85cSEd Tanous } 2684a0cb85cSEd Tanous } 2699a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 2709a6fc6feSRavi Teja { 2719a6fc6feSRavi Teja const std::string *defaultGateway6 = 2729a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 2739a6fc6feSRavi Teja &propertyPair.second); 2749a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 2759a6fc6feSRavi Teja { 2769a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 2779a6fc6feSRavi Teja } 2789a6fc6feSRavi Teja } 2794a0cb85cSEd Tanous } 2804a0cb85cSEd Tanous } 2814a0cb85cSEd Tanous } 2824a0cb85cSEd Tanous } 2834c9afe43SEd Tanous return idFound; 2844a0cb85cSEd Tanous } 2854a0cb85cSEd Tanous 286e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 287e48c0fc5SRavi Teja inline void extractIPV6Data( 288e48c0fc5SRavi Teja const std::string ðiface_id, const GetManagedObjects &dbus_data, 289e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> &ipv6_config, 290e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> &ipv6_static_config) 291e48c0fc5SRavi Teja { 292e48c0fc5SRavi Teja const std::string ipv6PathStart = 293e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/"; 294e48c0fc5SRavi Teja 295e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 296e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 297e48c0fc5SRavi Teja for (const auto &objpath : dbus_data) 298e48c0fc5SRavi Teja { 299e48c0fc5SRavi Teja // Check if proper pattern for object path appears 300e48c0fc5SRavi Teja if (boost::starts_with(objpath.first.str, ipv6PathStart)) 301e48c0fc5SRavi Teja { 302e48c0fc5SRavi Teja for (auto &interface : objpath.second) 303e48c0fc5SRavi Teja { 304e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 305e48c0fc5SRavi Teja { 306e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 307e48c0fc5SRavi Teja // appropriate 308e48c0fc5SRavi Teja std::pair< 309e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::iterator, 310e48c0fc5SRavi Teja bool> 311e48c0fc5SRavi Teja it = ipv6_config.insert( 312e48c0fc5SRavi Teja {objpath.first.str.substr(ipv6PathStart.size())}); 313e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 314e48c0fc5SRavi Teja for (auto &property : interface.second) 315e48c0fc5SRavi Teja { 316e48c0fc5SRavi Teja if (property.first == "Address") 317e48c0fc5SRavi Teja { 318e48c0fc5SRavi Teja const std::string *address = 319e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 320e48c0fc5SRavi Teja if (address != nullptr) 321e48c0fc5SRavi Teja { 322e48c0fc5SRavi Teja ipv6_address.address = *address; 323e48c0fc5SRavi Teja } 324e48c0fc5SRavi Teja } 325e48c0fc5SRavi Teja else if (property.first == "Origin") 326e48c0fc5SRavi Teja { 327e48c0fc5SRavi Teja const std::string *origin = 328e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 329e48c0fc5SRavi Teja if (origin != nullptr) 330e48c0fc5SRavi Teja { 331e48c0fc5SRavi Teja ipv6_address.origin = 332e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 333e48c0fc5SRavi Teja false); 334e48c0fc5SRavi Teja } 335e48c0fc5SRavi Teja } 336e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 337e48c0fc5SRavi Teja { 338e48c0fc5SRavi Teja const uint8_t *prefix = 339e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 340e48c0fc5SRavi Teja if (prefix != nullptr) 341e48c0fc5SRavi Teja { 342e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 343e48c0fc5SRavi Teja } 344e48c0fc5SRavi Teja } 345e48c0fc5SRavi Teja else 346e48c0fc5SRavi Teja { 347e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 348e48c0fc5SRavi Teja << "Got extra property: " << property.first 349e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 350e48c0fc5SRavi Teja } 351e48c0fc5SRavi Teja } 352e48c0fc5SRavi Teja if (ipv6_address.origin == "Static") 353e48c0fc5SRavi Teja { 354e48c0fc5SRavi Teja std::pair<boost::container::flat_set< 355e48c0fc5SRavi Teja IPv6AddressData>::iterator, 356e48c0fc5SRavi Teja bool> 357e48c0fc5SRavi Teja iter = ipv6_static_config.insert( 358e48c0fc5SRavi Teja {objpath.first.str.substr( 359e48c0fc5SRavi Teja ipv6PathStart.size())}); 360e48c0fc5SRavi Teja IPv6AddressData &ipv6_static_address = *iter.first; 361e48c0fc5SRavi Teja 362e48c0fc5SRavi Teja ipv6_static_address.address = ipv6_address.address; 363e48c0fc5SRavi Teja ipv6_static_address.prefixLength = 364e48c0fc5SRavi Teja ipv6_address.prefixLength; 365e48c0fc5SRavi Teja } 366e48c0fc5SRavi Teja } 367e48c0fc5SRavi Teja } 368e48c0fc5SRavi Teja } 369e48c0fc5SRavi Teja } 370e48c0fc5SRavi Teja } 371e48c0fc5SRavi Teja 3724a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 3734a0cb85cSEd Tanous inline void 3744a0cb85cSEd Tanous extractIPData(const std::string ðiface_id, 3754a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 3764a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> &ipv4_config) 3774a0cb85cSEd Tanous { 3784a0cb85cSEd Tanous const std::string ipv4PathStart = 3794a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 3804a0cb85cSEd Tanous 3814a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 3824a0cb85cSEd Tanous // single ethernet interface, loop over all of them 3834a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 3844a0cb85cSEd Tanous { 3854a0cb85cSEd Tanous // Check if proper pattern for object path appears 3864a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 3874a0cb85cSEd Tanous { 3884a0cb85cSEd Tanous for (auto &interface : objpath.second) 3894a0cb85cSEd Tanous { 3904a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 3914a0cb85cSEd Tanous { 3924a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 3934a0cb85cSEd Tanous // appropriate 3944a0cb85cSEd Tanous std::pair< 3954a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 3964a0cb85cSEd Tanous bool> 3974a0cb85cSEd Tanous it = ipv4_config.insert( 398b01bf299SEd Tanous {objpath.first.str.substr(ipv4PathStart.size())}); 3994a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 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 /** 574b01bf299SEd Tanous * @brief Changes IPv4 address type property (Address, Gateway) 575b01bf299SEd Tanous * 576b01bf299SEd Tanous * @param[in] ifaceId Id of interface whose IP should be modified 577b01bf299SEd Tanous * @param[in] ipIdx Index of IP in input array that should be modified 578b01bf299SEd Tanous * @param[in] ipHash DBus Hash id of modified IP 579b01bf299SEd Tanous * @param[in] name Name of field in JSON representation 580b01bf299SEd Tanous * @param[in] newValue New value that should be written 581b01bf299SEd Tanous * @param[io] asyncResp Response object that will be returned to client 582b01bf299SEd Tanous * 583b01bf299SEd Tanous * @return true if give IP is valid and has been sent do D-Bus, false 584b01bf299SEd Tanous * otherwise 585b01bf299SEd Tanous */ 586b01bf299SEd Tanous inline void changeIPv4AddressProperty( 587b01bf299SEd Tanous const std::string &ifaceId, int ipIdx, const std::string &ipHash, 588b01bf299SEd Tanous const std::string &name, const std::string &newValue, 589b01bf299SEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 590b01bf299SEd Tanous { 591b01bf299SEd Tanous auto callback = [asyncResp, ipIdx, name{std::string(name)}, 592b01bf299SEd Tanous newValue{std::move(newValue)}]( 593b01bf299SEd Tanous const boost::system::error_code ec) { 594b01bf299SEd Tanous if (ec) 595b01bf299SEd Tanous { 596b01bf299SEd Tanous messages::internalError(asyncResp->res); 597b01bf299SEd Tanous } 598b01bf299SEd Tanous else 599b01bf299SEd Tanous { 600b01bf299SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx][name] = newValue; 601b01bf299SEd Tanous } 602b01bf299SEd Tanous }; 603b01bf299SEd Tanous 604b01bf299SEd Tanous crow::connections::systemBus->async_method_call( 605b01bf299SEd Tanous std::move(callback), "xyz.openbmc_project.Network", 606b01bf299SEd Tanous "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 607b01bf299SEd Tanous "org.freedesktop.DBus.Properties", "Set", 608b01bf299SEd Tanous "xyz.openbmc_project.Network.IP", name, 609b01bf299SEd Tanous std::variant<std::string>(newValue)); 610b01bf299SEd Tanous } 611b01bf299SEd Tanous 612b01bf299SEd Tanous /** 613179db1d7SKowalski, Kamil * @brief Modifies SubnetMask for given IP 614179db1d7SKowalski, Kamil * 615179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be modified 6164a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be 6171abe55efSEd Tanous * modified 618179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of modified IP 619179db1d7SKowalski, Kamil * @param[in] newValueStr Mask in dot notation as string 620179db1d7SKowalski, Kamil * @param[in] newValue Mask as PrefixLength in bitcount 621179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 622179db1d7SKowalski, Kamil * 623179db1d7SKowalski, Kamil * @return None 624179db1d7SKowalski, Kamil */ 625b01bf299SEd Tanous inline void changeIPv4SubnetMaskProperty(const std::string &ifaceId, int ipIdx, 6264a0cb85cSEd Tanous const std::string &ipHash, 6274a0cb85cSEd Tanous const std::string &newValueStr, 6284a0cb85cSEd Tanous uint8_t &newValue, 6294a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6301abe55efSEd Tanous { 6314a0cb85cSEd Tanous auto callback = [asyncResp, ipIdx, newValueStr{std::move(newValueStr)}]( 6321abe55efSEd Tanous const boost::system::error_code ec) { 6331abe55efSEd Tanous if (ec) 6341abe55efSEd Tanous { 635a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6361abe55efSEd Tanous } 6371abe55efSEd Tanous else 6381abe55efSEd Tanous { 63955c7b7a2SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["SubnetMask"] = 640179db1d7SKowalski, Kamil newValueStr; 641179db1d7SKowalski, Kamil } 642179db1d7SKowalski, Kamil }; 643179db1d7SKowalski, Kamil 64455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 645179db1d7SKowalski, Kamil std::move(callback), "xyz.openbmc_project.Network", 646179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 647179db1d7SKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 648179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP", "PrefixLength", 649abf2add6SEd Tanous std::variant<uint8_t>(newValue)); 6504a0cb85cSEd Tanous } 651588c3f0dSKowalski, Kamil 652588c3f0dSKowalski, Kamil /** 653179db1d7SKowalski, Kamil * @brief Deletes given IPv4 654179db1d7SKowalski, Kamil * 655179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 6564a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 657179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 658179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 659179db1d7SKowalski, Kamil * 660179db1d7SKowalski, Kamil * @return None 661179db1d7SKowalski, Kamil */ 6624a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 663179db1d7SKowalski, Kamil unsigned int ipIdx, 6644a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 6651abe55efSEd Tanous { 66655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 6674a0cb85cSEd Tanous [ipIdx, asyncResp](const boost::system::error_code ec) { 6681abe55efSEd Tanous if (ec) 6691abe55efSEd Tanous { 670a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6711abe55efSEd Tanous } 6721abe55efSEd Tanous else 6731abe55efSEd Tanous { 67455c7b7a2SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx] = nullptr; 675179db1d7SKowalski, Kamil } 676179db1d7SKowalski, Kamil }, 677179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 678179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 679179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 680179db1d7SKowalski, Kamil } 681179db1d7SKowalski, Kamil 682179db1d7SKowalski, Kamil /** 683179db1d7SKowalski, Kamil * @brief Creates IPv4 with given data 684179db1d7SKowalski, Kamil * 685179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 6864a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 687179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 688179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 689179db1d7SKowalski, Kamil * 690179db1d7SKowalski, Kamil * @return None 691179db1d7SKowalski, Kamil */ 692b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 693b01bf299SEd Tanous uint8_t subnetMask, const std::string &gateway, 694b01bf299SEd Tanous const std::string &address, 6954a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6961abe55efSEd Tanous { 69743b761d0SEd Tanous auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 6981abe55efSEd Tanous if (ec) 6991abe55efSEd Tanous { 700a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 701179db1d7SKowalski, Kamil } 702179db1d7SKowalski, Kamil }; 703179db1d7SKowalski, Kamil 70455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 705179db1d7SKowalski, Kamil std::move(createIpHandler), "xyz.openbmc_project.Network", 706179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 707179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 708179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask, 709179db1d7SKowalski, Kamil gateway); 710179db1d7SKowalski, Kamil } 711e48c0fc5SRavi Teja 712e48c0fc5SRavi Teja /** 713e48c0fc5SRavi Teja * @brief Deletes given IPv6 714e48c0fc5SRavi Teja * 715e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 716e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 717e48c0fc5SRavi Teja * @param[in] ipIdx Index of IP in input array that should be deleted 718e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 719e48c0fc5SRavi Teja * 720e48c0fc5SRavi Teja * @return None 721e48c0fc5SRavi Teja */ 722e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 723e48c0fc5SRavi Teja unsigned int ipIdx, 724e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 725e48c0fc5SRavi Teja { 726e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 727e48c0fc5SRavi Teja [ipIdx, asyncResp](const boost::system::error_code ec) { 728e48c0fc5SRavi Teja if (ec) 729e48c0fc5SRavi Teja { 730e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 731e48c0fc5SRavi Teja } 732e48c0fc5SRavi Teja else 733e48c0fc5SRavi Teja { 734e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"][ipIdx] = 735e48c0fc5SRavi Teja nullptr; 736e48c0fc5SRavi Teja } 737e48c0fc5SRavi Teja }, 738e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 739e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 740e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 741e48c0fc5SRavi Teja } 742e48c0fc5SRavi Teja 743e48c0fc5SRavi Teja /** 744e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 745e48c0fc5SRavi Teja * 746e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 747e48c0fc5SRavi Teja * @param[in] ipIdx Index of IP in input array that should be added 748e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 749e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 750e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 751e48c0fc5SRavi Teja * 752e48c0fc5SRavi Teja * @return None 753e48c0fc5SRavi Teja */ 754e48c0fc5SRavi Teja inline void createIPv6(const std::string &ifaceId, unsigned int ipIdx, 755e48c0fc5SRavi Teja uint8_t prefixLength, const std::string &address, 756e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 757e48c0fc5SRavi Teja { 758e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 759e48c0fc5SRavi Teja if (ec) 760e48c0fc5SRavi Teja { 761e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 762e48c0fc5SRavi Teja } 763e48c0fc5SRavi Teja }; 764e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 765e48c0fc5SRavi Teja // does not have assosiated gateway property 766e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 767e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 768e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 769e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 770e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 771e48c0fc5SRavi Teja ""); 772e48c0fc5SRavi Teja } 773e48c0fc5SRavi Teja 7742a133282Smanojkiraneda using GetAllPropertiesType = 7752a133282Smanojkiraneda boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>; 7762a133282Smanojkiraneda 7772a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) 7782a133282Smanojkiraneda { 7792a133282Smanojkiraneda auto getConfig = [asyncResp](const boost::system::error_code error_code, 7802a133282Smanojkiraneda const GetAllPropertiesType &dbus_data) { 7812a133282Smanojkiraneda if (error_code) 7822a133282Smanojkiraneda { 7832a133282Smanojkiraneda BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code; 7842a133282Smanojkiraneda messages::internalError(asyncResp->res); 7852a133282Smanojkiraneda return; 7862a133282Smanojkiraneda } 787fda13ad2SSunitha Harish nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; 7882a133282Smanojkiraneda for (const auto &property : dbus_data) 7892a133282Smanojkiraneda { 7902a133282Smanojkiraneda auto value = 7912a133282Smanojkiraneda sdbusplus::message::variant_ns::get_if<bool>(&property.second); 7922a133282Smanojkiraneda 7932a133282Smanojkiraneda if (value == nullptr) 7942a133282Smanojkiraneda { 7952a133282Smanojkiraneda continue; 7962a133282Smanojkiraneda } 7972a133282Smanojkiraneda if (property.first == "DNSEnabled") 7982a133282Smanojkiraneda { 7992a133282Smanojkiraneda DHCPConfigTypeJson["UseDNSServers"] = *value; 8002a133282Smanojkiraneda } 8012a133282Smanojkiraneda else if (property.first == "HostNameEnabled") 8022a133282Smanojkiraneda { 8032a133282Smanojkiraneda DHCPConfigTypeJson["UseDomainName"] = *value; 8042a133282Smanojkiraneda } 8052a133282Smanojkiraneda else if (property.first == "NTPEnabled") 8062a133282Smanojkiraneda { 8072a133282Smanojkiraneda DHCPConfigTypeJson["UseNTPServers"] = *value; 8082a133282Smanojkiraneda } 8092a133282Smanojkiraneda } 8102a133282Smanojkiraneda }; 8112a133282Smanojkiraneda crow::connections::systemBus->async_method_call( 8122a133282Smanojkiraneda std::move(getConfig), "xyz.openbmc_project.Network", 8132a133282Smanojkiraneda "/xyz/openbmc_project/network/config/dhcp", 8142a133282Smanojkiraneda "org.freedesktop.DBus.Properties", "GetAll", 8152a133282Smanojkiraneda "xyz.openbmc_project.Network.DHCPConfiguration"); 8162a133282Smanojkiraneda } 817179db1d7SKowalski, Kamil 818179db1d7SKowalski, Kamil /** 819179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 820179db1d7SKowalski, Kamil * Object 821179db1d7SKowalski, Kamil * from EntityManager Network Manager 8224a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 823179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 824179db1d7SKowalski, Kamil * into JSON 825179db1d7SKowalski, Kamil */ 826179db1d7SKowalski, Kamil template <typename CallbackFunc> 8274a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8281abe55efSEd Tanous CallbackFunc &&callback) 8291abe55efSEd Tanous { 83055c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8314a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8321abe55efSEd Tanous const boost::system::error_code error_code, 8334a0cb85cSEd Tanous const GetManagedObjects &resp) { 83455c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8354a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 836e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 837e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6StaticData; 838179db1d7SKowalski, Kamil 8391abe55efSEd Tanous if (error_code) 8401abe55efSEd Tanous { 841e48c0fc5SRavi Teja callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData); 842179db1d7SKowalski, Kamil return; 843179db1d7SKowalski, Kamil } 844179db1d7SKowalski, Kamil 8454c9afe43SEd Tanous bool found = 8464a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 8474c9afe43SEd Tanous if (!found) 8484c9afe43SEd Tanous { 849e48c0fc5SRavi Teja callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData); 8504c9afe43SEd Tanous return; 8514c9afe43SEd Tanous } 8524c9afe43SEd Tanous 8534a0cb85cSEd Tanous extractIPData(ethiface_id, resp, ipv4Data); 854179db1d7SKowalski, Kamil // Fix global GW 8551abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 8561abe55efSEd Tanous { 8574a0cb85cSEd Tanous if ((ipv4.linktype == LinkType::Global) && 8584a0cb85cSEd Tanous (ipv4.gateway == "0.0.0.0")) 8591abe55efSEd Tanous { 8604a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 861179db1d7SKowalski, Kamil } 862179db1d7SKowalski, Kamil } 863179db1d7SKowalski, Kamil 864e48c0fc5SRavi Teja extractIPV6Data(ethiface_id, resp, ipv6Data, ipv6StaticData); 8654a0cb85cSEd Tanous // Finally make a callback with usefull data 866e48c0fc5SRavi Teja callback(true, ethData, ipv4Data, ipv6Data, ipv6StaticData); 867179db1d7SKowalski, Kamil }, 868179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 869179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 870179db1d7SKowalski, Kamil }; 871179db1d7SKowalski, Kamil 872179db1d7SKowalski, Kamil /** 8739391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8749391bb9cSRapkiewicz, Pawel * Manager 8751abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8761abe55efSEd Tanous * into JSON. 8779391bb9cSRapkiewicz, Pawel */ 8789391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8791abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 8801abe55efSEd Tanous { 88155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8824a0cb85cSEd Tanous [callback{std::move(callback)}]( 8839391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 8844a0cb85cSEd Tanous GetManagedObjects &resp) { 8851abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8861abe55efSEd Tanous // ethernet interfaces 8874c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 8884a0cb85cSEd Tanous iface_list.reserve(resp.size()); 8891abe55efSEd Tanous if (error_code) 8901abe55efSEd Tanous { 8914a0cb85cSEd Tanous callback(false, iface_list); 8929391bb9cSRapkiewicz, Pawel return; 8939391bb9cSRapkiewicz, Pawel } 8949391bb9cSRapkiewicz, Pawel 8959391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8964a0cb85cSEd Tanous for (const auto &objpath : resp) 8971abe55efSEd Tanous { 8989391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 8994a0cb85cSEd Tanous for (const auto &interface : objpath.second) 9001abe55efSEd Tanous { 9011abe55efSEd Tanous // If interface is 9024a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9034a0cb85cSEd Tanous // what we're looking for. 9049391bb9cSRapkiewicz, Pawel if (interface.first == 9051abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9061abe55efSEd Tanous { 9074a0cb85cSEd Tanous // Cut out everyting until last "/", ... 9084a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9094a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9104a0cb85cSEd Tanous if (last_pos != std::string::npos) 9111abe55efSEd Tanous { 9129391bb9cSRapkiewicz, Pawel // and put it into output vector. 9134c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9149391bb9cSRapkiewicz, Pawel } 9159391bb9cSRapkiewicz, Pawel } 9169391bb9cSRapkiewicz, Pawel } 9179391bb9cSRapkiewicz, Pawel } 918a434f2bdSEd Tanous // Finally make a callback with useful data 9194a0cb85cSEd Tanous callback(true, iface_list); 9209391bb9cSRapkiewicz, Pawel }, 921aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 922aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 9239391bb9cSRapkiewicz, Pawel }; 9249391bb9cSRapkiewicz, Pawel 9259391bb9cSRapkiewicz, Pawel /** 9269391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9279391bb9cSRapkiewicz, Pawel */ 9281abe55efSEd Tanous class EthernetCollection : public Node 9291abe55efSEd Tanous { 9309391bb9cSRapkiewicz, Pawel public: 9314a0cb85cSEd Tanous template <typename CrowApp> 9321abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9334a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9341abe55efSEd Tanous { 935588c3f0dSKowalski, Kamil entityPrivileges = { 936588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 937e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 938e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 939e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 940e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 941e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9429391bb9cSRapkiewicz, Pawel } 9439391bb9cSRapkiewicz, Pawel 9449391bb9cSRapkiewicz, Pawel private: 9459391bb9cSRapkiewicz, Pawel /** 9469391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 9479391bb9cSRapkiewicz, Pawel */ 94855c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 9491abe55efSEd Tanous const std::vector<std::string> ¶ms) override 9501abe55efSEd Tanous { 9510f74e643SEd Tanous res.jsonValue["@odata.type"] = 9520f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9530f74e643SEd Tanous res.jsonValue["@odata.context"] = 9540f74e643SEd Tanous "/redfish/v1/" 9550f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9560f74e643SEd Tanous res.jsonValue["@odata.id"] = 9570f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9580f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 9590f74e643SEd Tanous res.jsonValue["Description"] = 9600f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 9614c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 9624a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 9631abe55efSEd Tanous // preparation 964f12894f8SJason M. Bills getEthernetIfaceList( 9654c9afe43SEd Tanous [asyncResp]( 9664c9afe43SEd Tanous const bool &success, 9674c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 9684a0cb85cSEd Tanous if (!success) 9691abe55efSEd Tanous { 9704c9afe43SEd Tanous messages::internalError(asyncResp->res); 9714a0cb85cSEd Tanous return; 9724a0cb85cSEd Tanous } 9734a0cb85cSEd Tanous 9744c9afe43SEd Tanous nlohmann::json &iface_array = 9754c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 9764a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 977fda13ad2SSunitha Harish std::string tag = "_"; 9784a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 9791abe55efSEd Tanous { 980fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 981fda13ad2SSunitha Harish if (found == std::string::npos) 982fda13ad2SSunitha Harish { 9834a0cb85cSEd Tanous iface_array.push_back( 9844a0cb85cSEd Tanous {{"@odata.id", 9854a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 9864a0cb85cSEd Tanous iface_item}}); 9879391bb9cSRapkiewicz, Pawel } 988fda13ad2SSunitha Harish } 9894a0cb85cSEd Tanous 9904c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 9914c9afe43SEd Tanous iface_array.size(); 9924c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9934a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9949391bb9cSRapkiewicz, Pawel }); 9959391bb9cSRapkiewicz, Pawel } 9969391bb9cSRapkiewicz, Pawel }; 9979391bb9cSRapkiewicz, Pawel 9989391bb9cSRapkiewicz, Pawel /** 9999391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 10009391bb9cSRapkiewicz, Pawel */ 10011abe55efSEd Tanous class EthernetInterface : public Node 10021abe55efSEd Tanous { 10039391bb9cSRapkiewicz, Pawel public: 10049391bb9cSRapkiewicz, Pawel /* 10059391bb9cSRapkiewicz, Pawel * Default Constructor 10069391bb9cSRapkiewicz, Pawel */ 10074a0cb85cSEd Tanous template <typename CrowApp> 10081abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10094a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10101abe55efSEd Tanous std::string()) 10111abe55efSEd Tanous { 1012588c3f0dSKowalski, Kamil entityPrivileges = { 1013588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1014e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1015e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1016e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1017e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1018e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10199391bb9cSRapkiewicz, Pawel } 10209391bb9cSRapkiewicz, Pawel 1021e439f0f8SKowalski, Kamil private: 1022bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10234a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10241abe55efSEd Tanous { 1025bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1026bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1027bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10284a0cb85cSEd Tanous if (ec) 10294a0cb85cSEd Tanous { 1030a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10311abe55efSEd Tanous } 1032bc0bd6e0SEd Tanous }, 1033bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1034bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1035bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1036bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1037abf2add6SEd Tanous std::variant<std::string>(hostname)); 1038588c3f0dSKowalski, Kamil } 1039588c3f0dSKowalski, Kamil 1040d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1041d577665bSRatan Gupta const std::string &macAddress, 1042d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1043d577665bSRatan Gupta { 1044d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1045d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1046d577665bSRatan Gupta if (ec) 1047d577665bSRatan Gupta { 1048d577665bSRatan Gupta messages::internalError(asyncResp->res); 1049d577665bSRatan Gupta return; 1050d577665bSRatan Gupta } 1051d577665bSRatan Gupta asyncResp->res.jsonValue["MACAddress"] = std::move(macAddress); 1052d577665bSRatan Gupta }, 1053d577665bSRatan Gupta "xyz.openbmc_project.Network", 1054d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1055d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1056d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1057d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1058d577665bSRatan Gupta } 1059da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1060da131a9aSJennifer Lee const std::string &propertyName, const bool &value, 1061da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1062da131a9aSJennifer Lee { 1063da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1064da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1065da131a9aSJennifer Lee if (ec) 1066da131a9aSJennifer Lee { 1067da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1068da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1069da131a9aSJennifer Lee return; 1070da131a9aSJennifer Lee } 1071da131a9aSJennifer Lee }, 1072da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1073da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1074da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1075da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1076da131a9aSJennifer Lee std::variant<bool>{value}); 1077da131a9aSJennifer Lee } 1078da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1079da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1080da131a9aSJennifer Lee { 1081da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1082da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1083da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1084da131a9aSJennifer Lee if (ec) 1085da131a9aSJennifer Lee { 1086da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1087da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1088da131a9aSJennifer Lee return; 1089da131a9aSJennifer Lee } 1090da131a9aSJennifer Lee }, 1091da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1092da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1093da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1094da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1095da131a9aSJennifer Lee std::variant<bool>{value}); 1096da131a9aSJennifer Lee } 1097d577665bSRatan Gupta 1098da131a9aSJennifer Lee void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input, 1099da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1100da131a9aSJennifer Lee { 1101da131a9aSJennifer Lee std::optional<bool> dhcpEnabled; 1102da131a9aSJennifer Lee std::optional<bool> useDNSServers; 1103da131a9aSJennifer Lee std::optional<bool> useDomainName; 1104da131a9aSJennifer Lee std::optional<bool> useNTPServers; 1105da131a9aSJennifer Lee 1106da131a9aSJennifer Lee if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled", 1107da131a9aSJennifer Lee dhcpEnabled, "UseDNSServers", useDNSServers, 1108da131a9aSJennifer Lee "UseDomainName", useDomainName, 1109da131a9aSJennifer Lee "UseNTPServers", useNTPServers)) 1110da131a9aSJennifer Lee { 1111da131a9aSJennifer Lee return; 1112da131a9aSJennifer Lee } 1113da131a9aSJennifer Lee 1114da131a9aSJennifer Lee if (dhcpEnabled) 1115da131a9aSJennifer Lee { 1116da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1117da131a9aSJennifer Lee setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp); 1118da131a9aSJennifer Lee } 1119da131a9aSJennifer Lee 1120da131a9aSJennifer Lee if (useDNSServers) 1121da131a9aSJennifer Lee { 1122da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1123da131a9aSJennifer Lee setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp); 1124da131a9aSJennifer Lee } 1125da131a9aSJennifer Lee 1126da131a9aSJennifer Lee if (useDomainName) 1127da131a9aSJennifer Lee { 1128da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1129da131a9aSJennifer Lee setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp); 1130da131a9aSJennifer Lee } 1131da131a9aSJennifer Lee 1132da131a9aSJennifer Lee if (useNTPServers) 1133da131a9aSJennifer Lee { 1134da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1135da131a9aSJennifer Lee setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp); 1136da131a9aSJennifer Lee } 1137da131a9aSJennifer Lee } 11384a0cb85cSEd Tanous void handleIPv4Patch( 1139f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 11404a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data, 11414a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 11421abe55efSEd Tanous { 1143f476acbfSRatan Gupta if (!input.is_array()) 1144f476acbfSRatan Gupta { 1145f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1146f476acbfSRatan Gupta "IPv4Addresses"); 1147f476acbfSRatan Gupta return; 1148f476acbfSRatan Gupta } 1149f476acbfSRatan Gupta 11504a0cb85cSEd Tanous int entryIdx = 0; 11514a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::const_iterator thisData = 11524a0cb85cSEd Tanous ipv4Data.begin(); 1153537174c4SEd Tanous for (nlohmann::json &thisJson : input) 11541abe55efSEd Tanous { 11554a0cb85cSEd Tanous std::string pathString = 1156a08b46ccSJason M. Bills "IPv4Addresses/" + std::to_string(entryIdx); 1157179db1d7SKowalski, Kamil 1158f476acbfSRatan Gupta if (thisJson.is_null()) 1159f476acbfSRatan Gupta { 1160f476acbfSRatan Gupta if (thisData != ipv4Data.end()) 1161f476acbfSRatan Gupta { 1162f476acbfSRatan Gupta deleteIPv4(ifaceId, thisData->id, entryIdx, asyncResp); 1163f476acbfSRatan Gupta thisData++; 1164f476acbfSRatan Gupta } 1165f476acbfSRatan Gupta else 1166f476acbfSRatan Gupta { 1167f476acbfSRatan Gupta messages::propertyValueFormatError( 1168f476acbfSRatan Gupta asyncResp->res, input.dump(), pathString); 1169f476acbfSRatan Gupta return; 1170f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 1171f476acbfSRatan Gupta // list and if unable to update one of the 1172f476acbfSRatan Gupta // list value then should we proceed further or 1173f476acbfSRatan Gupta // break there, would ask in the redfish forum 1174f476acbfSRatan Gupta // till then we stop processing the next list item. 1175f476acbfSRatan Gupta } 1176f476acbfSRatan Gupta entryIdx++; 1177f476acbfSRatan Gupta continue; // not an error as per the redfish spec. 1178f476acbfSRatan Gupta } 1179f476acbfSRatan Gupta 11809474b378SRatan Gupta if (thisJson.empty()) 11819474b378SRatan Gupta { 11829474b378SRatan Gupta if (thisData != ipv4Data.end()) 11839474b378SRatan Gupta { 11849474b378SRatan Gupta thisData++; 11859474b378SRatan Gupta } 11869474b378SRatan Gupta else 11879474b378SRatan Gupta { 11889474b378SRatan Gupta messages::propertyMissing(asyncResp->res, 11899474b378SRatan Gupta pathString + "/Address"); 11909474b378SRatan Gupta return; 1191f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 11929474b378SRatan Gupta // list and if unable to update one of the 11939474b378SRatan Gupta // list value then should we proceed further or 11949474b378SRatan Gupta // break there, would ask in the redfish forum 11959474b378SRatan Gupta // till then we stop processing the next list item. 11969474b378SRatan Gupta } 11979474b378SRatan Gupta entryIdx++; 11989474b378SRatan Gupta continue; // not an error as per the redfish spec. 11999474b378SRatan Gupta } 12009474b378SRatan Gupta 1201537174c4SEd Tanous std::optional<std::string> address; 1202537174c4SEd Tanous std::optional<std::string> subnetMask; 1203537174c4SEd Tanous std::optional<std::string> gateway; 1204537174c4SEd Tanous 1205537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1206*7e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 1207*7e27d832SJohnathan Mantey "Gateway", gateway)) 1208537174c4SEd Tanous { 1209537174c4SEd Tanous return; 1210179db1d7SKowalski, Kamil } 1211179db1d7SKowalski, Kamil 1212537174c4SEd Tanous if (address) 12131abe55efSEd Tanous { 1214537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*address)) 12151abe55efSEd Tanous { 1216537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 12174a0cb85cSEd Tanous pathString + "/Address"); 1218537174c4SEd Tanous return; 12194a0cb85cSEd Tanous } 12204a0cb85cSEd Tanous } 12214a0cb85cSEd Tanous 1222537174c4SEd Tanous uint8_t prefixLength = 0; 1223537174c4SEd Tanous if (subnetMask) 12244a0cb85cSEd Tanous { 1225537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 12264a0cb85cSEd Tanous { 1227f12894f8SJason M. Bills messages::propertyValueFormatError( 1228537174c4SEd Tanous asyncResp->res, *subnetMask, 12294a0cb85cSEd Tanous pathString + "/SubnetMask"); 1230537174c4SEd Tanous return; 12314a0cb85cSEd Tanous } 12324a0cb85cSEd Tanous } 12334a0cb85cSEd Tanous 1234537174c4SEd Tanous if (gateway) 12354a0cb85cSEd Tanous { 1236537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*gateway)) 12374a0cb85cSEd Tanous { 1238537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1239537174c4SEd Tanous pathString + "/Gateway"); 1240537174c4SEd Tanous return; 12414a0cb85cSEd Tanous } 12424a0cb85cSEd Tanous } 12434a0cb85cSEd Tanous 1244f476acbfSRatan Gupta // if IP address exist then modify it. 12454a0cb85cSEd Tanous if (thisData != ipv4Data.end()) 12464a0cb85cSEd Tanous { 1247179db1d7SKowalski, Kamil // Apply changes 1248537174c4SEd Tanous if (address) 12491abe55efSEd Tanous { 1250f476acbfSRatan Gupta auto callback = [asyncResp, entryIdx, 1251f476acbfSRatan Gupta address{std::string(*address)}]( 12524a0cb85cSEd Tanous const boost::system::error_code ec) { 12534a0cb85cSEd Tanous if (ec) 12541abe55efSEd Tanous { 1255a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12564a0cb85cSEd Tanous return; 12574a0cb85cSEd Tanous } 1258f476acbfSRatan Gupta asyncResp->res 1259f476acbfSRatan Gupta .jsonValue["IPv4Addresses"][entryIdx]["Address"] = 1260f476acbfSRatan Gupta std::move(address); 12614a0cb85cSEd Tanous }; 12624a0cb85cSEd Tanous 12634a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12644a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1265f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1266f476acbfSRatan Gupta thisData->id, 12674a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12684a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Address", 1269537174c4SEd Tanous std::variant<std::string>(*address)); 1270179db1d7SKowalski, Kamil } 1271179db1d7SKowalski, Kamil 1272537174c4SEd Tanous if (subnetMask) 12731abe55efSEd Tanous { 12744a0cb85cSEd Tanous changeIPv4SubnetMaskProperty(ifaceId, entryIdx, 1275537174c4SEd Tanous thisData->id, *subnetMask, 1276537174c4SEd Tanous prefixLength, asyncResp); 1277179db1d7SKowalski, Kamil } 1278179db1d7SKowalski, Kamil 1279537174c4SEd Tanous if (gateway) 12801abe55efSEd Tanous { 1281f476acbfSRatan Gupta auto callback = [asyncResp, entryIdx, 1282537174c4SEd Tanous gateway{std::string(*gateway)}]( 12834a0cb85cSEd Tanous const boost::system::error_code ec) { 12844a0cb85cSEd Tanous if (ec) 12851abe55efSEd Tanous { 1286a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12874a0cb85cSEd Tanous return; 12884a0cb85cSEd Tanous } 1289f476acbfSRatan Gupta asyncResp->res 1290f476acbfSRatan Gupta .jsonValue["IPv4Addresses"][entryIdx]["Gateway"] = 1291537174c4SEd Tanous std::move(gateway); 12924a0cb85cSEd Tanous }; 12934a0cb85cSEd Tanous 12944a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12954a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1296f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1297f476acbfSRatan Gupta thisData->id, 12984a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12994a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Gateway", 1300537174c4SEd Tanous std::variant<std::string>(*gateway)); 13014a0cb85cSEd Tanous } 1302f476acbfSRatan Gupta 13034a0cb85cSEd Tanous thisData++; 13041abe55efSEd Tanous } 13051abe55efSEd Tanous else 13061abe55efSEd Tanous { 13074a0cb85cSEd Tanous // Create IPv4 with provided data 1308537174c4SEd Tanous if (!gateway) 13091abe55efSEd Tanous { 1310a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13114a0cb85cSEd Tanous pathString + "/Gateway"); 13124a0cb85cSEd Tanous continue; 13134a0cb85cSEd Tanous } 13144a0cb85cSEd Tanous 1315537174c4SEd Tanous if (!address) 13161abe55efSEd Tanous { 1317a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13184a0cb85cSEd Tanous pathString + "/Address"); 13194a0cb85cSEd Tanous continue; 13204a0cb85cSEd Tanous } 13214a0cb85cSEd Tanous 1322537174c4SEd Tanous if (!subnetMask) 13231abe55efSEd Tanous { 1324a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13254a0cb85cSEd Tanous pathString + "/SubnetMask"); 13264a0cb85cSEd Tanous continue; 1327588c3f0dSKowalski, Kamil } 1328588c3f0dSKowalski, Kamil 1329b01bf299SEd Tanous createIPv4(ifaceId, entryIdx, prefixLength, *gateway, *address, 1330b01bf299SEd Tanous asyncResp); 133195897b20SRatan Gupta 133295897b20SRatan Gupta nlohmann::json &ipv4AddressJson = 133395897b20SRatan Gupta asyncResp->res.jsonValue["IPv4Addresses"][entryIdx]; 133495897b20SRatan Gupta ipv4AddressJson["Address"] = *address; 133595897b20SRatan Gupta ipv4AddressJson["SubnetMask"] = *subnetMask; 133695897b20SRatan Gupta ipv4AddressJson["Gateway"] = *gateway; 13374a0cb85cSEd Tanous } 13384a0cb85cSEd Tanous entryIdx++; 13394a0cb85cSEd Tanous } 13404a0cb85cSEd Tanous } 13414a0cb85cSEd Tanous 1342f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1343f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1344f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1345f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1346f85837bfSRAJESWARAN THILLAIGOVINDAN { 1347f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1348f85837bfSRAJESWARAN THILLAIGOVINDAN [asyncResp, 1349f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers](const boost::system::error_code ec) { 1350f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1351f85837bfSRAJESWARAN THILLAIGOVINDAN { 1352f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1353f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1354f85837bfSRAJESWARAN THILLAIGOVINDAN } 1355f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp->res.jsonValue["NameServers"] = 1356f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers; 1357f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp->res.jsonValue["StaticNameServers"] = 1358f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers; 1359f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1360f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1361f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1362f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1363f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1364f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1365f85837bfSRAJESWARAN THILLAIGOVINDAN } 1366f85837bfSRAJESWARAN THILLAIGOVINDAN 1367e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1368e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 1369e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData, 1370e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1371e48c0fc5SRavi Teja { 1372e48c0fc5SRavi Teja if (!input.is_array()) 1373e48c0fc5SRavi Teja { 1374e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1375e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1376e48c0fc5SRavi Teja return; 1377e48c0fc5SRavi Teja } 1378e48c0fc5SRavi Teja 1379e48c0fc5SRavi Teja int entryIdx = 0; 1380e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::const_iterator thisData = 1381e48c0fc5SRavi Teja ipv6StaticData.begin(); 1382e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1383e48c0fc5SRavi Teja { 1384e48c0fc5SRavi Teja std::string pathString = 1385e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1386e48c0fc5SRavi Teja 1387e48c0fc5SRavi Teja if (thisJson.is_null()) 1388e48c0fc5SRavi Teja { 1389e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1390e48c0fc5SRavi Teja { 1391e48c0fc5SRavi Teja deleteIPv6(ifaceId, thisData->id, entryIdx, asyncResp); 1392e48c0fc5SRavi Teja thisData++; 1393e48c0fc5SRavi Teja } 1394e48c0fc5SRavi Teja else 1395e48c0fc5SRavi Teja { 1396e48c0fc5SRavi Teja messages::propertyValueFormatError( 1397e48c0fc5SRavi Teja asyncResp->res, input.dump(), pathString); 1398e48c0fc5SRavi Teja return; 1399e48c0fc5SRavi Teja } 1400e48c0fc5SRavi Teja entryIdx++; 1401e48c0fc5SRavi Teja continue; 1402e48c0fc5SRavi Teja } 1403e48c0fc5SRavi Teja 1404e48c0fc5SRavi Teja if (thisJson.empty()) 1405e48c0fc5SRavi Teja { 1406e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1407e48c0fc5SRavi Teja { 1408e48c0fc5SRavi Teja thisData++; 1409e48c0fc5SRavi Teja } 1410e48c0fc5SRavi Teja else 1411e48c0fc5SRavi Teja { 1412e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1413e48c0fc5SRavi Teja pathString + "/Address"); 1414e48c0fc5SRavi Teja return; 1415e48c0fc5SRavi Teja } 1416e48c0fc5SRavi Teja entryIdx++; 1417e48c0fc5SRavi Teja continue; 1418e48c0fc5SRavi Teja } 1419e48c0fc5SRavi Teja 1420e48c0fc5SRavi Teja std::optional<std::string> address; 1421e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1422e48c0fc5SRavi Teja 1423e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1424e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1425e48c0fc5SRavi Teja { 1426e48c0fc5SRavi Teja return; 1427e48c0fc5SRavi Teja } 1428e48c0fc5SRavi Teja 1429e48c0fc5SRavi Teja // if IP address exist then modify it. 1430e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1431e48c0fc5SRavi Teja { 1432e48c0fc5SRavi Teja // Apply changes 1433e48c0fc5SRavi Teja if (address) 1434e48c0fc5SRavi Teja { 1435e48c0fc5SRavi Teja auto callback = [asyncResp, entryIdx, 1436e48c0fc5SRavi Teja address{std::string(*address)}]( 1437e48c0fc5SRavi Teja const boost::system::error_code ec) { 1438e48c0fc5SRavi Teja if (ec) 1439e48c0fc5SRavi Teja { 1440e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1441e48c0fc5SRavi Teja return; 1442e48c0fc5SRavi Teja } 1443e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"] 1444e48c0fc5SRavi Teja [entryIdx]["Address"] = 1445e48c0fc5SRavi Teja std::move(address); 1446e48c0fc5SRavi Teja }; 1447e48c0fc5SRavi Teja 1448e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1449e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1450e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1451e48c0fc5SRavi Teja thisData->id, 1452e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1453e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "Address", 1454e48c0fc5SRavi Teja std::variant<std::string>(*address)); 1455e48c0fc5SRavi Teja } 1456e48c0fc5SRavi Teja 1457e48c0fc5SRavi Teja if (prefixLength) 1458e48c0fc5SRavi Teja { 1459e48c0fc5SRavi Teja auto callback = [asyncResp, entryIdx, 1460e48c0fc5SRavi Teja prefixLength{uint8_t(*prefixLength)}]( 1461e48c0fc5SRavi Teja const boost::system::error_code ec) { 1462e48c0fc5SRavi Teja if (ec) 1463e48c0fc5SRavi Teja { 1464e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1465e48c0fc5SRavi Teja return; 1466e48c0fc5SRavi Teja } 1467e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"] 1468e48c0fc5SRavi Teja [entryIdx]["PrefixLength"] = 1469e48c0fc5SRavi Teja std::move(prefixLength); 1470e48c0fc5SRavi Teja }; 1471e48c0fc5SRavi Teja 1472e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1473e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1474e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1475e48c0fc5SRavi Teja thisData->id, 1476e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1477e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "PrefixLength", 1478e48c0fc5SRavi Teja std::variant<uint8_t>(*prefixLength)); 1479e48c0fc5SRavi Teja } 1480e48c0fc5SRavi Teja 1481e48c0fc5SRavi Teja thisData++; 1482e48c0fc5SRavi Teja } 1483e48c0fc5SRavi Teja else 1484e48c0fc5SRavi Teja { 1485e48c0fc5SRavi Teja // Create IPv6 with provided data 1486e48c0fc5SRavi Teja 1487e48c0fc5SRavi Teja if (!prefixLength) 1488e48c0fc5SRavi Teja { 1489e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1490e48c0fc5SRavi Teja pathString + "/PrefixLength"); 1491e48c0fc5SRavi Teja continue; 1492e48c0fc5SRavi Teja } 1493e48c0fc5SRavi Teja 1494e48c0fc5SRavi Teja if (!address) 1495e48c0fc5SRavi Teja { 1496e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1497e48c0fc5SRavi Teja pathString + "/Address"); 1498e48c0fc5SRavi Teja continue; 1499e48c0fc5SRavi Teja } 1500e48c0fc5SRavi Teja 1501e48c0fc5SRavi Teja createIPv6(ifaceId, entryIdx, *prefixLength, *address, 1502e48c0fc5SRavi Teja asyncResp); 1503e48c0fc5SRavi Teja 1504e48c0fc5SRavi Teja nlohmann::json &ipv6StaticAddressJson = 1505e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"][entryIdx]; 1506e48c0fc5SRavi Teja ipv6StaticAddressJson["Address"] = *address; 1507e48c0fc5SRavi Teja ipv6StaticAddressJson["PrefixLength"] = *prefixLength; 1508e48c0fc5SRavi Teja } 1509e48c0fc5SRavi Teja entryIdx++; 1510e48c0fc5SRavi Teja } 1511e48c0fc5SRavi Teja } 1512e48c0fc5SRavi Teja 15130f74e643SEd Tanous void parseInterfaceData( 15140f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 15150f74e643SEd Tanous const EthernetInterfaceData ðData, 1516e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1517e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1518e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 15194a0cb85cSEd Tanous { 15204a0cb85cSEd Tanous json_response["Id"] = iface_id; 15214a0cb85cSEd Tanous json_response["@odata.id"] = 15224a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1523029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1524029573d4SEd Tanous if (ethData.speed == 0) 1525029573d4SEd Tanous { 1526029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1527029573d4SEd Tanous json_response["Status"] = { 1528029573d4SEd Tanous {"Health", "OK"}, 1529029573d4SEd Tanous {"State", "Disabled"}, 1530029573d4SEd Tanous }; 1531029573d4SEd Tanous } 1532029573d4SEd Tanous else 1533029573d4SEd Tanous { 1534029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1535029573d4SEd Tanous json_response["Status"] = { 1536029573d4SEd Tanous {"Health", "OK"}, 1537029573d4SEd Tanous {"State", "Enabled"}, 1538029573d4SEd Tanous }; 1539029573d4SEd Tanous } 15404a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 15414a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1542fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 15432a133282Smanojkiraneda 15444a0cb85cSEd Tanous if (!ethData.hostname.empty()) 15454a0cb85cSEd Tanous { 15464a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 15474a0cb85cSEd Tanous } 15484a0cb85cSEd Tanous 1549fda13ad2SSunitha Harish json_response["VLANs"] = { 1550fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1551fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1552fda13ad2SSunitha Harish 1553029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 1554f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 15554a0cb85cSEd Tanous 15564a0cb85cSEd Tanous if (ipv4Data.size() > 0) 15574a0cb85cSEd Tanous { 15584a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 15594a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 15604a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 15614a0cb85cSEd Tanous { 1562fa5053a6SGunnar Mills 1563fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1564fa5053a6SGunnar Mills if (gatewayStr.empty()) 1565fa5053a6SGunnar Mills { 1566fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1567fa5053a6SGunnar Mills } 1568fa5053a6SGunnar Mills 15694a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 15704a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1571029573d4SEd Tanous {"Address", ipv4_config.address}, 1572fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 15734a0cb85cSEd Tanous } 15744a0cb85cSEd Tanous } 15759a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1576e48c0fc5SRavi Teja 1577e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 1578e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 1579e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1580e48c0fc5SRavi Teja { 1581e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1582e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1583e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 1584e48c0fc5SRavi Teja } 1585e48c0fc5SRavi Teja 1586e48c0fc5SRavi Teja nlohmann::json &ipv6_static_array = 1587e48c0fc5SRavi Teja json_response["IPv6StaticAddresses"]; 1588e48c0fc5SRavi Teja ipv6_static_array = nlohmann::json::array(); 1589e48c0fc5SRavi Teja for (auto &ipv6_static_config : ipv6StaticData) 1590e48c0fc5SRavi Teja { 1591e48c0fc5SRavi Teja ipv6_static_array.push_back( 1592e48c0fc5SRavi Teja {{"Address", ipv6_static_config.address}, 1593e48c0fc5SRavi Teja {"PrefixLength", ipv6_static_config.prefixLength}}); 1594e48c0fc5SRavi Teja } 1595588c3f0dSKowalski, Kamil } 1596588c3f0dSKowalski, Kamil 15979391bb9cSRapkiewicz, Pawel /** 15989391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 15999391bb9cSRapkiewicz, Pawel */ 160055c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 16011abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16021abe55efSEd Tanous { 16034a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16041abe55efSEd Tanous if (params.size() != 1) 16051abe55efSEd Tanous { 1606f12894f8SJason M. Bills messages::internalError(asyncResp->res); 16079391bb9cSRapkiewicz, Pawel return; 16089391bb9cSRapkiewicz, Pawel } 16099391bb9cSRapkiewicz, Pawel 16104a0cb85cSEd Tanous getEthernetIfaceData( 16114a0cb85cSEd Tanous params[0], 16124a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 16134a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1614e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1615e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1616e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1617e48c0fc5SRavi Teja &ipv6StaticData) { 16184a0cb85cSEd Tanous if (!success) 16191abe55efSEd Tanous { 16201abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16211abe55efSEd Tanous // object, and other errors 1622f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1623f12894f8SJason M. Bills "EthernetInterface", iface_id); 16244a0cb85cSEd Tanous return; 16259391bb9cSRapkiewicz, Pawel } 16264c9afe43SEd Tanous 16274c9afe43SEd Tanous // because this has no dependence on the interface at this 16284c9afe43SEd Tanous // point, it needs to be done after we know the interface 16294c9afe43SEd Tanous // exists, not before. 16304c9afe43SEd Tanous getDHCPConfigData(asyncResp); 16314c9afe43SEd Tanous 16320f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1633fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 16340f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 16350f74e643SEd Tanous "/redfish/v1/$metadata#EthernetInterface.EthernetInterface"; 16360f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 16370f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 16380f74e643SEd Tanous "Management Network Interface"; 16390f74e643SEd Tanous 16400f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1641e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 16429391bb9cSRapkiewicz, Pawel }); 16439391bb9cSRapkiewicz, Pawel } 16449391bb9cSRapkiewicz, Pawel 164555c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 16461abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16471abe55efSEd Tanous { 16484a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16491abe55efSEd Tanous if (params.size() != 1) 16501abe55efSEd Tanous { 1651f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1652588c3f0dSKowalski, Kamil return; 1653588c3f0dSKowalski, Kamil } 1654588c3f0dSKowalski, Kamil 16554a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1656588c3f0dSKowalski, Kamil 1657bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1658d577665bSRatan Gupta std::optional<std::string> macAddress; 16599a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1660f476acbfSRatan Gupta std::optional<nlohmann::json> ipv4Addresses; 1661f476acbfSRatan Gupta std::optional<nlohmann::json> ipv6Addresses; 1662e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1663f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 16645112e9b4SRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> nameServers; 1665da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 16660627a2c7SEd Tanous 1667fda13ad2SSunitha Harish if (!json_util::readJson( 1668fda13ad2SSunitha Harish req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses, 16696ca6ac12SJohnathan Mantey "MACAddress", macAddress, "StaticNameServers", 16706ca6ac12SJohnathan Mantey staticNameServers, "IPv6DefaultGateway", ipv6DefaultGateway, 16716ca6ac12SJohnathan Mantey "IPv6StaticAddresses", ipv6StaticAddresses, "NameServers", 16726ca6ac12SJohnathan Mantey nameServers, "DHCPv4", dhcpv4)) 16731abe55efSEd Tanous { 1674588c3f0dSKowalski, Kamil return; 1675588c3f0dSKowalski, Kamil } 1676f15aad37SRatan Gupta 1677da131a9aSJennifer Lee if (dhcpv4) 1678da131a9aSJennifer Lee { 1679da131a9aSJennifer Lee handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp); 1680da131a9aSJennifer Lee } 1681da131a9aSJennifer Lee 16824a0cb85cSEd Tanous // Get single eth interface data, and call the below callback for JSON 1683588c3f0dSKowalski, Kamil // preparation 16844a0cb85cSEd Tanous getEthernetIfaceData( 16854a0cb85cSEd Tanous iface_id, 1686fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1687fda13ad2SSunitha Harish macAddress = std::move(macAddress), 16880627a2c7SEd Tanous ipv4Addresses = std::move(ipv4Addresses), 16899a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1690e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 16915112e9b4SRAJESWARAN THILLAIGOVINDAN staticNameServers = std::move(staticNameServers), 16925112e9b4SRAJESWARAN THILLAIGOVINDAN nameServers = std::move(nameServers)]( 16934a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1694e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1695e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1696e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1697e48c0fc5SRavi Teja &ipv6StaticData) { 16981abe55efSEd Tanous if (!success) 16991abe55efSEd Tanous { 1700588c3f0dSKowalski, Kamil // ... otherwise return error 17011abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 17021abe55efSEd Tanous // object, and other errors 1703fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1704fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1705588c3f0dSKowalski, Kamil return; 1706588c3f0dSKowalski, Kamil } 1707588c3f0dSKowalski, Kamil 17080f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1709e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 1710588c3f0dSKowalski, Kamil 17110627a2c7SEd Tanous if (hostname) 17121abe55efSEd Tanous { 17130627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 17141abe55efSEd Tanous } 17150627a2c7SEd Tanous 1716d577665bSRatan Gupta if (macAddress) 1717d577665bSRatan Gupta { 1718d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1719d577665bSRatan Gupta } 1720d577665bSRatan Gupta 17210627a2c7SEd Tanous if (ipv4Addresses) 17221abe55efSEd Tanous { 1723537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 1724537174c4SEd Tanous // above is returning a const value, not a non-const value. 1725537174c4SEd Tanous // This doesn't really work for us, as we need to be able to 1726537174c4SEd Tanous // efficiently move out the intermedia nlohmann::json 1727537174c4SEd Tanous // objects. This makes a copy of the structure, and operates 1728537174c4SEd Tanous // on that, but could be done more efficiently 1729f476acbfSRatan Gupta nlohmann::json ipv4 = std::move(*ipv4Addresses); 1730537174c4SEd Tanous handleIPv4Patch(iface_id, ipv4, ipv4Data, asyncResp); 17311abe55efSEd Tanous } 17320627a2c7SEd Tanous 17335112e9b4SRAJESWARAN THILLAIGOVINDAN if (nameServers) 17345112e9b4SRAJESWARAN THILLAIGOVINDAN { 17355112e9b4SRAJESWARAN THILLAIGOVINDAN // Data.Permissions is read-only 17365112e9b4SRAJESWARAN THILLAIGOVINDAN messages::propertyNotWritable(asyncResp->res, 17375112e9b4SRAJESWARAN THILLAIGOVINDAN "NameServers"); 17385112e9b4SRAJESWARAN THILLAIGOVINDAN } 17395112e9b4SRAJESWARAN THILLAIGOVINDAN 1740f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1741f85837bfSRAJESWARAN THILLAIGOVINDAN { 1742f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1743f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1744f85837bfSRAJESWARAN THILLAIGOVINDAN } 17459a6fc6feSRavi Teja 17469a6fc6feSRavi Teja if (ipv6DefaultGateway) 17479a6fc6feSRavi Teja { 17489a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 17499a6fc6feSRavi Teja "IPv6DefaultGateway"); 17509a6fc6feSRavi Teja } 1751e48c0fc5SRavi Teja 1752e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1753e48c0fc5SRavi Teja { 1754e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1755e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 1756e48c0fc5SRavi Teja ipv6StaticData, asyncResp); 1757e48c0fc5SRavi Teja 1758e48c0fc5SRavi Teja // call getEthernetIfaceData to populate updated static 1759e48c0fc5SRavi Teja // addresses data to "IPv6Addresses" json collection 1760e48c0fc5SRavi Teja getEthernetIfaceData( 1761e48c0fc5SRavi Teja iface_id, 1762e48c0fc5SRavi Teja [this, asyncResp, iface_id]( 1763e48c0fc5SRavi Teja const bool &success, 1764e48c0fc5SRavi Teja const EthernetInterfaceData ðData, 1765e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> 1766e48c0fc5SRavi Teja &ipv4Data, 1767e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1768e48c0fc5SRavi Teja &ipv6Data, 1769e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1770e48c0fc5SRavi Teja &ipv6StaticData) { 1771e48c0fc5SRavi Teja if (!success) 1772e48c0fc5SRavi Teja { 1773e48c0fc5SRavi Teja messages::resourceNotFound(asyncResp->res, 1774e48c0fc5SRavi Teja "Ethernet Interface", 1775e48c0fc5SRavi Teja iface_id); 1776e48c0fc5SRavi Teja return; 1777e48c0fc5SRavi Teja } 1778e48c0fc5SRavi Teja 1779e48c0fc5SRavi Teja parseInterfaceData(asyncResp->res.jsonValue, 1780e48c0fc5SRavi Teja iface_id, ethData, ipv4Data, 1781e48c0fc5SRavi Teja ipv6Data, ipv6StaticData); 1782e48c0fc5SRavi Teja }); 1783e48c0fc5SRavi Teja } 1784588c3f0dSKowalski, Kamil }); 1785588c3f0dSKowalski, Kamil } 17869391bb9cSRapkiewicz, Pawel }; 17879391bb9cSRapkiewicz, Pawel 1788e439f0f8SKowalski, Kamil /** 17894a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 17904a0cb85cSEd Tanous * Schema 1791e439f0f8SKowalski, Kamil */ 17921abe55efSEd Tanous class VlanNetworkInterface : public Node 17931abe55efSEd Tanous { 1794e439f0f8SKowalski, Kamil public: 1795e439f0f8SKowalski, Kamil /* 1796e439f0f8SKowalski, Kamil * Default Constructor 1797e439f0f8SKowalski, Kamil */ 1798e439f0f8SKowalski, Kamil template <typename CrowApp> 17991abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 18004a0cb85cSEd Tanous Node(app, 18010f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 18021abe55efSEd Tanous std::string(), std::string()) 18031abe55efSEd Tanous { 1804e439f0f8SKowalski, Kamil entityPrivileges = { 1805e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1806e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1807e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1808e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1809e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1810e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1811e439f0f8SKowalski, Kamil } 1812e439f0f8SKowalski, Kamil 1813e439f0f8SKowalski, Kamil private: 18140f74e643SEd Tanous void parseInterfaceData( 18150f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 18160f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1817e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1818e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1819e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 18201abe55efSEd Tanous { 1821e439f0f8SKowalski, Kamil // Fill out obvious data... 18224a0cb85cSEd Tanous json_response["Id"] = iface_id; 18234a0cb85cSEd Tanous json_response["@odata.id"] = 18244a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 18254a0cb85cSEd Tanous "/VLANs/" + iface_id; 1826e439f0f8SKowalski, Kamil 18274a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1828fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 18294a0cb85cSEd Tanous { 1830fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 18314a0cb85cSEd Tanous } 1832e439f0f8SKowalski, Kamil } 1833e439f0f8SKowalski, Kamil 1834fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 18351abe55efSEd Tanous { 18361abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 18371abe55efSEd Tanous { 1838927a505aSKowalski, Kamil return false; 18391abe55efSEd Tanous } 18401abe55efSEd Tanous else 18411abe55efSEd Tanous { 1842927a505aSKowalski, Kamil return true; 1843927a505aSKowalski, Kamil } 1844927a505aSKowalski, Kamil } 1845927a505aSKowalski, Kamil 1846e439f0f8SKowalski, Kamil /** 1847e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1848e439f0f8SKowalski, Kamil */ 184955c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 18501abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18511abe55efSEd Tanous { 18524a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18534a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1854e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1855e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1856e439f0f8SKowalski, Kamil // impossible. 18571abe55efSEd Tanous if (params.size() != 2) 18581abe55efSEd Tanous { 1859f12894f8SJason M. Bills messages::internalError(res); 1860e439f0f8SKowalski, Kamil res.end(); 1861e439f0f8SKowalski, Kamil return; 1862e439f0f8SKowalski, Kamil } 1863e439f0f8SKowalski, Kamil 18644a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 18654a0cb85cSEd Tanous const std::string &iface_id = params[1]; 18660f74e643SEd Tanous res.jsonValue["@odata.type"] = 18670f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 18680f74e643SEd Tanous res.jsonValue["@odata.context"] = 18690f74e643SEd Tanous "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface"; 18700f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1871e439f0f8SKowalski, Kamil 1872fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 18731abe55efSEd Tanous { 1874a434f2bdSEd Tanous return; 1875a434f2bdSEd Tanous } 1876a434f2bdSEd Tanous 1877e439f0f8SKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1878e439f0f8SKowalski, Kamil // preparation 18794a0cb85cSEd Tanous getEthernetIfaceData( 1880fda13ad2SSunitha Harish params[1], 1881fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1882fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 18834a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1884e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1885e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1886e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1887e48c0fc5SRavi Teja &ipv6StaticData) { 1888fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 18891abe55efSEd Tanous { 18900f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 18910f74e643SEd Tanous parent_iface_id, iface_id, ethData, 1892e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 18931abe55efSEd Tanous } 18941abe55efSEd Tanous else 18951abe55efSEd Tanous { 1896e439f0f8SKowalski, Kamil // ... otherwise return error 18971abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18981abe55efSEd Tanous // object, and other errors 1899f12894f8SJason M. Bills messages::resourceNotFound( 1900f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1901e439f0f8SKowalski, Kamil } 1902e439f0f8SKowalski, Kamil }); 1903e439f0f8SKowalski, Kamil } 1904e439f0f8SKowalski, Kamil 190555c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 19061abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19071abe55efSEd Tanous { 19084a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19091abe55efSEd Tanous if (params.size() != 2) 19101abe55efSEd Tanous { 1911f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1912e439f0f8SKowalski, Kamil return; 1913e439f0f8SKowalski, Kamil } 1914e439f0f8SKowalski, Kamil 1915d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 191655c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1917927a505aSKowalski, Kamil 1918fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19191abe55efSEd Tanous { 1920fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1921fda13ad2SSunitha Harish ifaceId); 1922927a505aSKowalski, Kamil return; 1923927a505aSKowalski, Kamil } 1924927a505aSKowalski, Kamil 19250627a2c7SEd Tanous bool vlanEnable = false; 19260627a2c7SEd Tanous uint64_t vlanId = 0; 19270627a2c7SEd Tanous 19280627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 19290627a2c7SEd Tanous vlanId)) 19301abe55efSEd Tanous { 1931927a505aSKowalski, Kamil return; 1932927a505aSKowalski, Kamil } 1933927a505aSKowalski, Kamil 1934927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1935927a505aSKowalski, Kamil // preparation 1936e48c0fc5SRavi Teja getEthernetIfaceData( 1937e48c0fc5SRavi Teja params[1], 1938e48c0fc5SRavi Teja [this, asyncResp, parentIfaceId{std::string(params[0])}, 1939e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 1940e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 1941e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1942e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1943e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1944e48c0fc5SRavi Teja &ipv6StaticData) { 194508244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 194608244d02SSunitha Harish { 194708244d02SSunitha Harish parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId, 1948e48c0fc5SRavi Teja ifaceId, ethData, ipv4Data, ipv6Data, 1949e48c0fc5SRavi Teja ipv6StaticData); 195008244d02SSunitha Harish auto callback = 195108244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 195208244d02SSunitha Harish if (ec) 195308244d02SSunitha Harish { 195408244d02SSunitha Harish messages::internalError(asyncResp->res); 195508244d02SSunitha Harish } 195608244d02SSunitha Harish }; 195708244d02SSunitha Harish 195808244d02SSunitha Harish if (vlanEnable == true) 195908244d02SSunitha Harish { 196008244d02SSunitha Harish crow::connections::systemBus->async_method_call( 196108244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 196208244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 196308244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 196408244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 196508244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 196608244d02SSunitha Harish } 196708244d02SSunitha Harish else 196808244d02SSunitha Harish { 1969e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 1970e48c0fc5SRavi Teja "vlan interface"; 197108244d02SSunitha Harish crow::connections::systemBus->async_method_call( 197208244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 1973e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 1974e48c0fc5SRavi Teja ifaceId, 197508244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 197608244d02SSunitha Harish } 197708244d02SSunitha Harish } 197808244d02SSunitha Harish else 19791abe55efSEd Tanous { 19801abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 19811abe55efSEd Tanous // object, and other errors 1982e48c0fc5SRavi Teja messages::resourceNotFound( 1983e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 1984927a505aSKowalski, Kamil return; 1985927a505aSKowalski, Kamil } 1986927a505aSKowalski, Kamil }); 1987e439f0f8SKowalski, Kamil } 1988e439f0f8SKowalski, Kamil 198955c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 19901abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19911abe55efSEd Tanous { 19924a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19931abe55efSEd Tanous if (params.size() != 2) 19941abe55efSEd Tanous { 1995f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1996e439f0f8SKowalski, Kamil return; 1997e439f0f8SKowalski, Kamil } 1998e439f0f8SKowalski, Kamil 1999d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 200055c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2001927a505aSKowalski, Kamil 2002fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 20031abe55efSEd Tanous { 2004fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2005fda13ad2SSunitha Harish ifaceId); 2006927a505aSKowalski, Kamil return; 2007927a505aSKowalski, Kamil } 2008927a505aSKowalski, Kamil 2009927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 2010927a505aSKowalski, Kamil // preparation 2011f12894f8SJason M. Bills getEthernetIfaceData( 2012fda13ad2SSunitha Harish params[1], 2013fda13ad2SSunitha Harish [this, asyncResp, parentIfaceId{std::string(params[0])}, 2014fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 2015f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 2016e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 2017e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 2018e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 2019e48c0fc5SRavi Teja &ipv6StaticData) { 2020fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 20211abe55efSEd Tanous { 20220f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId, 2023e48c0fc5SRavi Teja ifaceId, ethData, ipv4Data, ipv6Data, 2024e48c0fc5SRavi Teja ipv6StaticData); 2025927a505aSKowalski, Kamil 2026f12894f8SJason M. Bills auto callback = 2027f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 20281abe55efSEd Tanous if (ec) 20291abe55efSEd Tanous { 2030f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2031927a505aSKowalski, Kamil } 20324a0cb85cSEd Tanous }; 20334a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 20344a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 20354a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 20364a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 20371abe55efSEd Tanous } 20381abe55efSEd Tanous else 20391abe55efSEd Tanous { 2040927a505aSKowalski, Kamil // ... otherwise return error 2041f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 2042f12894f8SJason M. Bills // object, and other errors 2043f12894f8SJason M. Bills messages::resourceNotFound( 2044f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 2045927a505aSKowalski, Kamil } 2046927a505aSKowalski, Kamil }); 2047e439f0f8SKowalski, Kamil } 2048e439f0f8SKowalski, Kamil }; 2049e439f0f8SKowalski, Kamil 2050e439f0f8SKowalski, Kamil /** 2051e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 2052e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 2053e439f0f8SKowalski, Kamil */ 20541abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 20551abe55efSEd Tanous { 2056e439f0f8SKowalski, Kamil public: 2057e439f0f8SKowalski, Kamil template <typename CrowApp> 20581abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 20594a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 20604a0cb85cSEd Tanous std::string()) 20611abe55efSEd Tanous { 2062e439f0f8SKowalski, Kamil entityPrivileges = { 2063e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 2064e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2065e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2066e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2067e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2068e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2069e439f0f8SKowalski, Kamil } 2070e439f0f8SKowalski, Kamil 2071e439f0f8SKowalski, Kamil private: 2072e439f0f8SKowalski, Kamil /** 2073e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2074e439f0f8SKowalski, Kamil */ 207555c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 20761abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20771abe55efSEd Tanous { 20784a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20791abe55efSEd Tanous if (params.size() != 1) 20801abe55efSEd Tanous { 2081e439f0f8SKowalski, Kamil // This means there is a problem with the router 2082f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2083e439f0f8SKowalski, Kamil return; 2084e439f0f8SKowalski, Kamil } 2085e439f0f8SKowalski, Kamil 20864a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2087e439f0f8SKowalski, Kamil 20884a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 20891abe55efSEd Tanous // preparation 2090f12894f8SJason M. Bills getEthernetIfaceList( 209143b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 20921abe55efSEd Tanous const bool &success, 20934c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 20944a0cb85cSEd Tanous if (!success) 20951abe55efSEd Tanous { 2096f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20974a0cb85cSEd Tanous return; 20981abe55efSEd Tanous } 20994c9afe43SEd Tanous 21004c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 21014c9afe43SEd Tanous { 21024c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 21034c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 21044c9afe43SEd Tanous rootInterfaceName); 21054c9afe43SEd Tanous return; 21064c9afe43SEd Tanous } 21074c9afe43SEd Tanous 21080f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 21090f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 21100f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 21110f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 21120f74e643SEd Tanous "/redfish/v1/$metadata" 21130f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 21140f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 21150f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 21160f74e643SEd Tanous "VLAN Network Interface Collection"; 21174a0cb85cSEd Tanous 21184a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 21194a0cb85cSEd Tanous 21204a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 21211abe55efSEd Tanous { 21224a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 21234a0cb85cSEd Tanous { 21244a0cb85cSEd Tanous iface_array.push_back( 21254a0cb85cSEd Tanous {{"@odata.id", 21264a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 21274a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2128e439f0f8SKowalski, Kamil } 2129e439f0f8SKowalski, Kamil } 2130e439f0f8SKowalski, Kamil 21314a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 21324a0cb85cSEd Tanous iface_array.size(); 21334a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 21344a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 21354a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 21364a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2137e439f0f8SKowalski, Kamil }); 2138e439f0f8SKowalski, Kamil } 2139e439f0f8SKowalski, Kamil 214055c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 21411abe55efSEd Tanous const std::vector<std::string> ¶ms) override 21421abe55efSEd Tanous { 21434a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 21441abe55efSEd Tanous if (params.size() != 1) 21451abe55efSEd Tanous { 2146f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2147e439f0f8SKowalski, Kamil return; 2148e439f0f8SKowalski, Kamil } 2149fda13ad2SSunitha Harish bool vlanEnable = false; 21500627a2c7SEd Tanous uint32_t vlanId = 0; 2151fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2152fda13ad2SSunitha Harish vlanEnable)) 21531abe55efSEd Tanous { 21544a0cb85cSEd Tanous return; 2155e439f0f8SKowalski, Kamil } 2156fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2157fda13ad2SSunitha Harish if (!vlanId) 2158fda13ad2SSunitha Harish { 2159fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2160fda13ad2SSunitha Harish } 2161fda13ad2SSunitha Harish if (!vlanEnable) 2162fda13ad2SSunitha Harish { 2163fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2164fda13ad2SSunitha Harish } 2165fda13ad2SSunitha Harish if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) 2166fda13ad2SSunitha Harish { 2167fda13ad2SSunitha Harish return; 2168fda13ad2SSunitha Harish } 2169fda13ad2SSunitha Harish 21704a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 21714a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 21721abe55efSEd Tanous if (ec) 21731abe55efSEd Tanous { 21744a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 21754a0cb85cSEd Tanous // phosphor-network responses 2176f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21774a0cb85cSEd Tanous return; 21781abe55efSEd Tanous } 2179f12894f8SJason M. Bills messages::created(asyncResp->res); 2180e439f0f8SKowalski, Kamil }; 21814a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21824a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21834a0cb85cSEd Tanous "/xyz/openbmc_project/network", 21844a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 21850627a2c7SEd Tanous rootInterfaceName, vlanId); 21864a0cb85cSEd Tanous } 21874a0cb85cSEd Tanous }; 21889391bb9cSRapkiewicz, Pawel } // namespace redfish 2189