19391bb9cSRapkiewicz, Pawel /* 29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 39391bb9cSRapkiewicz, Pawel // 49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License. 69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at 79391bb9cSRapkiewicz, Pawel // 89391bb9cSRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 99391bb9cSRapkiewicz, Pawel // 109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and 149391bb9cSRapkiewicz, Pawel // limitations under the License. 159391bb9cSRapkiewicz, Pawel */ 169391bb9cSRapkiewicz, Pawel #pragma once 179391bb9cSRapkiewicz, Pawel 181abe55efSEd Tanous #include <boost/container/flat_map.hpp> 194a0cb85cSEd Tanous #include <boost/container/flat_set.hpp> 20179db1d7SKowalski, Kamil #include <dbus_singleton.hpp> 21588c3f0dSKowalski, Kamil #include <error_messages.hpp> 22179db1d7SKowalski, Kamil #include <node.hpp> 23a24526dcSEd Tanous #include <optional> 24588c3f0dSKowalski, Kamil #include <utils/json_utils.hpp> 25abf2add6SEd Tanous #include <variant> 269391bb9cSRapkiewicz, Pawel 271abe55efSEd Tanous namespace redfish 281abe55efSEd Tanous { 299391bb9cSRapkiewicz, Pawel 309391bb9cSRapkiewicz, Pawel /** 319391bb9cSRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 329391bb9cSRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 339391bb9cSRapkiewicz, Pawel */ 34aa2e59c1SEd Tanous using PropertiesMapType = boost::container::flat_map< 35abf2add6SEd Tanous std::string, std::variant<std::string, bool, uint8_t, int16_t, uint16_t, 36aa2e59c1SEd Tanous int32_t, uint32_t, int64_t, uint64_t, double>>; 379391bb9cSRapkiewicz, Pawel 384a0cb85cSEd Tanous using GetManagedObjects = std::vector<std::pair< 39aa2e59c1SEd Tanous sdbusplus::message::object_path, 404a0cb85cSEd Tanous std::vector<std::pair< 41aa2e59c1SEd Tanous std::string, 42aa2e59c1SEd Tanous boost::container::flat_map< 43029573d4SEd Tanous std::string, sdbusplus::message::variant< 44029573d4SEd Tanous std::string, bool, uint8_t, int16_t, uint16_t, 45029573d4SEd Tanous int32_t, uint32_t, int64_t, uint64_t, double, 46029573d4SEd Tanous std::vector<std::string>>>>>>>; 474a0cb85cSEd Tanous 484a0cb85cSEd Tanous enum class LinkType 494a0cb85cSEd Tanous { 504a0cb85cSEd Tanous Local, 514a0cb85cSEd Tanous Global 524a0cb85cSEd Tanous }; 539391bb9cSRapkiewicz, Pawel 549391bb9cSRapkiewicz, Pawel /** 559391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 569391bb9cSRapkiewicz, Pawel */ 571abe55efSEd Tanous struct IPv4AddressData 581abe55efSEd Tanous { 59179db1d7SKowalski, Kamil std::string id; 604a0cb85cSEd Tanous std::string address; 614a0cb85cSEd Tanous std::string domain; 624a0cb85cSEd Tanous std::string gateway; 639391bb9cSRapkiewicz, Pawel std::string netmask; 649391bb9cSRapkiewicz, Pawel std::string origin; 654a0cb85cSEd Tanous LinkType linktype; 664a0cb85cSEd Tanous 671abe55efSEd Tanous bool operator<(const IPv4AddressData &obj) const 681abe55efSEd Tanous { 694a0cb85cSEd Tanous return id < obj.id; 701abe55efSEd Tanous } 719391bb9cSRapkiewicz, Pawel }; 729391bb9cSRapkiewicz, Pawel 739391bb9cSRapkiewicz, Pawel /** 74e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 75e48c0fc5SRavi Teja */ 76e48c0fc5SRavi Teja struct IPv6AddressData 77e48c0fc5SRavi Teja { 78e48c0fc5SRavi Teja std::string id; 79e48c0fc5SRavi Teja std::string address; 80e48c0fc5SRavi Teja std::string origin; 81e48c0fc5SRavi Teja uint8_t prefixLength; 82e48c0fc5SRavi Teja 83e48c0fc5SRavi Teja bool operator<(const IPv6AddressData &obj) const 84e48c0fc5SRavi Teja { 85e48c0fc5SRavi Teja return id < obj.id; 86e48c0fc5SRavi Teja } 87e48c0fc5SRavi Teja }; 88e48c0fc5SRavi Teja /** 899391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 909391bb9cSRapkiewicz, Pawel * available from DBus 919391bb9cSRapkiewicz, Pawel */ 921abe55efSEd Tanous struct EthernetInterfaceData 931abe55efSEd Tanous { 944a0cb85cSEd Tanous uint32_t speed; 954a0cb85cSEd Tanous bool auto_neg; 962a133282Smanojkiraneda bool DHCPEnabled; 974a0cb85cSEd Tanous std::string hostname; 984a0cb85cSEd Tanous std::string default_gateway; 999a6fc6feSRavi Teja std::string ipv6_default_gateway; 1004a0cb85cSEd Tanous std::string mac_address; 101fda13ad2SSunitha Harish std::vector<std::uint32_t> vlan_id; 102029573d4SEd Tanous std::vector<std::string> nameservers; 103d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1049391bb9cSRapkiewicz, Pawel }; 1059391bb9cSRapkiewicz, Pawel 1069391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1079391bb9cSRapkiewicz, Pawel // into full dot notation 1081abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1091abe55efSEd Tanous { 1109391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1119391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1129391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1139391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1149391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1159391bb9cSRapkiewicz, Pawel return netmask; 1169391bb9cSRapkiewicz, Pawel } 1179391bb9cSRapkiewicz, Pawel 1184a0cb85cSEd Tanous inline std::string 1194a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string &inputOrigin, 1204a0cb85cSEd Tanous bool isIPv4) 1211abe55efSEd Tanous { 1224a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1231abe55efSEd Tanous { 1244a0cb85cSEd Tanous return "Static"; 1259391bb9cSRapkiewicz, Pawel } 1264a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1271abe55efSEd Tanous { 1284a0cb85cSEd Tanous if (isIPv4) 1291abe55efSEd Tanous { 1304a0cb85cSEd Tanous return "IPv4LinkLocal"; 1311abe55efSEd Tanous } 1321abe55efSEd Tanous else 1331abe55efSEd Tanous { 1344a0cb85cSEd Tanous return "LinkLocal"; 1359391bb9cSRapkiewicz, Pawel } 1369391bb9cSRapkiewicz, Pawel } 1374a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1381abe55efSEd Tanous { 1394a0cb85cSEd Tanous if (isIPv4) 1404a0cb85cSEd Tanous { 1414a0cb85cSEd Tanous return "DHCP"; 1424a0cb85cSEd Tanous } 1434a0cb85cSEd Tanous else 1444a0cb85cSEd Tanous { 1454a0cb85cSEd Tanous return "DHCPv6"; 1464a0cb85cSEd Tanous } 1474a0cb85cSEd Tanous } 1484a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1494a0cb85cSEd Tanous { 1504a0cb85cSEd Tanous return "SLAAC"; 1514a0cb85cSEd Tanous } 1524a0cb85cSEd Tanous return ""; 1534a0cb85cSEd Tanous } 1544a0cb85cSEd Tanous 1554c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string ðiface_id, 1564a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 1574a0cb85cSEd Tanous EthernetInterfaceData ðData) 1584a0cb85cSEd Tanous { 1594c9afe43SEd Tanous bool idFound = false; 1604a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 1614a0cb85cSEd Tanous { 1624a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 1634a0cb85cSEd Tanous { 164029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 165029573d4SEd Tanous { 1664c9afe43SEd Tanous idFound = true; 1674a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 1684a0cb85cSEd Tanous { 1694a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1704a0cb85cSEd Tanous { 1714a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 1724a0cb85cSEd Tanous { 1734a0cb85cSEd Tanous const std::string *mac = 174abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 1754a0cb85cSEd Tanous if (mac != nullptr) 1764a0cb85cSEd Tanous { 1774a0cb85cSEd Tanous ethData.mac_address = *mac; 1784a0cb85cSEd Tanous } 1794a0cb85cSEd Tanous } 1804a0cb85cSEd Tanous } 1814a0cb85cSEd Tanous } 1824a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 1834a0cb85cSEd Tanous { 1844a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1854a0cb85cSEd Tanous { 1864a0cb85cSEd Tanous if (propertyPair.first == "Id") 1874a0cb85cSEd Tanous { 1881b6b96c5SEd Tanous const uint32_t *id = 189abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 1904a0cb85cSEd Tanous if (id != nullptr) 1914a0cb85cSEd Tanous { 192fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 1934a0cb85cSEd Tanous } 1944a0cb85cSEd Tanous } 1954a0cb85cSEd Tanous } 1964a0cb85cSEd Tanous } 1974a0cb85cSEd Tanous else if (ifacePair.first == 1984a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 1994a0cb85cSEd Tanous { 2004a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2014a0cb85cSEd Tanous { 2024a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2034a0cb85cSEd Tanous { 2044a0cb85cSEd Tanous const bool *auto_neg = 205abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2064a0cb85cSEd Tanous if (auto_neg != nullptr) 2074a0cb85cSEd Tanous { 2084a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2094a0cb85cSEd Tanous } 2104a0cb85cSEd Tanous } 2114a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2124a0cb85cSEd Tanous { 2134a0cb85cSEd Tanous const uint32_t *speed = 214abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2154a0cb85cSEd Tanous if (speed != nullptr) 2164a0cb85cSEd Tanous { 2174a0cb85cSEd Tanous ethData.speed = *speed; 2184a0cb85cSEd Tanous } 2194a0cb85cSEd Tanous } 220f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 221029573d4SEd Tanous { 222029573d4SEd Tanous const std::vector<std::string> *nameservers = 223029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 224029573d4SEd Tanous std::vector<std::string>>( 225029573d4SEd Tanous &propertyPair.second); 226029573d4SEd Tanous if (nameservers != nullptr) 227029573d4SEd Tanous { 228029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous } 2312a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 2322a133282Smanojkiraneda { 2332a133282Smanojkiraneda const bool *DHCPEnabled = 2342a133282Smanojkiraneda std::get_if<bool>(&propertyPair.second); 2352a133282Smanojkiraneda if (DHCPEnabled != nullptr) 2362a133282Smanojkiraneda { 2372a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 2382a133282Smanojkiraneda } 2392a133282Smanojkiraneda } 240d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 241d24bfc7aSJennifer Lee { 242d24bfc7aSJennifer Lee const std::vector<std::string> *domainNames = 243d24bfc7aSJennifer Lee sdbusplus::message::variant_ns::get_if< 244d24bfc7aSJennifer Lee std::vector<std::string>>( 245d24bfc7aSJennifer Lee &propertyPair.second); 246d24bfc7aSJennifer Lee if (domainNames != nullptr) 247d24bfc7aSJennifer Lee { 248d24bfc7aSJennifer Lee ethData.domainnames = std::move(*domainNames); 249d24bfc7aSJennifer Lee } 250d24bfc7aSJennifer Lee } 251029573d4SEd Tanous } 252029573d4SEd Tanous } 253029573d4SEd Tanous } 254029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 255029573d4SEd Tanous // to check eth number 256029573d4SEd Tanous if (ifacePair.first == 2574a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 2584a0cb85cSEd Tanous { 2594a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2604a0cb85cSEd Tanous { 2614a0cb85cSEd Tanous if (propertyPair.first == "HostName") 2624a0cb85cSEd Tanous { 2634a0cb85cSEd Tanous const std::string *hostname = 264029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 265029573d4SEd Tanous &propertyPair.second); 2664a0cb85cSEd Tanous if (hostname != nullptr) 2674a0cb85cSEd Tanous { 2684a0cb85cSEd Tanous ethData.hostname = *hostname; 2694a0cb85cSEd Tanous } 2704a0cb85cSEd Tanous } 2714a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 2724a0cb85cSEd Tanous { 2734a0cb85cSEd Tanous const std::string *defaultGateway = 274029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 275029573d4SEd Tanous &propertyPair.second); 2764a0cb85cSEd Tanous if (defaultGateway != nullptr) 2774a0cb85cSEd Tanous { 2784a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 2794a0cb85cSEd Tanous } 2804a0cb85cSEd Tanous } 2819a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 2829a6fc6feSRavi Teja { 2839a6fc6feSRavi Teja const std::string *defaultGateway6 = 2849a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 2859a6fc6feSRavi Teja &propertyPair.second); 2869a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 2879a6fc6feSRavi Teja { 2889a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 2899a6fc6feSRavi Teja } 2909a6fc6feSRavi Teja } 2914a0cb85cSEd Tanous } 2924a0cb85cSEd Tanous } 2934a0cb85cSEd Tanous } 2944a0cb85cSEd Tanous } 2954c9afe43SEd Tanous return idFound; 2964a0cb85cSEd Tanous } 2974a0cb85cSEd Tanous 298e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 299e48c0fc5SRavi Teja inline void extractIPV6Data( 300e48c0fc5SRavi Teja const std::string ðiface_id, const GetManagedObjects &dbus_data, 301e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> &ipv6_config, 302e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> &ipv6_static_config) 303e48c0fc5SRavi Teja { 304e48c0fc5SRavi Teja const std::string ipv6PathStart = 305e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/"; 306e48c0fc5SRavi Teja 307e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 308e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 309e48c0fc5SRavi Teja for (const auto &objpath : dbus_data) 310e48c0fc5SRavi Teja { 311e48c0fc5SRavi Teja // Check if proper pattern for object path appears 312e48c0fc5SRavi Teja if (boost::starts_with(objpath.first.str, ipv6PathStart)) 313e48c0fc5SRavi Teja { 314e48c0fc5SRavi Teja for (auto &interface : objpath.second) 315e48c0fc5SRavi Teja { 316e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 317e48c0fc5SRavi Teja { 318e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 319e48c0fc5SRavi Teja // appropriate 320e48c0fc5SRavi Teja std::pair< 321e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::iterator, 322e48c0fc5SRavi Teja bool> 323e48c0fc5SRavi Teja it = ipv6_config.insert( 324e48c0fc5SRavi Teja {objpath.first.str.substr(ipv6PathStart.size())}); 325e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 326e48c0fc5SRavi Teja for (auto &property : interface.second) 327e48c0fc5SRavi Teja { 328e48c0fc5SRavi Teja if (property.first == "Address") 329e48c0fc5SRavi Teja { 330e48c0fc5SRavi Teja const std::string *address = 331e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 332e48c0fc5SRavi Teja if (address != nullptr) 333e48c0fc5SRavi Teja { 334e48c0fc5SRavi Teja ipv6_address.address = *address; 335e48c0fc5SRavi Teja } 336e48c0fc5SRavi Teja } 337e48c0fc5SRavi Teja else if (property.first == "Origin") 338e48c0fc5SRavi Teja { 339e48c0fc5SRavi Teja const std::string *origin = 340e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 341e48c0fc5SRavi Teja if (origin != nullptr) 342e48c0fc5SRavi Teja { 343e48c0fc5SRavi Teja ipv6_address.origin = 344e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 345e48c0fc5SRavi Teja false); 346e48c0fc5SRavi Teja } 347e48c0fc5SRavi Teja } 348e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 349e48c0fc5SRavi Teja { 350e48c0fc5SRavi Teja const uint8_t *prefix = 351e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 352e48c0fc5SRavi Teja if (prefix != nullptr) 353e48c0fc5SRavi Teja { 354e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 355e48c0fc5SRavi Teja } 356e48c0fc5SRavi Teja } 357e48c0fc5SRavi Teja else 358e48c0fc5SRavi Teja { 359e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 360e48c0fc5SRavi Teja << "Got extra property: " << property.first 361e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 362e48c0fc5SRavi Teja } 363e48c0fc5SRavi Teja } 364e48c0fc5SRavi Teja if (ipv6_address.origin == "Static") 365e48c0fc5SRavi Teja { 366e48c0fc5SRavi Teja std::pair<boost::container::flat_set< 367e48c0fc5SRavi Teja IPv6AddressData>::iterator, 368e48c0fc5SRavi Teja bool> 369e48c0fc5SRavi Teja iter = ipv6_static_config.insert( 370e48c0fc5SRavi Teja {objpath.first.str.substr( 371e48c0fc5SRavi Teja ipv6PathStart.size())}); 372e48c0fc5SRavi Teja IPv6AddressData &ipv6_static_address = *iter.first; 373e48c0fc5SRavi Teja 374e48c0fc5SRavi Teja ipv6_static_address.address = ipv6_address.address; 375e48c0fc5SRavi Teja ipv6_static_address.prefixLength = 376e48c0fc5SRavi Teja ipv6_address.prefixLength; 377e48c0fc5SRavi Teja } 378e48c0fc5SRavi Teja } 379e48c0fc5SRavi Teja } 380e48c0fc5SRavi Teja } 381e48c0fc5SRavi Teja } 382e48c0fc5SRavi Teja } 383e48c0fc5SRavi Teja 3844a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 385d1d50814SRavi Teja inline void extractIPData( 386d1d50814SRavi Teja const std::string ðiface_id, const GetManagedObjects &dbus_data, 387d1d50814SRavi Teja boost::container::flat_set<IPv4AddressData> &ipv4_config, 388d1d50814SRavi Teja boost::container::flat_set<IPv4AddressData> &ipv4_static_config) 3894a0cb85cSEd Tanous { 3904a0cb85cSEd Tanous const std::string ipv4PathStart = 3914a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 3924a0cb85cSEd Tanous 3934a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 3944a0cb85cSEd Tanous // single ethernet interface, loop over all of them 3954a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 3964a0cb85cSEd Tanous { 3974a0cb85cSEd Tanous // Check if proper pattern for object path appears 3984a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 3994a0cb85cSEd Tanous { 4004a0cb85cSEd Tanous for (auto &interface : objpath.second) 4014a0cb85cSEd Tanous { 4024a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 4034a0cb85cSEd Tanous { 4044a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 4054a0cb85cSEd Tanous // appropriate 4064a0cb85cSEd Tanous std::pair< 4074a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 4084a0cb85cSEd Tanous bool> 4094a0cb85cSEd Tanous it = ipv4_config.insert( 410b01bf299SEd Tanous {objpath.first.str.substr(ipv4PathStart.size())}); 4114a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 4124a0cb85cSEd Tanous for (auto &property : interface.second) 4134a0cb85cSEd Tanous { 4144a0cb85cSEd Tanous if (property.first == "Address") 4154a0cb85cSEd Tanous { 4164a0cb85cSEd Tanous const std::string *address = 417abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4184a0cb85cSEd Tanous if (address != nullptr) 4194a0cb85cSEd Tanous { 4204a0cb85cSEd Tanous ipv4_address.address = *address; 4214a0cb85cSEd Tanous } 4224a0cb85cSEd Tanous } 4234a0cb85cSEd Tanous else if (property.first == "Gateway") 4244a0cb85cSEd Tanous { 4254a0cb85cSEd Tanous const std::string *gateway = 426abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4274a0cb85cSEd Tanous if (gateway != nullptr) 4284a0cb85cSEd Tanous { 4294a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 4304a0cb85cSEd Tanous } 4314a0cb85cSEd Tanous } 4324a0cb85cSEd Tanous else if (property.first == "Origin") 4334a0cb85cSEd Tanous { 4344a0cb85cSEd Tanous const std::string *origin = 435abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4364a0cb85cSEd Tanous if (origin != nullptr) 4374a0cb85cSEd Tanous { 4384a0cb85cSEd Tanous ipv4_address.origin = 4394a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 4404a0cb85cSEd Tanous true); 4414a0cb85cSEd Tanous } 4424a0cb85cSEd Tanous } 4434a0cb85cSEd Tanous else if (property.first == "PrefixLength") 4444a0cb85cSEd Tanous { 4454a0cb85cSEd Tanous const uint8_t *mask = 446abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 4474a0cb85cSEd Tanous if (mask != nullptr) 4484a0cb85cSEd Tanous { 4494a0cb85cSEd Tanous // convert it to the string 4504a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 4514a0cb85cSEd Tanous } 4524a0cb85cSEd Tanous } 4534a0cb85cSEd Tanous else 4544a0cb85cSEd Tanous { 4554a0cb85cSEd Tanous BMCWEB_LOG_ERROR 4564a0cb85cSEd Tanous << "Got extra property: " << property.first 4574a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 4584a0cb85cSEd Tanous } 4594a0cb85cSEd Tanous } 460d1d50814SRavi Teja 461d1d50814SRavi Teja if (ipv4_address.origin == "Static") 462d1d50814SRavi Teja { 463d1d50814SRavi Teja IPv4AddressData ipv4_static_address = { 464d1d50814SRavi Teja objpath.first.str.substr(ipv4PathStart.size())}; 465d1d50814SRavi Teja ipv4_static_address.address = ipv4_address.address; 466d1d50814SRavi Teja ipv4_static_address.gateway = ipv4_address.gateway; 467d1d50814SRavi Teja ipv4_static_address.netmask = ipv4_address.netmask; 468d1d50814SRavi Teja ipv4_static_config.emplace(ipv4_static_address); 469d1d50814SRavi Teja } 470d1d50814SRavi Teja 4714a0cb85cSEd Tanous // Check if given address is local, or global 4724a0cb85cSEd Tanous ipv4_address.linktype = 4734a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 47418659d10SJohnathan Mantey ? LinkType::Local 47518659d10SJohnathan Mantey : LinkType::Global; 4764a0cb85cSEd Tanous } 4774a0cb85cSEd Tanous } 4784a0cb85cSEd Tanous } 4794a0cb85cSEd Tanous } 4804a0cb85cSEd Tanous } 481588c3f0dSKowalski, Kamil 482588c3f0dSKowalski, Kamil /** 483588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 484588c3f0dSKowalski, Kamil * 485588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 486588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 487588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 488588c3f0dSKowalski, Kamil * 489588c3f0dSKowalski, Kamil * @return None. 490588c3f0dSKowalski, Kamil */ 491588c3f0dSKowalski, Kamil template <typename CallbackFunc> 4924a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 4931abe55efSEd Tanous CallbackFunc &&callback) 4941abe55efSEd Tanous { 49555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 496588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 497588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 498588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 499588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 500abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 5014a0cb85cSEd Tanous } 502588c3f0dSKowalski, Kamil 503588c3f0dSKowalski, Kamil /** 504179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 505179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 506179db1d7SKowalski, Kamil * bit count for Subnet Mask. 507179db1d7SKowalski, Kamil * 508179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 509179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 510179db1d7SKowalski, Kamil * 511179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 512179db1d7SKowalski, Kamil */ 5134a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 5141abe55efSEd Tanous uint8_t *bits = nullptr) 5151abe55efSEd Tanous { 516179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 517179db1d7SKowalski, Kamil 518179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 519179db1d7SKowalski, Kamil 5204a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 5211abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 5221abe55efSEd Tanous { 523179db1d7SKowalski, Kamil return false; 524179db1d7SKowalski, Kamil } 525179db1d7SKowalski, Kamil 5261abe55efSEd Tanous if (bits != nullptr) 5271abe55efSEd Tanous { 528179db1d7SKowalski, Kamil *bits = 0; 529179db1d7SKowalski, Kamil } 530179db1d7SKowalski, Kamil 531179db1d7SKowalski, Kamil char *endPtr; 532179db1d7SKowalski, Kamil long previousValue = 255; 533179db1d7SKowalski, Kamil bool firstZeroInByteHit; 5341abe55efSEd Tanous for (const std::string &byte : bytesInMask) 5351abe55efSEd Tanous { 5361abe55efSEd Tanous if (byte.empty()) 5371abe55efSEd Tanous { 5381db9ca37SKowalski, Kamil return false; 5391db9ca37SKowalski, Kamil } 5401db9ca37SKowalski, Kamil 541179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 5421db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 543179db1d7SKowalski, Kamil 5444a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 5454a0cb85cSEd Tanous // is not 100% number 5461abe55efSEd Tanous if (*endPtr != '\0') 5471abe55efSEd Tanous { 548179db1d7SKowalski, Kamil return false; 549179db1d7SKowalski, Kamil } 550179db1d7SKowalski, Kamil 551179db1d7SKowalski, Kamil // Value should be contained in byte 5521abe55efSEd Tanous if (value < 0 || value > 255) 5531abe55efSEd Tanous { 554179db1d7SKowalski, Kamil return false; 555179db1d7SKowalski, Kamil } 556179db1d7SKowalski, Kamil 5571abe55efSEd Tanous if (bits != nullptr) 5581abe55efSEd Tanous { 559179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 5601abe55efSEd Tanous if (previousValue != 255 && value != 0) 5611abe55efSEd Tanous { 562179db1d7SKowalski, Kamil return false; 563179db1d7SKowalski, Kamil } 564179db1d7SKowalski, Kamil 565179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 566179db1d7SKowalski, Kamil firstZeroInByteHit = false; 567179db1d7SKowalski, Kamil 568179db1d7SKowalski, Kamil // Count bits 5691abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 5701abe55efSEd Tanous { 5711abe55efSEd Tanous if (value & (1 << bitIdx)) 5721abe55efSEd Tanous { 5731abe55efSEd Tanous if (firstZeroInByteHit) 5741abe55efSEd Tanous { 575179db1d7SKowalski, Kamil // Continuity not preserved 576179db1d7SKowalski, Kamil return false; 5771abe55efSEd Tanous } 5781abe55efSEd Tanous else 5791abe55efSEd Tanous { 580179db1d7SKowalski, Kamil (*bits)++; 581179db1d7SKowalski, Kamil } 5821abe55efSEd Tanous } 5831abe55efSEd Tanous else 5841abe55efSEd Tanous { 585179db1d7SKowalski, Kamil firstZeroInByteHit = true; 586179db1d7SKowalski, Kamil } 587179db1d7SKowalski, Kamil } 588179db1d7SKowalski, Kamil } 589179db1d7SKowalski, Kamil 590179db1d7SKowalski, Kamil previousValue = value; 591179db1d7SKowalski, Kamil } 592179db1d7SKowalski, Kamil 593179db1d7SKowalski, Kamil return true; 594179db1d7SKowalski, Kamil } 595179db1d7SKowalski, Kamil 596179db1d7SKowalski, Kamil /** 597b01bf299SEd Tanous * @brief Changes IPv4 address type property (Address, Gateway) 598b01bf299SEd Tanous * 599b01bf299SEd Tanous * @param[in] ifaceId Id of interface whose IP should be modified 600b01bf299SEd Tanous * @param[in] ipIdx Index of IP in input array that should be modified 601b01bf299SEd Tanous * @param[in] ipHash DBus Hash id of modified IP 602b01bf299SEd Tanous * @param[in] name Name of field in JSON representation 603b01bf299SEd Tanous * @param[in] newValue New value that should be written 604b01bf299SEd Tanous * @param[io] asyncResp Response object that will be returned to client 605b01bf299SEd Tanous * 606b01bf299SEd Tanous * @return true if give IP is valid and has been sent do D-Bus, false 607b01bf299SEd Tanous * otherwise 608b01bf299SEd Tanous */ 609b01bf299SEd Tanous inline void changeIPv4AddressProperty( 610b01bf299SEd Tanous const std::string &ifaceId, int ipIdx, const std::string &ipHash, 611b01bf299SEd Tanous const std::string &name, const std::string &newValue, 612b01bf299SEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 613b01bf299SEd Tanous { 614286b9118SJohnathan Mantey auto callback = 615286b9118SJohnathan Mantey [asyncResp, ipIdx, name{std::string(name)}, 616286b9118SJohnathan Mantey newValue{std::move(newValue)}](const boost::system::error_code ec) { 617b01bf299SEd Tanous if (ec) 618b01bf299SEd Tanous { 619b01bf299SEd Tanous messages::internalError(asyncResp->res); 620b01bf299SEd Tanous } 621b01bf299SEd Tanous }; 622b01bf299SEd Tanous 623b01bf299SEd Tanous crow::connections::systemBus->async_method_call( 624b01bf299SEd Tanous std::move(callback), "xyz.openbmc_project.Network", 625b01bf299SEd Tanous "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 626b01bf299SEd Tanous "org.freedesktop.DBus.Properties", "Set", 627b01bf299SEd Tanous "xyz.openbmc_project.Network.IP", name, 628b01bf299SEd Tanous std::variant<std::string>(newValue)); 629b01bf299SEd Tanous } 630b01bf299SEd Tanous 631b01bf299SEd Tanous /** 632179db1d7SKowalski, Kamil * @brief Modifies SubnetMask for given IP 633179db1d7SKowalski, Kamil * 634179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be modified 6354a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be 6361abe55efSEd Tanous * modified 637179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of modified IP 638179db1d7SKowalski, Kamil * @param[in] newValue Mask as PrefixLength in bitcount 639179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 640179db1d7SKowalski, Kamil * 641179db1d7SKowalski, Kamil * @return None 642179db1d7SKowalski, Kamil */ 643b01bf299SEd Tanous inline void changeIPv4SubnetMaskProperty(const std::string &ifaceId, int ipIdx, 6444a0cb85cSEd Tanous const std::string &ipHash, 6454a0cb85cSEd Tanous uint8_t &newValue, 6464a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6471abe55efSEd Tanous { 648286b9118SJohnathan Mantey auto callback = [asyncResp, ipIdx](const boost::system::error_code ec) { 6491abe55efSEd Tanous if (ec) 6501abe55efSEd Tanous { 651a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6521abe55efSEd Tanous } 653179db1d7SKowalski, Kamil }; 654179db1d7SKowalski, Kamil 65555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 656179db1d7SKowalski, Kamil std::move(callback), "xyz.openbmc_project.Network", 657179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 658179db1d7SKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 659179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP", "PrefixLength", 660abf2add6SEd Tanous std::variant<uint8_t>(newValue)); 6614a0cb85cSEd Tanous } 662588c3f0dSKowalski, Kamil 663588c3f0dSKowalski, Kamil /** 664179db1d7SKowalski, Kamil * @brief Deletes given IPv4 665179db1d7SKowalski, Kamil * 666179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 667179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 668179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 669179db1d7SKowalski, Kamil * 670179db1d7SKowalski, Kamil * @return None 671179db1d7SKowalski, Kamil */ 6724a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 6734a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 6741abe55efSEd Tanous { 67555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 676286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 6771abe55efSEd Tanous if (ec) 6781abe55efSEd Tanous { 679a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6801abe55efSEd Tanous } 681179db1d7SKowalski, Kamil }, 682179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 683179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 684179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 685179db1d7SKowalski, Kamil } 686179db1d7SKowalski, Kamil 687179db1d7SKowalski, Kamil /** 688179db1d7SKowalski, Kamil * @brief Creates IPv4 with given data 689179db1d7SKowalski, Kamil * 690179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 6914a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 692179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 693179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 694179db1d7SKowalski, Kamil * 695179db1d7SKowalski, Kamil * @return None 696179db1d7SKowalski, Kamil */ 697b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 698b01bf299SEd Tanous uint8_t subnetMask, const std::string &gateway, 699b01bf299SEd Tanous const std::string &address, 7004a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 7011abe55efSEd Tanous { 70243b761d0SEd Tanous auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 7031abe55efSEd Tanous if (ec) 7041abe55efSEd Tanous { 705a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 706179db1d7SKowalski, Kamil } 707179db1d7SKowalski, Kamil }; 708179db1d7SKowalski, Kamil 70955c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 710179db1d7SKowalski, Kamil std::move(createIpHandler), "xyz.openbmc_project.Network", 711179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 712179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 713179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask, 714179db1d7SKowalski, Kamil gateway); 715179db1d7SKowalski, Kamil } 716e48c0fc5SRavi Teja 717e48c0fc5SRavi Teja /** 718e48c0fc5SRavi Teja * @brief Deletes given IPv6 719e48c0fc5SRavi Teja * 720e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 721e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 722e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 723e48c0fc5SRavi Teja * 724e48c0fc5SRavi Teja * @return None 725e48c0fc5SRavi Teja */ 726e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 727e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 728e48c0fc5SRavi Teja { 729e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 730286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 731e48c0fc5SRavi Teja if (ec) 732e48c0fc5SRavi Teja { 733e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 734e48c0fc5SRavi Teja } 735e48c0fc5SRavi Teja }, 736e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 737e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 738e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 739e48c0fc5SRavi Teja } 740e48c0fc5SRavi Teja 741e48c0fc5SRavi Teja /** 742e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 743e48c0fc5SRavi Teja * 744e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 745e48c0fc5SRavi Teja * @param[in] ipIdx Index of IP in input array that should be added 746e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 747e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 748e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 749e48c0fc5SRavi Teja * 750e48c0fc5SRavi Teja * @return None 751e48c0fc5SRavi Teja */ 752e48c0fc5SRavi Teja inline void createIPv6(const std::string &ifaceId, unsigned int ipIdx, 753e48c0fc5SRavi Teja uint8_t prefixLength, const std::string &address, 754e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 755e48c0fc5SRavi Teja { 756e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 757e48c0fc5SRavi Teja if (ec) 758e48c0fc5SRavi Teja { 759e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 760e48c0fc5SRavi Teja } 761e48c0fc5SRavi Teja }; 762e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 763e48c0fc5SRavi Teja // does not have assosiated gateway property 764e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 765e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 766e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 767e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 768e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 769e48c0fc5SRavi Teja ""); 770e48c0fc5SRavi Teja } 771e48c0fc5SRavi Teja 7722a133282Smanojkiraneda using GetAllPropertiesType = 7732a133282Smanojkiraneda boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>; 7742a133282Smanojkiraneda 7752a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) 7762a133282Smanojkiraneda { 7772a133282Smanojkiraneda auto getConfig = [asyncResp](const boost::system::error_code error_code, 7782a133282Smanojkiraneda const GetAllPropertiesType &dbus_data) { 7792a133282Smanojkiraneda if (error_code) 7802a133282Smanojkiraneda { 7812a133282Smanojkiraneda BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code; 7822a133282Smanojkiraneda messages::internalError(asyncResp->res); 7832a133282Smanojkiraneda return; 7842a133282Smanojkiraneda } 785fda13ad2SSunitha Harish nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; 7862a133282Smanojkiraneda for (const auto &property : dbus_data) 7872a133282Smanojkiraneda { 7882a133282Smanojkiraneda auto value = 7892a133282Smanojkiraneda sdbusplus::message::variant_ns::get_if<bool>(&property.second); 7902a133282Smanojkiraneda 7912a133282Smanojkiraneda if (value == nullptr) 7922a133282Smanojkiraneda { 7932a133282Smanojkiraneda continue; 7942a133282Smanojkiraneda } 7952a133282Smanojkiraneda if (property.first == "DNSEnabled") 7962a133282Smanojkiraneda { 7972a133282Smanojkiraneda DHCPConfigTypeJson["UseDNSServers"] = *value; 7982a133282Smanojkiraneda } 7992a133282Smanojkiraneda else if (property.first == "HostNameEnabled") 8002a133282Smanojkiraneda { 8012a133282Smanojkiraneda DHCPConfigTypeJson["UseDomainName"] = *value; 8022a133282Smanojkiraneda } 8032a133282Smanojkiraneda else if (property.first == "NTPEnabled") 8042a133282Smanojkiraneda { 8052a133282Smanojkiraneda DHCPConfigTypeJson["UseNTPServers"] = *value; 8062a133282Smanojkiraneda } 8072a133282Smanojkiraneda } 8082a133282Smanojkiraneda }; 8092a133282Smanojkiraneda crow::connections::systemBus->async_method_call( 8102a133282Smanojkiraneda std::move(getConfig), "xyz.openbmc_project.Network", 8112a133282Smanojkiraneda "/xyz/openbmc_project/network/config/dhcp", 8122a133282Smanojkiraneda "org.freedesktop.DBus.Properties", "GetAll", 8132a133282Smanojkiraneda "xyz.openbmc_project.Network.DHCPConfiguration"); 8142a133282Smanojkiraneda } 815179db1d7SKowalski, Kamil 816179db1d7SKowalski, Kamil /** 817179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 818179db1d7SKowalski, Kamil * Object 819179db1d7SKowalski, Kamil * from EntityManager Network Manager 8204a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 821179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 822179db1d7SKowalski, Kamil * into JSON 823179db1d7SKowalski, Kamil */ 824179db1d7SKowalski, Kamil template <typename CallbackFunc> 8254a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8261abe55efSEd Tanous CallbackFunc &&callback) 8271abe55efSEd Tanous { 82855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8294a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8301abe55efSEd Tanous const boost::system::error_code error_code, 8314a0cb85cSEd Tanous const GetManagedObjects &resp) { 83255c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8334a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 834d1d50814SRavi Teja boost::container::flat_set<IPv4AddressData> ipv4StaticData; 835e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 836e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6StaticData; 837179db1d7SKowalski, Kamil 8381abe55efSEd Tanous if (error_code) 8391abe55efSEd Tanous { 840d1d50814SRavi Teja callback(false, ethData, ipv4Data, ipv4StaticData, ipv6Data, 841d1d50814SRavi Teja 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 { 849d1d50814SRavi Teja callback(false, ethData, ipv4Data, ipv4StaticData, ipv6Data, 850d1d50814SRavi Teja ipv6StaticData); 8514c9afe43SEd Tanous return; 8524c9afe43SEd Tanous } 8534c9afe43SEd Tanous 854d1d50814SRavi Teja extractIPData(ethiface_id, resp, ipv4Data, ipv4StaticData); 855179db1d7SKowalski, Kamil // Fix global GW 8561abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 8571abe55efSEd Tanous { 858*c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 859*c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 860*c619141bSRavi Teja (ipv4.origin == "DHCP")) 8611abe55efSEd Tanous { 8624a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 863179db1d7SKowalski, Kamil } 864179db1d7SKowalski, Kamil } 865179db1d7SKowalski, Kamil 866e48c0fc5SRavi Teja extractIPV6Data(ethiface_id, resp, ipv6Data, ipv6StaticData); 8674a0cb85cSEd Tanous // Finally make a callback with usefull data 868d1d50814SRavi Teja callback(true, ethData, ipv4Data, ipv4StaticData, ipv6Data, 869d1d50814SRavi Teja ipv6StaticData); 870179db1d7SKowalski, Kamil }, 871179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 872179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 873179db1d7SKowalski, Kamil }; 874179db1d7SKowalski, Kamil 875179db1d7SKowalski, Kamil /** 8769391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8779391bb9cSRapkiewicz, Pawel * Manager 8781abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8791abe55efSEd Tanous * into JSON. 8809391bb9cSRapkiewicz, Pawel */ 8819391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8821abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 8831abe55efSEd Tanous { 88455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8854a0cb85cSEd Tanous [callback{std::move(callback)}]( 8869391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 8874a0cb85cSEd Tanous GetManagedObjects &resp) { 8881abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8891abe55efSEd Tanous // ethernet interfaces 8904c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 8914a0cb85cSEd Tanous iface_list.reserve(resp.size()); 8921abe55efSEd Tanous if (error_code) 8931abe55efSEd Tanous { 8944a0cb85cSEd Tanous callback(false, iface_list); 8959391bb9cSRapkiewicz, Pawel return; 8969391bb9cSRapkiewicz, Pawel } 8979391bb9cSRapkiewicz, Pawel 8989391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8994a0cb85cSEd Tanous for (const auto &objpath : resp) 9001abe55efSEd Tanous { 9019391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 9024a0cb85cSEd Tanous for (const auto &interface : objpath.second) 9031abe55efSEd Tanous { 9041abe55efSEd Tanous // If interface is 9054a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9064a0cb85cSEd Tanous // what we're looking for. 9079391bb9cSRapkiewicz, Pawel if (interface.first == 9081abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9091abe55efSEd Tanous { 9104a0cb85cSEd Tanous // Cut out everyting until last "/", ... 9114a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9124a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9134a0cb85cSEd Tanous if (last_pos != std::string::npos) 9141abe55efSEd Tanous { 9159391bb9cSRapkiewicz, Pawel // and put it into output vector. 9164c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9179391bb9cSRapkiewicz, Pawel } 9189391bb9cSRapkiewicz, Pawel } 9199391bb9cSRapkiewicz, Pawel } 9209391bb9cSRapkiewicz, Pawel } 921a434f2bdSEd Tanous // Finally make a callback with useful data 9224a0cb85cSEd Tanous callback(true, iface_list); 9239391bb9cSRapkiewicz, Pawel }, 924aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 925aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 9269391bb9cSRapkiewicz, Pawel }; 9279391bb9cSRapkiewicz, Pawel 9289391bb9cSRapkiewicz, Pawel /** 9299391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9309391bb9cSRapkiewicz, Pawel */ 9311abe55efSEd Tanous class EthernetCollection : public Node 9321abe55efSEd Tanous { 9339391bb9cSRapkiewicz, Pawel public: 9344a0cb85cSEd Tanous template <typename CrowApp> 9351abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9364a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9371abe55efSEd Tanous { 938588c3f0dSKowalski, Kamil entityPrivileges = { 939588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 940e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 941e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 942e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 943e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 944e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9459391bb9cSRapkiewicz, Pawel } 9469391bb9cSRapkiewicz, Pawel 9479391bb9cSRapkiewicz, Pawel private: 9489391bb9cSRapkiewicz, Pawel /** 9499391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 9509391bb9cSRapkiewicz, Pawel */ 95155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 9521abe55efSEd Tanous const std::vector<std::string> ¶ms) override 9531abe55efSEd Tanous { 9540f74e643SEd Tanous res.jsonValue["@odata.type"] = 9550f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9560f74e643SEd Tanous res.jsonValue["@odata.context"] = 9570f74e643SEd Tanous "/redfish/v1/" 9580f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9590f74e643SEd Tanous res.jsonValue["@odata.id"] = 9600f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9610f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 9620f74e643SEd Tanous res.jsonValue["Description"] = 9630f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 9644c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 9654a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 9661abe55efSEd Tanous // preparation 967f12894f8SJason M. Bills getEthernetIfaceList( 9684c9afe43SEd Tanous [asyncResp]( 9694c9afe43SEd Tanous const bool &success, 9704c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 9714a0cb85cSEd Tanous if (!success) 9721abe55efSEd Tanous { 9734c9afe43SEd Tanous messages::internalError(asyncResp->res); 9744a0cb85cSEd Tanous return; 9754a0cb85cSEd Tanous } 9764a0cb85cSEd Tanous 9774c9afe43SEd Tanous nlohmann::json &iface_array = 9784c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 9794a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 980fda13ad2SSunitha Harish std::string tag = "_"; 9814a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 9821abe55efSEd Tanous { 983fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 984fda13ad2SSunitha Harish if (found == std::string::npos) 985fda13ad2SSunitha Harish { 9864a0cb85cSEd Tanous iface_array.push_back( 9874a0cb85cSEd Tanous {{"@odata.id", 9884a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 9894a0cb85cSEd Tanous iface_item}}); 9909391bb9cSRapkiewicz, Pawel } 991fda13ad2SSunitha Harish } 9924a0cb85cSEd Tanous 9934c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 9944c9afe43SEd Tanous iface_array.size(); 9954c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9964a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9979391bb9cSRapkiewicz, Pawel }); 9989391bb9cSRapkiewicz, Pawel } 9999391bb9cSRapkiewicz, Pawel }; 10009391bb9cSRapkiewicz, Pawel 10019391bb9cSRapkiewicz, Pawel /** 10029391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 10039391bb9cSRapkiewicz, Pawel */ 10041abe55efSEd Tanous class EthernetInterface : public Node 10051abe55efSEd Tanous { 10069391bb9cSRapkiewicz, Pawel public: 10079391bb9cSRapkiewicz, Pawel /* 10089391bb9cSRapkiewicz, Pawel * Default Constructor 10099391bb9cSRapkiewicz, Pawel */ 10104a0cb85cSEd Tanous template <typename CrowApp> 10111abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10124a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10131abe55efSEd Tanous std::string()) 10141abe55efSEd Tanous { 1015588c3f0dSKowalski, Kamil entityPrivileges = { 1016588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1017e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1018e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1019e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1020e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1021e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10229391bb9cSRapkiewicz, Pawel } 10239391bb9cSRapkiewicz, Pawel 1024e439f0f8SKowalski, Kamil private: 1025bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10264a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10271abe55efSEd Tanous { 1028bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1029bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1030bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10314a0cb85cSEd Tanous if (ec) 10324a0cb85cSEd Tanous { 1033a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10341abe55efSEd Tanous } 1035bc0bd6e0SEd Tanous }, 1036bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1037bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1038bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1039bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1040abf2add6SEd Tanous std::variant<std::string>(hostname)); 1041588c3f0dSKowalski, Kamil } 1042588c3f0dSKowalski, Kamil 1043d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1044d577665bSRatan Gupta const std::string &macAddress, 1045d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1046d577665bSRatan Gupta { 1047d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1048d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1049d577665bSRatan Gupta if (ec) 1050d577665bSRatan Gupta { 1051d577665bSRatan Gupta messages::internalError(asyncResp->res); 1052d577665bSRatan Gupta return; 1053d577665bSRatan Gupta } 1054d577665bSRatan Gupta }, 1055d577665bSRatan Gupta "xyz.openbmc_project.Network", 1056d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1057d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1058d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1059d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1060d577665bSRatan Gupta } 1061286b9118SJohnathan Mantey 1062da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1063da131a9aSJennifer Lee const std::string &propertyName, const bool &value, 1064da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1065da131a9aSJennifer Lee { 1066da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1067da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1068da131a9aSJennifer Lee if (ec) 1069da131a9aSJennifer Lee { 1070da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1071da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1072da131a9aSJennifer Lee return; 1073da131a9aSJennifer Lee } 1074da131a9aSJennifer Lee }, 1075da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1076da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1077da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1078da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1079da131a9aSJennifer Lee std::variant<bool>{value}); 1080da131a9aSJennifer Lee } 1081da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1082da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1083da131a9aSJennifer Lee { 1084da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1085da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1086da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1087da131a9aSJennifer Lee if (ec) 1088da131a9aSJennifer Lee { 1089da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1090da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1091da131a9aSJennifer Lee return; 1092da131a9aSJennifer Lee } 1093da131a9aSJennifer Lee }, 1094da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1095da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1096da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1097da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1098da131a9aSJennifer Lee std::variant<bool>{value}); 1099da131a9aSJennifer Lee } 1100d577665bSRatan Gupta 1101da131a9aSJennifer Lee void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input, 1102da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1103da131a9aSJennifer Lee { 1104da131a9aSJennifer Lee std::optional<bool> dhcpEnabled; 1105da131a9aSJennifer Lee std::optional<bool> useDNSServers; 1106da131a9aSJennifer Lee std::optional<bool> useDomainName; 1107da131a9aSJennifer Lee std::optional<bool> useNTPServers; 1108da131a9aSJennifer Lee 1109da131a9aSJennifer Lee if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled", 1110da131a9aSJennifer Lee dhcpEnabled, "UseDNSServers", useDNSServers, 1111da131a9aSJennifer Lee "UseDomainName", useDomainName, 1112da131a9aSJennifer Lee "UseNTPServers", useNTPServers)) 1113da131a9aSJennifer Lee { 1114da131a9aSJennifer Lee return; 1115da131a9aSJennifer Lee } 1116da131a9aSJennifer Lee 1117da131a9aSJennifer Lee if (dhcpEnabled) 1118da131a9aSJennifer Lee { 1119da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1120da131a9aSJennifer Lee setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp); 1121da131a9aSJennifer Lee } 1122da131a9aSJennifer Lee 1123da131a9aSJennifer Lee if (useDNSServers) 1124da131a9aSJennifer Lee { 1125da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1126da131a9aSJennifer Lee setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp); 1127da131a9aSJennifer Lee } 1128da131a9aSJennifer Lee 1129da131a9aSJennifer Lee if (useDomainName) 1130da131a9aSJennifer Lee { 1131da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1132da131a9aSJennifer Lee setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp); 1133da131a9aSJennifer Lee } 1134da131a9aSJennifer Lee 1135da131a9aSJennifer Lee if (useNTPServers) 1136da131a9aSJennifer Lee { 1137da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1138da131a9aSJennifer Lee setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp); 1139da131a9aSJennifer Lee } 1140da131a9aSJennifer Lee } 1141d1d50814SRavi Teja void handleIPv4StaticPatch( 1142f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 1143d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4StaticData, 11444a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 11451abe55efSEd Tanous { 1146f476acbfSRatan Gupta if (!input.is_array()) 1147f476acbfSRatan Gupta { 1148f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1149d1d50814SRavi Teja "IPv4StaticAddresses"); 1150f476acbfSRatan Gupta return; 1151f476acbfSRatan Gupta } 1152f476acbfSRatan Gupta 11534a0cb85cSEd Tanous int entryIdx = 0; 11544a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::const_iterator thisData = 1155d1d50814SRavi Teja ipv4StaticData.begin(); 1156537174c4SEd Tanous for (nlohmann::json &thisJson : input) 11571abe55efSEd Tanous { 11584a0cb85cSEd Tanous std::string pathString = 1159d1d50814SRavi Teja "IPv4StaticAddresses/" + std::to_string(entryIdx); 1160179db1d7SKowalski, Kamil 1161f476acbfSRatan Gupta if (thisJson.is_null()) 1162f476acbfSRatan Gupta { 1163d1d50814SRavi Teja if (thisData != ipv4StaticData.end()) 1164f476acbfSRatan Gupta { 1165286b9118SJohnathan Mantey deleteIPv4(ifaceId, thisData->id, asyncResp); 1166f476acbfSRatan Gupta thisData++; 1167f476acbfSRatan Gupta } 1168f476acbfSRatan Gupta else 1169f476acbfSRatan Gupta { 1170f476acbfSRatan Gupta messages::propertyValueFormatError( 1171f476acbfSRatan Gupta asyncResp->res, input.dump(), pathString); 1172f476acbfSRatan Gupta return; 1173f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 1174f476acbfSRatan Gupta // list and if unable to update one of the 1175f476acbfSRatan Gupta // list value then should we proceed further or 1176f476acbfSRatan Gupta // break there, would ask in the redfish forum 1177f476acbfSRatan Gupta // till then we stop processing the next list item. 1178f476acbfSRatan Gupta } 1179f476acbfSRatan Gupta entryIdx++; 1180f476acbfSRatan Gupta continue; // not an error as per the redfish spec. 1181f476acbfSRatan Gupta } 1182f476acbfSRatan Gupta 11839474b378SRatan Gupta if (thisJson.empty()) 11849474b378SRatan Gupta { 1185d1d50814SRavi Teja if (thisData != ipv4StaticData.end()) 11869474b378SRatan Gupta { 11879474b378SRatan Gupta thisData++; 11889474b378SRatan Gupta } 11899474b378SRatan Gupta else 11909474b378SRatan Gupta { 11919474b378SRatan Gupta messages::propertyMissing(asyncResp->res, 11929474b378SRatan Gupta pathString + "/Address"); 11939474b378SRatan Gupta return; 1194f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 11959474b378SRatan Gupta // list and if unable to update one of the 11969474b378SRatan Gupta // list value then should we proceed further or 11979474b378SRatan Gupta // break there, would ask in the redfish forum 11989474b378SRatan Gupta // till then we stop processing the next list item. 11999474b378SRatan Gupta } 12009474b378SRatan Gupta entryIdx++; 12019474b378SRatan Gupta continue; // not an error as per the redfish spec. 12029474b378SRatan Gupta } 12039474b378SRatan Gupta 1204537174c4SEd Tanous std::optional<std::string> address; 1205537174c4SEd Tanous std::optional<std::string> subnetMask; 1206537174c4SEd Tanous std::optional<std::string> gateway; 1207537174c4SEd Tanous 1208537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 12097e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 12107e27d832SJohnathan Mantey "Gateway", gateway)) 1211537174c4SEd Tanous { 1212537174c4SEd Tanous return; 1213179db1d7SKowalski, Kamil } 1214179db1d7SKowalski, Kamil 1215537174c4SEd Tanous if (address) 12161abe55efSEd Tanous { 1217537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*address)) 12181abe55efSEd Tanous { 1219537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 12204a0cb85cSEd Tanous pathString + "/Address"); 1221537174c4SEd Tanous return; 12224a0cb85cSEd Tanous } 12234a0cb85cSEd Tanous } 12244a0cb85cSEd Tanous 1225537174c4SEd Tanous uint8_t prefixLength = 0; 1226537174c4SEd Tanous if (subnetMask) 12274a0cb85cSEd Tanous { 1228537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 12294a0cb85cSEd Tanous { 1230f12894f8SJason M. Bills messages::propertyValueFormatError( 1231537174c4SEd Tanous asyncResp->res, *subnetMask, 12324a0cb85cSEd Tanous pathString + "/SubnetMask"); 1233537174c4SEd Tanous return; 12344a0cb85cSEd Tanous } 12354a0cb85cSEd Tanous } 12364a0cb85cSEd Tanous 1237537174c4SEd Tanous if (gateway) 12384a0cb85cSEd Tanous { 1239537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*gateway)) 12404a0cb85cSEd Tanous { 1241537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1242537174c4SEd Tanous pathString + "/Gateway"); 1243537174c4SEd Tanous return; 12444a0cb85cSEd Tanous } 12454a0cb85cSEd Tanous } 12464a0cb85cSEd Tanous 1247f476acbfSRatan Gupta // if IP address exist then modify it. 1248d1d50814SRavi Teja if (thisData != ipv4StaticData.end()) 12494a0cb85cSEd Tanous { 1250179db1d7SKowalski, Kamil // Apply changes 1251537174c4SEd Tanous if (address) 12521abe55efSEd Tanous { 1253286b9118SJohnathan Mantey auto callback = 1254286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 12554a0cb85cSEd Tanous if (ec) 12561abe55efSEd Tanous { 1257a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12584a0cb85cSEd Tanous return; 12594a0cb85cSEd Tanous } 12604a0cb85cSEd Tanous }; 12614a0cb85cSEd Tanous 12624a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12634a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1264f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1265f476acbfSRatan Gupta thisData->id, 12664a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12674a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Address", 1268537174c4SEd Tanous std::variant<std::string>(*address)); 1269179db1d7SKowalski, Kamil } 1270179db1d7SKowalski, Kamil 1271537174c4SEd Tanous if (subnetMask) 12721abe55efSEd Tanous { 12734a0cb85cSEd Tanous changeIPv4SubnetMaskProperty(ifaceId, entryIdx, 1274286b9118SJohnathan Mantey thisData->id, prefixLength, 1275286b9118SJohnathan Mantey asyncResp); 1276179db1d7SKowalski, Kamil } 1277179db1d7SKowalski, Kamil 1278537174c4SEd Tanous if (gateway) 12791abe55efSEd Tanous { 1280286b9118SJohnathan Mantey auto callback = 1281286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 12824a0cb85cSEd Tanous if (ec) 12831abe55efSEd Tanous { 1284a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12854a0cb85cSEd Tanous return; 12864a0cb85cSEd Tanous } 12874a0cb85cSEd Tanous }; 12884a0cb85cSEd Tanous 12894a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12904a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1291f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1292f476acbfSRatan Gupta thisData->id, 12934a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12944a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Gateway", 1295537174c4SEd Tanous std::variant<std::string>(*gateway)); 12964a0cb85cSEd Tanous } 1297f476acbfSRatan Gupta 12984a0cb85cSEd Tanous thisData++; 12991abe55efSEd Tanous } 13001abe55efSEd Tanous else 13011abe55efSEd Tanous { 13024a0cb85cSEd Tanous // Create IPv4 with provided data 1303537174c4SEd Tanous if (!gateway) 13041abe55efSEd Tanous { 1305a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13064a0cb85cSEd Tanous pathString + "/Gateway"); 13074a0cb85cSEd Tanous continue; 13084a0cb85cSEd Tanous } 13094a0cb85cSEd Tanous 1310537174c4SEd Tanous if (!address) 13111abe55efSEd Tanous { 1312a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13134a0cb85cSEd Tanous pathString + "/Address"); 13144a0cb85cSEd Tanous continue; 13154a0cb85cSEd Tanous } 13164a0cb85cSEd Tanous 1317537174c4SEd Tanous if (!subnetMask) 13181abe55efSEd Tanous { 1319a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13204a0cb85cSEd Tanous pathString + "/SubnetMask"); 13214a0cb85cSEd Tanous continue; 1322588c3f0dSKowalski, Kamil } 1323588c3f0dSKowalski, Kamil 1324b01bf299SEd Tanous createIPv4(ifaceId, entryIdx, prefixLength, *gateway, *address, 1325b01bf299SEd Tanous asyncResp); 132695897b20SRatan Gupta 1327d1d50814SRavi Teja nlohmann::json &ipv4StaticAddressJson = 1328d1d50814SRavi Teja asyncResp->res.jsonValue["IPv4StaticAddresses"][entryIdx]; 1329d1d50814SRavi Teja ipv4StaticAddressJson["Address"] = *address; 1330d1d50814SRavi Teja ipv4StaticAddressJson["SubnetMask"] = *subnetMask; 1331d1d50814SRavi Teja ipv4StaticAddressJson["Gateway"] = *gateway; 13324a0cb85cSEd Tanous } 13334a0cb85cSEd Tanous entryIdx++; 13344a0cb85cSEd Tanous } 13354a0cb85cSEd Tanous } 13364a0cb85cSEd Tanous 1337f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1338f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1339f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1340f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1341f85837bfSRAJESWARAN THILLAIGOVINDAN { 1342f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1343286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1344f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1345f85837bfSRAJESWARAN THILLAIGOVINDAN { 1346f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1347f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1348f85837bfSRAJESWARAN THILLAIGOVINDAN } 1349f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1350f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1351f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1352f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1353f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1354f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1355f85837bfSRAJESWARAN THILLAIGOVINDAN } 1356f85837bfSRAJESWARAN THILLAIGOVINDAN 1357e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1358e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 1359e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData, 1360e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1361e48c0fc5SRavi Teja { 1362e48c0fc5SRavi Teja if (!input.is_array()) 1363e48c0fc5SRavi Teja { 1364e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1365e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1366e48c0fc5SRavi Teja return; 1367e48c0fc5SRavi Teja } 1368e48c0fc5SRavi Teja 1369e48c0fc5SRavi Teja int entryIdx = 0; 1370e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::const_iterator thisData = 1371e48c0fc5SRavi Teja ipv6StaticData.begin(); 1372e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1373e48c0fc5SRavi Teja { 1374e48c0fc5SRavi Teja std::string pathString = 1375e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1376e48c0fc5SRavi Teja 1377e48c0fc5SRavi Teja if (thisJson.is_null()) 1378e48c0fc5SRavi Teja { 1379e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1380e48c0fc5SRavi Teja { 1381286b9118SJohnathan Mantey deleteIPv6(ifaceId, thisData->id, asyncResp); 1382e48c0fc5SRavi Teja thisData++; 1383e48c0fc5SRavi Teja } 1384e48c0fc5SRavi Teja else 1385e48c0fc5SRavi Teja { 1386e48c0fc5SRavi Teja messages::propertyValueFormatError( 1387e48c0fc5SRavi Teja asyncResp->res, input.dump(), pathString); 1388e48c0fc5SRavi Teja return; 1389e48c0fc5SRavi Teja } 1390e48c0fc5SRavi Teja entryIdx++; 1391e48c0fc5SRavi Teja continue; 1392e48c0fc5SRavi Teja } 1393e48c0fc5SRavi Teja 1394e48c0fc5SRavi Teja if (thisJson.empty()) 1395e48c0fc5SRavi Teja { 1396e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1397e48c0fc5SRavi Teja { 1398e48c0fc5SRavi Teja thisData++; 1399e48c0fc5SRavi Teja } 1400e48c0fc5SRavi Teja else 1401e48c0fc5SRavi Teja { 1402e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1403e48c0fc5SRavi Teja pathString + "/Address"); 1404e48c0fc5SRavi Teja return; 1405e48c0fc5SRavi Teja } 1406e48c0fc5SRavi Teja entryIdx++; 1407e48c0fc5SRavi Teja continue; 1408e48c0fc5SRavi Teja } 1409e48c0fc5SRavi Teja 1410e48c0fc5SRavi Teja std::optional<std::string> address; 1411e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1412e48c0fc5SRavi Teja 1413e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1414e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1415e48c0fc5SRavi Teja { 1416e48c0fc5SRavi Teja return; 1417e48c0fc5SRavi Teja } 1418e48c0fc5SRavi Teja 1419e48c0fc5SRavi Teja // if IP address exist then modify it. 1420e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1421e48c0fc5SRavi Teja { 1422e48c0fc5SRavi Teja // Apply changes 1423e48c0fc5SRavi Teja if (address) 1424e48c0fc5SRavi Teja { 1425286b9118SJohnathan Mantey auto callback = 1426286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1427e48c0fc5SRavi Teja if (ec) 1428e48c0fc5SRavi Teja { 1429e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1430e48c0fc5SRavi Teja return; 1431e48c0fc5SRavi Teja } 1432e48c0fc5SRavi Teja }; 1433e48c0fc5SRavi Teja 1434e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1435e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1436e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1437e48c0fc5SRavi Teja thisData->id, 1438e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1439e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "Address", 1440e48c0fc5SRavi Teja std::variant<std::string>(*address)); 1441e48c0fc5SRavi Teja } 1442e48c0fc5SRavi Teja 1443e48c0fc5SRavi Teja if (prefixLength) 1444e48c0fc5SRavi Teja { 1445286b9118SJohnathan Mantey auto callback = 1446286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1447e48c0fc5SRavi Teja if (ec) 1448e48c0fc5SRavi Teja { 1449e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1450e48c0fc5SRavi Teja return; 1451e48c0fc5SRavi Teja } 1452e48c0fc5SRavi Teja }; 1453e48c0fc5SRavi Teja 1454e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1455e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1456e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1457e48c0fc5SRavi Teja thisData->id, 1458e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1459e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "PrefixLength", 1460e48c0fc5SRavi Teja std::variant<uint8_t>(*prefixLength)); 1461e48c0fc5SRavi Teja } 1462e48c0fc5SRavi Teja 1463e48c0fc5SRavi Teja thisData++; 1464e48c0fc5SRavi Teja } 1465e48c0fc5SRavi Teja else 1466e48c0fc5SRavi Teja { 1467e48c0fc5SRavi Teja // Create IPv6 with provided data 1468e48c0fc5SRavi Teja 1469e48c0fc5SRavi Teja if (!prefixLength) 1470e48c0fc5SRavi Teja { 1471e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1472e48c0fc5SRavi Teja pathString + "/PrefixLength"); 1473e48c0fc5SRavi Teja continue; 1474e48c0fc5SRavi Teja } 1475e48c0fc5SRavi Teja 1476e48c0fc5SRavi Teja if (!address) 1477e48c0fc5SRavi Teja { 1478e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1479e48c0fc5SRavi Teja pathString + "/Address"); 1480e48c0fc5SRavi Teja continue; 1481e48c0fc5SRavi Teja } 1482e48c0fc5SRavi Teja 1483e48c0fc5SRavi Teja createIPv6(ifaceId, entryIdx, *prefixLength, *address, 1484e48c0fc5SRavi Teja asyncResp); 1485e48c0fc5SRavi Teja 1486e48c0fc5SRavi Teja nlohmann::json &ipv6StaticAddressJson = 1487e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"][entryIdx]; 1488e48c0fc5SRavi Teja ipv6StaticAddressJson["Address"] = *address; 1489e48c0fc5SRavi Teja ipv6StaticAddressJson["PrefixLength"] = *prefixLength; 1490e48c0fc5SRavi Teja } 1491e48c0fc5SRavi Teja entryIdx++; 1492e48c0fc5SRavi Teja } 1493e48c0fc5SRavi Teja } 1494e48c0fc5SRavi Teja 14950f74e643SEd Tanous void parseInterfaceData( 14960f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 14970f74e643SEd Tanous const EthernetInterfaceData ðData, 1498e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1499d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4StaticData, 1500e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1501e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 15024a0cb85cSEd Tanous { 15034a0cb85cSEd Tanous json_response["Id"] = iface_id; 15044a0cb85cSEd Tanous json_response["@odata.id"] = 15054a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1506029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1507029573d4SEd Tanous if (ethData.speed == 0) 1508029573d4SEd Tanous { 1509029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1510029573d4SEd Tanous json_response["Status"] = { 1511029573d4SEd Tanous {"Health", "OK"}, 1512029573d4SEd Tanous {"State", "Disabled"}, 1513029573d4SEd Tanous }; 1514029573d4SEd Tanous } 1515029573d4SEd Tanous else 1516029573d4SEd Tanous { 1517029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1518029573d4SEd Tanous json_response["Status"] = { 1519029573d4SEd Tanous {"Health", "OK"}, 1520029573d4SEd Tanous {"State", "Enabled"}, 1521029573d4SEd Tanous }; 1522029573d4SEd Tanous } 15234a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 15244a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1525fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 15262a133282Smanojkiraneda 15274a0cb85cSEd Tanous if (!ethData.hostname.empty()) 15284a0cb85cSEd Tanous { 15294a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 1530d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1531d24bfc7aSJennifer Lee { 1532d24bfc7aSJennifer Lee json_response["FQDN"] = 1533d24bfc7aSJennifer Lee ethData.hostname + "." + ethData.domainnames[0]; 1534d24bfc7aSJennifer Lee } 15354a0cb85cSEd Tanous } 15364a0cb85cSEd Tanous 1537fda13ad2SSunitha Harish json_response["VLANs"] = { 1538fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1539fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1540fda13ad2SSunitha Harish 1541029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 1542f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 15434a0cb85cSEd Tanous 15444a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 15454a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 15464a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 15474a0cb85cSEd Tanous { 1548fa5053a6SGunnar Mills 1549fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1550fa5053a6SGunnar Mills if (gatewayStr.empty()) 1551fa5053a6SGunnar Mills { 1552fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1553fa5053a6SGunnar Mills } 1554fa5053a6SGunnar Mills 15554a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 15564a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1557029573d4SEd Tanous {"Address", ipv4_config.address}, 1558fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 15594a0cb85cSEd Tanous } 1560d1d50814SRavi Teja 1561d1d50814SRavi Teja nlohmann::json &ipv4_static_array = 1562d1d50814SRavi Teja json_response["IPv4StaticAddresses"]; 1563d1d50814SRavi Teja ipv4_static_array = nlohmann::json::array(); 1564d1d50814SRavi Teja for (auto &ipv4_static_config : ipv4StaticData) 1565d1d50814SRavi Teja { 1566d1d50814SRavi Teja 1567d1d50814SRavi Teja std::string gatewayStr = ipv4_static_config.gateway; 1568d1d50814SRavi Teja if (gatewayStr.empty()) 1569d1d50814SRavi Teja { 1570d1d50814SRavi Teja gatewayStr = "0.0.0.0"; 15714a0cb85cSEd Tanous } 1572d1d50814SRavi Teja 1573d1d50814SRavi Teja ipv4_static_array.push_back( 1574d1d50814SRavi Teja {{"SubnetMask", ipv4_static_config.netmask}, 1575d1d50814SRavi Teja {"Address", ipv4_static_config.address}, 1576d1d50814SRavi Teja {"Gateway", gatewayStr}}); 1577d1d50814SRavi Teja } 1578d1d50814SRavi Teja 15799a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1580e48c0fc5SRavi Teja 1581e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 1582e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 1583e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1584e48c0fc5SRavi Teja { 1585e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1586e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1587e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 1588e48c0fc5SRavi Teja } 1589e48c0fc5SRavi Teja 1590e48c0fc5SRavi Teja nlohmann::json &ipv6_static_array = 1591e48c0fc5SRavi Teja json_response["IPv6StaticAddresses"]; 1592e48c0fc5SRavi Teja ipv6_static_array = nlohmann::json::array(); 1593e48c0fc5SRavi Teja for (auto &ipv6_static_config : ipv6StaticData) 1594e48c0fc5SRavi Teja { 1595e48c0fc5SRavi Teja ipv6_static_array.push_back( 1596e48c0fc5SRavi Teja {{"Address", ipv6_static_config.address}, 1597e48c0fc5SRavi Teja {"PrefixLength", ipv6_static_config.prefixLength}}); 1598e48c0fc5SRavi Teja } 1599588c3f0dSKowalski, Kamil } 1600588c3f0dSKowalski, Kamil 16019391bb9cSRapkiewicz, Pawel /** 16029391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 16039391bb9cSRapkiewicz, Pawel */ 160455c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 16051abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16061abe55efSEd Tanous { 16074a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16081abe55efSEd Tanous if (params.size() != 1) 16091abe55efSEd Tanous { 1610f12894f8SJason M. Bills messages::internalError(asyncResp->res); 16119391bb9cSRapkiewicz, Pawel return; 16129391bb9cSRapkiewicz, Pawel } 16139391bb9cSRapkiewicz, Pawel 16144a0cb85cSEd Tanous getEthernetIfaceData( 16154a0cb85cSEd Tanous params[0], 16164a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 16174a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1618e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1619d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 1620d1d50814SRavi Teja &ipv4StaticData, 1621e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1622e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1623e48c0fc5SRavi Teja &ipv6StaticData) { 16244a0cb85cSEd Tanous if (!success) 16251abe55efSEd Tanous { 16261abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16271abe55efSEd Tanous // object, and other errors 1628f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1629f12894f8SJason M. Bills "EthernetInterface", iface_id); 16304a0cb85cSEd Tanous return; 16319391bb9cSRapkiewicz, Pawel } 16324c9afe43SEd Tanous 16334c9afe43SEd Tanous // because this has no dependence on the interface at this 16344c9afe43SEd Tanous // point, it needs to be done after we know the interface 16354c9afe43SEd Tanous // exists, not before. 16364c9afe43SEd Tanous getDHCPConfigData(asyncResp); 16374c9afe43SEd Tanous 16380f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1639fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 16400f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 16410f74e643SEd Tanous "/redfish/v1/$metadata#EthernetInterface.EthernetInterface"; 16420f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 16430f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 16440f74e643SEd Tanous "Management Network Interface"; 16450f74e643SEd Tanous 16460f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1647d1d50814SRavi Teja ipv4Data, ipv4StaticData, ipv6Data, 1648d1d50814SRavi Teja ipv6StaticData); 16499391bb9cSRapkiewicz, Pawel }); 16509391bb9cSRapkiewicz, Pawel } 16519391bb9cSRapkiewicz, Pawel 165255c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 16531abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16541abe55efSEd Tanous { 16554a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16561abe55efSEd Tanous if (params.size() != 1) 16571abe55efSEd Tanous { 1658f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1659588c3f0dSKowalski, Kamil return; 1660588c3f0dSKowalski, Kamil } 1661588c3f0dSKowalski, Kamil 16624a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1663588c3f0dSKowalski, Kamil 1664bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1665d577665bSRatan Gupta std::optional<std::string> macAddress; 16669a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1667f476acbfSRatan Gupta std::optional<nlohmann::json> ipv4Addresses; 1668d1d50814SRavi Teja std::optional<nlohmann::json> ipv4StaticAddresses; 1669f476acbfSRatan Gupta std::optional<nlohmann::json> ipv6Addresses; 1670e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1671f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 16725112e9b4SRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> nameServers; 1673da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 16740627a2c7SEd Tanous 1675fda13ad2SSunitha Harish if (!json_util::readJson( 1676fda13ad2SSunitha Harish req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses, 1677d1d50814SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, "MACAddress", 1678d1d50814SRavi Teja macAddress, "StaticNameServers", staticNameServers, 1679d1d50814SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, "IPv6StaticAddresses", 1680d1d50814SRavi Teja ipv6StaticAddresses, "NameServers", nameServers, "DHCPv4", 1681d1d50814SRavi Teja dhcpv4)) 16821abe55efSEd Tanous { 1683588c3f0dSKowalski, Kamil return; 1684588c3f0dSKowalski, Kamil } 1685f15aad37SRatan Gupta 1686da131a9aSJennifer Lee if (dhcpv4) 1687da131a9aSJennifer Lee { 1688da131a9aSJennifer Lee handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp); 1689da131a9aSJennifer Lee } 1690da131a9aSJennifer Lee 16914a0cb85cSEd Tanous // Get single eth interface data, and call the below callback for JSON 1692588c3f0dSKowalski, Kamil // preparation 16934a0cb85cSEd Tanous getEthernetIfaceData( 16944a0cb85cSEd Tanous iface_id, 1695fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1696fda13ad2SSunitha Harish macAddress = std::move(macAddress), 16970627a2c7SEd Tanous ipv4Addresses = std::move(ipv4Addresses), 1698d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 16999a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1700e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 17015112e9b4SRAJESWARAN THILLAIGOVINDAN staticNameServers = std::move(staticNameServers), 17025112e9b4SRAJESWARAN THILLAIGOVINDAN nameServers = std::move(nameServers)]( 17034a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1704e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1705d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 1706d1d50814SRavi Teja &ipv4StaticData, 1707e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1708e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1709e48c0fc5SRavi Teja &ipv6StaticData) { 17101abe55efSEd Tanous if (!success) 17111abe55efSEd Tanous { 1712588c3f0dSKowalski, Kamil // ... otherwise return error 17131abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 17141abe55efSEd Tanous // object, and other errors 1715fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1716fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1717588c3f0dSKowalski, Kamil return; 1718588c3f0dSKowalski, Kamil } 1719588c3f0dSKowalski, Kamil 17200627a2c7SEd Tanous if (hostname) 17211abe55efSEd Tanous { 17220627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 17231abe55efSEd Tanous } 17240627a2c7SEd Tanous 1725d577665bSRatan Gupta if (macAddress) 1726d577665bSRatan Gupta { 1727d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1728d577665bSRatan Gupta } 1729d577665bSRatan Gupta 17300627a2c7SEd Tanous if (ipv4Addresses) 17311abe55efSEd Tanous { 1732d1d50814SRavi Teja messages::propertyNotWritable(asyncResp->res, 1733d1d50814SRavi Teja "IPv4Addresses"); 1734d1d50814SRavi Teja } 1735d1d50814SRavi Teja 1736d1d50814SRavi Teja if (ipv4StaticAddresses) 1737d1d50814SRavi Teja { 1738537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 1739537174c4SEd Tanous // above is returning a const value, not a non-const value. 1740537174c4SEd Tanous // This doesn't really work for us, as we need to be able to 1741537174c4SEd Tanous // efficiently move out the intermedia nlohmann::json 1742537174c4SEd Tanous // objects. This makes a copy of the structure, and operates 1743537174c4SEd Tanous // on that, but could be done more efficiently 1744d1d50814SRavi Teja nlohmann::json ipv4Static = std::move(*ipv4StaticAddresses); 1745d1d50814SRavi Teja handleIPv4StaticPatch(iface_id, ipv4Static, ipv4StaticData, 1746d1d50814SRavi Teja asyncResp); 17471abe55efSEd Tanous } 17480627a2c7SEd Tanous 17495112e9b4SRAJESWARAN THILLAIGOVINDAN if (nameServers) 17505112e9b4SRAJESWARAN THILLAIGOVINDAN { 17515112e9b4SRAJESWARAN THILLAIGOVINDAN // Data.Permissions is read-only 17525112e9b4SRAJESWARAN THILLAIGOVINDAN messages::propertyNotWritable(asyncResp->res, 17535112e9b4SRAJESWARAN THILLAIGOVINDAN "NameServers"); 17545112e9b4SRAJESWARAN THILLAIGOVINDAN } 17555112e9b4SRAJESWARAN THILLAIGOVINDAN 1756f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1757f85837bfSRAJESWARAN THILLAIGOVINDAN { 1758f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1759f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1760f85837bfSRAJESWARAN THILLAIGOVINDAN } 17619a6fc6feSRavi Teja 17629a6fc6feSRavi Teja if (ipv6DefaultGateway) 17639a6fc6feSRavi Teja { 17649a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 17659a6fc6feSRavi Teja "IPv6DefaultGateway"); 17669a6fc6feSRavi Teja } 1767e48c0fc5SRavi Teja 1768e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1769e48c0fc5SRavi Teja { 1770e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1771e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 1772e48c0fc5SRavi Teja ipv6StaticData, asyncResp); 1773e48c0fc5SRavi Teja } 1774588c3f0dSKowalski, Kamil }); 1775588c3f0dSKowalski, Kamil } 17769391bb9cSRapkiewicz, Pawel }; 17779391bb9cSRapkiewicz, Pawel 1778e439f0f8SKowalski, Kamil /** 17794a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 17804a0cb85cSEd Tanous * Schema 1781e439f0f8SKowalski, Kamil */ 17821abe55efSEd Tanous class VlanNetworkInterface : public Node 17831abe55efSEd Tanous { 1784e439f0f8SKowalski, Kamil public: 1785e439f0f8SKowalski, Kamil /* 1786e439f0f8SKowalski, Kamil * Default Constructor 1787e439f0f8SKowalski, Kamil */ 1788e439f0f8SKowalski, Kamil template <typename CrowApp> 17891abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 17904a0cb85cSEd Tanous Node(app, 17910f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 17921abe55efSEd Tanous std::string(), std::string()) 17931abe55efSEd Tanous { 1794e439f0f8SKowalski, Kamil entityPrivileges = { 1795e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1796e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1797e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1798e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1799e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1800e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1801e439f0f8SKowalski, Kamil } 1802e439f0f8SKowalski, Kamil 1803e439f0f8SKowalski, Kamil private: 18040f74e643SEd Tanous void parseInterfaceData( 18050f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 18060f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1807e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1808d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4StaticData, 1809e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1810e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 18111abe55efSEd Tanous { 1812e439f0f8SKowalski, Kamil // Fill out obvious data... 18134a0cb85cSEd Tanous json_response["Id"] = iface_id; 18144a0cb85cSEd Tanous json_response["@odata.id"] = 18154a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 18164a0cb85cSEd Tanous "/VLANs/" + iface_id; 1817e439f0f8SKowalski, Kamil 18184a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1819fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 18204a0cb85cSEd Tanous { 1821fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 18224a0cb85cSEd Tanous } 1823e439f0f8SKowalski, Kamil } 1824e439f0f8SKowalski, Kamil 1825fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 18261abe55efSEd Tanous { 18271abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 18281abe55efSEd Tanous { 1829927a505aSKowalski, Kamil return false; 18301abe55efSEd Tanous } 18311abe55efSEd Tanous else 18321abe55efSEd Tanous { 1833927a505aSKowalski, Kamil return true; 1834927a505aSKowalski, Kamil } 1835927a505aSKowalski, Kamil } 1836927a505aSKowalski, Kamil 1837e439f0f8SKowalski, Kamil /** 1838e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1839e439f0f8SKowalski, Kamil */ 184055c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 18411abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18421abe55efSEd Tanous { 18434a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18444a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1845e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1846e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1847e439f0f8SKowalski, Kamil // impossible. 18481abe55efSEd Tanous if (params.size() != 2) 18491abe55efSEd Tanous { 1850f12894f8SJason M. Bills messages::internalError(res); 1851e439f0f8SKowalski, Kamil res.end(); 1852e439f0f8SKowalski, Kamil return; 1853e439f0f8SKowalski, Kamil } 1854e439f0f8SKowalski, Kamil 18554a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 18564a0cb85cSEd Tanous const std::string &iface_id = params[1]; 18570f74e643SEd Tanous res.jsonValue["@odata.type"] = 18580f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 18590f74e643SEd Tanous res.jsonValue["@odata.context"] = 18600f74e643SEd Tanous "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface"; 18610f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1862e439f0f8SKowalski, Kamil 1863fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 18641abe55efSEd Tanous { 1865a434f2bdSEd Tanous return; 1866a434f2bdSEd Tanous } 1867a434f2bdSEd Tanous 1868e439f0f8SKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1869e439f0f8SKowalski, Kamil // preparation 18704a0cb85cSEd Tanous getEthernetIfaceData( 1871fda13ad2SSunitha Harish params[1], 1872fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1873fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 18744a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1875e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1876d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 1877d1d50814SRavi Teja &ipv4StaticData, 1878e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1879e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1880e48c0fc5SRavi Teja &ipv6StaticData) { 1881fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 18821abe55efSEd Tanous { 18830f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 18840f74e643SEd Tanous parent_iface_id, iface_id, ethData, 1885d1d50814SRavi Teja ipv4Data, ipv4StaticData, ipv6Data, 1886d1d50814SRavi Teja ipv6StaticData); 18871abe55efSEd Tanous } 18881abe55efSEd Tanous else 18891abe55efSEd Tanous { 1890e439f0f8SKowalski, Kamil // ... otherwise return error 18911abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18921abe55efSEd Tanous // object, and other errors 1893f12894f8SJason M. Bills messages::resourceNotFound( 1894f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1895e439f0f8SKowalski, Kamil } 1896e439f0f8SKowalski, Kamil }); 1897e439f0f8SKowalski, Kamil } 1898e439f0f8SKowalski, Kamil 189955c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 19001abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19011abe55efSEd Tanous { 19024a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19031abe55efSEd Tanous if (params.size() != 2) 19041abe55efSEd Tanous { 1905f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1906e439f0f8SKowalski, Kamil return; 1907e439f0f8SKowalski, Kamil } 1908e439f0f8SKowalski, Kamil 1909d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 191055c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1911927a505aSKowalski, Kamil 1912fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19131abe55efSEd Tanous { 1914fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1915fda13ad2SSunitha Harish ifaceId); 1916927a505aSKowalski, Kamil return; 1917927a505aSKowalski, Kamil } 1918927a505aSKowalski, Kamil 19190627a2c7SEd Tanous bool vlanEnable = false; 19200627a2c7SEd Tanous uint64_t vlanId = 0; 19210627a2c7SEd Tanous 19220627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 19230627a2c7SEd Tanous vlanId)) 19241abe55efSEd Tanous { 1925927a505aSKowalski, Kamil return; 1926927a505aSKowalski, Kamil } 1927927a505aSKowalski, Kamil 1928927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1929927a505aSKowalski, Kamil // preparation 1930e48c0fc5SRavi Teja getEthernetIfaceData( 1931e48c0fc5SRavi Teja params[1], 1932e48c0fc5SRavi Teja [this, asyncResp, parentIfaceId{std::string(params[0])}, 1933e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 1934e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 1935e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1936d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 1937d1d50814SRavi Teja &ipv4StaticData, 1938e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1939e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1940e48c0fc5SRavi Teja &ipv6StaticData) { 194108244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 194208244d02SSunitha Harish { 194308244d02SSunitha Harish auto callback = 194408244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 194508244d02SSunitha Harish if (ec) 194608244d02SSunitha Harish { 194708244d02SSunitha Harish messages::internalError(asyncResp->res); 194808244d02SSunitha Harish } 194908244d02SSunitha Harish }; 195008244d02SSunitha Harish 195108244d02SSunitha Harish if (vlanEnable == true) 195208244d02SSunitha Harish { 195308244d02SSunitha Harish crow::connections::systemBus->async_method_call( 195408244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 195508244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 195608244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 195708244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 195808244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 195908244d02SSunitha Harish } 196008244d02SSunitha Harish else 196108244d02SSunitha Harish { 1962e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 1963e48c0fc5SRavi Teja "vlan interface"; 196408244d02SSunitha Harish crow::connections::systemBus->async_method_call( 196508244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 1966e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 1967e48c0fc5SRavi Teja ifaceId, 196808244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 196908244d02SSunitha Harish } 197008244d02SSunitha Harish } 197108244d02SSunitha Harish else 19721abe55efSEd Tanous { 19731abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 19741abe55efSEd Tanous // object, and other errors 1975e48c0fc5SRavi Teja messages::resourceNotFound( 1976e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 1977927a505aSKowalski, Kamil return; 1978927a505aSKowalski, Kamil } 1979927a505aSKowalski, Kamil }); 1980e439f0f8SKowalski, Kamil } 1981e439f0f8SKowalski, Kamil 198255c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 19831abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19841abe55efSEd Tanous { 19854a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19861abe55efSEd Tanous if (params.size() != 2) 19871abe55efSEd Tanous { 1988f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1989e439f0f8SKowalski, Kamil return; 1990e439f0f8SKowalski, Kamil } 1991e439f0f8SKowalski, Kamil 1992d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 199355c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1994927a505aSKowalski, Kamil 1995fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19961abe55efSEd Tanous { 1997fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1998fda13ad2SSunitha Harish ifaceId); 1999927a505aSKowalski, Kamil return; 2000927a505aSKowalski, Kamil } 2001927a505aSKowalski, Kamil 2002927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 2003927a505aSKowalski, Kamil // preparation 2004f12894f8SJason M. Bills getEthernetIfaceData( 2005fda13ad2SSunitha Harish params[1], 2006fda13ad2SSunitha Harish [this, asyncResp, parentIfaceId{std::string(params[0])}, 2007fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 2008f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 2009e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 2010d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 2011d1d50814SRavi Teja &ipv4StaticData, 2012e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 2013e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 2014e48c0fc5SRavi Teja &ipv6StaticData) { 2015fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 20161abe55efSEd Tanous { 2017f12894f8SJason M. Bills auto callback = 2018f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 20191abe55efSEd Tanous if (ec) 20201abe55efSEd Tanous { 2021f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2022927a505aSKowalski, Kamil } 20234a0cb85cSEd Tanous }; 20244a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 20254a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 20264a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 20274a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 20281abe55efSEd Tanous } 20291abe55efSEd Tanous else 20301abe55efSEd Tanous { 2031927a505aSKowalski, Kamil // ... otherwise return error 2032f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 2033f12894f8SJason M. Bills // object, and other errors 2034f12894f8SJason M. Bills messages::resourceNotFound( 2035f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 2036927a505aSKowalski, Kamil } 2037927a505aSKowalski, Kamil }); 2038e439f0f8SKowalski, Kamil } 2039e439f0f8SKowalski, Kamil }; 2040e439f0f8SKowalski, Kamil 2041e439f0f8SKowalski, Kamil /** 2042e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 2043e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 2044e439f0f8SKowalski, Kamil */ 20451abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 20461abe55efSEd Tanous { 2047e439f0f8SKowalski, Kamil public: 2048e439f0f8SKowalski, Kamil template <typename CrowApp> 20491abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 20504a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 20514a0cb85cSEd Tanous std::string()) 20521abe55efSEd Tanous { 2053e439f0f8SKowalski, Kamil entityPrivileges = { 2054e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 2055e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2056e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2057e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2058e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2059e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2060e439f0f8SKowalski, Kamil } 2061e439f0f8SKowalski, Kamil 2062e439f0f8SKowalski, Kamil private: 2063e439f0f8SKowalski, Kamil /** 2064e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2065e439f0f8SKowalski, Kamil */ 206655c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 20671abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20681abe55efSEd Tanous { 20694a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20701abe55efSEd Tanous if (params.size() != 1) 20711abe55efSEd Tanous { 2072e439f0f8SKowalski, Kamil // This means there is a problem with the router 2073f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2074e439f0f8SKowalski, Kamil return; 2075e439f0f8SKowalski, Kamil } 2076e439f0f8SKowalski, Kamil 20774a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2078e439f0f8SKowalski, Kamil 20794a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 20801abe55efSEd Tanous // preparation 2081f12894f8SJason M. Bills getEthernetIfaceList( 208243b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 20831abe55efSEd Tanous const bool &success, 20844c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 20854a0cb85cSEd Tanous if (!success) 20861abe55efSEd Tanous { 2087f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20884a0cb85cSEd Tanous return; 20891abe55efSEd Tanous } 20904c9afe43SEd Tanous 20914c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 20924c9afe43SEd Tanous { 20934c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 20944c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 20954c9afe43SEd Tanous rootInterfaceName); 20964c9afe43SEd Tanous return; 20974c9afe43SEd Tanous } 20984c9afe43SEd Tanous 20990f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 21000f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 21010f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 21020f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 21030f74e643SEd Tanous "/redfish/v1/$metadata" 21040f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 21050f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 21060f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 21070f74e643SEd Tanous "VLAN Network Interface Collection"; 21084a0cb85cSEd Tanous 21094a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 21104a0cb85cSEd Tanous 21114a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 21121abe55efSEd Tanous { 21134a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 21144a0cb85cSEd Tanous { 21154a0cb85cSEd Tanous iface_array.push_back( 21164a0cb85cSEd Tanous {{"@odata.id", 21174a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 21184a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2119e439f0f8SKowalski, Kamil } 2120e439f0f8SKowalski, Kamil } 2121e439f0f8SKowalski, Kamil 21224a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 21234a0cb85cSEd Tanous iface_array.size(); 21244a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 21254a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 21264a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 21274a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2128e439f0f8SKowalski, Kamil }); 2129e439f0f8SKowalski, Kamil } 2130e439f0f8SKowalski, Kamil 213155c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 21321abe55efSEd Tanous const std::vector<std::string> ¶ms) override 21331abe55efSEd Tanous { 21344a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 21351abe55efSEd Tanous if (params.size() != 1) 21361abe55efSEd Tanous { 2137f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2138e439f0f8SKowalski, Kamil return; 2139e439f0f8SKowalski, Kamil } 2140fda13ad2SSunitha Harish bool vlanEnable = false; 21410627a2c7SEd Tanous uint32_t vlanId = 0; 2142fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2143fda13ad2SSunitha Harish vlanEnable)) 21441abe55efSEd Tanous { 21454a0cb85cSEd Tanous return; 2146e439f0f8SKowalski, Kamil } 2147fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2148fda13ad2SSunitha Harish if (!vlanId) 2149fda13ad2SSunitha Harish { 2150fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2151fda13ad2SSunitha Harish } 2152fda13ad2SSunitha Harish if (!vlanEnable) 2153fda13ad2SSunitha Harish { 2154fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2155fda13ad2SSunitha Harish } 2156fda13ad2SSunitha Harish if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) 2157fda13ad2SSunitha Harish { 2158fda13ad2SSunitha Harish return; 2159fda13ad2SSunitha Harish } 2160fda13ad2SSunitha Harish 21614a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 21624a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 21631abe55efSEd Tanous if (ec) 21641abe55efSEd Tanous { 21654a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 21664a0cb85cSEd Tanous // phosphor-network responses 2167f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21684a0cb85cSEd Tanous return; 21691abe55efSEd Tanous } 2170f12894f8SJason M. Bills messages::created(asyncResp->res); 2171e439f0f8SKowalski, Kamil }; 21724a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21734a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21744a0cb85cSEd Tanous "/xyz/openbmc_project/network", 21754a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 21760627a2c7SEd Tanous rootInterfaceName, vlanId); 21774a0cb85cSEd Tanous } 21784a0cb85cSEd Tanous }; 21799391bb9cSRapkiewicz, Pawel } // namespace redfish 2180