19391bb9cSRapkiewicz, Pawel /* 29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation 39391bb9cSRapkiewicz, Pawel // 49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License"); 59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License. 69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at 79391bb9cSRapkiewicz, Pawel // 89391bb9cSRapkiewicz, Pawel // http://www.apache.org/licenses/LICENSE-2.0 99391bb9cSRapkiewicz, Pawel // 109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software 119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS, 129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and 149391bb9cSRapkiewicz, Pawel // limitations under the License. 159391bb9cSRapkiewicz, Pawel */ 169391bb9cSRapkiewicz, Pawel #pragma once 179391bb9cSRapkiewicz, Pawel 181abe55efSEd Tanous #include <boost/container/flat_map.hpp> 194a0cb85cSEd Tanous #include <boost/container/flat_set.hpp> 20179db1d7SKowalski, Kamil #include <dbus_singleton.hpp> 21588c3f0dSKowalski, Kamil #include <error_messages.hpp> 22179db1d7SKowalski, Kamil #include <node.hpp> 23a24526dcSEd Tanous #include <optional> 24588c3f0dSKowalski, Kamil #include <utils/json_utils.hpp> 25abf2add6SEd Tanous #include <variant> 269391bb9cSRapkiewicz, Pawel 271abe55efSEd Tanous namespace redfish 281abe55efSEd Tanous { 299391bb9cSRapkiewicz, Pawel 309391bb9cSRapkiewicz, Pawel /** 319391bb9cSRapkiewicz, Pawel * DBus types primitives for several generic DBus interfaces 329391bb9cSRapkiewicz, Pawel * TODO(Pawel) consider move this to separate file into boost::dbus 339391bb9cSRapkiewicz, Pawel */ 34aa2e59c1SEd Tanous using PropertiesMapType = boost::container::flat_map< 35abf2add6SEd Tanous std::string, std::variant<std::string, bool, uint8_t, int16_t, uint16_t, 36aa2e59c1SEd Tanous int32_t, uint32_t, int64_t, uint64_t, double>>; 379391bb9cSRapkiewicz, Pawel 384a0cb85cSEd Tanous using GetManagedObjects = std::vector<std::pair< 39aa2e59c1SEd Tanous sdbusplus::message::object_path, 404a0cb85cSEd Tanous std::vector<std::pair< 41aa2e59c1SEd Tanous std::string, 42aa2e59c1SEd Tanous boost::container::flat_map< 43029573d4SEd Tanous std::string, sdbusplus::message::variant< 44029573d4SEd Tanous std::string, bool, uint8_t, int16_t, uint16_t, 45029573d4SEd Tanous int32_t, uint32_t, int64_t, uint64_t, double, 46029573d4SEd Tanous std::vector<std::string>>>>>>>; 474a0cb85cSEd Tanous 484a0cb85cSEd Tanous enum class LinkType 494a0cb85cSEd Tanous { 504a0cb85cSEd Tanous Local, 514a0cb85cSEd Tanous Global 524a0cb85cSEd Tanous }; 539391bb9cSRapkiewicz, Pawel 549391bb9cSRapkiewicz, Pawel /** 559391bb9cSRapkiewicz, Pawel * Structure for keeping IPv4 data required by Redfish 569391bb9cSRapkiewicz, Pawel */ 571abe55efSEd Tanous struct IPv4AddressData 581abe55efSEd Tanous { 59179db1d7SKowalski, Kamil std::string id; 604a0cb85cSEd Tanous std::string address; 614a0cb85cSEd Tanous std::string domain; 624a0cb85cSEd Tanous std::string gateway; 639391bb9cSRapkiewicz, Pawel std::string netmask; 649391bb9cSRapkiewicz, Pawel std::string origin; 654a0cb85cSEd Tanous LinkType linktype; 664a0cb85cSEd Tanous 671abe55efSEd Tanous bool operator<(const IPv4AddressData &obj) const 681abe55efSEd Tanous { 694a0cb85cSEd Tanous return id < obj.id; 701abe55efSEd Tanous } 719391bb9cSRapkiewicz, Pawel }; 729391bb9cSRapkiewicz, Pawel 739391bb9cSRapkiewicz, Pawel /** 74e48c0fc5SRavi Teja * Structure for keeping IPv6 data required by Redfish 75e48c0fc5SRavi Teja */ 76e48c0fc5SRavi Teja struct IPv6AddressData 77e48c0fc5SRavi Teja { 78e48c0fc5SRavi Teja std::string id; 79e48c0fc5SRavi Teja std::string address; 80e48c0fc5SRavi Teja std::string origin; 81e48c0fc5SRavi Teja uint8_t prefixLength; 82e48c0fc5SRavi Teja 83e48c0fc5SRavi Teja bool operator<(const IPv6AddressData &obj) const 84e48c0fc5SRavi Teja { 85e48c0fc5SRavi Teja return id < obj.id; 86e48c0fc5SRavi Teja } 87e48c0fc5SRavi Teja }; 88e48c0fc5SRavi Teja /** 899391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 909391bb9cSRapkiewicz, Pawel * available from DBus 919391bb9cSRapkiewicz, Pawel */ 921abe55efSEd Tanous struct EthernetInterfaceData 931abe55efSEd Tanous { 944a0cb85cSEd Tanous uint32_t speed; 954a0cb85cSEd Tanous bool auto_neg; 962a133282Smanojkiraneda bool DHCPEnabled; 974a0cb85cSEd Tanous std::string hostname; 984a0cb85cSEd Tanous std::string default_gateway; 999a6fc6feSRavi Teja std::string ipv6_default_gateway; 1004a0cb85cSEd Tanous std::string mac_address; 101fda13ad2SSunitha Harish std::vector<std::uint32_t> vlan_id; 102029573d4SEd Tanous std::vector<std::string> nameservers; 1039391bb9cSRapkiewicz, Pawel }; 1049391bb9cSRapkiewicz, Pawel 1059391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1069391bb9cSRapkiewicz, Pawel // into full dot notation 1071abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1081abe55efSEd Tanous { 1099391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1109391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1119391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1129391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1139391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1149391bb9cSRapkiewicz, Pawel return netmask; 1159391bb9cSRapkiewicz, Pawel } 1169391bb9cSRapkiewicz, Pawel 1174a0cb85cSEd Tanous inline std::string 1184a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string &inputOrigin, 1194a0cb85cSEd Tanous bool isIPv4) 1201abe55efSEd Tanous { 1214a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1221abe55efSEd Tanous { 1234a0cb85cSEd Tanous return "Static"; 1249391bb9cSRapkiewicz, Pawel } 1254a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1261abe55efSEd Tanous { 1274a0cb85cSEd Tanous if (isIPv4) 1281abe55efSEd Tanous { 1294a0cb85cSEd Tanous return "IPv4LinkLocal"; 1301abe55efSEd Tanous } 1311abe55efSEd Tanous else 1321abe55efSEd Tanous { 1334a0cb85cSEd Tanous return "LinkLocal"; 1349391bb9cSRapkiewicz, Pawel } 1359391bb9cSRapkiewicz, Pawel } 1364a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1371abe55efSEd Tanous { 1384a0cb85cSEd Tanous if (isIPv4) 1394a0cb85cSEd Tanous { 1404a0cb85cSEd Tanous return "DHCP"; 1414a0cb85cSEd Tanous } 1424a0cb85cSEd Tanous else 1434a0cb85cSEd Tanous { 1444a0cb85cSEd Tanous return "DHCPv6"; 1454a0cb85cSEd Tanous } 1464a0cb85cSEd Tanous } 1474a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1484a0cb85cSEd Tanous { 1494a0cb85cSEd Tanous return "SLAAC"; 1504a0cb85cSEd Tanous } 1514a0cb85cSEd Tanous return ""; 1524a0cb85cSEd Tanous } 1534a0cb85cSEd Tanous 1544c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string ðiface_id, 1554a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 1564a0cb85cSEd Tanous EthernetInterfaceData ðData) 1574a0cb85cSEd Tanous { 1584c9afe43SEd Tanous bool idFound = false; 1594a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 1604a0cb85cSEd Tanous { 1614a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 1624a0cb85cSEd Tanous { 163029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 164029573d4SEd Tanous { 1654c9afe43SEd Tanous idFound = true; 1664a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 1674a0cb85cSEd Tanous { 1684a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1694a0cb85cSEd Tanous { 1704a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 1714a0cb85cSEd Tanous { 1724a0cb85cSEd Tanous const std::string *mac = 173abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 1744a0cb85cSEd Tanous if (mac != nullptr) 1754a0cb85cSEd Tanous { 1764a0cb85cSEd Tanous ethData.mac_address = *mac; 1774a0cb85cSEd Tanous } 1784a0cb85cSEd Tanous } 1794a0cb85cSEd Tanous } 1804a0cb85cSEd Tanous } 1814a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 1824a0cb85cSEd Tanous { 1834a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1844a0cb85cSEd Tanous { 1854a0cb85cSEd Tanous if (propertyPair.first == "Id") 1864a0cb85cSEd Tanous { 1871b6b96c5SEd Tanous const uint32_t *id = 188abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 1894a0cb85cSEd Tanous if (id != nullptr) 1904a0cb85cSEd Tanous { 191fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 1924a0cb85cSEd Tanous } 1934a0cb85cSEd Tanous } 1944a0cb85cSEd Tanous } 1954a0cb85cSEd Tanous } 1964a0cb85cSEd Tanous else if (ifacePair.first == 1974a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 1984a0cb85cSEd Tanous { 1994a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2004a0cb85cSEd Tanous { 2014a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2024a0cb85cSEd Tanous { 2034a0cb85cSEd Tanous const bool *auto_neg = 204abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2054a0cb85cSEd Tanous if (auto_neg != nullptr) 2064a0cb85cSEd Tanous { 2074a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2084a0cb85cSEd Tanous } 2094a0cb85cSEd Tanous } 2104a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2114a0cb85cSEd Tanous { 2124a0cb85cSEd Tanous const uint32_t *speed = 213abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2144a0cb85cSEd Tanous if (speed != nullptr) 2154a0cb85cSEd Tanous { 2164a0cb85cSEd Tanous ethData.speed = *speed; 2174a0cb85cSEd Tanous } 2184a0cb85cSEd Tanous } 219f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 220029573d4SEd Tanous { 221029573d4SEd Tanous const std::vector<std::string> *nameservers = 222029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 223029573d4SEd Tanous std::vector<std::string>>( 224029573d4SEd Tanous &propertyPair.second); 225029573d4SEd Tanous if (nameservers != nullptr) 226029573d4SEd Tanous { 227029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2284a0cb85cSEd Tanous } 2294a0cb85cSEd Tanous } 2302a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 2312a133282Smanojkiraneda { 2322a133282Smanojkiraneda const bool *DHCPEnabled = 2332a133282Smanojkiraneda std::get_if<bool>(&propertyPair.second); 2342a133282Smanojkiraneda if (DHCPEnabled != nullptr) 2352a133282Smanojkiraneda { 2362a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 2372a133282Smanojkiraneda } 2382a133282Smanojkiraneda } 239029573d4SEd Tanous } 240029573d4SEd Tanous } 241029573d4SEd Tanous } 242029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 243029573d4SEd Tanous // to check eth number 244029573d4SEd Tanous if (ifacePair.first == 2454a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 2464a0cb85cSEd Tanous { 2474a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2484a0cb85cSEd Tanous { 2494a0cb85cSEd Tanous if (propertyPair.first == "HostName") 2504a0cb85cSEd Tanous { 2514a0cb85cSEd Tanous const std::string *hostname = 252029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 253029573d4SEd Tanous &propertyPair.second); 2544a0cb85cSEd Tanous if (hostname != nullptr) 2554a0cb85cSEd Tanous { 2564a0cb85cSEd Tanous ethData.hostname = *hostname; 2574a0cb85cSEd Tanous } 2584a0cb85cSEd Tanous } 2594a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 2604a0cb85cSEd Tanous { 2614a0cb85cSEd Tanous const std::string *defaultGateway = 262029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 263029573d4SEd Tanous &propertyPair.second); 2644a0cb85cSEd Tanous if (defaultGateway != nullptr) 2654a0cb85cSEd Tanous { 2664a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 2674a0cb85cSEd Tanous } 2684a0cb85cSEd Tanous } 2699a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 2709a6fc6feSRavi Teja { 2719a6fc6feSRavi Teja const std::string *defaultGateway6 = 2729a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 2739a6fc6feSRavi Teja &propertyPair.second); 2749a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 2759a6fc6feSRavi Teja { 2769a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 2779a6fc6feSRavi Teja } 2789a6fc6feSRavi Teja } 2794a0cb85cSEd Tanous } 2804a0cb85cSEd Tanous } 2814a0cb85cSEd Tanous } 2824a0cb85cSEd Tanous } 2834c9afe43SEd Tanous return idFound; 2844a0cb85cSEd Tanous } 2854a0cb85cSEd Tanous 286e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 287e48c0fc5SRavi Teja inline void extractIPV6Data( 288e48c0fc5SRavi Teja const std::string ðiface_id, const GetManagedObjects &dbus_data, 289e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> &ipv6_config, 290e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> &ipv6_static_config) 291e48c0fc5SRavi Teja { 292e48c0fc5SRavi Teja const std::string ipv6PathStart = 293e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/"; 294e48c0fc5SRavi Teja 295e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 296e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 297e48c0fc5SRavi Teja for (const auto &objpath : dbus_data) 298e48c0fc5SRavi Teja { 299e48c0fc5SRavi Teja // Check if proper pattern for object path appears 300e48c0fc5SRavi Teja if (boost::starts_with(objpath.first.str, ipv6PathStart)) 301e48c0fc5SRavi Teja { 302e48c0fc5SRavi Teja for (auto &interface : objpath.second) 303e48c0fc5SRavi Teja { 304e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 305e48c0fc5SRavi Teja { 306e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 307e48c0fc5SRavi Teja // appropriate 308e48c0fc5SRavi Teja std::pair< 309e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::iterator, 310e48c0fc5SRavi Teja bool> 311e48c0fc5SRavi Teja it = ipv6_config.insert( 312e48c0fc5SRavi Teja {objpath.first.str.substr(ipv6PathStart.size())}); 313e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 314e48c0fc5SRavi Teja for (auto &property : interface.second) 315e48c0fc5SRavi Teja { 316e48c0fc5SRavi Teja if (property.first == "Address") 317e48c0fc5SRavi Teja { 318e48c0fc5SRavi Teja const std::string *address = 319e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 320e48c0fc5SRavi Teja if (address != nullptr) 321e48c0fc5SRavi Teja { 322e48c0fc5SRavi Teja ipv6_address.address = *address; 323e48c0fc5SRavi Teja } 324e48c0fc5SRavi Teja } 325e48c0fc5SRavi Teja else if (property.first == "Origin") 326e48c0fc5SRavi Teja { 327e48c0fc5SRavi Teja const std::string *origin = 328e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 329e48c0fc5SRavi Teja if (origin != nullptr) 330e48c0fc5SRavi Teja { 331e48c0fc5SRavi Teja ipv6_address.origin = 332e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 333e48c0fc5SRavi Teja false); 334e48c0fc5SRavi Teja } 335e48c0fc5SRavi Teja } 336e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 337e48c0fc5SRavi Teja { 338e48c0fc5SRavi Teja const uint8_t *prefix = 339e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 340e48c0fc5SRavi Teja if (prefix != nullptr) 341e48c0fc5SRavi Teja { 342e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 343e48c0fc5SRavi Teja } 344e48c0fc5SRavi Teja } 345e48c0fc5SRavi Teja else 346e48c0fc5SRavi Teja { 347e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 348e48c0fc5SRavi Teja << "Got extra property: " << property.first 349e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 350e48c0fc5SRavi Teja } 351e48c0fc5SRavi Teja } 352e48c0fc5SRavi Teja if (ipv6_address.origin == "Static") 353e48c0fc5SRavi Teja { 354e48c0fc5SRavi Teja std::pair<boost::container::flat_set< 355e48c0fc5SRavi Teja IPv6AddressData>::iterator, 356e48c0fc5SRavi Teja bool> 357e48c0fc5SRavi Teja iter = ipv6_static_config.insert( 358e48c0fc5SRavi Teja {objpath.first.str.substr( 359e48c0fc5SRavi Teja ipv6PathStart.size())}); 360e48c0fc5SRavi Teja IPv6AddressData &ipv6_static_address = *iter.first; 361e48c0fc5SRavi Teja 362e48c0fc5SRavi Teja ipv6_static_address.address = ipv6_address.address; 363e48c0fc5SRavi Teja ipv6_static_address.prefixLength = 364e48c0fc5SRavi Teja ipv6_address.prefixLength; 365e48c0fc5SRavi Teja } 366e48c0fc5SRavi Teja } 367e48c0fc5SRavi Teja } 368e48c0fc5SRavi Teja } 369e48c0fc5SRavi Teja } 370e48c0fc5SRavi Teja } 371e48c0fc5SRavi Teja 3724a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 3734a0cb85cSEd Tanous inline void 3744a0cb85cSEd Tanous extractIPData(const std::string ðiface_id, 3754a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 3764a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> &ipv4_config) 3774a0cb85cSEd Tanous { 3784a0cb85cSEd Tanous const std::string ipv4PathStart = 3794a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 3804a0cb85cSEd Tanous 3814a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 3824a0cb85cSEd Tanous // single ethernet interface, loop over all of them 3834a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 3844a0cb85cSEd Tanous { 3854a0cb85cSEd Tanous // Check if proper pattern for object path appears 3864a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 3874a0cb85cSEd Tanous { 3884a0cb85cSEd Tanous for (auto &interface : objpath.second) 3894a0cb85cSEd Tanous { 3904a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 3914a0cb85cSEd Tanous { 3924a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 3934a0cb85cSEd Tanous // appropriate 3944a0cb85cSEd Tanous std::pair< 3954a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 3964a0cb85cSEd Tanous bool> 3974a0cb85cSEd Tanous it = ipv4_config.insert( 398b01bf299SEd Tanous {objpath.first.str.substr(ipv4PathStart.size())}); 3994a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 4004a0cb85cSEd Tanous for (auto &property : interface.second) 4014a0cb85cSEd Tanous { 4024a0cb85cSEd Tanous if (property.first == "Address") 4034a0cb85cSEd Tanous { 4044a0cb85cSEd Tanous const std::string *address = 405abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4064a0cb85cSEd Tanous if (address != nullptr) 4074a0cb85cSEd Tanous { 4084a0cb85cSEd Tanous ipv4_address.address = *address; 4094a0cb85cSEd Tanous } 4104a0cb85cSEd Tanous } 4114a0cb85cSEd Tanous else if (property.first == "Gateway") 4124a0cb85cSEd Tanous { 4134a0cb85cSEd Tanous const std::string *gateway = 414abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4154a0cb85cSEd Tanous if (gateway != nullptr) 4164a0cb85cSEd Tanous { 4174a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 4184a0cb85cSEd Tanous } 4194a0cb85cSEd Tanous } 4204a0cb85cSEd Tanous else if (property.first == "Origin") 4214a0cb85cSEd Tanous { 4224a0cb85cSEd Tanous const std::string *origin = 423abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4244a0cb85cSEd Tanous if (origin != nullptr) 4254a0cb85cSEd Tanous { 4264a0cb85cSEd Tanous ipv4_address.origin = 4274a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 4284a0cb85cSEd Tanous true); 4294a0cb85cSEd Tanous } 4304a0cb85cSEd Tanous } 4314a0cb85cSEd Tanous else if (property.first == "PrefixLength") 4324a0cb85cSEd Tanous { 4334a0cb85cSEd Tanous const uint8_t *mask = 434abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 4354a0cb85cSEd Tanous if (mask != nullptr) 4364a0cb85cSEd Tanous { 4374a0cb85cSEd Tanous // convert it to the string 4384a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 4394a0cb85cSEd Tanous } 4404a0cb85cSEd Tanous } 4414a0cb85cSEd Tanous else 4424a0cb85cSEd Tanous { 4434a0cb85cSEd Tanous BMCWEB_LOG_ERROR 4444a0cb85cSEd Tanous << "Got extra property: " << property.first 4454a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 4464a0cb85cSEd Tanous } 4474a0cb85cSEd Tanous } 4484a0cb85cSEd Tanous // Check if given address is local, or global 4494a0cb85cSEd Tanous ipv4_address.linktype = 4504a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 45118659d10SJohnathan Mantey ? LinkType::Local 45218659d10SJohnathan Mantey : LinkType::Global; 4534a0cb85cSEd Tanous } 4544a0cb85cSEd Tanous } 4554a0cb85cSEd Tanous } 4564a0cb85cSEd Tanous } 4574a0cb85cSEd Tanous } 458588c3f0dSKowalski, Kamil 459588c3f0dSKowalski, Kamil /** 460588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 461588c3f0dSKowalski, Kamil * 462588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 463588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 464588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 465588c3f0dSKowalski, Kamil * 466588c3f0dSKowalski, Kamil * @return None. 467588c3f0dSKowalski, Kamil */ 468588c3f0dSKowalski, Kamil template <typename CallbackFunc> 4694a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 4701abe55efSEd Tanous CallbackFunc &&callback) 4711abe55efSEd Tanous { 47255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 473588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 474588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 475588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 476588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 477abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 4784a0cb85cSEd Tanous } 479588c3f0dSKowalski, Kamil 480588c3f0dSKowalski, Kamil /** 481179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 482179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 483179db1d7SKowalski, Kamil * bit count for Subnet Mask. 484179db1d7SKowalski, Kamil * 485179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 486179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 487179db1d7SKowalski, Kamil * 488179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 489179db1d7SKowalski, Kamil */ 4904a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 4911abe55efSEd Tanous uint8_t *bits = nullptr) 4921abe55efSEd Tanous { 493179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 494179db1d7SKowalski, Kamil 495179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 496179db1d7SKowalski, Kamil 4974a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 4981abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 4991abe55efSEd Tanous { 500179db1d7SKowalski, Kamil return false; 501179db1d7SKowalski, Kamil } 502179db1d7SKowalski, Kamil 5031abe55efSEd Tanous if (bits != nullptr) 5041abe55efSEd Tanous { 505179db1d7SKowalski, Kamil *bits = 0; 506179db1d7SKowalski, Kamil } 507179db1d7SKowalski, Kamil 508179db1d7SKowalski, Kamil char *endPtr; 509179db1d7SKowalski, Kamil long previousValue = 255; 510179db1d7SKowalski, Kamil bool firstZeroInByteHit; 5111abe55efSEd Tanous for (const std::string &byte : bytesInMask) 5121abe55efSEd Tanous { 5131abe55efSEd Tanous if (byte.empty()) 5141abe55efSEd Tanous { 5151db9ca37SKowalski, Kamil return false; 5161db9ca37SKowalski, Kamil } 5171db9ca37SKowalski, Kamil 518179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 5191db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 520179db1d7SKowalski, Kamil 5214a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 5224a0cb85cSEd Tanous // is not 100% number 5231abe55efSEd Tanous if (*endPtr != '\0') 5241abe55efSEd Tanous { 525179db1d7SKowalski, Kamil return false; 526179db1d7SKowalski, Kamil } 527179db1d7SKowalski, Kamil 528179db1d7SKowalski, Kamil // Value should be contained in byte 5291abe55efSEd Tanous if (value < 0 || value > 255) 5301abe55efSEd Tanous { 531179db1d7SKowalski, Kamil return false; 532179db1d7SKowalski, Kamil } 533179db1d7SKowalski, Kamil 5341abe55efSEd Tanous if (bits != nullptr) 5351abe55efSEd Tanous { 536179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 5371abe55efSEd Tanous if (previousValue != 255 && value != 0) 5381abe55efSEd Tanous { 539179db1d7SKowalski, Kamil return false; 540179db1d7SKowalski, Kamil } 541179db1d7SKowalski, Kamil 542179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 543179db1d7SKowalski, Kamil firstZeroInByteHit = false; 544179db1d7SKowalski, Kamil 545179db1d7SKowalski, Kamil // Count bits 5461abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 5471abe55efSEd Tanous { 5481abe55efSEd Tanous if (value & (1 << bitIdx)) 5491abe55efSEd Tanous { 5501abe55efSEd Tanous if (firstZeroInByteHit) 5511abe55efSEd Tanous { 552179db1d7SKowalski, Kamil // Continuity not preserved 553179db1d7SKowalski, Kamil return false; 5541abe55efSEd Tanous } 5551abe55efSEd Tanous else 5561abe55efSEd Tanous { 557179db1d7SKowalski, Kamil (*bits)++; 558179db1d7SKowalski, Kamil } 5591abe55efSEd Tanous } 5601abe55efSEd Tanous else 5611abe55efSEd Tanous { 562179db1d7SKowalski, Kamil firstZeroInByteHit = true; 563179db1d7SKowalski, Kamil } 564179db1d7SKowalski, Kamil } 565179db1d7SKowalski, Kamil } 566179db1d7SKowalski, Kamil 567179db1d7SKowalski, Kamil previousValue = value; 568179db1d7SKowalski, Kamil } 569179db1d7SKowalski, Kamil 570179db1d7SKowalski, Kamil return true; 571179db1d7SKowalski, Kamil } 572179db1d7SKowalski, Kamil 573179db1d7SKowalski, Kamil /** 574b01bf299SEd Tanous * @brief Changes IPv4 address type property (Address, Gateway) 575b01bf299SEd Tanous * 576b01bf299SEd Tanous * @param[in] ifaceId Id of interface whose IP should be modified 577b01bf299SEd Tanous * @param[in] ipIdx Index of IP in input array that should be modified 578b01bf299SEd Tanous * @param[in] ipHash DBus Hash id of modified IP 579b01bf299SEd Tanous * @param[in] name Name of field in JSON representation 580b01bf299SEd Tanous * @param[in] newValue New value that should be written 581b01bf299SEd Tanous * @param[io] asyncResp Response object that will be returned to client 582b01bf299SEd Tanous * 583b01bf299SEd Tanous * @return true if give IP is valid and has been sent do D-Bus, false 584b01bf299SEd Tanous * otherwise 585b01bf299SEd Tanous */ 586b01bf299SEd Tanous inline void changeIPv4AddressProperty( 587b01bf299SEd Tanous const std::string &ifaceId, int ipIdx, const std::string &ipHash, 588b01bf299SEd Tanous const std::string &name, const std::string &newValue, 589b01bf299SEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 590b01bf299SEd Tanous { 591*286b9118SJohnathan Mantey auto callback = 592*286b9118SJohnathan Mantey [asyncResp, ipIdx, name{std::string(name)}, 593*286b9118SJohnathan Mantey newValue{std::move(newValue)}](const boost::system::error_code ec) { 594b01bf299SEd Tanous if (ec) 595b01bf299SEd Tanous { 596b01bf299SEd Tanous messages::internalError(asyncResp->res); 597b01bf299SEd Tanous } 598b01bf299SEd Tanous }; 599b01bf299SEd Tanous 600b01bf299SEd Tanous crow::connections::systemBus->async_method_call( 601b01bf299SEd Tanous std::move(callback), "xyz.openbmc_project.Network", 602b01bf299SEd Tanous "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 603b01bf299SEd Tanous "org.freedesktop.DBus.Properties", "Set", 604b01bf299SEd Tanous "xyz.openbmc_project.Network.IP", name, 605b01bf299SEd Tanous std::variant<std::string>(newValue)); 606b01bf299SEd Tanous } 607b01bf299SEd Tanous 608b01bf299SEd Tanous /** 609179db1d7SKowalski, Kamil * @brief Modifies SubnetMask for given IP 610179db1d7SKowalski, Kamil * 611179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be modified 6124a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be 6131abe55efSEd Tanous * modified 614179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of modified IP 615179db1d7SKowalski, Kamil * @param[in] newValue Mask as PrefixLength in bitcount 616179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 617179db1d7SKowalski, Kamil * 618179db1d7SKowalski, Kamil * @return None 619179db1d7SKowalski, Kamil */ 620b01bf299SEd Tanous inline void changeIPv4SubnetMaskProperty(const std::string &ifaceId, int ipIdx, 6214a0cb85cSEd Tanous const std::string &ipHash, 6224a0cb85cSEd Tanous uint8_t &newValue, 6234a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6241abe55efSEd Tanous { 625*286b9118SJohnathan Mantey auto callback = [asyncResp, ipIdx](const boost::system::error_code ec) { 6261abe55efSEd Tanous if (ec) 6271abe55efSEd Tanous { 628a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6291abe55efSEd Tanous } 630179db1d7SKowalski, Kamil }; 631179db1d7SKowalski, Kamil 63255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 633179db1d7SKowalski, Kamil std::move(callback), "xyz.openbmc_project.Network", 634179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 635179db1d7SKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 636179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP", "PrefixLength", 637abf2add6SEd Tanous std::variant<uint8_t>(newValue)); 6384a0cb85cSEd Tanous } 639588c3f0dSKowalski, Kamil 640588c3f0dSKowalski, Kamil /** 641179db1d7SKowalski, Kamil * @brief Deletes given IPv4 642179db1d7SKowalski, Kamil * 643179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 644179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 645179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 646179db1d7SKowalski, Kamil * 647179db1d7SKowalski, Kamil * @return None 648179db1d7SKowalski, Kamil */ 6494a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 6504a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 6511abe55efSEd Tanous { 65255c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 653*286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 6541abe55efSEd Tanous if (ec) 6551abe55efSEd Tanous { 656a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6571abe55efSEd Tanous } 658179db1d7SKowalski, Kamil }, 659179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 660179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 661179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 662179db1d7SKowalski, Kamil } 663179db1d7SKowalski, Kamil 664179db1d7SKowalski, Kamil /** 665179db1d7SKowalski, Kamil * @brief Creates IPv4 with given data 666179db1d7SKowalski, Kamil * 667179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 6684a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 669179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 670179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 671179db1d7SKowalski, Kamil * 672179db1d7SKowalski, Kamil * @return None 673179db1d7SKowalski, Kamil */ 674b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 675b01bf299SEd Tanous uint8_t subnetMask, const std::string &gateway, 676b01bf299SEd Tanous const std::string &address, 6774a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6781abe55efSEd Tanous { 67943b761d0SEd Tanous auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 6801abe55efSEd Tanous if (ec) 6811abe55efSEd Tanous { 682a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 683179db1d7SKowalski, Kamil } 684179db1d7SKowalski, Kamil }; 685179db1d7SKowalski, Kamil 68655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 687179db1d7SKowalski, Kamil std::move(createIpHandler), "xyz.openbmc_project.Network", 688179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 689179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 690179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask, 691179db1d7SKowalski, Kamil gateway); 692179db1d7SKowalski, Kamil } 693e48c0fc5SRavi Teja 694e48c0fc5SRavi Teja /** 695e48c0fc5SRavi Teja * @brief Deletes given IPv6 696e48c0fc5SRavi Teja * 697e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 698e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 699e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 700e48c0fc5SRavi Teja * 701e48c0fc5SRavi Teja * @return None 702e48c0fc5SRavi Teja */ 703e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 704e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 705e48c0fc5SRavi Teja { 706e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 707*286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 708e48c0fc5SRavi Teja if (ec) 709e48c0fc5SRavi Teja { 710e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 711e48c0fc5SRavi Teja } 712e48c0fc5SRavi Teja }, 713e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 714e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 715e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 716e48c0fc5SRavi Teja } 717e48c0fc5SRavi Teja 718e48c0fc5SRavi Teja /** 719e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 720e48c0fc5SRavi Teja * 721e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 722e48c0fc5SRavi Teja * @param[in] ipIdx Index of IP in input array that should be added 723e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 724e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 725e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 726e48c0fc5SRavi Teja * 727e48c0fc5SRavi Teja * @return None 728e48c0fc5SRavi Teja */ 729e48c0fc5SRavi Teja inline void createIPv6(const std::string &ifaceId, unsigned int ipIdx, 730e48c0fc5SRavi Teja uint8_t prefixLength, const std::string &address, 731e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 732e48c0fc5SRavi Teja { 733e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 734e48c0fc5SRavi Teja if (ec) 735e48c0fc5SRavi Teja { 736e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 737e48c0fc5SRavi Teja } 738e48c0fc5SRavi Teja }; 739e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 740e48c0fc5SRavi Teja // does not have assosiated gateway property 741e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 742e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 743e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 744e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 745e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 746e48c0fc5SRavi Teja ""); 747e48c0fc5SRavi Teja } 748e48c0fc5SRavi Teja 7492a133282Smanojkiraneda using GetAllPropertiesType = 7502a133282Smanojkiraneda boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>; 7512a133282Smanojkiraneda 7522a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) 7532a133282Smanojkiraneda { 7542a133282Smanojkiraneda auto getConfig = [asyncResp](const boost::system::error_code error_code, 7552a133282Smanojkiraneda const GetAllPropertiesType &dbus_data) { 7562a133282Smanojkiraneda if (error_code) 7572a133282Smanojkiraneda { 7582a133282Smanojkiraneda BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code; 7592a133282Smanojkiraneda messages::internalError(asyncResp->res); 7602a133282Smanojkiraneda return; 7612a133282Smanojkiraneda } 762fda13ad2SSunitha Harish nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; 7632a133282Smanojkiraneda for (const auto &property : dbus_data) 7642a133282Smanojkiraneda { 7652a133282Smanojkiraneda auto value = 7662a133282Smanojkiraneda sdbusplus::message::variant_ns::get_if<bool>(&property.second); 7672a133282Smanojkiraneda 7682a133282Smanojkiraneda if (value == nullptr) 7692a133282Smanojkiraneda { 7702a133282Smanojkiraneda continue; 7712a133282Smanojkiraneda } 7722a133282Smanojkiraneda if (property.first == "DNSEnabled") 7732a133282Smanojkiraneda { 7742a133282Smanojkiraneda DHCPConfigTypeJson["UseDNSServers"] = *value; 7752a133282Smanojkiraneda } 7762a133282Smanojkiraneda else if (property.first == "HostNameEnabled") 7772a133282Smanojkiraneda { 7782a133282Smanojkiraneda DHCPConfigTypeJson["UseDomainName"] = *value; 7792a133282Smanojkiraneda } 7802a133282Smanojkiraneda else if (property.first == "NTPEnabled") 7812a133282Smanojkiraneda { 7822a133282Smanojkiraneda DHCPConfigTypeJson["UseNTPServers"] = *value; 7832a133282Smanojkiraneda } 7842a133282Smanojkiraneda } 7852a133282Smanojkiraneda }; 7862a133282Smanojkiraneda crow::connections::systemBus->async_method_call( 7872a133282Smanojkiraneda std::move(getConfig), "xyz.openbmc_project.Network", 7882a133282Smanojkiraneda "/xyz/openbmc_project/network/config/dhcp", 7892a133282Smanojkiraneda "org.freedesktop.DBus.Properties", "GetAll", 7902a133282Smanojkiraneda "xyz.openbmc_project.Network.DHCPConfiguration"); 7912a133282Smanojkiraneda } 792179db1d7SKowalski, Kamil 793179db1d7SKowalski, Kamil /** 794179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 795179db1d7SKowalski, Kamil * Object 796179db1d7SKowalski, Kamil * from EntityManager Network Manager 7974a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 798179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 799179db1d7SKowalski, Kamil * into JSON 800179db1d7SKowalski, Kamil */ 801179db1d7SKowalski, Kamil template <typename CallbackFunc> 8024a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8031abe55efSEd Tanous CallbackFunc &&callback) 8041abe55efSEd Tanous { 80555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8064a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8071abe55efSEd Tanous const boost::system::error_code error_code, 8084a0cb85cSEd Tanous const GetManagedObjects &resp) { 80955c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8104a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 811e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 812e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6StaticData; 813179db1d7SKowalski, Kamil 8141abe55efSEd Tanous if (error_code) 8151abe55efSEd Tanous { 816e48c0fc5SRavi Teja callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData); 817179db1d7SKowalski, Kamil return; 818179db1d7SKowalski, Kamil } 819179db1d7SKowalski, Kamil 8204c9afe43SEd Tanous bool found = 8214a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 8224c9afe43SEd Tanous if (!found) 8234c9afe43SEd Tanous { 824e48c0fc5SRavi Teja callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData); 8254c9afe43SEd Tanous return; 8264c9afe43SEd Tanous } 8274c9afe43SEd Tanous 8284a0cb85cSEd Tanous extractIPData(ethiface_id, resp, ipv4Data); 829179db1d7SKowalski, Kamil // Fix global GW 8301abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 8311abe55efSEd Tanous { 8324a0cb85cSEd Tanous if ((ipv4.linktype == LinkType::Global) && 8334a0cb85cSEd Tanous (ipv4.gateway == "0.0.0.0")) 8341abe55efSEd Tanous { 8354a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 836179db1d7SKowalski, Kamil } 837179db1d7SKowalski, Kamil } 838179db1d7SKowalski, Kamil 839e48c0fc5SRavi Teja extractIPV6Data(ethiface_id, resp, ipv6Data, ipv6StaticData); 8404a0cb85cSEd Tanous // Finally make a callback with usefull data 841e48c0fc5SRavi Teja callback(true, ethData, ipv4Data, ipv6Data, ipv6StaticData); 842179db1d7SKowalski, Kamil }, 843179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 844179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 845179db1d7SKowalski, Kamil }; 846179db1d7SKowalski, Kamil 847179db1d7SKowalski, Kamil /** 8489391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 8499391bb9cSRapkiewicz, Pawel * Manager 8501abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 8511abe55efSEd Tanous * into JSON. 8529391bb9cSRapkiewicz, Pawel */ 8539391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 8541abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 8551abe55efSEd Tanous { 85655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8574a0cb85cSEd Tanous [callback{std::move(callback)}]( 8589391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 8594a0cb85cSEd Tanous GetManagedObjects &resp) { 8601abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 8611abe55efSEd Tanous // ethernet interfaces 8624c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 8634a0cb85cSEd Tanous iface_list.reserve(resp.size()); 8641abe55efSEd Tanous if (error_code) 8651abe55efSEd Tanous { 8664a0cb85cSEd Tanous callback(false, iface_list); 8679391bb9cSRapkiewicz, Pawel return; 8689391bb9cSRapkiewicz, Pawel } 8699391bb9cSRapkiewicz, Pawel 8709391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 8714a0cb85cSEd Tanous for (const auto &objpath : resp) 8721abe55efSEd Tanous { 8739391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 8744a0cb85cSEd Tanous for (const auto &interface : objpath.second) 8751abe55efSEd Tanous { 8761abe55efSEd Tanous // If interface is 8774a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 8784a0cb85cSEd Tanous // what we're looking for. 8799391bb9cSRapkiewicz, Pawel if (interface.first == 8801abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 8811abe55efSEd Tanous { 8824a0cb85cSEd Tanous // Cut out everyting until last "/", ... 8834a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 8844a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 8854a0cb85cSEd Tanous if (last_pos != std::string::npos) 8861abe55efSEd Tanous { 8879391bb9cSRapkiewicz, Pawel // and put it into output vector. 8884c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 8899391bb9cSRapkiewicz, Pawel } 8909391bb9cSRapkiewicz, Pawel } 8919391bb9cSRapkiewicz, Pawel } 8929391bb9cSRapkiewicz, Pawel } 893a434f2bdSEd Tanous // Finally make a callback with useful data 8944a0cb85cSEd Tanous callback(true, iface_list); 8959391bb9cSRapkiewicz, Pawel }, 896aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 897aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 8989391bb9cSRapkiewicz, Pawel }; 8999391bb9cSRapkiewicz, Pawel 9009391bb9cSRapkiewicz, Pawel /** 9019391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9029391bb9cSRapkiewicz, Pawel */ 9031abe55efSEd Tanous class EthernetCollection : public Node 9041abe55efSEd Tanous { 9059391bb9cSRapkiewicz, Pawel public: 9064a0cb85cSEd Tanous template <typename CrowApp> 9071abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9084a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9091abe55efSEd Tanous { 910588c3f0dSKowalski, Kamil entityPrivileges = { 911588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 912e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 913e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 914e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 915e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 916e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9179391bb9cSRapkiewicz, Pawel } 9189391bb9cSRapkiewicz, Pawel 9199391bb9cSRapkiewicz, Pawel private: 9209391bb9cSRapkiewicz, Pawel /** 9219391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 9229391bb9cSRapkiewicz, Pawel */ 92355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 9241abe55efSEd Tanous const std::vector<std::string> ¶ms) override 9251abe55efSEd Tanous { 9260f74e643SEd Tanous res.jsonValue["@odata.type"] = 9270f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9280f74e643SEd Tanous res.jsonValue["@odata.context"] = 9290f74e643SEd Tanous "/redfish/v1/" 9300f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 9310f74e643SEd Tanous res.jsonValue["@odata.id"] = 9320f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9330f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 9340f74e643SEd Tanous res.jsonValue["Description"] = 9350f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 9364c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 9374a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 9381abe55efSEd Tanous // preparation 939f12894f8SJason M. Bills getEthernetIfaceList( 9404c9afe43SEd Tanous [asyncResp]( 9414c9afe43SEd Tanous const bool &success, 9424c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 9434a0cb85cSEd Tanous if (!success) 9441abe55efSEd Tanous { 9454c9afe43SEd Tanous messages::internalError(asyncResp->res); 9464a0cb85cSEd Tanous return; 9474a0cb85cSEd Tanous } 9484a0cb85cSEd Tanous 9494c9afe43SEd Tanous nlohmann::json &iface_array = 9504c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 9514a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 952fda13ad2SSunitha Harish std::string tag = "_"; 9534a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 9541abe55efSEd Tanous { 955fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 956fda13ad2SSunitha Harish if (found == std::string::npos) 957fda13ad2SSunitha Harish { 9584a0cb85cSEd Tanous iface_array.push_back( 9594a0cb85cSEd Tanous {{"@odata.id", 9604a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 9614a0cb85cSEd Tanous iface_item}}); 9629391bb9cSRapkiewicz, Pawel } 963fda13ad2SSunitha Harish } 9644a0cb85cSEd Tanous 9654c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 9664c9afe43SEd Tanous iface_array.size(); 9674c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9684a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 9699391bb9cSRapkiewicz, Pawel }); 9709391bb9cSRapkiewicz, Pawel } 9719391bb9cSRapkiewicz, Pawel }; 9729391bb9cSRapkiewicz, Pawel 9739391bb9cSRapkiewicz, Pawel /** 9749391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 9759391bb9cSRapkiewicz, Pawel */ 9761abe55efSEd Tanous class EthernetInterface : public Node 9771abe55efSEd Tanous { 9789391bb9cSRapkiewicz, Pawel public: 9799391bb9cSRapkiewicz, Pawel /* 9809391bb9cSRapkiewicz, Pawel * Default Constructor 9819391bb9cSRapkiewicz, Pawel */ 9824a0cb85cSEd Tanous template <typename CrowApp> 9831abe55efSEd Tanous EthernetInterface(CrowApp &app) : 9844a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 9851abe55efSEd Tanous std::string()) 9861abe55efSEd Tanous { 987588c3f0dSKowalski, Kamil entityPrivileges = { 988588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 989e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 990e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 991e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 992e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 993e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9949391bb9cSRapkiewicz, Pawel } 9959391bb9cSRapkiewicz, Pawel 996e439f0f8SKowalski, Kamil private: 997bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 9984a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 9991abe55efSEd Tanous { 1000bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1001bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1002bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10034a0cb85cSEd Tanous if (ec) 10044a0cb85cSEd Tanous { 1005a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10061abe55efSEd Tanous } 1007bc0bd6e0SEd Tanous }, 1008bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1009bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1010bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1011bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1012abf2add6SEd Tanous std::variant<std::string>(hostname)); 1013588c3f0dSKowalski, Kamil } 1014588c3f0dSKowalski, Kamil 1015d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1016d577665bSRatan Gupta const std::string &macAddress, 1017d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1018d577665bSRatan Gupta { 1019d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1020d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1021d577665bSRatan Gupta if (ec) 1022d577665bSRatan Gupta { 1023d577665bSRatan Gupta messages::internalError(asyncResp->res); 1024d577665bSRatan Gupta return; 1025d577665bSRatan Gupta } 1026d577665bSRatan Gupta }, 1027d577665bSRatan Gupta "xyz.openbmc_project.Network", 1028d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1029d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1030d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1031d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1032d577665bSRatan Gupta } 1033*286b9118SJohnathan Mantey 1034da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1035da131a9aSJennifer Lee const std::string &propertyName, const bool &value, 1036da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1037da131a9aSJennifer Lee { 1038da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1039da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1040da131a9aSJennifer Lee if (ec) 1041da131a9aSJennifer Lee { 1042da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1043da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1044da131a9aSJennifer Lee return; 1045da131a9aSJennifer Lee } 1046da131a9aSJennifer Lee }, 1047da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1048da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1049da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1050da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1051da131a9aSJennifer Lee std::variant<bool>{value}); 1052da131a9aSJennifer Lee } 1053da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1054da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1055da131a9aSJennifer Lee { 1056da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1057da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1058da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1059da131a9aSJennifer Lee if (ec) 1060da131a9aSJennifer Lee { 1061da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1062da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1063da131a9aSJennifer Lee return; 1064da131a9aSJennifer Lee } 1065da131a9aSJennifer Lee }, 1066da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1067da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1068da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1069da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1070da131a9aSJennifer Lee std::variant<bool>{value}); 1071da131a9aSJennifer Lee } 1072d577665bSRatan Gupta 1073da131a9aSJennifer Lee void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input, 1074da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1075da131a9aSJennifer Lee { 1076da131a9aSJennifer Lee std::optional<bool> dhcpEnabled; 1077da131a9aSJennifer Lee std::optional<bool> useDNSServers; 1078da131a9aSJennifer Lee std::optional<bool> useDomainName; 1079da131a9aSJennifer Lee std::optional<bool> useNTPServers; 1080da131a9aSJennifer Lee 1081da131a9aSJennifer Lee if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled", 1082da131a9aSJennifer Lee dhcpEnabled, "UseDNSServers", useDNSServers, 1083da131a9aSJennifer Lee "UseDomainName", useDomainName, 1084da131a9aSJennifer Lee "UseNTPServers", useNTPServers)) 1085da131a9aSJennifer Lee { 1086da131a9aSJennifer Lee return; 1087da131a9aSJennifer Lee } 1088da131a9aSJennifer Lee 1089da131a9aSJennifer Lee if (dhcpEnabled) 1090da131a9aSJennifer Lee { 1091da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1092da131a9aSJennifer Lee setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp); 1093da131a9aSJennifer Lee } 1094da131a9aSJennifer Lee 1095da131a9aSJennifer Lee if (useDNSServers) 1096da131a9aSJennifer Lee { 1097da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1098da131a9aSJennifer Lee setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp); 1099da131a9aSJennifer Lee } 1100da131a9aSJennifer Lee 1101da131a9aSJennifer Lee if (useDomainName) 1102da131a9aSJennifer Lee { 1103da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1104da131a9aSJennifer Lee setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp); 1105da131a9aSJennifer Lee } 1106da131a9aSJennifer Lee 1107da131a9aSJennifer Lee if (useNTPServers) 1108da131a9aSJennifer Lee { 1109da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1110da131a9aSJennifer Lee setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp); 1111da131a9aSJennifer Lee } 1112da131a9aSJennifer Lee } 11134a0cb85cSEd Tanous void handleIPv4Patch( 1114f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 11154a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data, 11164a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 11171abe55efSEd Tanous { 1118f476acbfSRatan Gupta if (!input.is_array()) 1119f476acbfSRatan Gupta { 1120f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1121f476acbfSRatan Gupta "IPv4Addresses"); 1122f476acbfSRatan Gupta return; 1123f476acbfSRatan Gupta } 1124f476acbfSRatan Gupta 11254a0cb85cSEd Tanous int entryIdx = 0; 11264a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::const_iterator thisData = 11274a0cb85cSEd Tanous ipv4Data.begin(); 1128537174c4SEd Tanous for (nlohmann::json &thisJson : input) 11291abe55efSEd Tanous { 11304a0cb85cSEd Tanous std::string pathString = 1131a08b46ccSJason M. Bills "IPv4Addresses/" + std::to_string(entryIdx); 1132179db1d7SKowalski, Kamil 1133f476acbfSRatan Gupta if (thisJson.is_null()) 1134f476acbfSRatan Gupta { 1135f476acbfSRatan Gupta if (thisData != ipv4Data.end()) 1136f476acbfSRatan Gupta { 1137*286b9118SJohnathan Mantey deleteIPv4(ifaceId, thisData->id, asyncResp); 1138f476acbfSRatan Gupta thisData++; 1139f476acbfSRatan Gupta } 1140f476acbfSRatan Gupta else 1141f476acbfSRatan Gupta { 1142f476acbfSRatan Gupta messages::propertyValueFormatError( 1143f476acbfSRatan Gupta asyncResp->res, input.dump(), pathString); 1144f476acbfSRatan Gupta return; 1145f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 1146f476acbfSRatan Gupta // list and if unable to update one of the 1147f476acbfSRatan Gupta // list value then should we proceed further or 1148f476acbfSRatan Gupta // break there, would ask in the redfish forum 1149f476acbfSRatan Gupta // till then we stop processing the next list item. 1150f476acbfSRatan Gupta } 1151f476acbfSRatan Gupta entryIdx++; 1152f476acbfSRatan Gupta continue; // not an error as per the redfish spec. 1153f476acbfSRatan Gupta } 1154f476acbfSRatan Gupta 11559474b378SRatan Gupta if (thisJson.empty()) 11569474b378SRatan Gupta { 11579474b378SRatan Gupta if (thisData != ipv4Data.end()) 11589474b378SRatan Gupta { 11599474b378SRatan Gupta thisData++; 11609474b378SRatan Gupta } 11619474b378SRatan Gupta else 11629474b378SRatan Gupta { 11639474b378SRatan Gupta messages::propertyMissing(asyncResp->res, 11649474b378SRatan Gupta pathString + "/Address"); 11659474b378SRatan Gupta return; 1166f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 11679474b378SRatan Gupta // list and if unable to update one of the 11689474b378SRatan Gupta // list value then should we proceed further or 11699474b378SRatan Gupta // break there, would ask in the redfish forum 11709474b378SRatan Gupta // till then we stop processing the next list item. 11719474b378SRatan Gupta } 11729474b378SRatan Gupta entryIdx++; 11739474b378SRatan Gupta continue; // not an error as per the redfish spec. 11749474b378SRatan Gupta } 11759474b378SRatan Gupta 1176537174c4SEd Tanous std::optional<std::string> address; 1177537174c4SEd Tanous std::optional<std::string> subnetMask; 1178537174c4SEd Tanous std::optional<std::string> gateway; 1179537174c4SEd Tanous 1180537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 11817e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 11827e27d832SJohnathan Mantey "Gateway", gateway)) 1183537174c4SEd Tanous { 1184537174c4SEd Tanous return; 1185179db1d7SKowalski, Kamil } 1186179db1d7SKowalski, Kamil 1187537174c4SEd Tanous if (address) 11881abe55efSEd Tanous { 1189537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*address)) 11901abe55efSEd Tanous { 1191537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 11924a0cb85cSEd Tanous pathString + "/Address"); 1193537174c4SEd Tanous return; 11944a0cb85cSEd Tanous } 11954a0cb85cSEd Tanous } 11964a0cb85cSEd Tanous 1197537174c4SEd Tanous uint8_t prefixLength = 0; 1198537174c4SEd Tanous if (subnetMask) 11994a0cb85cSEd Tanous { 1200537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 12014a0cb85cSEd Tanous { 1202f12894f8SJason M. Bills messages::propertyValueFormatError( 1203537174c4SEd Tanous asyncResp->res, *subnetMask, 12044a0cb85cSEd Tanous pathString + "/SubnetMask"); 1205537174c4SEd Tanous return; 12064a0cb85cSEd Tanous } 12074a0cb85cSEd Tanous } 12084a0cb85cSEd Tanous 1209537174c4SEd Tanous if (gateway) 12104a0cb85cSEd Tanous { 1211537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*gateway)) 12124a0cb85cSEd Tanous { 1213537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1214537174c4SEd Tanous pathString + "/Gateway"); 1215537174c4SEd Tanous return; 12164a0cb85cSEd Tanous } 12174a0cb85cSEd Tanous } 12184a0cb85cSEd Tanous 1219f476acbfSRatan Gupta // if IP address exist then modify it. 12204a0cb85cSEd Tanous if (thisData != ipv4Data.end()) 12214a0cb85cSEd Tanous { 1222179db1d7SKowalski, Kamil // Apply changes 1223537174c4SEd Tanous if (address) 12241abe55efSEd Tanous { 1225*286b9118SJohnathan Mantey auto callback = 1226*286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 12274a0cb85cSEd Tanous if (ec) 12281abe55efSEd Tanous { 1229a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12304a0cb85cSEd Tanous return; 12314a0cb85cSEd Tanous } 12324a0cb85cSEd Tanous }; 12334a0cb85cSEd Tanous 12344a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12354a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1236f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1237f476acbfSRatan Gupta thisData->id, 12384a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12394a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Address", 1240537174c4SEd Tanous std::variant<std::string>(*address)); 1241179db1d7SKowalski, Kamil } 1242179db1d7SKowalski, Kamil 1243537174c4SEd Tanous if (subnetMask) 12441abe55efSEd Tanous { 12454a0cb85cSEd Tanous changeIPv4SubnetMaskProperty(ifaceId, entryIdx, 1246*286b9118SJohnathan Mantey thisData->id, prefixLength, 1247*286b9118SJohnathan Mantey asyncResp); 1248179db1d7SKowalski, Kamil } 1249179db1d7SKowalski, Kamil 1250537174c4SEd Tanous if (gateway) 12511abe55efSEd Tanous { 1252*286b9118SJohnathan Mantey auto callback = 1253*286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 12544a0cb85cSEd Tanous if (ec) 12551abe55efSEd Tanous { 1256a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 12574a0cb85cSEd Tanous return; 12584a0cb85cSEd Tanous } 12594a0cb85cSEd Tanous }; 12604a0cb85cSEd Tanous 12614a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 12624a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1263f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1264f476acbfSRatan Gupta thisData->id, 12654a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 12664a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Gateway", 1267537174c4SEd Tanous std::variant<std::string>(*gateway)); 12684a0cb85cSEd Tanous } 1269f476acbfSRatan Gupta 12704a0cb85cSEd Tanous thisData++; 12711abe55efSEd Tanous } 12721abe55efSEd Tanous else 12731abe55efSEd Tanous { 12744a0cb85cSEd Tanous // Create IPv4 with provided data 1275537174c4SEd Tanous if (!gateway) 12761abe55efSEd Tanous { 1277a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 12784a0cb85cSEd Tanous pathString + "/Gateway"); 12794a0cb85cSEd Tanous continue; 12804a0cb85cSEd Tanous } 12814a0cb85cSEd Tanous 1282537174c4SEd Tanous if (!address) 12831abe55efSEd Tanous { 1284a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 12854a0cb85cSEd Tanous pathString + "/Address"); 12864a0cb85cSEd Tanous continue; 12874a0cb85cSEd Tanous } 12884a0cb85cSEd Tanous 1289537174c4SEd Tanous if (!subnetMask) 12901abe55efSEd Tanous { 1291a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 12924a0cb85cSEd Tanous pathString + "/SubnetMask"); 12934a0cb85cSEd Tanous continue; 1294588c3f0dSKowalski, Kamil } 1295588c3f0dSKowalski, Kamil 1296b01bf299SEd Tanous createIPv4(ifaceId, entryIdx, prefixLength, *gateway, *address, 1297b01bf299SEd Tanous asyncResp); 129895897b20SRatan Gupta 129995897b20SRatan Gupta nlohmann::json &ipv4AddressJson = 130095897b20SRatan Gupta asyncResp->res.jsonValue["IPv4Addresses"][entryIdx]; 130195897b20SRatan Gupta ipv4AddressJson["Address"] = *address; 130295897b20SRatan Gupta ipv4AddressJson["SubnetMask"] = *subnetMask; 130395897b20SRatan Gupta ipv4AddressJson["Gateway"] = *gateway; 13044a0cb85cSEd Tanous } 13054a0cb85cSEd Tanous entryIdx++; 13064a0cb85cSEd Tanous } 13074a0cb85cSEd Tanous } 13084a0cb85cSEd Tanous 1309f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1310f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1311f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1312f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1313f85837bfSRAJESWARAN THILLAIGOVINDAN { 1314f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1315*286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1316f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1317f85837bfSRAJESWARAN THILLAIGOVINDAN { 1318f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1319f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1320f85837bfSRAJESWARAN THILLAIGOVINDAN } 1321f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1322f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1323f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1324f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1325f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1326f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1327f85837bfSRAJESWARAN THILLAIGOVINDAN } 1328f85837bfSRAJESWARAN THILLAIGOVINDAN 1329e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1330e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 1331e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData, 1332e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1333e48c0fc5SRavi Teja { 1334e48c0fc5SRavi Teja if (!input.is_array()) 1335e48c0fc5SRavi Teja { 1336e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1337e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1338e48c0fc5SRavi Teja return; 1339e48c0fc5SRavi Teja } 1340e48c0fc5SRavi Teja 1341e48c0fc5SRavi Teja int entryIdx = 0; 1342e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::const_iterator thisData = 1343e48c0fc5SRavi Teja ipv6StaticData.begin(); 1344e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1345e48c0fc5SRavi Teja { 1346e48c0fc5SRavi Teja std::string pathString = 1347e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1348e48c0fc5SRavi Teja 1349e48c0fc5SRavi Teja if (thisJson.is_null()) 1350e48c0fc5SRavi Teja { 1351e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1352e48c0fc5SRavi Teja { 1353*286b9118SJohnathan Mantey deleteIPv6(ifaceId, thisData->id, asyncResp); 1354e48c0fc5SRavi Teja thisData++; 1355e48c0fc5SRavi Teja } 1356e48c0fc5SRavi Teja else 1357e48c0fc5SRavi Teja { 1358e48c0fc5SRavi Teja messages::propertyValueFormatError( 1359e48c0fc5SRavi Teja asyncResp->res, input.dump(), pathString); 1360e48c0fc5SRavi Teja return; 1361e48c0fc5SRavi Teja } 1362e48c0fc5SRavi Teja entryIdx++; 1363e48c0fc5SRavi Teja continue; 1364e48c0fc5SRavi Teja } 1365e48c0fc5SRavi Teja 1366e48c0fc5SRavi Teja if (thisJson.empty()) 1367e48c0fc5SRavi Teja { 1368e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1369e48c0fc5SRavi Teja { 1370e48c0fc5SRavi Teja thisData++; 1371e48c0fc5SRavi Teja } 1372e48c0fc5SRavi Teja else 1373e48c0fc5SRavi Teja { 1374e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1375e48c0fc5SRavi Teja pathString + "/Address"); 1376e48c0fc5SRavi Teja return; 1377e48c0fc5SRavi Teja } 1378e48c0fc5SRavi Teja entryIdx++; 1379e48c0fc5SRavi Teja continue; 1380e48c0fc5SRavi Teja } 1381e48c0fc5SRavi Teja 1382e48c0fc5SRavi Teja std::optional<std::string> address; 1383e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1384e48c0fc5SRavi Teja 1385e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1386e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1387e48c0fc5SRavi Teja { 1388e48c0fc5SRavi Teja return; 1389e48c0fc5SRavi Teja } 1390e48c0fc5SRavi Teja 1391e48c0fc5SRavi Teja // if IP address exist then modify it. 1392e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1393e48c0fc5SRavi Teja { 1394e48c0fc5SRavi Teja // Apply changes 1395e48c0fc5SRavi Teja if (address) 1396e48c0fc5SRavi Teja { 1397*286b9118SJohnathan Mantey auto callback = 1398*286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1399e48c0fc5SRavi Teja if (ec) 1400e48c0fc5SRavi Teja { 1401e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1402e48c0fc5SRavi Teja return; 1403e48c0fc5SRavi Teja } 1404e48c0fc5SRavi Teja }; 1405e48c0fc5SRavi Teja 1406e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1407e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1408e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1409e48c0fc5SRavi Teja thisData->id, 1410e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1411e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "Address", 1412e48c0fc5SRavi Teja std::variant<std::string>(*address)); 1413e48c0fc5SRavi Teja } 1414e48c0fc5SRavi Teja 1415e48c0fc5SRavi Teja if (prefixLength) 1416e48c0fc5SRavi Teja { 1417*286b9118SJohnathan Mantey auto callback = 1418*286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1419e48c0fc5SRavi Teja if (ec) 1420e48c0fc5SRavi Teja { 1421e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1422e48c0fc5SRavi Teja return; 1423e48c0fc5SRavi Teja } 1424e48c0fc5SRavi Teja }; 1425e48c0fc5SRavi Teja 1426e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1427e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1428e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1429e48c0fc5SRavi Teja thisData->id, 1430e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1431e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "PrefixLength", 1432e48c0fc5SRavi Teja std::variant<uint8_t>(*prefixLength)); 1433e48c0fc5SRavi Teja } 1434e48c0fc5SRavi Teja 1435e48c0fc5SRavi Teja thisData++; 1436e48c0fc5SRavi Teja } 1437e48c0fc5SRavi Teja else 1438e48c0fc5SRavi Teja { 1439e48c0fc5SRavi Teja // Create IPv6 with provided data 1440e48c0fc5SRavi Teja 1441e48c0fc5SRavi Teja if (!prefixLength) 1442e48c0fc5SRavi Teja { 1443e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1444e48c0fc5SRavi Teja pathString + "/PrefixLength"); 1445e48c0fc5SRavi Teja continue; 1446e48c0fc5SRavi Teja } 1447e48c0fc5SRavi Teja 1448e48c0fc5SRavi Teja if (!address) 1449e48c0fc5SRavi Teja { 1450e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1451e48c0fc5SRavi Teja pathString + "/Address"); 1452e48c0fc5SRavi Teja continue; 1453e48c0fc5SRavi Teja } 1454e48c0fc5SRavi Teja 1455e48c0fc5SRavi Teja createIPv6(ifaceId, entryIdx, *prefixLength, *address, 1456e48c0fc5SRavi Teja asyncResp); 1457e48c0fc5SRavi Teja 1458e48c0fc5SRavi Teja nlohmann::json &ipv6StaticAddressJson = 1459e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"][entryIdx]; 1460e48c0fc5SRavi Teja ipv6StaticAddressJson["Address"] = *address; 1461e48c0fc5SRavi Teja ipv6StaticAddressJson["PrefixLength"] = *prefixLength; 1462e48c0fc5SRavi Teja } 1463e48c0fc5SRavi Teja entryIdx++; 1464e48c0fc5SRavi Teja } 1465e48c0fc5SRavi Teja } 1466e48c0fc5SRavi Teja 14670f74e643SEd Tanous void parseInterfaceData( 14680f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 14690f74e643SEd Tanous const EthernetInterfaceData ðData, 1470e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1471e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1472e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 14734a0cb85cSEd Tanous { 14744a0cb85cSEd Tanous json_response["Id"] = iface_id; 14754a0cb85cSEd Tanous json_response["@odata.id"] = 14764a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1477029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1478029573d4SEd Tanous if (ethData.speed == 0) 1479029573d4SEd Tanous { 1480029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1481029573d4SEd Tanous json_response["Status"] = { 1482029573d4SEd Tanous {"Health", "OK"}, 1483029573d4SEd Tanous {"State", "Disabled"}, 1484029573d4SEd Tanous }; 1485029573d4SEd Tanous } 1486029573d4SEd Tanous else 1487029573d4SEd Tanous { 1488029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1489029573d4SEd Tanous json_response["Status"] = { 1490029573d4SEd Tanous {"Health", "OK"}, 1491029573d4SEd Tanous {"State", "Enabled"}, 1492029573d4SEd Tanous }; 1493029573d4SEd Tanous } 14944a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 14954a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1496fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 14972a133282Smanojkiraneda 14984a0cb85cSEd Tanous if (!ethData.hostname.empty()) 14994a0cb85cSEd Tanous { 15004a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 15014a0cb85cSEd Tanous } 15024a0cb85cSEd Tanous 1503fda13ad2SSunitha Harish json_response["VLANs"] = { 1504fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1505fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1506fda13ad2SSunitha Harish 1507029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 1508f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 15094a0cb85cSEd Tanous 15104a0cb85cSEd Tanous if (ipv4Data.size() > 0) 15114a0cb85cSEd Tanous { 15124a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 15134a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 15144a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 15154a0cb85cSEd Tanous { 1516fa5053a6SGunnar Mills 1517fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1518fa5053a6SGunnar Mills if (gatewayStr.empty()) 1519fa5053a6SGunnar Mills { 1520fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1521fa5053a6SGunnar Mills } 1522fa5053a6SGunnar Mills 15234a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 15244a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1525029573d4SEd Tanous {"Address", ipv4_config.address}, 1526fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 15274a0cb85cSEd Tanous } 15284a0cb85cSEd Tanous } 15299a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1530e48c0fc5SRavi Teja 1531e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 1532e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 1533e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1534e48c0fc5SRavi Teja { 1535e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1536e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1537e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 1538e48c0fc5SRavi Teja } 1539e48c0fc5SRavi Teja 1540e48c0fc5SRavi Teja nlohmann::json &ipv6_static_array = 1541e48c0fc5SRavi Teja json_response["IPv6StaticAddresses"]; 1542e48c0fc5SRavi Teja ipv6_static_array = nlohmann::json::array(); 1543e48c0fc5SRavi Teja for (auto &ipv6_static_config : ipv6StaticData) 1544e48c0fc5SRavi Teja { 1545e48c0fc5SRavi Teja ipv6_static_array.push_back( 1546e48c0fc5SRavi Teja {{"Address", ipv6_static_config.address}, 1547e48c0fc5SRavi Teja {"PrefixLength", ipv6_static_config.prefixLength}}); 1548e48c0fc5SRavi Teja } 1549588c3f0dSKowalski, Kamil } 1550588c3f0dSKowalski, Kamil 15519391bb9cSRapkiewicz, Pawel /** 15529391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 15539391bb9cSRapkiewicz, Pawel */ 155455c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 15551abe55efSEd Tanous const std::vector<std::string> ¶ms) override 15561abe55efSEd Tanous { 15574a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 15581abe55efSEd Tanous if (params.size() != 1) 15591abe55efSEd Tanous { 1560f12894f8SJason M. Bills messages::internalError(asyncResp->res); 15619391bb9cSRapkiewicz, Pawel return; 15629391bb9cSRapkiewicz, Pawel } 15639391bb9cSRapkiewicz, Pawel 15644a0cb85cSEd Tanous getEthernetIfaceData( 15654a0cb85cSEd Tanous params[0], 15664a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 15674a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1568e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1569e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1570e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1571e48c0fc5SRavi Teja &ipv6StaticData) { 15724a0cb85cSEd Tanous if (!success) 15731abe55efSEd Tanous { 15741abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 15751abe55efSEd Tanous // object, and other errors 1576f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1577f12894f8SJason M. Bills "EthernetInterface", iface_id); 15784a0cb85cSEd Tanous return; 15799391bb9cSRapkiewicz, Pawel } 15804c9afe43SEd Tanous 15814c9afe43SEd Tanous // because this has no dependence on the interface at this 15824c9afe43SEd Tanous // point, it needs to be done after we know the interface 15834c9afe43SEd Tanous // exists, not before. 15844c9afe43SEd Tanous getDHCPConfigData(asyncResp); 15854c9afe43SEd Tanous 15860f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1587fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 15880f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 15890f74e643SEd Tanous "/redfish/v1/$metadata#EthernetInterface.EthernetInterface"; 15900f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 15910f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 15920f74e643SEd Tanous "Management Network Interface"; 15930f74e643SEd Tanous 15940f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1595e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 15969391bb9cSRapkiewicz, Pawel }); 15979391bb9cSRapkiewicz, Pawel } 15989391bb9cSRapkiewicz, Pawel 159955c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 16001abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16011abe55efSEd Tanous { 16024a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16031abe55efSEd Tanous if (params.size() != 1) 16041abe55efSEd Tanous { 1605f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1606588c3f0dSKowalski, Kamil return; 1607588c3f0dSKowalski, Kamil } 1608588c3f0dSKowalski, Kamil 16094a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1610588c3f0dSKowalski, Kamil 1611bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1612d577665bSRatan Gupta std::optional<std::string> macAddress; 16139a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1614f476acbfSRatan Gupta std::optional<nlohmann::json> ipv4Addresses; 1615f476acbfSRatan Gupta std::optional<nlohmann::json> ipv6Addresses; 1616e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1617f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 16185112e9b4SRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> nameServers; 1619da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 16200627a2c7SEd Tanous 1621fda13ad2SSunitha Harish if (!json_util::readJson( 1622fda13ad2SSunitha Harish req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses, 16236ca6ac12SJohnathan Mantey "MACAddress", macAddress, "StaticNameServers", 16246ca6ac12SJohnathan Mantey staticNameServers, "IPv6DefaultGateway", ipv6DefaultGateway, 16256ca6ac12SJohnathan Mantey "IPv6StaticAddresses", ipv6StaticAddresses, "NameServers", 16266ca6ac12SJohnathan Mantey nameServers, "DHCPv4", dhcpv4)) 16271abe55efSEd Tanous { 1628588c3f0dSKowalski, Kamil return; 1629588c3f0dSKowalski, Kamil } 1630f15aad37SRatan Gupta 1631da131a9aSJennifer Lee if (dhcpv4) 1632da131a9aSJennifer Lee { 1633da131a9aSJennifer Lee handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp); 1634da131a9aSJennifer Lee } 1635da131a9aSJennifer Lee 16364a0cb85cSEd Tanous // Get single eth interface data, and call the below callback for JSON 1637588c3f0dSKowalski, Kamil // preparation 16384a0cb85cSEd Tanous getEthernetIfaceData( 16394a0cb85cSEd Tanous iface_id, 1640fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1641fda13ad2SSunitha Harish macAddress = std::move(macAddress), 16420627a2c7SEd Tanous ipv4Addresses = std::move(ipv4Addresses), 16439a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1644e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 16455112e9b4SRAJESWARAN THILLAIGOVINDAN staticNameServers = std::move(staticNameServers), 16465112e9b4SRAJESWARAN THILLAIGOVINDAN nameServers = std::move(nameServers)]( 16474a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1648e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1649e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1650e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1651e48c0fc5SRavi Teja &ipv6StaticData) { 16521abe55efSEd Tanous if (!success) 16531abe55efSEd Tanous { 1654588c3f0dSKowalski, Kamil // ... otherwise return error 16551abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 16561abe55efSEd Tanous // object, and other errors 1657fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1658fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1659588c3f0dSKowalski, Kamil return; 1660588c3f0dSKowalski, Kamil } 1661588c3f0dSKowalski, Kamil 16620627a2c7SEd Tanous if (hostname) 16631abe55efSEd Tanous { 16640627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 16651abe55efSEd Tanous } 16660627a2c7SEd Tanous 1667d577665bSRatan Gupta if (macAddress) 1668d577665bSRatan Gupta { 1669d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1670d577665bSRatan Gupta } 1671d577665bSRatan Gupta 16720627a2c7SEd Tanous if (ipv4Addresses) 16731abe55efSEd Tanous { 1674537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 1675537174c4SEd Tanous // above is returning a const value, not a non-const value. 1676537174c4SEd Tanous // This doesn't really work for us, as we need to be able to 1677537174c4SEd Tanous // efficiently move out the intermedia nlohmann::json 1678537174c4SEd Tanous // objects. This makes a copy of the structure, and operates 1679537174c4SEd Tanous // on that, but could be done more efficiently 1680f476acbfSRatan Gupta nlohmann::json ipv4 = std::move(*ipv4Addresses); 1681537174c4SEd Tanous handleIPv4Patch(iface_id, ipv4, ipv4Data, asyncResp); 16821abe55efSEd Tanous } 16830627a2c7SEd Tanous 16845112e9b4SRAJESWARAN THILLAIGOVINDAN if (nameServers) 16855112e9b4SRAJESWARAN THILLAIGOVINDAN { 16865112e9b4SRAJESWARAN THILLAIGOVINDAN // Data.Permissions is read-only 16875112e9b4SRAJESWARAN THILLAIGOVINDAN messages::propertyNotWritable(asyncResp->res, 16885112e9b4SRAJESWARAN THILLAIGOVINDAN "NameServers"); 16895112e9b4SRAJESWARAN THILLAIGOVINDAN } 16905112e9b4SRAJESWARAN THILLAIGOVINDAN 1691f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1692f85837bfSRAJESWARAN THILLAIGOVINDAN { 1693f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1694f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1695f85837bfSRAJESWARAN THILLAIGOVINDAN } 16969a6fc6feSRavi Teja 16979a6fc6feSRavi Teja if (ipv6DefaultGateway) 16989a6fc6feSRavi Teja { 16999a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 17009a6fc6feSRavi Teja "IPv6DefaultGateway"); 17019a6fc6feSRavi Teja } 1702e48c0fc5SRavi Teja 1703e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1704e48c0fc5SRavi Teja { 1705e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1706e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 1707e48c0fc5SRavi Teja ipv6StaticData, asyncResp); 1708e48c0fc5SRavi Teja } 1709588c3f0dSKowalski, Kamil }); 1710588c3f0dSKowalski, Kamil } 17119391bb9cSRapkiewicz, Pawel }; 17129391bb9cSRapkiewicz, Pawel 1713e439f0f8SKowalski, Kamil /** 17144a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 17154a0cb85cSEd Tanous * Schema 1716e439f0f8SKowalski, Kamil */ 17171abe55efSEd Tanous class VlanNetworkInterface : public Node 17181abe55efSEd Tanous { 1719e439f0f8SKowalski, Kamil public: 1720e439f0f8SKowalski, Kamil /* 1721e439f0f8SKowalski, Kamil * Default Constructor 1722e439f0f8SKowalski, Kamil */ 1723e439f0f8SKowalski, Kamil template <typename CrowApp> 17241abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 17254a0cb85cSEd Tanous Node(app, 17260f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 17271abe55efSEd Tanous std::string(), std::string()) 17281abe55efSEd Tanous { 1729e439f0f8SKowalski, Kamil entityPrivileges = { 1730e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1731e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1732e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1733e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1734e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1735e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1736e439f0f8SKowalski, Kamil } 1737e439f0f8SKowalski, Kamil 1738e439f0f8SKowalski, Kamil private: 17390f74e643SEd Tanous void parseInterfaceData( 17400f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 17410f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1742e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1743e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1744e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 17451abe55efSEd Tanous { 1746e439f0f8SKowalski, Kamil // Fill out obvious data... 17474a0cb85cSEd Tanous json_response["Id"] = iface_id; 17484a0cb85cSEd Tanous json_response["@odata.id"] = 17494a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 17504a0cb85cSEd Tanous "/VLANs/" + iface_id; 1751e439f0f8SKowalski, Kamil 17524a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1753fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 17544a0cb85cSEd Tanous { 1755fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 17564a0cb85cSEd Tanous } 1757e439f0f8SKowalski, Kamil } 1758e439f0f8SKowalski, Kamil 1759fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 17601abe55efSEd Tanous { 17611abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 17621abe55efSEd Tanous { 1763927a505aSKowalski, Kamil return false; 17641abe55efSEd Tanous } 17651abe55efSEd Tanous else 17661abe55efSEd Tanous { 1767927a505aSKowalski, Kamil return true; 1768927a505aSKowalski, Kamil } 1769927a505aSKowalski, Kamil } 1770927a505aSKowalski, Kamil 1771e439f0f8SKowalski, Kamil /** 1772e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1773e439f0f8SKowalski, Kamil */ 177455c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 17751abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17761abe55efSEd Tanous { 17774a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17784a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1779e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1780e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1781e439f0f8SKowalski, Kamil // impossible. 17821abe55efSEd Tanous if (params.size() != 2) 17831abe55efSEd Tanous { 1784f12894f8SJason M. Bills messages::internalError(res); 1785e439f0f8SKowalski, Kamil res.end(); 1786e439f0f8SKowalski, Kamil return; 1787e439f0f8SKowalski, Kamil } 1788e439f0f8SKowalski, Kamil 17894a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 17904a0cb85cSEd Tanous const std::string &iface_id = params[1]; 17910f74e643SEd Tanous res.jsonValue["@odata.type"] = 17920f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 17930f74e643SEd Tanous res.jsonValue["@odata.context"] = 17940f74e643SEd Tanous "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface"; 17950f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1796e439f0f8SKowalski, Kamil 1797fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 17981abe55efSEd Tanous { 1799a434f2bdSEd Tanous return; 1800a434f2bdSEd Tanous } 1801a434f2bdSEd Tanous 1802e439f0f8SKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1803e439f0f8SKowalski, Kamil // preparation 18044a0cb85cSEd Tanous getEthernetIfaceData( 1805fda13ad2SSunitha Harish params[1], 1806fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1807fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 18084a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1809e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1810e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1811e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1812e48c0fc5SRavi Teja &ipv6StaticData) { 1813fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 18141abe55efSEd Tanous { 18150f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 18160f74e643SEd Tanous parent_iface_id, iface_id, ethData, 1817e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 18181abe55efSEd Tanous } 18191abe55efSEd Tanous else 18201abe55efSEd Tanous { 1821e439f0f8SKowalski, Kamil // ... otherwise return error 18221abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18231abe55efSEd Tanous // object, and other errors 1824f12894f8SJason M. Bills messages::resourceNotFound( 1825f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1826e439f0f8SKowalski, Kamil } 1827e439f0f8SKowalski, Kamil }); 1828e439f0f8SKowalski, Kamil } 1829e439f0f8SKowalski, Kamil 183055c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 18311abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18321abe55efSEd Tanous { 18334a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18341abe55efSEd Tanous if (params.size() != 2) 18351abe55efSEd Tanous { 1836f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1837e439f0f8SKowalski, Kamil return; 1838e439f0f8SKowalski, Kamil } 1839e439f0f8SKowalski, Kamil 1840d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 184155c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1842927a505aSKowalski, Kamil 1843fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 18441abe55efSEd Tanous { 1845fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1846fda13ad2SSunitha Harish ifaceId); 1847927a505aSKowalski, Kamil return; 1848927a505aSKowalski, Kamil } 1849927a505aSKowalski, Kamil 18500627a2c7SEd Tanous bool vlanEnable = false; 18510627a2c7SEd Tanous uint64_t vlanId = 0; 18520627a2c7SEd Tanous 18530627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 18540627a2c7SEd Tanous vlanId)) 18551abe55efSEd Tanous { 1856927a505aSKowalski, Kamil return; 1857927a505aSKowalski, Kamil } 1858927a505aSKowalski, Kamil 1859927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1860927a505aSKowalski, Kamil // preparation 1861e48c0fc5SRavi Teja getEthernetIfaceData( 1862e48c0fc5SRavi Teja params[1], 1863e48c0fc5SRavi Teja [this, asyncResp, parentIfaceId{std::string(params[0])}, 1864e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 1865e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 1866e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1867e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1868e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1869e48c0fc5SRavi Teja &ipv6StaticData) { 187008244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 187108244d02SSunitha Harish { 187208244d02SSunitha Harish auto callback = 187308244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 187408244d02SSunitha Harish if (ec) 187508244d02SSunitha Harish { 187608244d02SSunitha Harish messages::internalError(asyncResp->res); 187708244d02SSunitha Harish } 187808244d02SSunitha Harish }; 187908244d02SSunitha Harish 188008244d02SSunitha Harish if (vlanEnable == true) 188108244d02SSunitha Harish { 188208244d02SSunitha Harish crow::connections::systemBus->async_method_call( 188308244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 188408244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 188508244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 188608244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 188708244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 188808244d02SSunitha Harish } 188908244d02SSunitha Harish else 189008244d02SSunitha Harish { 1891e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 1892e48c0fc5SRavi Teja "vlan interface"; 189308244d02SSunitha Harish crow::connections::systemBus->async_method_call( 189408244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 1895e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 1896e48c0fc5SRavi Teja ifaceId, 189708244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 189808244d02SSunitha Harish } 189908244d02SSunitha Harish } 190008244d02SSunitha Harish else 19011abe55efSEd Tanous { 19021abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 19031abe55efSEd Tanous // object, and other errors 1904e48c0fc5SRavi Teja messages::resourceNotFound( 1905e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 1906927a505aSKowalski, Kamil return; 1907927a505aSKowalski, Kamil } 1908927a505aSKowalski, Kamil }); 1909e439f0f8SKowalski, Kamil } 1910e439f0f8SKowalski, Kamil 191155c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 19121abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19131abe55efSEd Tanous { 19144a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19151abe55efSEd Tanous if (params.size() != 2) 19161abe55efSEd Tanous { 1917f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1918e439f0f8SKowalski, Kamil return; 1919e439f0f8SKowalski, Kamil } 1920e439f0f8SKowalski, Kamil 1921d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 192255c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1923927a505aSKowalski, Kamil 1924fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 19251abe55efSEd Tanous { 1926fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1927fda13ad2SSunitha Harish ifaceId); 1928927a505aSKowalski, Kamil return; 1929927a505aSKowalski, Kamil } 1930927a505aSKowalski, Kamil 1931927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1932927a505aSKowalski, Kamil // preparation 1933f12894f8SJason M. Bills getEthernetIfaceData( 1934fda13ad2SSunitha Harish params[1], 1935fda13ad2SSunitha Harish [this, asyncResp, parentIfaceId{std::string(params[0])}, 1936fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 1937f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 1938e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1939e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1940e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1941e48c0fc5SRavi Teja &ipv6StaticData) { 1942fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 19431abe55efSEd Tanous { 1944f12894f8SJason M. Bills auto callback = 1945f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 19461abe55efSEd Tanous if (ec) 19471abe55efSEd Tanous { 1948f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1949927a505aSKowalski, Kamil } 19504a0cb85cSEd Tanous }; 19514a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 19524a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 19534a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 19544a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 19551abe55efSEd Tanous } 19561abe55efSEd Tanous else 19571abe55efSEd Tanous { 1958927a505aSKowalski, Kamil // ... otherwise return error 1959f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 1960f12894f8SJason M. Bills // object, and other errors 1961f12894f8SJason M. Bills messages::resourceNotFound( 1962f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 1963927a505aSKowalski, Kamil } 1964927a505aSKowalski, Kamil }); 1965e439f0f8SKowalski, Kamil } 1966e439f0f8SKowalski, Kamil }; 1967e439f0f8SKowalski, Kamil 1968e439f0f8SKowalski, Kamil /** 1969e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 1970e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 1971e439f0f8SKowalski, Kamil */ 19721abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 19731abe55efSEd Tanous { 1974e439f0f8SKowalski, Kamil public: 1975e439f0f8SKowalski, Kamil template <typename CrowApp> 19761abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 19774a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 19784a0cb85cSEd Tanous std::string()) 19791abe55efSEd Tanous { 1980e439f0f8SKowalski, Kamil entityPrivileges = { 1981e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1982e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1983e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1984e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1985e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1986e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1987e439f0f8SKowalski, Kamil } 1988e439f0f8SKowalski, Kamil 1989e439f0f8SKowalski, Kamil private: 1990e439f0f8SKowalski, Kamil /** 1991e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1992e439f0f8SKowalski, Kamil */ 199355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 19941abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19951abe55efSEd Tanous { 19964a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19971abe55efSEd Tanous if (params.size() != 1) 19981abe55efSEd Tanous { 1999e439f0f8SKowalski, Kamil // This means there is a problem with the router 2000f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2001e439f0f8SKowalski, Kamil return; 2002e439f0f8SKowalski, Kamil } 2003e439f0f8SKowalski, Kamil 20044a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2005e439f0f8SKowalski, Kamil 20064a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 20071abe55efSEd Tanous // preparation 2008f12894f8SJason M. Bills getEthernetIfaceList( 200943b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 20101abe55efSEd Tanous const bool &success, 20114c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 20124a0cb85cSEd Tanous if (!success) 20131abe55efSEd Tanous { 2014f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20154a0cb85cSEd Tanous return; 20161abe55efSEd Tanous } 20174c9afe43SEd Tanous 20184c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 20194c9afe43SEd Tanous { 20204c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 20214c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 20224c9afe43SEd Tanous rootInterfaceName); 20234c9afe43SEd Tanous return; 20244c9afe43SEd Tanous } 20254c9afe43SEd Tanous 20260f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 20270f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 20280f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 20290f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 20300f74e643SEd Tanous "/redfish/v1/$metadata" 20310f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 20320f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 20330f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 20340f74e643SEd Tanous "VLAN Network Interface Collection"; 20354a0cb85cSEd Tanous 20364a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 20374a0cb85cSEd Tanous 20384a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 20391abe55efSEd Tanous { 20404a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 20414a0cb85cSEd Tanous { 20424a0cb85cSEd Tanous iface_array.push_back( 20434a0cb85cSEd Tanous {{"@odata.id", 20444a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 20454a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2046e439f0f8SKowalski, Kamil } 2047e439f0f8SKowalski, Kamil } 2048e439f0f8SKowalski, Kamil 20494a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 20504a0cb85cSEd Tanous iface_array.size(); 20514a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 20524a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 20534a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 20544a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2055e439f0f8SKowalski, Kamil }); 2056e439f0f8SKowalski, Kamil } 2057e439f0f8SKowalski, Kamil 205855c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 20591abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20601abe55efSEd Tanous { 20614a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20621abe55efSEd Tanous if (params.size() != 1) 20631abe55efSEd Tanous { 2064f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2065e439f0f8SKowalski, Kamil return; 2066e439f0f8SKowalski, Kamil } 2067fda13ad2SSunitha Harish bool vlanEnable = false; 20680627a2c7SEd Tanous uint32_t vlanId = 0; 2069fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2070fda13ad2SSunitha Harish vlanEnable)) 20711abe55efSEd Tanous { 20724a0cb85cSEd Tanous return; 2073e439f0f8SKowalski, Kamil } 2074fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2075fda13ad2SSunitha Harish if (!vlanId) 2076fda13ad2SSunitha Harish { 2077fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2078fda13ad2SSunitha Harish } 2079fda13ad2SSunitha Harish if (!vlanEnable) 2080fda13ad2SSunitha Harish { 2081fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2082fda13ad2SSunitha Harish } 2083fda13ad2SSunitha Harish if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) 2084fda13ad2SSunitha Harish { 2085fda13ad2SSunitha Harish return; 2086fda13ad2SSunitha Harish } 2087fda13ad2SSunitha Harish 20884a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 20894a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 20901abe55efSEd Tanous if (ec) 20911abe55efSEd Tanous { 20924a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 20934a0cb85cSEd Tanous // phosphor-network responses 2094f12894f8SJason M. Bills messages::internalError(asyncResp->res); 20954a0cb85cSEd Tanous return; 20961abe55efSEd Tanous } 2097f12894f8SJason M. Bills messages::created(asyncResp->res); 2098e439f0f8SKowalski, Kamil }; 20994a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21004a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21014a0cb85cSEd Tanous "/xyz/openbmc_project/network", 21024a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 21030627a2c7SEd Tanous rootInterfaceName, vlanId); 21044a0cb85cSEd Tanous } 21054a0cb85cSEd Tanous }; 21069391bb9cSRapkiewicz, Pawel } // namespace redfish 2107