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 385*d1d50814SRavi Teja inline void extractIPData( 386*d1d50814SRavi Teja const std::string ðiface_id, const GetManagedObjects &dbus_data, 387*d1d50814SRavi Teja boost::container::flat_set<IPv4AddressData> &ipv4_config, 388*d1d50814SRavi 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 } 460*d1d50814SRavi Teja 461*d1d50814SRavi Teja if (ipv4_address.origin == "Static") 462*d1d50814SRavi Teja { 463*d1d50814SRavi Teja IPv4AddressData ipv4_static_address = { 464*d1d50814SRavi Teja objpath.first.str.substr(ipv4PathStart.size())}; 465*d1d50814SRavi Teja ipv4_static_address.address = ipv4_address.address; 466*d1d50814SRavi Teja ipv4_static_address.gateway = ipv4_address.gateway; 467*d1d50814SRavi Teja ipv4_static_address.netmask = ipv4_address.netmask; 468*d1d50814SRavi Teja ipv4_static_config.emplace(ipv4_static_address); 469*d1d50814SRavi Teja } 470*d1d50814SRavi 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; 834*d1d50814SRavi 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 { 840*d1d50814SRavi Teja callback(false, ethData, ipv4Data, ipv4StaticData, ipv6Data, 841*d1d50814SRavi 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 { 849*d1d50814SRavi Teja callback(false, ethData, ipv4Data, ipv4StaticData, ipv6Data, 850*d1d50814SRavi Teja ipv6StaticData); 8514c9afe43SEd Tanous return; 8524c9afe43SEd Tanous } 8534c9afe43SEd Tanous 854*d1d50814SRavi Teja extractIPData(ethiface_id, resp, ipv4Data, ipv4StaticData); 855179db1d7SKowalski, Kamil // Fix global GW 8561abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 8571abe55efSEd Tanous { 8584a0cb85cSEd Tanous if ((ipv4.linktype == LinkType::Global) && 8594a0cb85cSEd Tanous (ipv4.gateway == "0.0.0.0")) 8601abe55efSEd Tanous { 8614a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 862179db1d7SKowalski, Kamil } 863179db1d7SKowalski, Kamil } 864179db1d7SKowalski, Kamil 865e48c0fc5SRavi Teja extractIPV6Data(ethiface_id, resp, ipv6Data, ipv6StaticData); 8664a0cb85cSEd Tanous // Finally make a callback with usefull data 867*d1d50814SRavi Teja callback(true, ethData, ipv4Data, ipv4StaticData, ipv6Data, 868*d1d50814SRavi Teja ipv6StaticData); 869179db1d7SKowalski, Kamil }, 870179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 871179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 872179db1d7SKowalski, Kamil }; 873179db1d7SKowalski, Kamil 874179db1d7SKowalski, Kamil /** 8759391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8769391bb9cSRapkiewicz, Pawel * Manager 8771abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8781abe55efSEd Tanous * into JSON. 8799391bb9cSRapkiewicz, Pawel */ 8809391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8811abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 8821abe55efSEd Tanous { 88355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8844a0cb85cSEd Tanous [callback{std::move(callback)}]( 8859391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 8864a0cb85cSEd Tanous GetManagedObjects &resp) { 8871abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8881abe55efSEd Tanous // ethernet interfaces 8894c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 8904a0cb85cSEd Tanous iface_list.reserve(resp.size()); 8911abe55efSEd Tanous if (error_code) 8921abe55efSEd Tanous { 8934a0cb85cSEd Tanous callback(false, iface_list); 8949391bb9cSRapkiewicz, Pawel return; 8959391bb9cSRapkiewicz, Pawel } 8969391bb9cSRapkiewicz, Pawel 8979391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8984a0cb85cSEd Tanous for (const auto &objpath : resp) 8991abe55efSEd Tanous { 9009391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 9014a0cb85cSEd Tanous for (const auto &interface : objpath.second) 9021abe55efSEd Tanous { 9031abe55efSEd Tanous // If interface is 9044a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9054a0cb85cSEd Tanous // what we're looking for. 9069391bb9cSRapkiewicz, Pawel if (interface.first == 9071abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9081abe55efSEd Tanous { 9094a0cb85cSEd Tanous // Cut out everyting until last "/", ... 9104a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9114a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9124a0cb85cSEd Tanous if (last_pos != std::string::npos) 9131abe55efSEd Tanous { 9149391bb9cSRapkiewicz, Pawel // and put it into output vector. 9154c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9169391bb9cSRapkiewicz, Pawel } 9179391bb9cSRapkiewicz, Pawel } 9189391bb9cSRapkiewicz, Pawel } 9199391bb9cSRapkiewicz, Pawel } 920a434f2bdSEd Tanous // Finally make a callback with useful data 9214a0cb85cSEd Tanous callback(true, iface_list); 9229391bb9cSRapkiewicz, Pawel }, 923aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 924aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 9259391bb9cSRapkiewicz, Pawel }; 9269391bb9cSRapkiewicz, Pawel 9279391bb9cSRapkiewicz, Pawel /** 9289391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9299391bb9cSRapkiewicz, Pawel */ 9301abe55efSEd Tanous class EthernetCollection : public Node 9311abe55efSEd Tanous { 9329391bb9cSRapkiewicz, Pawel public: 9334a0cb85cSEd Tanous template <typename CrowApp> 9341abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9354a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9361abe55efSEd Tanous { 937588c3f0dSKowalski, Kamil entityPrivileges = { 938588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 939e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 940e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 941e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 942e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 943e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9449391bb9cSRapkiewicz, Pawel } 9459391bb9cSRapkiewicz, Pawel 9469391bb9cSRapkiewicz, Pawel private: 9479391bb9cSRapkiewicz, Pawel /** 9489391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 9499391bb9cSRapkiewicz, Pawel */ 95055c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 9511abe55efSEd Tanous const std::vector<std::string> ¶ms) override 9521abe55efSEd Tanous { 9530f74e643SEd Tanous res.jsonValue["@odata.type"] = 9540f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9550f74e643SEd Tanous res.jsonValue["@odata.context"] = 9560f74e643SEd Tanous "/redfish/v1/" 9570f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9580f74e643SEd Tanous res.jsonValue["@odata.id"] = 9590f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9600f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 9610f74e643SEd Tanous res.jsonValue["Description"] = 9620f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 9634c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 9644a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 9651abe55efSEd Tanous // preparation 966f12894f8SJason M. Bills getEthernetIfaceList( 9674c9afe43SEd Tanous [asyncResp]( 9684c9afe43SEd Tanous const bool &success, 9694c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 9704a0cb85cSEd Tanous if (!success) 9711abe55efSEd Tanous { 9724c9afe43SEd Tanous messages::internalError(asyncResp->res); 9734a0cb85cSEd Tanous return; 9744a0cb85cSEd Tanous } 9754a0cb85cSEd Tanous 9764c9afe43SEd Tanous nlohmann::json &iface_array = 9774c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 9784a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 979fda13ad2SSunitha Harish std::string tag = "_"; 9804a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 9811abe55efSEd Tanous { 982fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 983fda13ad2SSunitha Harish if (found == std::string::npos) 984fda13ad2SSunitha Harish { 9854a0cb85cSEd Tanous iface_array.push_back( 9864a0cb85cSEd Tanous {{"@odata.id", 9874a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 9884a0cb85cSEd Tanous iface_item}}); 9899391bb9cSRapkiewicz, Pawel } 990fda13ad2SSunitha Harish } 9914a0cb85cSEd Tanous 9924c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 9934c9afe43SEd Tanous iface_array.size(); 9944c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9954a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9969391bb9cSRapkiewicz, Pawel }); 9979391bb9cSRapkiewicz, Pawel } 9989391bb9cSRapkiewicz, Pawel }; 9999391bb9cSRapkiewicz, Pawel 10009391bb9cSRapkiewicz, Pawel /** 10019391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 10029391bb9cSRapkiewicz, Pawel */ 10031abe55efSEd Tanous class EthernetInterface : public Node 10041abe55efSEd Tanous { 10059391bb9cSRapkiewicz, Pawel public: 10069391bb9cSRapkiewicz, Pawel /* 10079391bb9cSRapkiewicz, Pawel * Default Constructor 10089391bb9cSRapkiewicz, Pawel */ 10094a0cb85cSEd Tanous template <typename CrowApp> 10101abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10114a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10121abe55efSEd Tanous std::string()) 10131abe55efSEd Tanous { 1014588c3f0dSKowalski, Kamil entityPrivileges = { 1015588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1016e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1017e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1018e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1019e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1020e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10219391bb9cSRapkiewicz, Pawel } 10229391bb9cSRapkiewicz, Pawel 1023e439f0f8SKowalski, Kamil private: 1024bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10254a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10261abe55efSEd Tanous { 1027bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1028bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1029bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10304a0cb85cSEd Tanous if (ec) 10314a0cb85cSEd Tanous { 1032a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10331abe55efSEd Tanous } 1034bc0bd6e0SEd Tanous }, 1035bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1036bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1037bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1038bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1039abf2add6SEd Tanous std::variant<std::string>(hostname)); 1040588c3f0dSKowalski, Kamil } 1041588c3f0dSKowalski, Kamil 1042d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1043d577665bSRatan Gupta const std::string &macAddress, 1044d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1045d577665bSRatan Gupta { 1046d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1047d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1048d577665bSRatan Gupta if (ec) 1049d577665bSRatan Gupta { 1050d577665bSRatan Gupta messages::internalError(asyncResp->res); 1051d577665bSRatan Gupta return; 1052d577665bSRatan Gupta } 1053d577665bSRatan Gupta }, 1054d577665bSRatan Gupta "xyz.openbmc_project.Network", 1055d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1056d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1057d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1058d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1059d577665bSRatan Gupta } 1060286b9118SJohnathan Mantey 1061da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1062da131a9aSJennifer Lee const std::string &propertyName, const bool &value, 1063da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1064da131a9aSJennifer Lee { 1065da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1066da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1067da131a9aSJennifer Lee if (ec) 1068da131a9aSJennifer Lee { 1069da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1070da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1071da131a9aSJennifer Lee return; 1072da131a9aSJennifer Lee } 1073da131a9aSJennifer Lee }, 1074da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1075da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1076da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1077da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1078da131a9aSJennifer Lee std::variant<bool>{value}); 1079da131a9aSJennifer Lee } 1080da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1081da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1082da131a9aSJennifer Lee { 1083da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1084da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1085da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1086da131a9aSJennifer Lee if (ec) 1087da131a9aSJennifer Lee { 1088da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1089da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1090da131a9aSJennifer Lee return; 1091da131a9aSJennifer Lee } 1092da131a9aSJennifer Lee }, 1093da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1094da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1095da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1096da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1097da131a9aSJennifer Lee std::variant<bool>{value}); 1098da131a9aSJennifer Lee } 1099d577665bSRatan Gupta 1100da131a9aSJennifer Lee void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input, 1101da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1102da131a9aSJennifer Lee { 1103da131a9aSJennifer Lee std::optional<bool> dhcpEnabled; 1104da131a9aSJennifer Lee std::optional<bool> useDNSServers; 1105da131a9aSJennifer Lee std::optional<bool> useDomainName; 1106da131a9aSJennifer Lee std::optional<bool> useNTPServers; 1107da131a9aSJennifer Lee 1108da131a9aSJennifer Lee if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled", 1109da131a9aSJennifer Lee dhcpEnabled, "UseDNSServers", useDNSServers, 1110da131a9aSJennifer Lee "UseDomainName", useDomainName, 1111da131a9aSJennifer Lee "UseNTPServers", useNTPServers)) 1112da131a9aSJennifer Lee { 1113da131a9aSJennifer Lee return; 1114da131a9aSJennifer Lee } 1115da131a9aSJennifer Lee 1116da131a9aSJennifer Lee if (dhcpEnabled) 1117da131a9aSJennifer Lee { 1118da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1119da131a9aSJennifer Lee setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp); 1120da131a9aSJennifer Lee } 1121da131a9aSJennifer Lee 1122da131a9aSJennifer Lee if (useDNSServers) 1123da131a9aSJennifer Lee { 1124da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1125da131a9aSJennifer Lee setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp); 1126da131a9aSJennifer Lee } 1127da131a9aSJennifer Lee 1128da131a9aSJennifer Lee if (useDomainName) 1129da131a9aSJennifer Lee { 1130da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1131da131a9aSJennifer Lee setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp); 1132da131a9aSJennifer Lee } 1133da131a9aSJennifer Lee 1134da131a9aSJennifer Lee if (useNTPServers) 1135da131a9aSJennifer Lee { 1136da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1137da131a9aSJennifer Lee setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp); 1138da131a9aSJennifer Lee } 1139da131a9aSJennifer Lee } 1140*d1d50814SRavi Teja void handleIPv4StaticPatch( 1141f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 1142*d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4StaticData, 11434a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 11441abe55efSEd Tanous { 1145f476acbfSRatan Gupta if (!input.is_array()) 1146f476acbfSRatan Gupta { 1147f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1148*d1d50814SRavi Teja "IPv4StaticAddresses"); 1149f476acbfSRatan Gupta return; 1150f476acbfSRatan Gupta } 1151f476acbfSRatan Gupta 11524a0cb85cSEd Tanous int entryIdx = 0; 11534a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::const_iterator thisData = 1154*d1d50814SRavi Teja ipv4StaticData.begin(); 1155537174c4SEd Tanous for (nlohmann::json &thisJson : input) 11561abe55efSEd Tanous { 11574a0cb85cSEd Tanous std::string pathString = 1158*d1d50814SRavi Teja "IPv4StaticAddresses/" + std::to_string(entryIdx); 1159179db1d7SKowalski, Kamil 1160f476acbfSRatan Gupta if (thisJson.is_null()) 1161f476acbfSRatan Gupta { 1162*d1d50814SRavi Teja if (thisData != ipv4StaticData.end()) 1163f476acbfSRatan Gupta { 1164286b9118SJohnathan Mantey deleteIPv4(ifaceId, thisData->id, asyncResp); 1165f476acbfSRatan Gupta thisData++; 1166f476acbfSRatan Gupta } 1167f476acbfSRatan Gupta else 1168f476acbfSRatan Gupta { 1169f476acbfSRatan Gupta messages::propertyValueFormatError( 1170f476acbfSRatan Gupta asyncResp->res, input.dump(), pathString); 1171f476acbfSRatan Gupta return; 1172f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 1173f476acbfSRatan Gupta // list and if unable to update one of the 1174f476acbfSRatan Gupta // list value then should we proceed further or 1175f476acbfSRatan Gupta // break there, would ask in the redfish forum 1176f476acbfSRatan Gupta // till then we stop processing the next list item. 1177f476acbfSRatan Gupta } 1178f476acbfSRatan Gupta entryIdx++; 1179f476acbfSRatan Gupta continue; // not an error as per the redfish spec. 1180f476acbfSRatan Gupta } 1181f476acbfSRatan Gupta 11829474b378SRatan Gupta if (thisJson.empty()) 11839474b378SRatan Gupta { 1184*d1d50814SRavi Teja if (thisData != ipv4StaticData.end()) 11859474b378SRatan Gupta { 11869474b378SRatan Gupta thisData++; 11879474b378SRatan Gupta } 11889474b378SRatan Gupta else 11899474b378SRatan Gupta { 11909474b378SRatan Gupta messages::propertyMissing(asyncResp->res, 11919474b378SRatan Gupta pathString + "/Address"); 11929474b378SRatan Gupta return; 1193f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 11949474b378SRatan Gupta // list and if unable to update one of the 11959474b378SRatan Gupta // list value then should we proceed further or 11969474b378SRatan Gupta // break there, would ask in the redfish forum 11979474b378SRatan Gupta // till then we stop processing the next list item. 11989474b378SRatan Gupta } 11999474b378SRatan Gupta entryIdx++; 12009474b378SRatan Gupta continue; // not an error as per the redfish spec. 12019474b378SRatan Gupta } 12029474b378SRatan Gupta 1203537174c4SEd Tanous std::optional<std::string> address; 1204537174c4SEd Tanous std::optional<std::string> subnetMask; 1205537174c4SEd Tanous std::optional<std::string> gateway; 1206537174c4SEd Tanous 1207537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 12087e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 12097e27d832SJohnathan Mantey "Gateway", gateway)) 1210537174c4SEd Tanous { 1211537174c4SEd Tanous return; 1212179db1d7SKowalski, Kamil } 1213179db1d7SKowalski, Kamil 1214537174c4SEd Tanous if (address) 12151abe55efSEd Tanous { 1216537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*address)) 12171abe55efSEd Tanous { 1218537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 12194a0cb85cSEd Tanous pathString + "/Address"); 1220537174c4SEd Tanous return; 12214a0cb85cSEd Tanous } 12224a0cb85cSEd Tanous } 12234a0cb85cSEd Tanous 1224537174c4SEd Tanous uint8_t prefixLength = 0; 1225537174c4SEd Tanous if (subnetMask) 12264a0cb85cSEd Tanous { 1227537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 12284a0cb85cSEd Tanous { 1229f12894f8SJason M. Bills messages::propertyValueFormatError( 1230537174c4SEd Tanous asyncResp->res, *subnetMask, 12314a0cb85cSEd Tanous pathString + "/SubnetMask"); 1232537174c4SEd Tanous return; 12334a0cb85cSEd Tanous } 12344a0cb85cSEd Tanous } 12354a0cb85cSEd Tanous 1236537174c4SEd Tanous if (gateway) 12374a0cb85cSEd Tanous { 1238537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*gateway)) 12394a0cb85cSEd Tanous { 1240537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1241537174c4SEd Tanous pathString + "/Gateway"); 1242537174c4SEd Tanous return; 12434a0cb85cSEd Tanous } 12444a0cb85cSEd Tanous } 12454a0cb85cSEd Tanous 1246f476acbfSRatan Gupta // if IP address exist then modify it. 1247*d1d50814SRavi Teja if (thisData != ipv4StaticData.end()) 12484a0cb85cSEd Tanous { 1249179db1d7SKowalski, Kamil // Apply changes 1250537174c4SEd Tanous if (address) 12511abe55efSEd Tanous { 1252286b9118SJohnathan Mantey auto callback = 1253286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 12544a0cb85cSEd Tanous if (ec) 12551abe55efSEd Tanous { 1256a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12574a0cb85cSEd Tanous return; 12584a0cb85cSEd Tanous } 12594a0cb85cSEd Tanous }; 12604a0cb85cSEd Tanous 12614a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12624a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1263f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1264f476acbfSRatan Gupta thisData->id, 12654a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12664a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Address", 1267537174c4SEd Tanous std::variant<std::string>(*address)); 1268179db1d7SKowalski, Kamil } 1269179db1d7SKowalski, Kamil 1270537174c4SEd Tanous if (subnetMask) 12711abe55efSEd Tanous { 12724a0cb85cSEd Tanous changeIPv4SubnetMaskProperty(ifaceId, entryIdx, 1273286b9118SJohnathan Mantey thisData->id, prefixLength, 1274286b9118SJohnathan Mantey asyncResp); 1275179db1d7SKowalski, Kamil } 1276179db1d7SKowalski, Kamil 1277537174c4SEd Tanous if (gateway) 12781abe55efSEd Tanous { 1279286b9118SJohnathan Mantey auto callback = 1280286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 12814a0cb85cSEd Tanous if (ec) 12821abe55efSEd Tanous { 1283a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12844a0cb85cSEd Tanous return; 12854a0cb85cSEd Tanous } 12864a0cb85cSEd Tanous }; 12874a0cb85cSEd Tanous 12884a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12894a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1290f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1291f476acbfSRatan Gupta thisData->id, 12924a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12934a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Gateway", 1294537174c4SEd Tanous std::variant<std::string>(*gateway)); 12954a0cb85cSEd Tanous } 1296f476acbfSRatan Gupta 12974a0cb85cSEd Tanous thisData++; 12981abe55efSEd Tanous } 12991abe55efSEd Tanous else 13001abe55efSEd Tanous { 13014a0cb85cSEd Tanous // Create IPv4 with provided data 1302537174c4SEd Tanous if (!gateway) 13031abe55efSEd Tanous { 1304a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13054a0cb85cSEd Tanous pathString + "/Gateway"); 13064a0cb85cSEd Tanous continue; 13074a0cb85cSEd Tanous } 13084a0cb85cSEd Tanous 1309537174c4SEd Tanous if (!address) 13101abe55efSEd Tanous { 1311a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13124a0cb85cSEd Tanous pathString + "/Address"); 13134a0cb85cSEd Tanous continue; 13144a0cb85cSEd Tanous } 13154a0cb85cSEd Tanous 1316537174c4SEd Tanous if (!subnetMask) 13171abe55efSEd Tanous { 1318a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13194a0cb85cSEd Tanous pathString + "/SubnetMask"); 13204a0cb85cSEd Tanous continue; 1321588c3f0dSKowalski, Kamil } 1322588c3f0dSKowalski, Kamil 1323b01bf299SEd Tanous createIPv4(ifaceId, entryIdx, prefixLength, *gateway, *address, 1324b01bf299SEd Tanous asyncResp); 132595897b20SRatan Gupta 1326*d1d50814SRavi Teja nlohmann::json &ipv4StaticAddressJson = 1327*d1d50814SRavi Teja asyncResp->res.jsonValue["IPv4StaticAddresses"][entryIdx]; 1328*d1d50814SRavi Teja ipv4StaticAddressJson["Address"] = *address; 1329*d1d50814SRavi Teja ipv4StaticAddressJson["SubnetMask"] = *subnetMask; 1330*d1d50814SRavi Teja ipv4StaticAddressJson["Gateway"] = *gateway; 13314a0cb85cSEd Tanous } 13324a0cb85cSEd Tanous entryIdx++; 13334a0cb85cSEd Tanous } 13344a0cb85cSEd Tanous } 13354a0cb85cSEd Tanous 1336f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1337f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1338f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1339f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1340f85837bfSRAJESWARAN THILLAIGOVINDAN { 1341f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1342286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1343f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1344f85837bfSRAJESWARAN THILLAIGOVINDAN { 1345f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1346f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1347f85837bfSRAJESWARAN THILLAIGOVINDAN } 1348f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1349f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1350f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1351f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1352f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1353f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1354f85837bfSRAJESWARAN THILLAIGOVINDAN } 1355f85837bfSRAJESWARAN THILLAIGOVINDAN 1356e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1357e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 1358e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData, 1359e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1360e48c0fc5SRavi Teja { 1361e48c0fc5SRavi Teja if (!input.is_array()) 1362e48c0fc5SRavi Teja { 1363e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1364e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1365e48c0fc5SRavi Teja return; 1366e48c0fc5SRavi Teja } 1367e48c0fc5SRavi Teja 1368e48c0fc5SRavi Teja int entryIdx = 0; 1369e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::const_iterator thisData = 1370e48c0fc5SRavi Teja ipv6StaticData.begin(); 1371e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1372e48c0fc5SRavi Teja { 1373e48c0fc5SRavi Teja std::string pathString = 1374e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1375e48c0fc5SRavi Teja 1376e48c0fc5SRavi Teja if (thisJson.is_null()) 1377e48c0fc5SRavi Teja { 1378e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1379e48c0fc5SRavi Teja { 1380286b9118SJohnathan Mantey deleteIPv6(ifaceId, thisData->id, asyncResp); 1381e48c0fc5SRavi Teja thisData++; 1382e48c0fc5SRavi Teja } 1383e48c0fc5SRavi Teja else 1384e48c0fc5SRavi Teja { 1385e48c0fc5SRavi Teja messages::propertyValueFormatError( 1386e48c0fc5SRavi Teja asyncResp->res, input.dump(), pathString); 1387e48c0fc5SRavi Teja return; 1388e48c0fc5SRavi Teja } 1389e48c0fc5SRavi Teja entryIdx++; 1390e48c0fc5SRavi Teja continue; 1391e48c0fc5SRavi Teja } 1392e48c0fc5SRavi Teja 1393e48c0fc5SRavi Teja if (thisJson.empty()) 1394e48c0fc5SRavi Teja { 1395e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1396e48c0fc5SRavi Teja { 1397e48c0fc5SRavi Teja thisData++; 1398e48c0fc5SRavi Teja } 1399e48c0fc5SRavi Teja else 1400e48c0fc5SRavi Teja { 1401e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1402e48c0fc5SRavi Teja pathString + "/Address"); 1403e48c0fc5SRavi Teja return; 1404e48c0fc5SRavi Teja } 1405e48c0fc5SRavi Teja entryIdx++; 1406e48c0fc5SRavi Teja continue; 1407e48c0fc5SRavi Teja } 1408e48c0fc5SRavi Teja 1409e48c0fc5SRavi Teja std::optional<std::string> address; 1410e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1411e48c0fc5SRavi Teja 1412e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1413e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1414e48c0fc5SRavi Teja { 1415e48c0fc5SRavi Teja return; 1416e48c0fc5SRavi Teja } 1417e48c0fc5SRavi Teja 1418e48c0fc5SRavi Teja // if IP address exist then modify it. 1419e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1420e48c0fc5SRavi Teja { 1421e48c0fc5SRavi Teja // Apply changes 1422e48c0fc5SRavi Teja if (address) 1423e48c0fc5SRavi Teja { 1424286b9118SJohnathan Mantey auto callback = 1425286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1426e48c0fc5SRavi Teja if (ec) 1427e48c0fc5SRavi Teja { 1428e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1429e48c0fc5SRavi Teja return; 1430e48c0fc5SRavi Teja } 1431e48c0fc5SRavi Teja }; 1432e48c0fc5SRavi Teja 1433e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1434e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1435e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1436e48c0fc5SRavi Teja thisData->id, 1437e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1438e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "Address", 1439e48c0fc5SRavi Teja std::variant<std::string>(*address)); 1440e48c0fc5SRavi Teja } 1441e48c0fc5SRavi Teja 1442e48c0fc5SRavi Teja if (prefixLength) 1443e48c0fc5SRavi Teja { 1444286b9118SJohnathan Mantey auto callback = 1445286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1446e48c0fc5SRavi Teja if (ec) 1447e48c0fc5SRavi Teja { 1448e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1449e48c0fc5SRavi Teja return; 1450e48c0fc5SRavi Teja } 1451e48c0fc5SRavi Teja }; 1452e48c0fc5SRavi Teja 1453e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1454e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1455e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1456e48c0fc5SRavi Teja thisData->id, 1457e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1458e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "PrefixLength", 1459e48c0fc5SRavi Teja std::variant<uint8_t>(*prefixLength)); 1460e48c0fc5SRavi Teja } 1461e48c0fc5SRavi Teja 1462e48c0fc5SRavi Teja thisData++; 1463e48c0fc5SRavi Teja } 1464e48c0fc5SRavi Teja else 1465e48c0fc5SRavi Teja { 1466e48c0fc5SRavi Teja // Create IPv6 with provided data 1467e48c0fc5SRavi Teja 1468e48c0fc5SRavi Teja if (!prefixLength) 1469e48c0fc5SRavi Teja { 1470e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1471e48c0fc5SRavi Teja pathString + "/PrefixLength"); 1472e48c0fc5SRavi Teja continue; 1473e48c0fc5SRavi Teja } 1474e48c0fc5SRavi Teja 1475e48c0fc5SRavi Teja if (!address) 1476e48c0fc5SRavi Teja { 1477e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1478e48c0fc5SRavi Teja pathString + "/Address"); 1479e48c0fc5SRavi Teja continue; 1480e48c0fc5SRavi Teja } 1481e48c0fc5SRavi Teja 1482e48c0fc5SRavi Teja createIPv6(ifaceId, entryIdx, *prefixLength, *address, 1483e48c0fc5SRavi Teja asyncResp); 1484e48c0fc5SRavi Teja 1485e48c0fc5SRavi Teja nlohmann::json &ipv6StaticAddressJson = 1486e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"][entryIdx]; 1487e48c0fc5SRavi Teja ipv6StaticAddressJson["Address"] = *address; 1488e48c0fc5SRavi Teja ipv6StaticAddressJson["PrefixLength"] = *prefixLength; 1489e48c0fc5SRavi Teja } 1490e48c0fc5SRavi Teja entryIdx++; 1491e48c0fc5SRavi Teja } 1492e48c0fc5SRavi Teja } 1493e48c0fc5SRavi Teja 14940f74e643SEd Tanous void parseInterfaceData( 14950f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 14960f74e643SEd Tanous const EthernetInterfaceData ðData, 1497e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1498*d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4StaticData, 1499e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1500e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 15014a0cb85cSEd Tanous { 15024a0cb85cSEd Tanous json_response["Id"] = iface_id; 15034a0cb85cSEd Tanous json_response["@odata.id"] = 15044a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1505029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1506029573d4SEd Tanous if (ethData.speed == 0) 1507029573d4SEd Tanous { 1508029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1509029573d4SEd Tanous json_response["Status"] = { 1510029573d4SEd Tanous {"Health", "OK"}, 1511029573d4SEd Tanous {"State", "Disabled"}, 1512029573d4SEd Tanous }; 1513029573d4SEd Tanous } 1514029573d4SEd Tanous else 1515029573d4SEd Tanous { 1516029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1517029573d4SEd Tanous json_response["Status"] = { 1518029573d4SEd Tanous {"Health", "OK"}, 1519029573d4SEd Tanous {"State", "Enabled"}, 1520029573d4SEd Tanous }; 1521029573d4SEd Tanous } 15224a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 15234a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1524fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 15252a133282Smanojkiraneda 15264a0cb85cSEd Tanous if (!ethData.hostname.empty()) 15274a0cb85cSEd Tanous { 15284a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 1529d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1530d24bfc7aSJennifer Lee { 1531d24bfc7aSJennifer Lee json_response["FQDN"] = 1532d24bfc7aSJennifer Lee ethData.hostname + "." + ethData.domainnames[0]; 1533d24bfc7aSJennifer Lee } 15344a0cb85cSEd Tanous } 15354a0cb85cSEd Tanous 1536fda13ad2SSunitha Harish json_response["VLANs"] = { 1537fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1538fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1539fda13ad2SSunitha Harish 1540029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 1541f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 15424a0cb85cSEd Tanous 15434a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 15444a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 15454a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 15464a0cb85cSEd Tanous { 1547fa5053a6SGunnar Mills 1548fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1549fa5053a6SGunnar Mills if (gatewayStr.empty()) 1550fa5053a6SGunnar Mills { 1551fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1552fa5053a6SGunnar Mills } 1553fa5053a6SGunnar Mills 15544a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 15554a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1556029573d4SEd Tanous {"Address", ipv4_config.address}, 1557fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 15584a0cb85cSEd Tanous } 1559*d1d50814SRavi Teja 1560*d1d50814SRavi Teja nlohmann::json &ipv4_static_array = 1561*d1d50814SRavi Teja json_response["IPv4StaticAddresses"]; 1562*d1d50814SRavi Teja ipv4_static_array = nlohmann::json::array(); 1563*d1d50814SRavi Teja for (auto &ipv4_static_config : ipv4StaticData) 1564*d1d50814SRavi Teja { 1565*d1d50814SRavi Teja 1566*d1d50814SRavi Teja std::string gatewayStr = ipv4_static_config.gateway; 1567*d1d50814SRavi Teja if (gatewayStr.empty()) 1568*d1d50814SRavi Teja { 1569*d1d50814SRavi Teja gatewayStr = "0.0.0.0"; 15704a0cb85cSEd Tanous } 1571*d1d50814SRavi Teja 1572*d1d50814SRavi Teja ipv4_static_array.push_back( 1573*d1d50814SRavi Teja {{"SubnetMask", ipv4_static_config.netmask}, 1574*d1d50814SRavi Teja {"Address", ipv4_static_config.address}, 1575*d1d50814SRavi Teja {"Gateway", gatewayStr}}); 1576*d1d50814SRavi Teja } 1577*d1d50814SRavi Teja 15789a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1579e48c0fc5SRavi Teja 1580e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 1581e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 1582e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1583e48c0fc5SRavi Teja { 1584e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1585e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1586e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 1587e48c0fc5SRavi Teja } 1588e48c0fc5SRavi Teja 1589e48c0fc5SRavi Teja nlohmann::json &ipv6_static_array = 1590e48c0fc5SRavi Teja json_response["IPv6StaticAddresses"]; 1591e48c0fc5SRavi Teja ipv6_static_array = nlohmann::json::array(); 1592e48c0fc5SRavi Teja for (auto &ipv6_static_config : ipv6StaticData) 1593e48c0fc5SRavi Teja { 1594e48c0fc5SRavi Teja ipv6_static_array.push_back( 1595e48c0fc5SRavi Teja {{"Address", ipv6_static_config.address}, 1596e48c0fc5SRavi Teja {"PrefixLength", ipv6_static_config.prefixLength}}); 1597e48c0fc5SRavi Teja } 1598588c3f0dSKowalski, Kamil } 1599588c3f0dSKowalski, Kamil 16009391bb9cSRapkiewicz, Pawel /** 16019391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 16029391bb9cSRapkiewicz, Pawel */ 160355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 16041abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16051abe55efSEd Tanous { 16064a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16071abe55efSEd Tanous if (params.size() != 1) 16081abe55efSEd Tanous { 1609f12894f8SJason M. Bills messages::internalError(asyncResp->res); 16109391bb9cSRapkiewicz, Pawel return; 16119391bb9cSRapkiewicz, Pawel } 16129391bb9cSRapkiewicz, Pawel 16134a0cb85cSEd Tanous getEthernetIfaceData( 16144a0cb85cSEd Tanous params[0], 16154a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 16164a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1617e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1618*d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 1619*d1d50814SRavi Teja &ipv4StaticData, 1620e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1621e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1622e48c0fc5SRavi Teja &ipv6StaticData) { 16234a0cb85cSEd Tanous if (!success) 16241abe55efSEd Tanous { 16251abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16261abe55efSEd Tanous // object, and other errors 1627f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1628f12894f8SJason M. Bills "EthernetInterface", iface_id); 16294a0cb85cSEd Tanous return; 16309391bb9cSRapkiewicz, Pawel } 16314c9afe43SEd Tanous 16324c9afe43SEd Tanous // because this has no dependence on the interface at this 16334c9afe43SEd Tanous // point, it needs to be done after we know the interface 16344c9afe43SEd Tanous // exists, not before. 16354c9afe43SEd Tanous getDHCPConfigData(asyncResp); 16364c9afe43SEd Tanous 16370f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1638fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 16390f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 16400f74e643SEd Tanous "/redfish/v1/$metadata#EthernetInterface.EthernetInterface"; 16410f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 16420f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 16430f74e643SEd Tanous "Management Network Interface"; 16440f74e643SEd Tanous 16450f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1646*d1d50814SRavi Teja ipv4Data, ipv4StaticData, ipv6Data, 1647*d1d50814SRavi Teja ipv6StaticData); 16489391bb9cSRapkiewicz, Pawel }); 16499391bb9cSRapkiewicz, Pawel } 16509391bb9cSRapkiewicz, Pawel 165155c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 16521abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16531abe55efSEd Tanous { 16544a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16551abe55efSEd Tanous if (params.size() != 1) 16561abe55efSEd Tanous { 1657f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1658588c3f0dSKowalski, Kamil return; 1659588c3f0dSKowalski, Kamil } 1660588c3f0dSKowalski, Kamil 16614a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1662588c3f0dSKowalski, Kamil 1663bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1664d577665bSRatan Gupta std::optional<std::string> macAddress; 16659a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1666f476acbfSRatan Gupta std::optional<nlohmann::json> ipv4Addresses; 1667*d1d50814SRavi Teja std::optional<nlohmann::json> ipv4StaticAddresses; 1668f476acbfSRatan Gupta std::optional<nlohmann::json> ipv6Addresses; 1669e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1670f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 16715112e9b4SRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> nameServers; 1672da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 16730627a2c7SEd Tanous 1674fda13ad2SSunitha Harish if (!json_util::readJson( 1675fda13ad2SSunitha Harish req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses, 1676*d1d50814SRavi Teja "IPv4StaticAddresses", ipv4StaticAddresses, "MACAddress", 1677*d1d50814SRavi Teja macAddress, "StaticNameServers", staticNameServers, 1678*d1d50814SRavi Teja "IPv6DefaultGateway", ipv6DefaultGateway, "IPv6StaticAddresses", 1679*d1d50814SRavi Teja ipv6StaticAddresses, "NameServers", nameServers, "DHCPv4", 1680*d1d50814SRavi Teja dhcpv4)) 16811abe55efSEd Tanous { 1682588c3f0dSKowalski, Kamil return; 1683588c3f0dSKowalski, Kamil } 1684f15aad37SRatan Gupta 1685da131a9aSJennifer Lee if (dhcpv4) 1686da131a9aSJennifer Lee { 1687da131a9aSJennifer Lee handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp); 1688da131a9aSJennifer Lee } 1689da131a9aSJennifer Lee 16904a0cb85cSEd Tanous // Get single eth interface data, and call the below callback for JSON 1691588c3f0dSKowalski, Kamil // preparation 16924a0cb85cSEd Tanous getEthernetIfaceData( 16934a0cb85cSEd Tanous iface_id, 1694fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1695fda13ad2SSunitha Harish macAddress = std::move(macAddress), 16960627a2c7SEd Tanous ipv4Addresses = std::move(ipv4Addresses), 1697*d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 16989a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1699e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 17005112e9b4SRAJESWARAN THILLAIGOVINDAN staticNameServers = std::move(staticNameServers), 17015112e9b4SRAJESWARAN THILLAIGOVINDAN nameServers = std::move(nameServers)]( 17024a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1703e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1704*d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 1705*d1d50814SRavi Teja &ipv4StaticData, 1706e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1707e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1708e48c0fc5SRavi Teja &ipv6StaticData) { 17091abe55efSEd Tanous if (!success) 17101abe55efSEd Tanous { 1711588c3f0dSKowalski, Kamil // ... otherwise return error 17121abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 17131abe55efSEd Tanous // object, and other errors 1714fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1715fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1716588c3f0dSKowalski, Kamil return; 1717588c3f0dSKowalski, Kamil } 1718588c3f0dSKowalski, Kamil 17190627a2c7SEd Tanous if (hostname) 17201abe55efSEd Tanous { 17210627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 17221abe55efSEd Tanous } 17230627a2c7SEd Tanous 1724d577665bSRatan Gupta if (macAddress) 1725d577665bSRatan Gupta { 1726d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1727d577665bSRatan Gupta } 1728d577665bSRatan Gupta 17290627a2c7SEd Tanous if (ipv4Addresses) 17301abe55efSEd Tanous { 1731*d1d50814SRavi Teja messages::propertyNotWritable(asyncResp->res, 1732*d1d50814SRavi Teja "IPv4Addresses"); 1733*d1d50814SRavi Teja } 1734*d1d50814SRavi Teja 1735*d1d50814SRavi Teja if (ipv4StaticAddresses) 1736*d1d50814SRavi Teja { 1737537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 1738537174c4SEd Tanous // above is returning a const value, not a non-const value. 1739537174c4SEd Tanous // This doesn't really work for us, as we need to be able to 1740537174c4SEd Tanous // efficiently move out the intermedia nlohmann::json 1741537174c4SEd Tanous // objects. This makes a copy of the structure, and operates 1742537174c4SEd Tanous // on that, but could be done more efficiently 1743*d1d50814SRavi Teja nlohmann::json ipv4Static = std::move(*ipv4StaticAddresses); 1744*d1d50814SRavi Teja handleIPv4StaticPatch(iface_id, ipv4Static, ipv4StaticData, 1745*d1d50814SRavi Teja asyncResp); 17461abe55efSEd Tanous } 17470627a2c7SEd Tanous 17485112e9b4SRAJESWARAN THILLAIGOVINDAN if (nameServers) 17495112e9b4SRAJESWARAN THILLAIGOVINDAN { 17505112e9b4SRAJESWARAN THILLAIGOVINDAN // Data.Permissions is read-only 17515112e9b4SRAJESWARAN THILLAIGOVINDAN messages::propertyNotWritable(asyncResp->res, 17525112e9b4SRAJESWARAN THILLAIGOVINDAN "NameServers"); 17535112e9b4SRAJESWARAN THILLAIGOVINDAN } 17545112e9b4SRAJESWARAN THILLAIGOVINDAN 1755f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1756f85837bfSRAJESWARAN THILLAIGOVINDAN { 1757f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1758f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1759f85837bfSRAJESWARAN THILLAIGOVINDAN } 17609a6fc6feSRavi Teja 17619a6fc6feSRavi Teja if (ipv6DefaultGateway) 17629a6fc6feSRavi Teja { 17639a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 17649a6fc6feSRavi Teja "IPv6DefaultGateway"); 17659a6fc6feSRavi Teja } 1766e48c0fc5SRavi Teja 1767e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1768e48c0fc5SRavi Teja { 1769e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1770e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 1771e48c0fc5SRavi Teja ipv6StaticData, asyncResp); 1772e48c0fc5SRavi Teja } 1773588c3f0dSKowalski, Kamil }); 1774588c3f0dSKowalski, Kamil } 17759391bb9cSRapkiewicz, Pawel }; 17769391bb9cSRapkiewicz, Pawel 1777e439f0f8SKowalski, Kamil /** 17784a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 17794a0cb85cSEd Tanous * Schema 1780e439f0f8SKowalski, Kamil */ 17811abe55efSEd Tanous class VlanNetworkInterface : public Node 17821abe55efSEd Tanous { 1783e439f0f8SKowalski, Kamil public: 1784e439f0f8SKowalski, Kamil /* 1785e439f0f8SKowalski, Kamil * Default Constructor 1786e439f0f8SKowalski, Kamil */ 1787e439f0f8SKowalski, Kamil template <typename CrowApp> 17881abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 17894a0cb85cSEd Tanous Node(app, 17900f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 17911abe55efSEd Tanous std::string(), std::string()) 17921abe55efSEd Tanous { 1793e439f0f8SKowalski, Kamil entityPrivileges = { 1794e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1795e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1796e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1797e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1798e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1799e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1800e439f0f8SKowalski, Kamil } 1801e439f0f8SKowalski, Kamil 1802e439f0f8SKowalski, Kamil private: 18030f74e643SEd Tanous void parseInterfaceData( 18040f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 18050f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1806e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1807*d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4StaticData, 1808e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1809e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 18101abe55efSEd Tanous { 1811e439f0f8SKowalski, Kamil // Fill out obvious data... 18124a0cb85cSEd Tanous json_response["Id"] = iface_id; 18134a0cb85cSEd Tanous json_response["@odata.id"] = 18144a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 18154a0cb85cSEd Tanous "/VLANs/" + iface_id; 1816e439f0f8SKowalski, Kamil 18174a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1818fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 18194a0cb85cSEd Tanous { 1820fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 18214a0cb85cSEd Tanous } 1822e439f0f8SKowalski, Kamil } 1823e439f0f8SKowalski, Kamil 1824fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 18251abe55efSEd Tanous { 18261abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 18271abe55efSEd Tanous { 1828927a505aSKowalski, Kamil return false; 18291abe55efSEd Tanous } 18301abe55efSEd Tanous else 18311abe55efSEd Tanous { 1832927a505aSKowalski, Kamil return true; 1833927a505aSKowalski, Kamil } 1834927a505aSKowalski, Kamil } 1835927a505aSKowalski, Kamil 1836e439f0f8SKowalski, Kamil /** 1837e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1838e439f0f8SKowalski, Kamil */ 183955c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 18401abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18411abe55efSEd Tanous { 18424a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18434a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1844e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1845e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1846e439f0f8SKowalski, Kamil // impossible. 18471abe55efSEd Tanous if (params.size() != 2) 18481abe55efSEd Tanous { 1849f12894f8SJason M. Bills messages::internalError(res); 1850e439f0f8SKowalski, Kamil res.end(); 1851e439f0f8SKowalski, Kamil return; 1852e439f0f8SKowalski, Kamil } 1853e439f0f8SKowalski, Kamil 18544a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 18554a0cb85cSEd Tanous const std::string &iface_id = params[1]; 18560f74e643SEd Tanous res.jsonValue["@odata.type"] = 18570f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 18580f74e643SEd Tanous res.jsonValue["@odata.context"] = 18590f74e643SEd Tanous "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface"; 18600f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1861e439f0f8SKowalski, Kamil 1862fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 18631abe55efSEd Tanous { 1864a434f2bdSEd Tanous return; 1865a434f2bdSEd Tanous } 1866a434f2bdSEd Tanous 1867e439f0f8SKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1868e439f0f8SKowalski, Kamil // preparation 18694a0cb85cSEd Tanous getEthernetIfaceData( 1870fda13ad2SSunitha Harish params[1], 1871fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1872fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 18734a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1874e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1875*d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 1876*d1d50814SRavi Teja &ipv4StaticData, 1877e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1878e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1879e48c0fc5SRavi Teja &ipv6StaticData) { 1880fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 18811abe55efSEd Tanous { 18820f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 18830f74e643SEd Tanous parent_iface_id, iface_id, ethData, 1884*d1d50814SRavi Teja ipv4Data, ipv4StaticData, ipv6Data, 1885*d1d50814SRavi Teja ipv6StaticData); 18861abe55efSEd Tanous } 18871abe55efSEd Tanous else 18881abe55efSEd Tanous { 1889e439f0f8SKowalski, Kamil // ... otherwise return error 18901abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18911abe55efSEd Tanous // object, and other errors 1892f12894f8SJason M. Bills messages::resourceNotFound( 1893f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1894e439f0f8SKowalski, Kamil } 1895e439f0f8SKowalski, Kamil }); 1896e439f0f8SKowalski, Kamil } 1897e439f0f8SKowalski, Kamil 189855c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 18991abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19001abe55efSEd Tanous { 19014a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19021abe55efSEd Tanous if (params.size() != 2) 19031abe55efSEd Tanous { 1904f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1905e439f0f8SKowalski, Kamil return; 1906e439f0f8SKowalski, Kamil } 1907e439f0f8SKowalski, Kamil 1908d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 190955c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1910927a505aSKowalski, Kamil 1911fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19121abe55efSEd Tanous { 1913fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1914fda13ad2SSunitha Harish ifaceId); 1915927a505aSKowalski, Kamil return; 1916927a505aSKowalski, Kamil } 1917927a505aSKowalski, Kamil 19180627a2c7SEd Tanous bool vlanEnable = false; 19190627a2c7SEd Tanous uint64_t vlanId = 0; 19200627a2c7SEd Tanous 19210627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 19220627a2c7SEd Tanous vlanId)) 19231abe55efSEd Tanous { 1924927a505aSKowalski, Kamil return; 1925927a505aSKowalski, Kamil } 1926927a505aSKowalski, Kamil 1927927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1928927a505aSKowalski, Kamil // preparation 1929e48c0fc5SRavi Teja getEthernetIfaceData( 1930e48c0fc5SRavi Teja params[1], 1931e48c0fc5SRavi Teja [this, asyncResp, parentIfaceId{std::string(params[0])}, 1932e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 1933e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 1934e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1935*d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 1936*d1d50814SRavi Teja &ipv4StaticData, 1937e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1938e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1939e48c0fc5SRavi Teja &ipv6StaticData) { 194008244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 194108244d02SSunitha Harish { 194208244d02SSunitha Harish auto callback = 194308244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 194408244d02SSunitha Harish if (ec) 194508244d02SSunitha Harish { 194608244d02SSunitha Harish messages::internalError(asyncResp->res); 194708244d02SSunitha Harish } 194808244d02SSunitha Harish }; 194908244d02SSunitha Harish 195008244d02SSunitha Harish if (vlanEnable == true) 195108244d02SSunitha Harish { 195208244d02SSunitha Harish crow::connections::systemBus->async_method_call( 195308244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 195408244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 195508244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 195608244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 195708244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 195808244d02SSunitha Harish } 195908244d02SSunitha Harish else 196008244d02SSunitha Harish { 1961e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 1962e48c0fc5SRavi Teja "vlan interface"; 196308244d02SSunitha Harish crow::connections::systemBus->async_method_call( 196408244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 1965e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 1966e48c0fc5SRavi Teja ifaceId, 196708244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 196808244d02SSunitha Harish } 196908244d02SSunitha Harish } 197008244d02SSunitha Harish else 19711abe55efSEd Tanous { 19721abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 19731abe55efSEd Tanous // object, and other errors 1974e48c0fc5SRavi Teja messages::resourceNotFound( 1975e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 1976927a505aSKowalski, Kamil return; 1977927a505aSKowalski, Kamil } 1978927a505aSKowalski, Kamil }); 1979e439f0f8SKowalski, Kamil } 1980e439f0f8SKowalski, Kamil 198155c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 19821abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19831abe55efSEd Tanous { 19844a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19851abe55efSEd Tanous if (params.size() != 2) 19861abe55efSEd Tanous { 1987f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1988e439f0f8SKowalski, Kamil return; 1989e439f0f8SKowalski, Kamil } 1990e439f0f8SKowalski, Kamil 1991d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 199255c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1993927a505aSKowalski, Kamil 1994fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19951abe55efSEd Tanous { 1996fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1997fda13ad2SSunitha Harish ifaceId); 1998927a505aSKowalski, Kamil return; 1999927a505aSKowalski, Kamil } 2000927a505aSKowalski, Kamil 2001927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 2002927a505aSKowalski, Kamil // preparation 2003f12894f8SJason M. Bills getEthernetIfaceData( 2004fda13ad2SSunitha Harish params[1], 2005fda13ad2SSunitha Harish [this, asyncResp, parentIfaceId{std::string(params[0])}, 2006fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 2007f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 2008e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 2009*d1d50814SRavi Teja const boost::container::flat_set<IPv4AddressData> 2010*d1d50814SRavi Teja &ipv4StaticData, 2011e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 2012e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 2013e48c0fc5SRavi Teja &ipv6StaticData) { 2014fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 20151abe55efSEd Tanous { 2016f12894f8SJason M. Bills auto callback = 2017f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 20181abe55efSEd Tanous if (ec) 20191abe55efSEd Tanous { 2020f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2021927a505aSKowalski, Kamil } 20224a0cb85cSEd Tanous }; 20234a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 20244a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 20254a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 20264a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 20271abe55efSEd Tanous } 20281abe55efSEd Tanous else 20291abe55efSEd Tanous { 2030927a505aSKowalski, Kamil // ... otherwise return error 2031f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 2032f12894f8SJason M. Bills // object, and other errors 2033f12894f8SJason M. Bills messages::resourceNotFound( 2034f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 2035927a505aSKowalski, Kamil } 2036927a505aSKowalski, Kamil }); 2037e439f0f8SKowalski, Kamil } 2038e439f0f8SKowalski, Kamil }; 2039e439f0f8SKowalski, Kamil 2040e439f0f8SKowalski, Kamil /** 2041e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 2042e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 2043e439f0f8SKowalski, Kamil */ 20441abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 20451abe55efSEd Tanous { 2046e439f0f8SKowalski, Kamil public: 2047e439f0f8SKowalski, Kamil template <typename CrowApp> 20481abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 20494a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 20504a0cb85cSEd Tanous std::string()) 20511abe55efSEd Tanous { 2052e439f0f8SKowalski, Kamil entityPrivileges = { 2053e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 2054e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2055e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2056e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2057e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2058e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2059e439f0f8SKowalski, Kamil } 2060e439f0f8SKowalski, Kamil 2061e439f0f8SKowalski, Kamil private: 2062e439f0f8SKowalski, Kamil /** 2063e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2064e439f0f8SKowalski, Kamil */ 206555c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 20661abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20671abe55efSEd Tanous { 20684a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20691abe55efSEd Tanous if (params.size() != 1) 20701abe55efSEd Tanous { 2071e439f0f8SKowalski, Kamil // This means there is a problem with the router 2072f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2073e439f0f8SKowalski, Kamil return; 2074e439f0f8SKowalski, Kamil } 2075e439f0f8SKowalski, Kamil 20764a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2077e439f0f8SKowalski, Kamil 20784a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 20791abe55efSEd Tanous // preparation 2080f12894f8SJason M. Bills getEthernetIfaceList( 208143b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 20821abe55efSEd Tanous const bool &success, 20834c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 20844a0cb85cSEd Tanous if (!success) 20851abe55efSEd Tanous { 2086f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20874a0cb85cSEd Tanous return; 20881abe55efSEd Tanous } 20894c9afe43SEd Tanous 20904c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 20914c9afe43SEd Tanous { 20924c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 20934c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 20944c9afe43SEd Tanous rootInterfaceName); 20954c9afe43SEd Tanous return; 20964c9afe43SEd Tanous } 20974c9afe43SEd Tanous 20980f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 20990f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 21000f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 21010f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 21020f74e643SEd Tanous "/redfish/v1/$metadata" 21030f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 21040f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 21050f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 21060f74e643SEd Tanous "VLAN Network Interface Collection"; 21074a0cb85cSEd Tanous 21084a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 21094a0cb85cSEd Tanous 21104a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 21111abe55efSEd Tanous { 21124a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 21134a0cb85cSEd Tanous { 21144a0cb85cSEd Tanous iface_array.push_back( 21154a0cb85cSEd Tanous {{"@odata.id", 21164a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 21174a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2118e439f0f8SKowalski, Kamil } 2119e439f0f8SKowalski, Kamil } 2120e439f0f8SKowalski, Kamil 21214a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 21224a0cb85cSEd Tanous iface_array.size(); 21234a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 21244a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 21254a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 21264a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2127e439f0f8SKowalski, Kamil }); 2128e439f0f8SKowalski, Kamil } 2129e439f0f8SKowalski, Kamil 213055c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 21311abe55efSEd Tanous const std::vector<std::string> ¶ms) override 21321abe55efSEd Tanous { 21334a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 21341abe55efSEd Tanous if (params.size() != 1) 21351abe55efSEd Tanous { 2136f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2137e439f0f8SKowalski, Kamil return; 2138e439f0f8SKowalski, Kamil } 2139fda13ad2SSunitha Harish bool vlanEnable = false; 21400627a2c7SEd Tanous uint32_t vlanId = 0; 2141fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2142fda13ad2SSunitha Harish vlanEnable)) 21431abe55efSEd Tanous { 21444a0cb85cSEd Tanous return; 2145e439f0f8SKowalski, Kamil } 2146fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2147fda13ad2SSunitha Harish if (!vlanId) 2148fda13ad2SSunitha Harish { 2149fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2150fda13ad2SSunitha Harish } 2151fda13ad2SSunitha Harish if (!vlanEnable) 2152fda13ad2SSunitha Harish { 2153fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2154fda13ad2SSunitha Harish } 2155fda13ad2SSunitha Harish if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) 2156fda13ad2SSunitha Harish { 2157fda13ad2SSunitha Harish return; 2158fda13ad2SSunitha Harish } 2159fda13ad2SSunitha Harish 21604a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 21614a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 21621abe55efSEd Tanous if (ec) 21631abe55efSEd Tanous { 21644a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 21654a0cb85cSEd Tanous // phosphor-network responses 2166f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21674a0cb85cSEd Tanous return; 21681abe55efSEd Tanous } 2169f12894f8SJason M. Bills messages::created(asyncResp->res); 2170e439f0f8SKowalski, Kamil }; 21714a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21724a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21734a0cb85cSEd Tanous "/xyz/openbmc_project/network", 21744a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 21750627a2c7SEd Tanous rootInterfaceName, vlanId); 21764a0cb85cSEd Tanous } 21774a0cb85cSEd Tanous }; 21789391bb9cSRapkiewicz, Pawel } // namespace redfish 2179