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; 103*d24bfc7aSJennifer 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 } 240*d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 241*d24bfc7aSJennifer Lee { 242*d24bfc7aSJennifer Lee const std::vector<std::string> *domainNames = 243*d24bfc7aSJennifer Lee sdbusplus::message::variant_ns::get_if< 244*d24bfc7aSJennifer Lee std::vector<std::string>>( 245*d24bfc7aSJennifer Lee &propertyPair.second); 246*d24bfc7aSJennifer Lee if (domainNames != nullptr) 247*d24bfc7aSJennifer Lee { 248*d24bfc7aSJennifer Lee ethData.domainnames = std::move(*domainNames); 249*d24bfc7aSJennifer Lee } 250*d24bfc7aSJennifer 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 3854a0cb85cSEd Tanous inline void 3864a0cb85cSEd Tanous extractIPData(const std::string ðiface_id, 3874a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 3884a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> &ipv4_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 } 4604a0cb85cSEd Tanous // Check if given address is local, or global 4614a0cb85cSEd Tanous ipv4_address.linktype = 4624a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 46318659d10SJohnathan Mantey ? LinkType::Local 46418659d10SJohnathan Mantey : LinkType::Global; 4654a0cb85cSEd Tanous } 4664a0cb85cSEd Tanous } 4674a0cb85cSEd Tanous } 4684a0cb85cSEd Tanous } 4694a0cb85cSEd Tanous } 470588c3f0dSKowalski, Kamil 471588c3f0dSKowalski, Kamil /** 472588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 473588c3f0dSKowalski, Kamil * 474588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 475588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 476588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 477588c3f0dSKowalski, Kamil * 478588c3f0dSKowalski, Kamil * @return None. 479588c3f0dSKowalski, Kamil */ 480588c3f0dSKowalski, Kamil template <typename CallbackFunc> 4814a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 4821abe55efSEd Tanous CallbackFunc &&callback) 4831abe55efSEd Tanous { 48455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 485588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 486588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 487588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 488588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 489abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 4904a0cb85cSEd Tanous } 491588c3f0dSKowalski, Kamil 492588c3f0dSKowalski, Kamil /** 493179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 494179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 495179db1d7SKowalski, Kamil * bit count for Subnet Mask. 496179db1d7SKowalski, Kamil * 497179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 498179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 499179db1d7SKowalski, Kamil * 500179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 501179db1d7SKowalski, Kamil */ 5024a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 5031abe55efSEd Tanous uint8_t *bits = nullptr) 5041abe55efSEd Tanous { 505179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 506179db1d7SKowalski, Kamil 507179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 508179db1d7SKowalski, Kamil 5094a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 5101abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 5111abe55efSEd Tanous { 512179db1d7SKowalski, Kamil return false; 513179db1d7SKowalski, Kamil } 514179db1d7SKowalski, Kamil 5151abe55efSEd Tanous if (bits != nullptr) 5161abe55efSEd Tanous { 517179db1d7SKowalski, Kamil *bits = 0; 518179db1d7SKowalski, Kamil } 519179db1d7SKowalski, Kamil 520179db1d7SKowalski, Kamil char *endPtr; 521179db1d7SKowalski, Kamil long previousValue = 255; 522179db1d7SKowalski, Kamil bool firstZeroInByteHit; 5231abe55efSEd Tanous for (const std::string &byte : bytesInMask) 5241abe55efSEd Tanous { 5251abe55efSEd Tanous if (byte.empty()) 5261abe55efSEd Tanous { 5271db9ca37SKowalski, Kamil return false; 5281db9ca37SKowalski, Kamil } 5291db9ca37SKowalski, Kamil 530179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 5311db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 532179db1d7SKowalski, Kamil 5334a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 5344a0cb85cSEd Tanous // is not 100% number 5351abe55efSEd Tanous if (*endPtr != '\0') 5361abe55efSEd Tanous { 537179db1d7SKowalski, Kamil return false; 538179db1d7SKowalski, Kamil } 539179db1d7SKowalski, Kamil 540179db1d7SKowalski, Kamil // Value should be contained in byte 5411abe55efSEd Tanous if (value < 0 || value > 255) 5421abe55efSEd Tanous { 543179db1d7SKowalski, Kamil return false; 544179db1d7SKowalski, Kamil } 545179db1d7SKowalski, Kamil 5461abe55efSEd Tanous if (bits != nullptr) 5471abe55efSEd Tanous { 548179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 5491abe55efSEd Tanous if (previousValue != 255 && value != 0) 5501abe55efSEd Tanous { 551179db1d7SKowalski, Kamil return false; 552179db1d7SKowalski, Kamil } 553179db1d7SKowalski, Kamil 554179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 555179db1d7SKowalski, Kamil firstZeroInByteHit = false; 556179db1d7SKowalski, Kamil 557179db1d7SKowalski, Kamil // Count bits 5581abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 5591abe55efSEd Tanous { 5601abe55efSEd Tanous if (value & (1 << bitIdx)) 5611abe55efSEd Tanous { 5621abe55efSEd Tanous if (firstZeroInByteHit) 5631abe55efSEd Tanous { 564179db1d7SKowalski, Kamil // Continuity not preserved 565179db1d7SKowalski, Kamil return false; 5661abe55efSEd Tanous } 5671abe55efSEd Tanous else 5681abe55efSEd Tanous { 569179db1d7SKowalski, Kamil (*bits)++; 570179db1d7SKowalski, Kamil } 5711abe55efSEd Tanous } 5721abe55efSEd Tanous else 5731abe55efSEd Tanous { 574179db1d7SKowalski, Kamil firstZeroInByteHit = true; 575179db1d7SKowalski, Kamil } 576179db1d7SKowalski, Kamil } 577179db1d7SKowalski, Kamil } 578179db1d7SKowalski, Kamil 579179db1d7SKowalski, Kamil previousValue = value; 580179db1d7SKowalski, Kamil } 581179db1d7SKowalski, Kamil 582179db1d7SKowalski, Kamil return true; 583179db1d7SKowalski, Kamil } 584179db1d7SKowalski, Kamil 585179db1d7SKowalski, Kamil /** 586b01bf299SEd Tanous * @brief Changes IPv4 address type property (Address, Gateway) 587b01bf299SEd Tanous * 588b01bf299SEd Tanous * @param[in] ifaceId Id of interface whose IP should be modified 589b01bf299SEd Tanous * @param[in] ipIdx Index of IP in input array that should be modified 590b01bf299SEd Tanous * @param[in] ipHash DBus Hash id of modified IP 591b01bf299SEd Tanous * @param[in] name Name of field in JSON representation 592b01bf299SEd Tanous * @param[in] newValue New value that should be written 593b01bf299SEd Tanous * @param[io] asyncResp Response object that will be returned to client 594b01bf299SEd Tanous * 595b01bf299SEd Tanous * @return true if give IP is valid and has been sent do D-Bus, false 596b01bf299SEd Tanous * otherwise 597b01bf299SEd Tanous */ 598b01bf299SEd Tanous inline void changeIPv4AddressProperty( 599b01bf299SEd Tanous const std::string &ifaceId, int ipIdx, const std::string &ipHash, 600b01bf299SEd Tanous const std::string &name, const std::string &newValue, 601b01bf299SEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 602b01bf299SEd Tanous { 603286b9118SJohnathan Mantey auto callback = 604286b9118SJohnathan Mantey [asyncResp, ipIdx, name{std::string(name)}, 605286b9118SJohnathan Mantey newValue{std::move(newValue)}](const boost::system::error_code ec) { 606b01bf299SEd Tanous if (ec) 607b01bf299SEd Tanous { 608b01bf299SEd Tanous messages::internalError(asyncResp->res); 609b01bf299SEd Tanous } 610b01bf299SEd Tanous }; 611b01bf299SEd Tanous 612b01bf299SEd Tanous crow::connections::systemBus->async_method_call( 613b01bf299SEd Tanous std::move(callback), "xyz.openbmc_project.Network", 614b01bf299SEd Tanous "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 615b01bf299SEd Tanous "org.freedesktop.DBus.Properties", "Set", 616b01bf299SEd Tanous "xyz.openbmc_project.Network.IP", name, 617b01bf299SEd Tanous std::variant<std::string>(newValue)); 618b01bf299SEd Tanous } 619b01bf299SEd Tanous 620b01bf299SEd Tanous /** 621179db1d7SKowalski, Kamil * @brief Modifies SubnetMask for given IP 622179db1d7SKowalski, Kamil * 623179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be modified 6244a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be 6251abe55efSEd Tanous * modified 626179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of modified IP 627179db1d7SKowalski, Kamil * @param[in] newValue Mask as PrefixLength in bitcount 628179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 629179db1d7SKowalski, Kamil * 630179db1d7SKowalski, Kamil * @return None 631179db1d7SKowalski, Kamil */ 632b01bf299SEd Tanous inline void changeIPv4SubnetMaskProperty(const std::string &ifaceId, int ipIdx, 6334a0cb85cSEd Tanous const std::string &ipHash, 6344a0cb85cSEd Tanous uint8_t &newValue, 6354a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6361abe55efSEd Tanous { 637286b9118SJohnathan Mantey auto callback = [asyncResp, ipIdx](const boost::system::error_code ec) { 6381abe55efSEd Tanous if (ec) 6391abe55efSEd Tanous { 640a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6411abe55efSEd Tanous } 642179db1d7SKowalski, Kamil }; 643179db1d7SKowalski, Kamil 64455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 645179db1d7SKowalski, Kamil std::move(callback), "xyz.openbmc_project.Network", 646179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 647179db1d7SKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 648179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP", "PrefixLength", 649abf2add6SEd Tanous std::variant<uint8_t>(newValue)); 6504a0cb85cSEd Tanous } 651588c3f0dSKowalski, Kamil 652588c3f0dSKowalski, Kamil /** 653179db1d7SKowalski, Kamil * @brief Deletes given IPv4 654179db1d7SKowalski, Kamil * 655179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 656179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 657179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 658179db1d7SKowalski, Kamil * 659179db1d7SKowalski, Kamil * @return None 660179db1d7SKowalski, Kamil */ 6614a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 6624a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 6631abe55efSEd Tanous { 66455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 665286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 6661abe55efSEd Tanous if (ec) 6671abe55efSEd Tanous { 668a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6691abe55efSEd Tanous } 670179db1d7SKowalski, Kamil }, 671179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 672179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 673179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 674179db1d7SKowalski, Kamil } 675179db1d7SKowalski, Kamil 676179db1d7SKowalski, Kamil /** 677179db1d7SKowalski, Kamil * @brief Creates IPv4 with given data 678179db1d7SKowalski, Kamil * 679179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 6804a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 681179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 682179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 683179db1d7SKowalski, Kamil * 684179db1d7SKowalski, Kamil * @return None 685179db1d7SKowalski, Kamil */ 686b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 687b01bf299SEd Tanous uint8_t subnetMask, const std::string &gateway, 688b01bf299SEd Tanous const std::string &address, 6894a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6901abe55efSEd Tanous { 69143b761d0SEd Tanous auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 6921abe55efSEd Tanous if (ec) 6931abe55efSEd Tanous { 694a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 695179db1d7SKowalski, Kamil } 696179db1d7SKowalski, Kamil }; 697179db1d7SKowalski, Kamil 69855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 699179db1d7SKowalski, Kamil std::move(createIpHandler), "xyz.openbmc_project.Network", 700179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 701179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 702179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask, 703179db1d7SKowalski, Kamil gateway); 704179db1d7SKowalski, Kamil } 705e48c0fc5SRavi Teja 706e48c0fc5SRavi Teja /** 707e48c0fc5SRavi Teja * @brief Deletes given IPv6 708e48c0fc5SRavi Teja * 709e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 710e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 711e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 712e48c0fc5SRavi Teja * 713e48c0fc5SRavi Teja * @return None 714e48c0fc5SRavi Teja */ 715e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 716e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 717e48c0fc5SRavi Teja { 718e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 719286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 720e48c0fc5SRavi Teja if (ec) 721e48c0fc5SRavi Teja { 722e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 723e48c0fc5SRavi Teja } 724e48c0fc5SRavi Teja }, 725e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 726e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 727e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 728e48c0fc5SRavi Teja } 729e48c0fc5SRavi Teja 730e48c0fc5SRavi Teja /** 731e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 732e48c0fc5SRavi Teja * 733e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 734e48c0fc5SRavi Teja * @param[in] ipIdx Index of IP in input array that should be added 735e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 736e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 737e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 738e48c0fc5SRavi Teja * 739e48c0fc5SRavi Teja * @return None 740e48c0fc5SRavi Teja */ 741e48c0fc5SRavi Teja inline void createIPv6(const std::string &ifaceId, unsigned int ipIdx, 742e48c0fc5SRavi Teja uint8_t prefixLength, const std::string &address, 743e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 744e48c0fc5SRavi Teja { 745e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 746e48c0fc5SRavi Teja if (ec) 747e48c0fc5SRavi Teja { 748e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 749e48c0fc5SRavi Teja } 750e48c0fc5SRavi Teja }; 751e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 752e48c0fc5SRavi Teja // does not have assosiated gateway property 753e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 754e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 755e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 756e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 757e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 758e48c0fc5SRavi Teja ""); 759e48c0fc5SRavi Teja } 760e48c0fc5SRavi Teja 7612a133282Smanojkiraneda using GetAllPropertiesType = 7622a133282Smanojkiraneda boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>; 7632a133282Smanojkiraneda 7642a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) 7652a133282Smanojkiraneda { 7662a133282Smanojkiraneda auto getConfig = [asyncResp](const boost::system::error_code error_code, 7672a133282Smanojkiraneda const GetAllPropertiesType &dbus_data) { 7682a133282Smanojkiraneda if (error_code) 7692a133282Smanojkiraneda { 7702a133282Smanojkiraneda BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code; 7712a133282Smanojkiraneda messages::internalError(asyncResp->res); 7722a133282Smanojkiraneda return; 7732a133282Smanojkiraneda } 774fda13ad2SSunitha Harish nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; 7752a133282Smanojkiraneda for (const auto &property : dbus_data) 7762a133282Smanojkiraneda { 7772a133282Smanojkiraneda auto value = 7782a133282Smanojkiraneda sdbusplus::message::variant_ns::get_if<bool>(&property.second); 7792a133282Smanojkiraneda 7802a133282Smanojkiraneda if (value == nullptr) 7812a133282Smanojkiraneda { 7822a133282Smanojkiraneda continue; 7832a133282Smanojkiraneda } 7842a133282Smanojkiraneda if (property.first == "DNSEnabled") 7852a133282Smanojkiraneda { 7862a133282Smanojkiraneda DHCPConfigTypeJson["UseDNSServers"] = *value; 7872a133282Smanojkiraneda } 7882a133282Smanojkiraneda else if (property.first == "HostNameEnabled") 7892a133282Smanojkiraneda { 7902a133282Smanojkiraneda DHCPConfigTypeJson["UseDomainName"] = *value; 7912a133282Smanojkiraneda } 7922a133282Smanojkiraneda else if (property.first == "NTPEnabled") 7932a133282Smanojkiraneda { 7942a133282Smanojkiraneda DHCPConfigTypeJson["UseNTPServers"] = *value; 7952a133282Smanojkiraneda } 7962a133282Smanojkiraneda } 7972a133282Smanojkiraneda }; 7982a133282Smanojkiraneda crow::connections::systemBus->async_method_call( 7992a133282Smanojkiraneda std::move(getConfig), "xyz.openbmc_project.Network", 8002a133282Smanojkiraneda "/xyz/openbmc_project/network/config/dhcp", 8012a133282Smanojkiraneda "org.freedesktop.DBus.Properties", "GetAll", 8022a133282Smanojkiraneda "xyz.openbmc_project.Network.DHCPConfiguration"); 8032a133282Smanojkiraneda } 804179db1d7SKowalski, Kamil 805179db1d7SKowalski, Kamil /** 806179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 807179db1d7SKowalski, Kamil * Object 808179db1d7SKowalski, Kamil * from EntityManager Network Manager 8094a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 810179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 811179db1d7SKowalski, Kamil * into JSON 812179db1d7SKowalski, Kamil */ 813179db1d7SKowalski, Kamil template <typename CallbackFunc> 8144a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8151abe55efSEd Tanous CallbackFunc &&callback) 8161abe55efSEd Tanous { 81755c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8184a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8191abe55efSEd Tanous const boost::system::error_code error_code, 8204a0cb85cSEd Tanous const GetManagedObjects &resp) { 82155c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8224a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 823e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 824e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6StaticData; 825179db1d7SKowalski, Kamil 8261abe55efSEd Tanous if (error_code) 8271abe55efSEd Tanous { 828e48c0fc5SRavi Teja callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData); 829179db1d7SKowalski, Kamil return; 830179db1d7SKowalski, Kamil } 831179db1d7SKowalski, Kamil 8324c9afe43SEd Tanous bool found = 8334a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 8344c9afe43SEd Tanous if (!found) 8354c9afe43SEd Tanous { 836e48c0fc5SRavi Teja callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData); 8374c9afe43SEd Tanous return; 8384c9afe43SEd Tanous } 8394c9afe43SEd Tanous 8404a0cb85cSEd Tanous extractIPData(ethiface_id, resp, ipv4Data); 841179db1d7SKowalski, Kamil // Fix global GW 8421abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 8431abe55efSEd Tanous { 8444a0cb85cSEd Tanous if ((ipv4.linktype == LinkType::Global) && 8454a0cb85cSEd Tanous (ipv4.gateway == "0.0.0.0")) 8461abe55efSEd Tanous { 8474a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 848179db1d7SKowalski, Kamil } 849179db1d7SKowalski, Kamil } 850179db1d7SKowalski, Kamil 851e48c0fc5SRavi Teja extractIPV6Data(ethiface_id, resp, ipv6Data, ipv6StaticData); 8524a0cb85cSEd Tanous // Finally make a callback with usefull data 853e48c0fc5SRavi Teja callback(true, ethData, ipv4Data, ipv6Data, ipv6StaticData); 854179db1d7SKowalski, Kamil }, 855179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 856179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 857179db1d7SKowalski, Kamil }; 858179db1d7SKowalski, Kamil 859179db1d7SKowalski, Kamil /** 8609391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8619391bb9cSRapkiewicz, Pawel * Manager 8621abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8631abe55efSEd Tanous * into JSON. 8649391bb9cSRapkiewicz, Pawel */ 8659391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8661abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 8671abe55efSEd Tanous { 86855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8694a0cb85cSEd Tanous [callback{std::move(callback)}]( 8709391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 8714a0cb85cSEd Tanous GetManagedObjects &resp) { 8721abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8731abe55efSEd Tanous // ethernet interfaces 8744c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 8754a0cb85cSEd Tanous iface_list.reserve(resp.size()); 8761abe55efSEd Tanous if (error_code) 8771abe55efSEd Tanous { 8784a0cb85cSEd Tanous callback(false, iface_list); 8799391bb9cSRapkiewicz, Pawel return; 8809391bb9cSRapkiewicz, Pawel } 8819391bb9cSRapkiewicz, Pawel 8829391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8834a0cb85cSEd Tanous for (const auto &objpath : resp) 8841abe55efSEd Tanous { 8859391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 8864a0cb85cSEd Tanous for (const auto &interface : objpath.second) 8871abe55efSEd Tanous { 8881abe55efSEd Tanous // If interface is 8894a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 8904a0cb85cSEd Tanous // what we're looking for. 8919391bb9cSRapkiewicz, Pawel if (interface.first == 8921abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 8931abe55efSEd Tanous { 8944a0cb85cSEd Tanous // Cut out everyting until last "/", ... 8954a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 8964a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 8974a0cb85cSEd Tanous if (last_pos != std::string::npos) 8981abe55efSEd Tanous { 8999391bb9cSRapkiewicz, Pawel // and put it into output vector. 9004c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9019391bb9cSRapkiewicz, Pawel } 9029391bb9cSRapkiewicz, Pawel } 9039391bb9cSRapkiewicz, Pawel } 9049391bb9cSRapkiewicz, Pawel } 905a434f2bdSEd Tanous // Finally make a callback with useful data 9064a0cb85cSEd Tanous callback(true, iface_list); 9079391bb9cSRapkiewicz, Pawel }, 908aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 909aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 9109391bb9cSRapkiewicz, Pawel }; 9119391bb9cSRapkiewicz, Pawel 9129391bb9cSRapkiewicz, Pawel /** 9139391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9149391bb9cSRapkiewicz, Pawel */ 9151abe55efSEd Tanous class EthernetCollection : public Node 9161abe55efSEd Tanous { 9179391bb9cSRapkiewicz, Pawel public: 9184a0cb85cSEd Tanous template <typename CrowApp> 9191abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9204a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9211abe55efSEd Tanous { 922588c3f0dSKowalski, Kamil entityPrivileges = { 923588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 924e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 925e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 926e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 927e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 928e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9299391bb9cSRapkiewicz, Pawel } 9309391bb9cSRapkiewicz, Pawel 9319391bb9cSRapkiewicz, Pawel private: 9329391bb9cSRapkiewicz, Pawel /** 9339391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 9349391bb9cSRapkiewicz, Pawel */ 93555c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 9361abe55efSEd Tanous const std::vector<std::string> ¶ms) override 9371abe55efSEd Tanous { 9380f74e643SEd Tanous res.jsonValue["@odata.type"] = 9390f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9400f74e643SEd Tanous res.jsonValue["@odata.context"] = 9410f74e643SEd Tanous "/redfish/v1/" 9420f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9430f74e643SEd Tanous res.jsonValue["@odata.id"] = 9440f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9450f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 9460f74e643SEd Tanous res.jsonValue["Description"] = 9470f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 9484c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 9494a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 9501abe55efSEd Tanous // preparation 951f12894f8SJason M. Bills getEthernetIfaceList( 9524c9afe43SEd Tanous [asyncResp]( 9534c9afe43SEd Tanous const bool &success, 9544c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 9554a0cb85cSEd Tanous if (!success) 9561abe55efSEd Tanous { 9574c9afe43SEd Tanous messages::internalError(asyncResp->res); 9584a0cb85cSEd Tanous return; 9594a0cb85cSEd Tanous } 9604a0cb85cSEd Tanous 9614c9afe43SEd Tanous nlohmann::json &iface_array = 9624c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 9634a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 964fda13ad2SSunitha Harish std::string tag = "_"; 9654a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 9661abe55efSEd Tanous { 967fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 968fda13ad2SSunitha Harish if (found == std::string::npos) 969fda13ad2SSunitha Harish { 9704a0cb85cSEd Tanous iface_array.push_back( 9714a0cb85cSEd Tanous {{"@odata.id", 9724a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 9734a0cb85cSEd Tanous iface_item}}); 9749391bb9cSRapkiewicz, Pawel } 975fda13ad2SSunitha Harish } 9764a0cb85cSEd Tanous 9774c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 9784c9afe43SEd Tanous iface_array.size(); 9794c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9804a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9819391bb9cSRapkiewicz, Pawel }); 9829391bb9cSRapkiewicz, Pawel } 9839391bb9cSRapkiewicz, Pawel }; 9849391bb9cSRapkiewicz, Pawel 9859391bb9cSRapkiewicz, Pawel /** 9869391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 9879391bb9cSRapkiewicz, Pawel */ 9881abe55efSEd Tanous class EthernetInterface : public Node 9891abe55efSEd Tanous { 9909391bb9cSRapkiewicz, Pawel public: 9919391bb9cSRapkiewicz, Pawel /* 9929391bb9cSRapkiewicz, Pawel * Default Constructor 9939391bb9cSRapkiewicz, Pawel */ 9944a0cb85cSEd Tanous template <typename CrowApp> 9951abe55efSEd Tanous EthernetInterface(CrowApp &app) : 9964a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 9971abe55efSEd Tanous std::string()) 9981abe55efSEd Tanous { 999588c3f0dSKowalski, Kamil entityPrivileges = { 1000588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1001e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1002e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1003e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1004e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1005e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10069391bb9cSRapkiewicz, Pawel } 10079391bb9cSRapkiewicz, Pawel 1008e439f0f8SKowalski, Kamil private: 1009bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10104a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10111abe55efSEd Tanous { 1012bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1013bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1014bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10154a0cb85cSEd Tanous if (ec) 10164a0cb85cSEd Tanous { 1017a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10181abe55efSEd Tanous } 1019bc0bd6e0SEd Tanous }, 1020bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1021bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1022bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1023bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1024abf2add6SEd Tanous std::variant<std::string>(hostname)); 1025588c3f0dSKowalski, Kamil } 1026588c3f0dSKowalski, Kamil 1027d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1028d577665bSRatan Gupta const std::string &macAddress, 1029d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1030d577665bSRatan Gupta { 1031d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1032d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1033d577665bSRatan Gupta if (ec) 1034d577665bSRatan Gupta { 1035d577665bSRatan Gupta messages::internalError(asyncResp->res); 1036d577665bSRatan Gupta return; 1037d577665bSRatan Gupta } 1038d577665bSRatan Gupta }, 1039d577665bSRatan Gupta "xyz.openbmc_project.Network", 1040d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1041d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1042d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1043d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1044d577665bSRatan Gupta } 1045286b9118SJohnathan Mantey 1046da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1047da131a9aSJennifer Lee const std::string &propertyName, const bool &value, 1048da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1049da131a9aSJennifer Lee { 1050da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1051da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1052da131a9aSJennifer Lee if (ec) 1053da131a9aSJennifer Lee { 1054da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1055da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1056da131a9aSJennifer Lee return; 1057da131a9aSJennifer Lee } 1058da131a9aSJennifer Lee }, 1059da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1060da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1061da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1062da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1063da131a9aSJennifer Lee std::variant<bool>{value}); 1064da131a9aSJennifer Lee } 1065da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1066da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1067da131a9aSJennifer Lee { 1068da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1069da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1070da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1071da131a9aSJennifer Lee if (ec) 1072da131a9aSJennifer Lee { 1073da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1074da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1075da131a9aSJennifer Lee return; 1076da131a9aSJennifer Lee } 1077da131a9aSJennifer Lee }, 1078da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1079da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1080da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1081da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1082da131a9aSJennifer Lee std::variant<bool>{value}); 1083da131a9aSJennifer Lee } 1084d577665bSRatan Gupta 1085da131a9aSJennifer Lee void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input, 1086da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1087da131a9aSJennifer Lee { 1088da131a9aSJennifer Lee std::optional<bool> dhcpEnabled; 1089da131a9aSJennifer Lee std::optional<bool> useDNSServers; 1090da131a9aSJennifer Lee std::optional<bool> useDomainName; 1091da131a9aSJennifer Lee std::optional<bool> useNTPServers; 1092da131a9aSJennifer Lee 1093da131a9aSJennifer Lee if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled", 1094da131a9aSJennifer Lee dhcpEnabled, "UseDNSServers", useDNSServers, 1095da131a9aSJennifer Lee "UseDomainName", useDomainName, 1096da131a9aSJennifer Lee "UseNTPServers", useNTPServers)) 1097da131a9aSJennifer Lee { 1098da131a9aSJennifer Lee return; 1099da131a9aSJennifer Lee } 1100da131a9aSJennifer Lee 1101da131a9aSJennifer Lee if (dhcpEnabled) 1102da131a9aSJennifer Lee { 1103da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1104da131a9aSJennifer Lee setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp); 1105da131a9aSJennifer Lee } 1106da131a9aSJennifer Lee 1107da131a9aSJennifer Lee if (useDNSServers) 1108da131a9aSJennifer Lee { 1109da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1110da131a9aSJennifer Lee setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp); 1111da131a9aSJennifer Lee } 1112da131a9aSJennifer Lee 1113da131a9aSJennifer Lee if (useDomainName) 1114da131a9aSJennifer Lee { 1115da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1116da131a9aSJennifer Lee setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp); 1117da131a9aSJennifer Lee } 1118da131a9aSJennifer Lee 1119da131a9aSJennifer Lee if (useNTPServers) 1120da131a9aSJennifer Lee { 1121da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1122da131a9aSJennifer Lee setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp); 1123da131a9aSJennifer Lee } 1124da131a9aSJennifer Lee } 11254a0cb85cSEd Tanous void handleIPv4Patch( 1126f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 11274a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data, 11284a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 11291abe55efSEd Tanous { 1130f476acbfSRatan Gupta if (!input.is_array()) 1131f476acbfSRatan Gupta { 1132f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1133f476acbfSRatan Gupta "IPv4Addresses"); 1134f476acbfSRatan Gupta return; 1135f476acbfSRatan Gupta } 1136f476acbfSRatan Gupta 11374a0cb85cSEd Tanous int entryIdx = 0; 11384a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::const_iterator thisData = 11394a0cb85cSEd Tanous ipv4Data.begin(); 1140537174c4SEd Tanous for (nlohmann::json &thisJson : input) 11411abe55efSEd Tanous { 11424a0cb85cSEd Tanous std::string pathString = 1143a08b46ccSJason M. Bills "IPv4Addresses/" + std::to_string(entryIdx); 1144179db1d7SKowalski, Kamil 1145f476acbfSRatan Gupta if (thisJson.is_null()) 1146f476acbfSRatan Gupta { 1147f476acbfSRatan Gupta if (thisData != ipv4Data.end()) 1148f476acbfSRatan Gupta { 1149286b9118SJohnathan Mantey deleteIPv4(ifaceId, thisData->id, asyncResp); 1150f476acbfSRatan Gupta thisData++; 1151f476acbfSRatan Gupta } 1152f476acbfSRatan Gupta else 1153f476acbfSRatan Gupta { 1154f476acbfSRatan Gupta messages::propertyValueFormatError( 1155f476acbfSRatan Gupta asyncResp->res, input.dump(), pathString); 1156f476acbfSRatan Gupta return; 1157f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 1158f476acbfSRatan Gupta // list and if unable to update one of the 1159f476acbfSRatan Gupta // list value then should we proceed further or 1160f476acbfSRatan Gupta // break there, would ask in the redfish forum 1161f476acbfSRatan Gupta // till then we stop processing the next list item. 1162f476acbfSRatan Gupta } 1163f476acbfSRatan Gupta entryIdx++; 1164f476acbfSRatan Gupta continue; // not an error as per the redfish spec. 1165f476acbfSRatan Gupta } 1166f476acbfSRatan Gupta 11679474b378SRatan Gupta if (thisJson.empty()) 11689474b378SRatan Gupta { 11699474b378SRatan Gupta if (thisData != ipv4Data.end()) 11709474b378SRatan Gupta { 11719474b378SRatan Gupta thisData++; 11729474b378SRatan Gupta } 11739474b378SRatan Gupta else 11749474b378SRatan Gupta { 11759474b378SRatan Gupta messages::propertyMissing(asyncResp->res, 11769474b378SRatan Gupta pathString + "/Address"); 11779474b378SRatan Gupta return; 1178f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 11799474b378SRatan Gupta // list and if unable to update one of the 11809474b378SRatan Gupta // list value then should we proceed further or 11819474b378SRatan Gupta // break there, would ask in the redfish forum 11829474b378SRatan Gupta // till then we stop processing the next list item. 11839474b378SRatan Gupta } 11849474b378SRatan Gupta entryIdx++; 11859474b378SRatan Gupta continue; // not an error as per the redfish spec. 11869474b378SRatan Gupta } 11879474b378SRatan Gupta 1188537174c4SEd Tanous std::optional<std::string> address; 1189537174c4SEd Tanous std::optional<std::string> subnetMask; 1190537174c4SEd Tanous std::optional<std::string> gateway; 1191537174c4SEd Tanous 1192537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 11937e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 11947e27d832SJohnathan Mantey "Gateway", gateway)) 1195537174c4SEd Tanous { 1196537174c4SEd Tanous return; 1197179db1d7SKowalski, Kamil } 1198179db1d7SKowalski, Kamil 1199537174c4SEd Tanous if (address) 12001abe55efSEd Tanous { 1201537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*address)) 12021abe55efSEd Tanous { 1203537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 12044a0cb85cSEd Tanous pathString + "/Address"); 1205537174c4SEd Tanous return; 12064a0cb85cSEd Tanous } 12074a0cb85cSEd Tanous } 12084a0cb85cSEd Tanous 1209537174c4SEd Tanous uint8_t prefixLength = 0; 1210537174c4SEd Tanous if (subnetMask) 12114a0cb85cSEd Tanous { 1212537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 12134a0cb85cSEd Tanous { 1214f12894f8SJason M. Bills messages::propertyValueFormatError( 1215537174c4SEd Tanous asyncResp->res, *subnetMask, 12164a0cb85cSEd Tanous pathString + "/SubnetMask"); 1217537174c4SEd Tanous return; 12184a0cb85cSEd Tanous } 12194a0cb85cSEd Tanous } 12204a0cb85cSEd Tanous 1221537174c4SEd Tanous if (gateway) 12224a0cb85cSEd Tanous { 1223537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*gateway)) 12244a0cb85cSEd Tanous { 1225537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1226537174c4SEd Tanous pathString + "/Gateway"); 1227537174c4SEd Tanous return; 12284a0cb85cSEd Tanous } 12294a0cb85cSEd Tanous } 12304a0cb85cSEd Tanous 1231f476acbfSRatan Gupta // if IP address exist then modify it. 12324a0cb85cSEd Tanous if (thisData != ipv4Data.end()) 12334a0cb85cSEd Tanous { 1234179db1d7SKowalski, Kamil // Apply changes 1235537174c4SEd Tanous if (address) 12361abe55efSEd Tanous { 1237286b9118SJohnathan Mantey auto callback = 1238286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 12394a0cb85cSEd Tanous if (ec) 12401abe55efSEd Tanous { 1241a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12424a0cb85cSEd Tanous return; 12434a0cb85cSEd Tanous } 12444a0cb85cSEd Tanous }; 12454a0cb85cSEd Tanous 12464a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12474a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1248f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1249f476acbfSRatan Gupta thisData->id, 12504a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12514a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Address", 1252537174c4SEd Tanous std::variant<std::string>(*address)); 1253179db1d7SKowalski, Kamil } 1254179db1d7SKowalski, Kamil 1255537174c4SEd Tanous if (subnetMask) 12561abe55efSEd Tanous { 12574a0cb85cSEd Tanous changeIPv4SubnetMaskProperty(ifaceId, entryIdx, 1258286b9118SJohnathan Mantey thisData->id, prefixLength, 1259286b9118SJohnathan Mantey asyncResp); 1260179db1d7SKowalski, Kamil } 1261179db1d7SKowalski, Kamil 1262537174c4SEd Tanous if (gateway) 12631abe55efSEd Tanous { 1264286b9118SJohnathan Mantey auto callback = 1265286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 12664a0cb85cSEd Tanous if (ec) 12671abe55efSEd Tanous { 1268a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12694a0cb85cSEd Tanous return; 12704a0cb85cSEd Tanous } 12714a0cb85cSEd Tanous }; 12724a0cb85cSEd Tanous 12734a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12744a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1275f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1276f476acbfSRatan Gupta thisData->id, 12774a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12784a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Gateway", 1279537174c4SEd Tanous std::variant<std::string>(*gateway)); 12804a0cb85cSEd Tanous } 1281f476acbfSRatan Gupta 12824a0cb85cSEd Tanous thisData++; 12831abe55efSEd Tanous } 12841abe55efSEd Tanous else 12851abe55efSEd Tanous { 12864a0cb85cSEd Tanous // Create IPv4 with provided data 1287537174c4SEd Tanous if (!gateway) 12881abe55efSEd Tanous { 1289a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 12904a0cb85cSEd Tanous pathString + "/Gateway"); 12914a0cb85cSEd Tanous continue; 12924a0cb85cSEd Tanous } 12934a0cb85cSEd Tanous 1294537174c4SEd Tanous if (!address) 12951abe55efSEd Tanous { 1296a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 12974a0cb85cSEd Tanous pathString + "/Address"); 12984a0cb85cSEd Tanous continue; 12994a0cb85cSEd Tanous } 13004a0cb85cSEd Tanous 1301537174c4SEd Tanous if (!subnetMask) 13021abe55efSEd Tanous { 1303a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13044a0cb85cSEd Tanous pathString + "/SubnetMask"); 13054a0cb85cSEd Tanous continue; 1306588c3f0dSKowalski, Kamil } 1307588c3f0dSKowalski, Kamil 1308b01bf299SEd Tanous createIPv4(ifaceId, entryIdx, prefixLength, *gateway, *address, 1309b01bf299SEd Tanous asyncResp); 131095897b20SRatan Gupta 131195897b20SRatan Gupta nlohmann::json &ipv4AddressJson = 131295897b20SRatan Gupta asyncResp->res.jsonValue["IPv4Addresses"][entryIdx]; 131395897b20SRatan Gupta ipv4AddressJson["Address"] = *address; 131495897b20SRatan Gupta ipv4AddressJson["SubnetMask"] = *subnetMask; 131595897b20SRatan Gupta ipv4AddressJson["Gateway"] = *gateway; 13164a0cb85cSEd Tanous } 13174a0cb85cSEd Tanous entryIdx++; 13184a0cb85cSEd Tanous } 13194a0cb85cSEd Tanous } 13204a0cb85cSEd Tanous 1321f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1322f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1323f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1324f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1325f85837bfSRAJESWARAN THILLAIGOVINDAN { 1326f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1327286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1328f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1329f85837bfSRAJESWARAN THILLAIGOVINDAN { 1330f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1331f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1332f85837bfSRAJESWARAN THILLAIGOVINDAN } 1333f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1334f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1335f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1336f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1337f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1338f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1339f85837bfSRAJESWARAN THILLAIGOVINDAN } 1340f85837bfSRAJESWARAN THILLAIGOVINDAN 1341e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1342e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 1343e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData, 1344e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1345e48c0fc5SRavi Teja { 1346e48c0fc5SRavi Teja if (!input.is_array()) 1347e48c0fc5SRavi Teja { 1348e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1349e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1350e48c0fc5SRavi Teja return; 1351e48c0fc5SRavi Teja } 1352e48c0fc5SRavi Teja 1353e48c0fc5SRavi Teja int entryIdx = 0; 1354e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::const_iterator thisData = 1355e48c0fc5SRavi Teja ipv6StaticData.begin(); 1356e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1357e48c0fc5SRavi Teja { 1358e48c0fc5SRavi Teja std::string pathString = 1359e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1360e48c0fc5SRavi Teja 1361e48c0fc5SRavi Teja if (thisJson.is_null()) 1362e48c0fc5SRavi Teja { 1363e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1364e48c0fc5SRavi Teja { 1365286b9118SJohnathan Mantey deleteIPv6(ifaceId, thisData->id, asyncResp); 1366e48c0fc5SRavi Teja thisData++; 1367e48c0fc5SRavi Teja } 1368e48c0fc5SRavi Teja else 1369e48c0fc5SRavi Teja { 1370e48c0fc5SRavi Teja messages::propertyValueFormatError( 1371e48c0fc5SRavi Teja asyncResp->res, input.dump(), pathString); 1372e48c0fc5SRavi Teja return; 1373e48c0fc5SRavi Teja } 1374e48c0fc5SRavi Teja entryIdx++; 1375e48c0fc5SRavi Teja continue; 1376e48c0fc5SRavi Teja } 1377e48c0fc5SRavi Teja 1378e48c0fc5SRavi Teja if (thisJson.empty()) 1379e48c0fc5SRavi Teja { 1380e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1381e48c0fc5SRavi Teja { 1382e48c0fc5SRavi Teja thisData++; 1383e48c0fc5SRavi Teja } 1384e48c0fc5SRavi Teja else 1385e48c0fc5SRavi Teja { 1386e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1387e48c0fc5SRavi Teja pathString + "/Address"); 1388e48c0fc5SRavi Teja return; 1389e48c0fc5SRavi Teja } 1390e48c0fc5SRavi Teja entryIdx++; 1391e48c0fc5SRavi Teja continue; 1392e48c0fc5SRavi Teja } 1393e48c0fc5SRavi Teja 1394e48c0fc5SRavi Teja std::optional<std::string> address; 1395e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1396e48c0fc5SRavi Teja 1397e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1398e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1399e48c0fc5SRavi Teja { 1400e48c0fc5SRavi Teja return; 1401e48c0fc5SRavi Teja } 1402e48c0fc5SRavi Teja 1403e48c0fc5SRavi Teja // if IP address exist then modify it. 1404e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1405e48c0fc5SRavi Teja { 1406e48c0fc5SRavi Teja // Apply changes 1407e48c0fc5SRavi Teja if (address) 1408e48c0fc5SRavi Teja { 1409286b9118SJohnathan Mantey auto callback = 1410286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1411e48c0fc5SRavi Teja if (ec) 1412e48c0fc5SRavi Teja { 1413e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1414e48c0fc5SRavi Teja return; 1415e48c0fc5SRavi Teja } 1416e48c0fc5SRavi Teja }; 1417e48c0fc5SRavi Teja 1418e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1419e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1420e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1421e48c0fc5SRavi Teja thisData->id, 1422e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1423e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "Address", 1424e48c0fc5SRavi Teja std::variant<std::string>(*address)); 1425e48c0fc5SRavi Teja } 1426e48c0fc5SRavi Teja 1427e48c0fc5SRavi Teja if (prefixLength) 1428e48c0fc5SRavi Teja { 1429286b9118SJohnathan Mantey auto callback = 1430286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1431e48c0fc5SRavi Teja if (ec) 1432e48c0fc5SRavi Teja { 1433e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1434e48c0fc5SRavi Teja return; 1435e48c0fc5SRavi Teja } 1436e48c0fc5SRavi Teja }; 1437e48c0fc5SRavi Teja 1438e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1439e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1440e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1441e48c0fc5SRavi Teja thisData->id, 1442e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1443e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "PrefixLength", 1444e48c0fc5SRavi Teja std::variant<uint8_t>(*prefixLength)); 1445e48c0fc5SRavi Teja } 1446e48c0fc5SRavi Teja 1447e48c0fc5SRavi Teja thisData++; 1448e48c0fc5SRavi Teja } 1449e48c0fc5SRavi Teja else 1450e48c0fc5SRavi Teja { 1451e48c0fc5SRavi Teja // Create IPv6 with provided data 1452e48c0fc5SRavi Teja 1453e48c0fc5SRavi Teja if (!prefixLength) 1454e48c0fc5SRavi Teja { 1455e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1456e48c0fc5SRavi Teja pathString + "/PrefixLength"); 1457e48c0fc5SRavi Teja continue; 1458e48c0fc5SRavi Teja } 1459e48c0fc5SRavi Teja 1460e48c0fc5SRavi Teja if (!address) 1461e48c0fc5SRavi Teja { 1462e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1463e48c0fc5SRavi Teja pathString + "/Address"); 1464e48c0fc5SRavi Teja continue; 1465e48c0fc5SRavi Teja } 1466e48c0fc5SRavi Teja 1467e48c0fc5SRavi Teja createIPv6(ifaceId, entryIdx, *prefixLength, *address, 1468e48c0fc5SRavi Teja asyncResp); 1469e48c0fc5SRavi Teja 1470e48c0fc5SRavi Teja nlohmann::json &ipv6StaticAddressJson = 1471e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"][entryIdx]; 1472e48c0fc5SRavi Teja ipv6StaticAddressJson["Address"] = *address; 1473e48c0fc5SRavi Teja ipv6StaticAddressJson["PrefixLength"] = *prefixLength; 1474e48c0fc5SRavi Teja } 1475e48c0fc5SRavi Teja entryIdx++; 1476e48c0fc5SRavi Teja } 1477e48c0fc5SRavi Teja } 1478e48c0fc5SRavi Teja 14790f74e643SEd Tanous void parseInterfaceData( 14800f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 14810f74e643SEd Tanous const EthernetInterfaceData ðData, 1482e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1483e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1484e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 14854a0cb85cSEd Tanous { 14864a0cb85cSEd Tanous json_response["Id"] = iface_id; 14874a0cb85cSEd Tanous json_response["@odata.id"] = 14884a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1489029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1490029573d4SEd Tanous if (ethData.speed == 0) 1491029573d4SEd Tanous { 1492029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1493029573d4SEd Tanous json_response["Status"] = { 1494029573d4SEd Tanous {"Health", "OK"}, 1495029573d4SEd Tanous {"State", "Disabled"}, 1496029573d4SEd Tanous }; 1497029573d4SEd Tanous } 1498029573d4SEd Tanous else 1499029573d4SEd Tanous { 1500029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1501029573d4SEd Tanous json_response["Status"] = { 1502029573d4SEd Tanous {"Health", "OK"}, 1503029573d4SEd Tanous {"State", "Enabled"}, 1504029573d4SEd Tanous }; 1505029573d4SEd Tanous } 15064a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 15074a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1508fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 15092a133282Smanojkiraneda 15104a0cb85cSEd Tanous if (!ethData.hostname.empty()) 15114a0cb85cSEd Tanous { 15124a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 1513*d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1514*d24bfc7aSJennifer Lee { 1515*d24bfc7aSJennifer Lee json_response["FQDN"] = 1516*d24bfc7aSJennifer Lee ethData.hostname + "." + ethData.domainnames[0]; 1517*d24bfc7aSJennifer Lee } 15184a0cb85cSEd Tanous } 15194a0cb85cSEd Tanous 1520fda13ad2SSunitha Harish json_response["VLANs"] = { 1521fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1522fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1523fda13ad2SSunitha Harish 1524029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 1525f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 15264a0cb85cSEd Tanous 15274a0cb85cSEd Tanous if (ipv4Data.size() > 0) 15284a0cb85cSEd Tanous { 15294a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 15304a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 15314a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 15324a0cb85cSEd Tanous { 1533fa5053a6SGunnar Mills 1534fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1535fa5053a6SGunnar Mills if (gatewayStr.empty()) 1536fa5053a6SGunnar Mills { 1537fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1538fa5053a6SGunnar Mills } 1539fa5053a6SGunnar Mills 15404a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 15414a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1542029573d4SEd Tanous {"Address", ipv4_config.address}, 1543fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 15444a0cb85cSEd Tanous } 15454a0cb85cSEd Tanous } 15469a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1547e48c0fc5SRavi Teja 1548e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 1549e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 1550e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1551e48c0fc5SRavi Teja { 1552e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1553e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1554e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 1555e48c0fc5SRavi Teja } 1556e48c0fc5SRavi Teja 1557e48c0fc5SRavi Teja nlohmann::json &ipv6_static_array = 1558e48c0fc5SRavi Teja json_response["IPv6StaticAddresses"]; 1559e48c0fc5SRavi Teja ipv6_static_array = nlohmann::json::array(); 1560e48c0fc5SRavi Teja for (auto &ipv6_static_config : ipv6StaticData) 1561e48c0fc5SRavi Teja { 1562e48c0fc5SRavi Teja ipv6_static_array.push_back( 1563e48c0fc5SRavi Teja {{"Address", ipv6_static_config.address}, 1564e48c0fc5SRavi Teja {"PrefixLength", ipv6_static_config.prefixLength}}); 1565e48c0fc5SRavi Teja } 1566588c3f0dSKowalski, Kamil } 1567588c3f0dSKowalski, Kamil 15689391bb9cSRapkiewicz, Pawel /** 15699391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 15709391bb9cSRapkiewicz, Pawel */ 157155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 15721abe55efSEd Tanous const std::vector<std::string> ¶ms) override 15731abe55efSEd Tanous { 15744a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 15751abe55efSEd Tanous if (params.size() != 1) 15761abe55efSEd Tanous { 1577f12894f8SJason M. Bills messages::internalError(asyncResp->res); 15789391bb9cSRapkiewicz, Pawel return; 15799391bb9cSRapkiewicz, Pawel } 15809391bb9cSRapkiewicz, Pawel 15814a0cb85cSEd Tanous getEthernetIfaceData( 15824a0cb85cSEd Tanous params[0], 15834a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 15844a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1585e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1586e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1587e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1588e48c0fc5SRavi Teja &ipv6StaticData) { 15894a0cb85cSEd Tanous if (!success) 15901abe55efSEd Tanous { 15911abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 15921abe55efSEd Tanous // object, and other errors 1593f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1594f12894f8SJason M. Bills "EthernetInterface", iface_id); 15954a0cb85cSEd Tanous return; 15969391bb9cSRapkiewicz, Pawel } 15974c9afe43SEd Tanous 15984c9afe43SEd Tanous // because this has no dependence on the interface at this 15994c9afe43SEd Tanous // point, it needs to be done after we know the interface 16004c9afe43SEd Tanous // exists, not before. 16014c9afe43SEd Tanous getDHCPConfigData(asyncResp); 16024c9afe43SEd Tanous 16030f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1604fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 16050f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 16060f74e643SEd Tanous "/redfish/v1/$metadata#EthernetInterface.EthernetInterface"; 16070f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 16080f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 16090f74e643SEd Tanous "Management Network Interface"; 16100f74e643SEd Tanous 16110f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1612e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 16139391bb9cSRapkiewicz, Pawel }); 16149391bb9cSRapkiewicz, Pawel } 16159391bb9cSRapkiewicz, Pawel 161655c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 16171abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16181abe55efSEd Tanous { 16194a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16201abe55efSEd Tanous if (params.size() != 1) 16211abe55efSEd Tanous { 1622f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1623588c3f0dSKowalski, Kamil return; 1624588c3f0dSKowalski, Kamil } 1625588c3f0dSKowalski, Kamil 16264a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1627588c3f0dSKowalski, Kamil 1628bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1629d577665bSRatan Gupta std::optional<std::string> macAddress; 16309a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1631f476acbfSRatan Gupta std::optional<nlohmann::json> ipv4Addresses; 1632f476acbfSRatan Gupta std::optional<nlohmann::json> ipv6Addresses; 1633e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1634f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 16355112e9b4SRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> nameServers; 1636da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 16370627a2c7SEd Tanous 1638fda13ad2SSunitha Harish if (!json_util::readJson( 1639fda13ad2SSunitha Harish req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses, 16406ca6ac12SJohnathan Mantey "MACAddress", macAddress, "StaticNameServers", 16416ca6ac12SJohnathan Mantey staticNameServers, "IPv6DefaultGateway", ipv6DefaultGateway, 16426ca6ac12SJohnathan Mantey "IPv6StaticAddresses", ipv6StaticAddresses, "NameServers", 16436ca6ac12SJohnathan Mantey nameServers, "DHCPv4", dhcpv4)) 16441abe55efSEd Tanous { 1645588c3f0dSKowalski, Kamil return; 1646588c3f0dSKowalski, Kamil } 1647f15aad37SRatan Gupta 1648da131a9aSJennifer Lee if (dhcpv4) 1649da131a9aSJennifer Lee { 1650da131a9aSJennifer Lee handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp); 1651da131a9aSJennifer Lee } 1652da131a9aSJennifer Lee 16534a0cb85cSEd Tanous // Get single eth interface data, and call the below callback for JSON 1654588c3f0dSKowalski, Kamil // preparation 16554a0cb85cSEd Tanous getEthernetIfaceData( 16564a0cb85cSEd Tanous iface_id, 1657fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1658fda13ad2SSunitha Harish macAddress = std::move(macAddress), 16590627a2c7SEd Tanous ipv4Addresses = std::move(ipv4Addresses), 16609a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1661e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 16625112e9b4SRAJESWARAN THILLAIGOVINDAN staticNameServers = std::move(staticNameServers), 16635112e9b4SRAJESWARAN THILLAIGOVINDAN nameServers = std::move(nameServers)]( 16644a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1665e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1666e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1667e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1668e48c0fc5SRavi Teja &ipv6StaticData) { 16691abe55efSEd Tanous if (!success) 16701abe55efSEd Tanous { 1671588c3f0dSKowalski, Kamil // ... otherwise return error 16721abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16731abe55efSEd Tanous // object, and other errors 1674fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1675fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1676588c3f0dSKowalski, Kamil return; 1677588c3f0dSKowalski, Kamil } 1678588c3f0dSKowalski, Kamil 16790627a2c7SEd Tanous if (hostname) 16801abe55efSEd Tanous { 16810627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 16821abe55efSEd Tanous } 16830627a2c7SEd Tanous 1684d577665bSRatan Gupta if (macAddress) 1685d577665bSRatan Gupta { 1686d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1687d577665bSRatan Gupta } 1688d577665bSRatan Gupta 16890627a2c7SEd Tanous if (ipv4Addresses) 16901abe55efSEd Tanous { 1691537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 1692537174c4SEd Tanous // above is returning a const value, not a non-const value. 1693537174c4SEd Tanous // This doesn't really work for us, as we need to be able to 1694537174c4SEd Tanous // efficiently move out the intermedia nlohmann::json 1695537174c4SEd Tanous // objects. This makes a copy of the structure, and operates 1696537174c4SEd Tanous // on that, but could be done more efficiently 1697f476acbfSRatan Gupta nlohmann::json ipv4 = std::move(*ipv4Addresses); 1698537174c4SEd Tanous handleIPv4Patch(iface_id, ipv4, ipv4Data, asyncResp); 16991abe55efSEd Tanous } 17000627a2c7SEd Tanous 17015112e9b4SRAJESWARAN THILLAIGOVINDAN if (nameServers) 17025112e9b4SRAJESWARAN THILLAIGOVINDAN { 17035112e9b4SRAJESWARAN THILLAIGOVINDAN // Data.Permissions is read-only 17045112e9b4SRAJESWARAN THILLAIGOVINDAN messages::propertyNotWritable(asyncResp->res, 17055112e9b4SRAJESWARAN THILLAIGOVINDAN "NameServers"); 17065112e9b4SRAJESWARAN THILLAIGOVINDAN } 17075112e9b4SRAJESWARAN THILLAIGOVINDAN 1708f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1709f85837bfSRAJESWARAN THILLAIGOVINDAN { 1710f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1711f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1712f85837bfSRAJESWARAN THILLAIGOVINDAN } 17139a6fc6feSRavi Teja 17149a6fc6feSRavi Teja if (ipv6DefaultGateway) 17159a6fc6feSRavi Teja { 17169a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 17179a6fc6feSRavi Teja "IPv6DefaultGateway"); 17189a6fc6feSRavi Teja } 1719e48c0fc5SRavi Teja 1720e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1721e48c0fc5SRavi Teja { 1722e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1723e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 1724e48c0fc5SRavi Teja ipv6StaticData, asyncResp); 1725e48c0fc5SRavi Teja } 1726588c3f0dSKowalski, Kamil }); 1727588c3f0dSKowalski, Kamil } 17289391bb9cSRapkiewicz, Pawel }; 17299391bb9cSRapkiewicz, Pawel 1730e439f0f8SKowalski, Kamil /** 17314a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 17324a0cb85cSEd Tanous * Schema 1733e439f0f8SKowalski, Kamil */ 17341abe55efSEd Tanous class VlanNetworkInterface : public Node 17351abe55efSEd Tanous { 1736e439f0f8SKowalski, Kamil public: 1737e439f0f8SKowalski, Kamil /* 1738e439f0f8SKowalski, Kamil * Default Constructor 1739e439f0f8SKowalski, Kamil */ 1740e439f0f8SKowalski, Kamil template <typename CrowApp> 17411abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 17424a0cb85cSEd Tanous Node(app, 17430f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 17441abe55efSEd Tanous std::string(), std::string()) 17451abe55efSEd Tanous { 1746e439f0f8SKowalski, Kamil entityPrivileges = { 1747e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1748e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1749e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1750e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1751e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1752e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1753e439f0f8SKowalski, Kamil } 1754e439f0f8SKowalski, Kamil 1755e439f0f8SKowalski, Kamil private: 17560f74e643SEd Tanous void parseInterfaceData( 17570f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 17580f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1759e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1760e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1761e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 17621abe55efSEd Tanous { 1763e439f0f8SKowalski, Kamil // Fill out obvious data... 17644a0cb85cSEd Tanous json_response["Id"] = iface_id; 17654a0cb85cSEd Tanous json_response["@odata.id"] = 17664a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 17674a0cb85cSEd Tanous "/VLANs/" + iface_id; 1768e439f0f8SKowalski, Kamil 17694a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1770fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 17714a0cb85cSEd Tanous { 1772fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 17734a0cb85cSEd Tanous } 1774e439f0f8SKowalski, Kamil } 1775e439f0f8SKowalski, Kamil 1776fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 17771abe55efSEd Tanous { 17781abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 17791abe55efSEd Tanous { 1780927a505aSKowalski, Kamil return false; 17811abe55efSEd Tanous } 17821abe55efSEd Tanous else 17831abe55efSEd Tanous { 1784927a505aSKowalski, Kamil return true; 1785927a505aSKowalski, Kamil } 1786927a505aSKowalski, Kamil } 1787927a505aSKowalski, Kamil 1788e439f0f8SKowalski, Kamil /** 1789e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1790e439f0f8SKowalski, Kamil */ 179155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 17921abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17931abe55efSEd Tanous { 17944a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17954a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1796e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1797e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1798e439f0f8SKowalski, Kamil // impossible. 17991abe55efSEd Tanous if (params.size() != 2) 18001abe55efSEd Tanous { 1801f12894f8SJason M. Bills messages::internalError(res); 1802e439f0f8SKowalski, Kamil res.end(); 1803e439f0f8SKowalski, Kamil return; 1804e439f0f8SKowalski, Kamil } 1805e439f0f8SKowalski, Kamil 18064a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 18074a0cb85cSEd Tanous const std::string &iface_id = params[1]; 18080f74e643SEd Tanous res.jsonValue["@odata.type"] = 18090f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 18100f74e643SEd Tanous res.jsonValue["@odata.context"] = 18110f74e643SEd Tanous "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface"; 18120f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1813e439f0f8SKowalski, Kamil 1814fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 18151abe55efSEd Tanous { 1816a434f2bdSEd Tanous return; 1817a434f2bdSEd Tanous } 1818a434f2bdSEd Tanous 1819e439f0f8SKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1820e439f0f8SKowalski, Kamil // preparation 18214a0cb85cSEd Tanous getEthernetIfaceData( 1822fda13ad2SSunitha Harish params[1], 1823fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1824fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 18254a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1826e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1827e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1828e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1829e48c0fc5SRavi Teja &ipv6StaticData) { 1830fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 18311abe55efSEd Tanous { 18320f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 18330f74e643SEd Tanous parent_iface_id, iface_id, ethData, 1834e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 18351abe55efSEd Tanous } 18361abe55efSEd Tanous else 18371abe55efSEd Tanous { 1838e439f0f8SKowalski, Kamil // ... otherwise return error 18391abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18401abe55efSEd Tanous // object, and other errors 1841f12894f8SJason M. Bills messages::resourceNotFound( 1842f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1843e439f0f8SKowalski, Kamil } 1844e439f0f8SKowalski, Kamil }); 1845e439f0f8SKowalski, Kamil } 1846e439f0f8SKowalski, Kamil 184755c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 18481abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18491abe55efSEd Tanous { 18504a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18511abe55efSEd Tanous if (params.size() != 2) 18521abe55efSEd Tanous { 1853f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1854e439f0f8SKowalski, Kamil return; 1855e439f0f8SKowalski, Kamil } 1856e439f0f8SKowalski, Kamil 1857d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 185855c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1859927a505aSKowalski, Kamil 1860fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 18611abe55efSEd Tanous { 1862fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1863fda13ad2SSunitha Harish ifaceId); 1864927a505aSKowalski, Kamil return; 1865927a505aSKowalski, Kamil } 1866927a505aSKowalski, Kamil 18670627a2c7SEd Tanous bool vlanEnable = false; 18680627a2c7SEd Tanous uint64_t vlanId = 0; 18690627a2c7SEd Tanous 18700627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 18710627a2c7SEd Tanous vlanId)) 18721abe55efSEd Tanous { 1873927a505aSKowalski, Kamil return; 1874927a505aSKowalski, Kamil } 1875927a505aSKowalski, Kamil 1876927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1877927a505aSKowalski, Kamil // preparation 1878e48c0fc5SRavi Teja getEthernetIfaceData( 1879e48c0fc5SRavi Teja params[1], 1880e48c0fc5SRavi Teja [this, asyncResp, parentIfaceId{std::string(params[0])}, 1881e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 1882e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 1883e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1884e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1885e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1886e48c0fc5SRavi Teja &ipv6StaticData) { 188708244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 188808244d02SSunitha Harish { 188908244d02SSunitha Harish auto callback = 189008244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 189108244d02SSunitha Harish if (ec) 189208244d02SSunitha Harish { 189308244d02SSunitha Harish messages::internalError(asyncResp->res); 189408244d02SSunitha Harish } 189508244d02SSunitha Harish }; 189608244d02SSunitha Harish 189708244d02SSunitha Harish if (vlanEnable == true) 189808244d02SSunitha Harish { 189908244d02SSunitha Harish crow::connections::systemBus->async_method_call( 190008244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 190108244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 190208244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 190308244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 190408244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 190508244d02SSunitha Harish } 190608244d02SSunitha Harish else 190708244d02SSunitha Harish { 1908e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 1909e48c0fc5SRavi Teja "vlan interface"; 191008244d02SSunitha Harish crow::connections::systemBus->async_method_call( 191108244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 1912e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 1913e48c0fc5SRavi Teja ifaceId, 191408244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 191508244d02SSunitha Harish } 191608244d02SSunitha Harish } 191708244d02SSunitha Harish else 19181abe55efSEd Tanous { 19191abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 19201abe55efSEd Tanous // object, and other errors 1921e48c0fc5SRavi Teja messages::resourceNotFound( 1922e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 1923927a505aSKowalski, Kamil return; 1924927a505aSKowalski, Kamil } 1925927a505aSKowalski, Kamil }); 1926e439f0f8SKowalski, Kamil } 1927e439f0f8SKowalski, Kamil 192855c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 19291abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19301abe55efSEd Tanous { 19314a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19321abe55efSEd Tanous if (params.size() != 2) 19331abe55efSEd Tanous { 1934f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1935e439f0f8SKowalski, Kamil return; 1936e439f0f8SKowalski, Kamil } 1937e439f0f8SKowalski, Kamil 1938d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 193955c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1940927a505aSKowalski, Kamil 1941fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19421abe55efSEd Tanous { 1943fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1944fda13ad2SSunitha Harish ifaceId); 1945927a505aSKowalski, Kamil return; 1946927a505aSKowalski, Kamil } 1947927a505aSKowalski, Kamil 1948927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1949927a505aSKowalski, Kamil // preparation 1950f12894f8SJason M. Bills getEthernetIfaceData( 1951fda13ad2SSunitha Harish params[1], 1952fda13ad2SSunitha Harish [this, asyncResp, parentIfaceId{std::string(params[0])}, 1953fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 1954f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 1955e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1956e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1957e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1958e48c0fc5SRavi Teja &ipv6StaticData) { 1959fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 19601abe55efSEd Tanous { 1961f12894f8SJason M. Bills auto callback = 1962f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 19631abe55efSEd Tanous if (ec) 19641abe55efSEd Tanous { 1965f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1966927a505aSKowalski, Kamil } 19674a0cb85cSEd Tanous }; 19684a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 19694a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 19704a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 19714a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 19721abe55efSEd Tanous } 19731abe55efSEd Tanous else 19741abe55efSEd Tanous { 1975927a505aSKowalski, Kamil // ... otherwise return error 1976f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 1977f12894f8SJason M. Bills // object, and other errors 1978f12894f8SJason M. Bills messages::resourceNotFound( 1979f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 1980927a505aSKowalski, Kamil } 1981927a505aSKowalski, Kamil }); 1982e439f0f8SKowalski, Kamil } 1983e439f0f8SKowalski, Kamil }; 1984e439f0f8SKowalski, Kamil 1985e439f0f8SKowalski, Kamil /** 1986e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 1987e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 1988e439f0f8SKowalski, Kamil */ 19891abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 19901abe55efSEd Tanous { 1991e439f0f8SKowalski, Kamil public: 1992e439f0f8SKowalski, Kamil template <typename CrowApp> 19931abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 19944a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 19954a0cb85cSEd Tanous std::string()) 19961abe55efSEd Tanous { 1997e439f0f8SKowalski, Kamil entityPrivileges = { 1998e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1999e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2000e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2001e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2002e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2003e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2004e439f0f8SKowalski, Kamil } 2005e439f0f8SKowalski, Kamil 2006e439f0f8SKowalski, Kamil private: 2007e439f0f8SKowalski, Kamil /** 2008e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2009e439f0f8SKowalski, Kamil */ 201055c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 20111abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20121abe55efSEd Tanous { 20134a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20141abe55efSEd Tanous if (params.size() != 1) 20151abe55efSEd Tanous { 2016e439f0f8SKowalski, Kamil // This means there is a problem with the router 2017f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2018e439f0f8SKowalski, Kamil return; 2019e439f0f8SKowalski, Kamil } 2020e439f0f8SKowalski, Kamil 20214a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2022e439f0f8SKowalski, Kamil 20234a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 20241abe55efSEd Tanous // preparation 2025f12894f8SJason M. Bills getEthernetIfaceList( 202643b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 20271abe55efSEd Tanous const bool &success, 20284c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 20294a0cb85cSEd Tanous if (!success) 20301abe55efSEd Tanous { 2031f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20324a0cb85cSEd Tanous return; 20331abe55efSEd Tanous } 20344c9afe43SEd Tanous 20354c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 20364c9afe43SEd Tanous { 20374c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 20384c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 20394c9afe43SEd Tanous rootInterfaceName); 20404c9afe43SEd Tanous return; 20414c9afe43SEd Tanous } 20424c9afe43SEd Tanous 20430f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 20440f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 20450f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 20460f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 20470f74e643SEd Tanous "/redfish/v1/$metadata" 20480f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 20490f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 20500f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 20510f74e643SEd Tanous "VLAN Network Interface Collection"; 20524a0cb85cSEd Tanous 20534a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 20544a0cb85cSEd Tanous 20554a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 20561abe55efSEd Tanous { 20574a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 20584a0cb85cSEd Tanous { 20594a0cb85cSEd Tanous iface_array.push_back( 20604a0cb85cSEd Tanous {{"@odata.id", 20614a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 20624a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2063e439f0f8SKowalski, Kamil } 2064e439f0f8SKowalski, Kamil } 2065e439f0f8SKowalski, Kamil 20664a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 20674a0cb85cSEd Tanous iface_array.size(); 20684a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 20694a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 20704a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 20714a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2072e439f0f8SKowalski, Kamil }); 2073e439f0f8SKowalski, Kamil } 2074e439f0f8SKowalski, Kamil 207555c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 20761abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20771abe55efSEd Tanous { 20784a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20791abe55efSEd Tanous if (params.size() != 1) 20801abe55efSEd Tanous { 2081f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2082e439f0f8SKowalski, Kamil return; 2083e439f0f8SKowalski, Kamil } 2084fda13ad2SSunitha Harish bool vlanEnable = false; 20850627a2c7SEd Tanous uint32_t vlanId = 0; 2086fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2087fda13ad2SSunitha Harish vlanEnable)) 20881abe55efSEd Tanous { 20894a0cb85cSEd Tanous return; 2090e439f0f8SKowalski, Kamil } 2091fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2092fda13ad2SSunitha Harish if (!vlanId) 2093fda13ad2SSunitha Harish { 2094fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2095fda13ad2SSunitha Harish } 2096fda13ad2SSunitha Harish if (!vlanEnable) 2097fda13ad2SSunitha Harish { 2098fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2099fda13ad2SSunitha Harish } 2100fda13ad2SSunitha Harish if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) 2101fda13ad2SSunitha Harish { 2102fda13ad2SSunitha Harish return; 2103fda13ad2SSunitha Harish } 2104fda13ad2SSunitha Harish 21054a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 21064a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 21071abe55efSEd Tanous if (ec) 21081abe55efSEd Tanous { 21094a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 21104a0cb85cSEd Tanous // phosphor-network responses 2111f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21124a0cb85cSEd Tanous return; 21131abe55efSEd Tanous } 2114f12894f8SJason M. Bills messages::created(asyncResp->res); 2115e439f0f8SKowalski, Kamil }; 21164a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21174a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21184a0cb85cSEd Tanous "/xyz/openbmc_project/network", 21194a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 21200627a2c7SEd Tanous rootInterfaceName, vlanId); 21214a0cb85cSEd Tanous } 21224a0cb85cSEd Tanous }; 21239391bb9cSRapkiewicz, Pawel } // namespace redfish 2124