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 /** 749391bb9cSRapkiewicz, Pawel * Structure for keeping basic single Ethernet Interface information 759391bb9cSRapkiewicz, Pawel * available from DBus 769391bb9cSRapkiewicz, Pawel */ 771abe55efSEd Tanous struct EthernetInterfaceData 781abe55efSEd Tanous { 794a0cb85cSEd Tanous uint32_t speed; 804a0cb85cSEd Tanous bool auto_neg; 812a133282Smanojkiraneda bool DHCPEnabled; 824a0cb85cSEd Tanous std::string hostname; 834a0cb85cSEd Tanous std::string default_gateway; 84*9a6fc6feSRavi Teja std::string ipv6_default_gateway; 854a0cb85cSEd Tanous std::string mac_address; 86fda13ad2SSunitha Harish std::vector<std::uint32_t> vlan_id; 87029573d4SEd Tanous std::vector<std::string> nameservers; 889391bb9cSRapkiewicz, Pawel }; 899391bb9cSRapkiewicz, Pawel 909391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 919391bb9cSRapkiewicz, Pawel // into full dot notation 921abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 931abe55efSEd Tanous { 949391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 959391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 969391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 979391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 989391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 999391bb9cSRapkiewicz, Pawel return netmask; 1009391bb9cSRapkiewicz, Pawel } 1019391bb9cSRapkiewicz, Pawel 1024a0cb85cSEd Tanous inline std::string 1034a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string &inputOrigin, 1044a0cb85cSEd Tanous bool isIPv4) 1051abe55efSEd Tanous { 1064a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1071abe55efSEd Tanous { 1084a0cb85cSEd Tanous return "Static"; 1099391bb9cSRapkiewicz, Pawel } 1104a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1111abe55efSEd Tanous { 1124a0cb85cSEd Tanous if (isIPv4) 1131abe55efSEd Tanous { 1144a0cb85cSEd Tanous return "IPv4LinkLocal"; 1151abe55efSEd Tanous } 1161abe55efSEd Tanous else 1171abe55efSEd Tanous { 1184a0cb85cSEd Tanous return "LinkLocal"; 1199391bb9cSRapkiewicz, Pawel } 1209391bb9cSRapkiewicz, Pawel } 1214a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1221abe55efSEd Tanous { 1234a0cb85cSEd Tanous if (isIPv4) 1244a0cb85cSEd Tanous { 1254a0cb85cSEd Tanous return "DHCP"; 1264a0cb85cSEd Tanous } 1274a0cb85cSEd Tanous else 1284a0cb85cSEd Tanous { 1294a0cb85cSEd Tanous return "DHCPv6"; 1304a0cb85cSEd Tanous } 1314a0cb85cSEd Tanous } 1324a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1334a0cb85cSEd Tanous { 1344a0cb85cSEd Tanous return "SLAAC"; 1354a0cb85cSEd Tanous } 1364a0cb85cSEd Tanous return ""; 1374a0cb85cSEd Tanous } 1384a0cb85cSEd Tanous 1394a0cb85cSEd Tanous inline std::string 1404a0cb85cSEd Tanous translateAddressOriginRedfishToDbus(const std::string &inputOrigin) 1414a0cb85cSEd Tanous { 1424a0cb85cSEd Tanous if (inputOrigin == "Static") 1434a0cb85cSEd Tanous { 1444a0cb85cSEd Tanous return "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 1454a0cb85cSEd Tanous } 1464a0cb85cSEd Tanous if (inputOrigin == "DHCP" || inputOrigin == "DHCPv6") 1474a0cb85cSEd Tanous { 1484a0cb85cSEd Tanous return "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 1494a0cb85cSEd Tanous } 1504a0cb85cSEd Tanous if (inputOrigin == "IPv4LinkLocal" || inputOrigin == "LinkLocal") 1514a0cb85cSEd Tanous { 1524a0cb85cSEd Tanous return "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal"; 1534a0cb85cSEd Tanous } 1544a0cb85cSEd Tanous if (inputOrigin == "SLAAC") 1554a0cb85cSEd Tanous { 1564a0cb85cSEd Tanous return "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC"; 1574a0cb85cSEd Tanous } 1584a0cb85cSEd Tanous return ""; 1594a0cb85cSEd Tanous } 1604a0cb85cSEd Tanous 1614a0cb85cSEd Tanous inline void extractEthernetInterfaceData(const std::string ðiface_id, 1624a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 1634a0cb85cSEd Tanous EthernetInterfaceData ðData) 1644a0cb85cSEd Tanous { 1654a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 1664a0cb85cSEd Tanous { 1674a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 1684a0cb85cSEd Tanous { 169029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 170029573d4SEd Tanous { 1714a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 1724a0cb85cSEd Tanous { 1734a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1744a0cb85cSEd Tanous { 1754a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 1764a0cb85cSEd Tanous { 1774a0cb85cSEd Tanous const std::string *mac = 178abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 1794a0cb85cSEd Tanous if (mac != nullptr) 1804a0cb85cSEd Tanous { 1814a0cb85cSEd Tanous ethData.mac_address = *mac; 1824a0cb85cSEd Tanous } 1834a0cb85cSEd Tanous } 1844a0cb85cSEd Tanous } 1854a0cb85cSEd Tanous } 1864a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 1874a0cb85cSEd Tanous { 1884a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1894a0cb85cSEd Tanous { 1904a0cb85cSEd Tanous if (propertyPair.first == "Id") 1914a0cb85cSEd Tanous { 1921b6b96c5SEd Tanous const uint32_t *id = 193abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 1944a0cb85cSEd Tanous if (id != nullptr) 1954a0cb85cSEd Tanous { 196fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 1974a0cb85cSEd Tanous } 1984a0cb85cSEd Tanous } 1994a0cb85cSEd Tanous } 2004a0cb85cSEd Tanous } 2014a0cb85cSEd Tanous else if (ifacePair.first == 2024a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2034a0cb85cSEd Tanous { 2044a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2054a0cb85cSEd Tanous { 2064a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2074a0cb85cSEd Tanous { 2084a0cb85cSEd Tanous const bool *auto_neg = 209abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2104a0cb85cSEd Tanous if (auto_neg != nullptr) 2114a0cb85cSEd Tanous { 2124a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2134a0cb85cSEd Tanous } 2144a0cb85cSEd Tanous } 2154a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2164a0cb85cSEd Tanous { 2174a0cb85cSEd Tanous const uint32_t *speed = 218abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2194a0cb85cSEd Tanous if (speed != nullptr) 2204a0cb85cSEd Tanous { 2214a0cb85cSEd Tanous ethData.speed = *speed; 2224a0cb85cSEd Tanous } 2234a0cb85cSEd Tanous } 224f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 225029573d4SEd Tanous { 226029573d4SEd Tanous const std::vector<std::string> *nameservers = 227029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 228029573d4SEd Tanous std::vector<std::string>>( 229029573d4SEd Tanous &propertyPair.second); 230029573d4SEd Tanous if (nameservers != nullptr) 231029573d4SEd Tanous { 232029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2334a0cb85cSEd Tanous } 2344a0cb85cSEd Tanous } 2352a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 2362a133282Smanojkiraneda { 2372a133282Smanojkiraneda const bool *DHCPEnabled = 2382a133282Smanojkiraneda std::get_if<bool>(&propertyPair.second); 2392a133282Smanojkiraneda if (DHCPEnabled != nullptr) 2402a133282Smanojkiraneda { 2412a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 2422a133282Smanojkiraneda } 2432a133282Smanojkiraneda } 244029573d4SEd Tanous } 245029573d4SEd Tanous } 246029573d4SEd Tanous } 247029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 248029573d4SEd Tanous // to check eth number 249029573d4SEd Tanous if (ifacePair.first == 2504a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 2514a0cb85cSEd Tanous { 2524a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2534a0cb85cSEd Tanous { 2544a0cb85cSEd Tanous if (propertyPair.first == "HostName") 2554a0cb85cSEd Tanous { 2564a0cb85cSEd Tanous const std::string *hostname = 257029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 258029573d4SEd Tanous &propertyPair.second); 2594a0cb85cSEd Tanous if (hostname != nullptr) 2604a0cb85cSEd Tanous { 2614a0cb85cSEd Tanous ethData.hostname = *hostname; 2624a0cb85cSEd Tanous } 2634a0cb85cSEd Tanous } 2644a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 2654a0cb85cSEd Tanous { 2664a0cb85cSEd Tanous const std::string *defaultGateway = 267029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 268029573d4SEd Tanous &propertyPair.second); 2694a0cb85cSEd Tanous if (defaultGateway != nullptr) 2704a0cb85cSEd Tanous { 2714a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 2724a0cb85cSEd Tanous } 2734a0cb85cSEd Tanous } 274*9a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 275*9a6fc6feSRavi Teja { 276*9a6fc6feSRavi Teja const std::string *defaultGateway6 = 277*9a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 278*9a6fc6feSRavi Teja &propertyPair.second); 279*9a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 280*9a6fc6feSRavi Teja { 281*9a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 282*9a6fc6feSRavi Teja } 283*9a6fc6feSRavi Teja } 2844a0cb85cSEd Tanous } 2854a0cb85cSEd Tanous } 2864a0cb85cSEd Tanous } 2874a0cb85cSEd Tanous } 2884a0cb85cSEd Tanous } 2894a0cb85cSEd Tanous 2904a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 2914a0cb85cSEd Tanous inline void 2924a0cb85cSEd Tanous extractIPData(const std::string ðiface_id, 2934a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 2944a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> &ipv4_config) 2954a0cb85cSEd Tanous { 2964a0cb85cSEd Tanous const std::string ipv4PathStart = 2974a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 2984a0cb85cSEd Tanous 2994a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 3004a0cb85cSEd Tanous // single ethernet interface, loop over all of them 3014a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 3024a0cb85cSEd Tanous { 3034a0cb85cSEd Tanous // Check if proper pattern for object path appears 3044a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 3054a0cb85cSEd Tanous { 3064a0cb85cSEd Tanous for (auto &interface : objpath.second) 3074a0cb85cSEd Tanous { 3084a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 3094a0cb85cSEd Tanous { 3104a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 3114a0cb85cSEd Tanous // appropriate 3124a0cb85cSEd Tanous std::pair< 3134a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 3144a0cb85cSEd Tanous bool> 3154a0cb85cSEd Tanous it = ipv4_config.insert( 316b01bf299SEd Tanous {objpath.first.str.substr(ipv4PathStart.size())}); 3174a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 3184a0cb85cSEd Tanous for (auto &property : interface.second) 3194a0cb85cSEd Tanous { 3204a0cb85cSEd Tanous if (property.first == "Address") 3214a0cb85cSEd Tanous { 3224a0cb85cSEd Tanous const std::string *address = 323abf2add6SEd Tanous std::get_if<std::string>(&property.second); 3244a0cb85cSEd Tanous if (address != nullptr) 3254a0cb85cSEd Tanous { 3264a0cb85cSEd Tanous ipv4_address.address = *address; 3274a0cb85cSEd Tanous } 3284a0cb85cSEd Tanous } 3294a0cb85cSEd Tanous else if (property.first == "Gateway") 3304a0cb85cSEd Tanous { 3314a0cb85cSEd Tanous const std::string *gateway = 332abf2add6SEd Tanous std::get_if<std::string>(&property.second); 3334a0cb85cSEd Tanous if (gateway != nullptr) 3344a0cb85cSEd Tanous { 3354a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 3364a0cb85cSEd Tanous } 3374a0cb85cSEd Tanous } 3384a0cb85cSEd Tanous else if (property.first == "Origin") 3394a0cb85cSEd Tanous { 3404a0cb85cSEd Tanous const std::string *origin = 341abf2add6SEd Tanous std::get_if<std::string>(&property.second); 3424a0cb85cSEd Tanous if (origin != nullptr) 3434a0cb85cSEd Tanous { 3444a0cb85cSEd Tanous ipv4_address.origin = 3454a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 3464a0cb85cSEd Tanous true); 3474a0cb85cSEd Tanous } 3484a0cb85cSEd Tanous } 3494a0cb85cSEd Tanous else if (property.first == "PrefixLength") 3504a0cb85cSEd Tanous { 3514a0cb85cSEd Tanous const uint8_t *mask = 352abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 3534a0cb85cSEd Tanous if (mask != nullptr) 3544a0cb85cSEd Tanous { 3554a0cb85cSEd Tanous // convert it to the string 3564a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 3574a0cb85cSEd Tanous } 3584a0cb85cSEd Tanous } 3594a0cb85cSEd Tanous else 3604a0cb85cSEd Tanous { 3614a0cb85cSEd Tanous BMCWEB_LOG_ERROR 3624a0cb85cSEd Tanous << "Got extra property: " << property.first 3634a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 3644a0cb85cSEd Tanous } 3654a0cb85cSEd Tanous } 3664a0cb85cSEd Tanous // Check if given address is local, or global 3674a0cb85cSEd Tanous ipv4_address.linktype = 3684a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 3694a0cb85cSEd Tanous ? LinkType::Global 3704a0cb85cSEd Tanous : LinkType::Local; 3714a0cb85cSEd Tanous } 3724a0cb85cSEd Tanous } 3734a0cb85cSEd Tanous } 3744a0cb85cSEd Tanous } 3754a0cb85cSEd Tanous } 376588c3f0dSKowalski, Kamil 377588c3f0dSKowalski, Kamil /** 378588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 379588c3f0dSKowalski, Kamil * 380588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 381588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 382588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 383588c3f0dSKowalski, Kamil * 384588c3f0dSKowalski, Kamil * @return None. 385588c3f0dSKowalski, Kamil */ 386588c3f0dSKowalski, Kamil template <typename CallbackFunc> 3874a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 3881abe55efSEd Tanous CallbackFunc &&callback) 3891abe55efSEd Tanous { 39055c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 391588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 392588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 393588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 394588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 395abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 3964a0cb85cSEd Tanous } 397588c3f0dSKowalski, Kamil 398588c3f0dSKowalski, Kamil /** 399179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 400179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 401179db1d7SKowalski, Kamil * bit count for Subnet Mask. 402179db1d7SKowalski, Kamil * 403179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 404179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 405179db1d7SKowalski, Kamil * 406179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 407179db1d7SKowalski, Kamil */ 4084a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 4091abe55efSEd Tanous uint8_t *bits = nullptr) 4101abe55efSEd Tanous { 411179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 412179db1d7SKowalski, Kamil 413179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 414179db1d7SKowalski, Kamil 4154a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 4161abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 4171abe55efSEd Tanous { 418179db1d7SKowalski, Kamil return false; 419179db1d7SKowalski, Kamil } 420179db1d7SKowalski, Kamil 4211abe55efSEd Tanous if (bits != nullptr) 4221abe55efSEd Tanous { 423179db1d7SKowalski, Kamil *bits = 0; 424179db1d7SKowalski, Kamil } 425179db1d7SKowalski, Kamil 426179db1d7SKowalski, Kamil char *endPtr; 427179db1d7SKowalski, Kamil long previousValue = 255; 428179db1d7SKowalski, Kamil bool firstZeroInByteHit; 4291abe55efSEd Tanous for (const std::string &byte : bytesInMask) 4301abe55efSEd Tanous { 4311abe55efSEd Tanous if (byte.empty()) 4321abe55efSEd Tanous { 4331db9ca37SKowalski, Kamil return false; 4341db9ca37SKowalski, Kamil } 4351db9ca37SKowalski, Kamil 436179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 4371db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 438179db1d7SKowalski, Kamil 4394a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 4404a0cb85cSEd Tanous // is not 100% number 4411abe55efSEd Tanous if (*endPtr != '\0') 4421abe55efSEd Tanous { 443179db1d7SKowalski, Kamil return false; 444179db1d7SKowalski, Kamil } 445179db1d7SKowalski, Kamil 446179db1d7SKowalski, Kamil // Value should be contained in byte 4471abe55efSEd Tanous if (value < 0 || value > 255) 4481abe55efSEd Tanous { 449179db1d7SKowalski, Kamil return false; 450179db1d7SKowalski, Kamil } 451179db1d7SKowalski, Kamil 4521abe55efSEd Tanous if (bits != nullptr) 4531abe55efSEd Tanous { 454179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 4551abe55efSEd Tanous if (previousValue != 255 && value != 0) 4561abe55efSEd Tanous { 457179db1d7SKowalski, Kamil return false; 458179db1d7SKowalski, Kamil } 459179db1d7SKowalski, Kamil 460179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 461179db1d7SKowalski, Kamil firstZeroInByteHit = false; 462179db1d7SKowalski, Kamil 463179db1d7SKowalski, Kamil // Count bits 4641abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 4651abe55efSEd Tanous { 4661abe55efSEd Tanous if (value & (1 << bitIdx)) 4671abe55efSEd Tanous { 4681abe55efSEd Tanous if (firstZeroInByteHit) 4691abe55efSEd Tanous { 470179db1d7SKowalski, Kamil // Continuity not preserved 471179db1d7SKowalski, Kamil return false; 4721abe55efSEd Tanous } 4731abe55efSEd Tanous else 4741abe55efSEd Tanous { 475179db1d7SKowalski, Kamil (*bits)++; 476179db1d7SKowalski, Kamil } 4771abe55efSEd Tanous } 4781abe55efSEd Tanous else 4791abe55efSEd Tanous { 480179db1d7SKowalski, Kamil firstZeroInByteHit = true; 481179db1d7SKowalski, Kamil } 482179db1d7SKowalski, Kamil } 483179db1d7SKowalski, Kamil } 484179db1d7SKowalski, Kamil 485179db1d7SKowalski, Kamil previousValue = value; 486179db1d7SKowalski, Kamil } 487179db1d7SKowalski, Kamil 488179db1d7SKowalski, Kamil return true; 489179db1d7SKowalski, Kamil } 490179db1d7SKowalski, Kamil 491179db1d7SKowalski, Kamil /** 492b01bf299SEd Tanous * @brief Changes IPv4 address type property (Address, Gateway) 493b01bf299SEd Tanous * 494b01bf299SEd Tanous * @param[in] ifaceId Id of interface whose IP should be modified 495b01bf299SEd Tanous * @param[in] ipIdx Index of IP in input array that should be modified 496b01bf299SEd Tanous * @param[in] ipHash DBus Hash id of modified IP 497b01bf299SEd Tanous * @param[in] name Name of field in JSON representation 498b01bf299SEd Tanous * @param[in] newValue New value that should be written 499b01bf299SEd Tanous * @param[io] asyncResp Response object that will be returned to client 500b01bf299SEd Tanous * 501b01bf299SEd Tanous * @return true if give IP is valid and has been sent do D-Bus, false 502b01bf299SEd Tanous * otherwise 503b01bf299SEd Tanous */ 504b01bf299SEd Tanous inline void changeIPv4AddressProperty( 505b01bf299SEd Tanous const std::string &ifaceId, int ipIdx, const std::string &ipHash, 506b01bf299SEd Tanous const std::string &name, const std::string &newValue, 507b01bf299SEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 508b01bf299SEd Tanous { 509b01bf299SEd Tanous auto callback = [asyncResp, ipIdx, name{std::string(name)}, 510b01bf299SEd Tanous newValue{std::move(newValue)}]( 511b01bf299SEd Tanous const boost::system::error_code ec) { 512b01bf299SEd Tanous if (ec) 513b01bf299SEd Tanous { 514b01bf299SEd Tanous messages::internalError(asyncResp->res); 515b01bf299SEd Tanous } 516b01bf299SEd Tanous else 517b01bf299SEd Tanous { 518b01bf299SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx][name] = newValue; 519b01bf299SEd Tanous } 520b01bf299SEd Tanous }; 521b01bf299SEd Tanous 522b01bf299SEd Tanous crow::connections::systemBus->async_method_call( 523b01bf299SEd Tanous std::move(callback), "xyz.openbmc_project.Network", 524b01bf299SEd Tanous "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 525b01bf299SEd Tanous "org.freedesktop.DBus.Properties", "Set", 526b01bf299SEd Tanous "xyz.openbmc_project.Network.IP", name, 527b01bf299SEd Tanous std::variant<std::string>(newValue)); 528b01bf299SEd Tanous } 529b01bf299SEd Tanous 530b01bf299SEd Tanous /** 531179db1d7SKowalski, Kamil * @brief Changes IPv4 address origin property 532179db1d7SKowalski, Kamil * 533179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be modified 5344a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be 5351abe55efSEd Tanous * modified 536179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of modified IP 537179db1d7SKowalski, Kamil * @param[in] newValue New value in Redfish format 538179db1d7SKowalski, Kamil * @param[in] newValueDbus New value in D-Bus format 539179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 540179db1d7SKowalski, Kamil * 541179db1d7SKowalski, Kamil * @return true if give IP is valid and has been sent do D-Bus, false 542179db1d7SKowalski, Kamil * otherwise 543179db1d7SKowalski, Kamil */ 544b01bf299SEd Tanous inline void changeIPv4Origin(const std::string &ifaceId, int ipIdx, 5451abe55efSEd Tanous const std::string &ipHash, 5461abe55efSEd Tanous const std::string &newValue, 547179db1d7SKowalski, Kamil const std::string &newValueDbus, 5484a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 5491abe55efSEd Tanous { 5504a0cb85cSEd Tanous auto callback = [asyncResp, ipIdx, newValue{std::move(newValue)}]( 5511abe55efSEd Tanous const boost::system::error_code ec) { 5521abe55efSEd Tanous if (ec) 5531abe55efSEd Tanous { 554a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 5551abe55efSEd Tanous } 5561abe55efSEd Tanous else 5571abe55efSEd Tanous { 5584a0cb85cSEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["AddressOrigin"] = 559179db1d7SKowalski, Kamil newValue; 560179db1d7SKowalski, Kamil } 561179db1d7SKowalski, Kamil }; 562179db1d7SKowalski, Kamil 56355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 564179db1d7SKowalski, Kamil std::move(callback), "xyz.openbmc_project.Network", 565179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 566179db1d7SKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 567179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP", "Origin", 568abf2add6SEd Tanous std::variant<std::string>(newValueDbus)); 5694a0cb85cSEd Tanous } 570179db1d7SKowalski, Kamil 571179db1d7SKowalski, Kamil /** 572179db1d7SKowalski, Kamil * @brief Modifies SubnetMask for given IP 573179db1d7SKowalski, Kamil * 574179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be modified 5754a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be 5761abe55efSEd Tanous * modified 577179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of modified IP 578179db1d7SKowalski, Kamil * @param[in] newValueStr Mask in dot notation as string 579179db1d7SKowalski, Kamil * @param[in] newValue Mask as PrefixLength in bitcount 580179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 581179db1d7SKowalski, Kamil * 582179db1d7SKowalski, Kamil * @return None 583179db1d7SKowalski, Kamil */ 584b01bf299SEd Tanous inline void changeIPv4SubnetMaskProperty(const std::string &ifaceId, int ipIdx, 5854a0cb85cSEd Tanous const std::string &ipHash, 5864a0cb85cSEd Tanous const std::string &newValueStr, 5874a0cb85cSEd Tanous uint8_t &newValue, 5884a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 5891abe55efSEd Tanous { 5904a0cb85cSEd Tanous auto callback = [asyncResp, ipIdx, newValueStr{std::move(newValueStr)}]( 5911abe55efSEd Tanous const boost::system::error_code ec) { 5921abe55efSEd Tanous if (ec) 5931abe55efSEd Tanous { 594a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 5951abe55efSEd Tanous } 5961abe55efSEd Tanous else 5971abe55efSEd Tanous { 59855c7b7a2SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["SubnetMask"] = 599179db1d7SKowalski, Kamil newValueStr; 600179db1d7SKowalski, Kamil } 601179db1d7SKowalski, Kamil }; 602179db1d7SKowalski, Kamil 60355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 604179db1d7SKowalski, Kamil std::move(callback), "xyz.openbmc_project.Network", 605179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 606179db1d7SKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 607179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP", "PrefixLength", 608abf2add6SEd Tanous std::variant<uint8_t>(newValue)); 6094a0cb85cSEd Tanous } 610588c3f0dSKowalski, Kamil 611588c3f0dSKowalski, Kamil /** 612179db1d7SKowalski, Kamil * @brief Deletes given IPv4 613179db1d7SKowalski, Kamil * 614179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 6154a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 616179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 617179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 618179db1d7SKowalski, Kamil * 619179db1d7SKowalski, Kamil * @return None 620179db1d7SKowalski, Kamil */ 6214a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 622179db1d7SKowalski, Kamil unsigned int ipIdx, 6234a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 6241abe55efSEd Tanous { 62555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 6264a0cb85cSEd Tanous [ipIdx, asyncResp](const boost::system::error_code ec) { 6271abe55efSEd Tanous if (ec) 6281abe55efSEd Tanous { 629a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6301abe55efSEd Tanous } 6311abe55efSEd Tanous else 6321abe55efSEd Tanous { 63355c7b7a2SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx] = nullptr; 634179db1d7SKowalski, Kamil } 635179db1d7SKowalski, Kamil }, 636179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 637179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 638179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 639179db1d7SKowalski, Kamil } 640179db1d7SKowalski, Kamil 641179db1d7SKowalski, Kamil /** 642179db1d7SKowalski, Kamil * @brief Creates IPv4 with given data 643179db1d7SKowalski, Kamil * 644179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 6454a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 646179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 647179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 648179db1d7SKowalski, Kamil * 649179db1d7SKowalski, Kamil * @return None 650179db1d7SKowalski, Kamil */ 651b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 652b01bf299SEd Tanous uint8_t subnetMask, const std::string &gateway, 653b01bf299SEd Tanous const std::string &address, 6544a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6551abe55efSEd Tanous { 65643b761d0SEd Tanous auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 6571abe55efSEd Tanous if (ec) 6581abe55efSEd Tanous { 659a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 660179db1d7SKowalski, Kamil } 661179db1d7SKowalski, Kamil }; 662179db1d7SKowalski, Kamil 66355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 664179db1d7SKowalski, Kamil std::move(createIpHandler), "xyz.openbmc_project.Network", 665179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 666179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 667179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask, 668179db1d7SKowalski, Kamil gateway); 669179db1d7SKowalski, Kamil } 6702a133282Smanojkiraneda using GetAllPropertiesType = 6712a133282Smanojkiraneda boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>; 6722a133282Smanojkiraneda 6732a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) 6742a133282Smanojkiraneda { 6752a133282Smanojkiraneda auto getConfig = [asyncResp](const boost::system::error_code error_code, 6762a133282Smanojkiraneda const GetAllPropertiesType &dbus_data) { 6772a133282Smanojkiraneda if (error_code) 6782a133282Smanojkiraneda { 6792a133282Smanojkiraneda BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code; 6802a133282Smanojkiraneda messages::internalError(asyncResp->res); 6812a133282Smanojkiraneda return; 6822a133282Smanojkiraneda } 683fda13ad2SSunitha Harish nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; 6842a133282Smanojkiraneda for (const auto &property : dbus_data) 6852a133282Smanojkiraneda { 6862a133282Smanojkiraneda auto value = 6872a133282Smanojkiraneda sdbusplus::message::variant_ns::get_if<bool>(&property.second); 6882a133282Smanojkiraneda 6892a133282Smanojkiraneda if (value == nullptr) 6902a133282Smanojkiraneda { 6912a133282Smanojkiraneda continue; 6922a133282Smanojkiraneda } 6932a133282Smanojkiraneda if (property.first == "DNSEnabled") 6942a133282Smanojkiraneda { 6952a133282Smanojkiraneda DHCPConfigTypeJson["UseDNSServers"] = *value; 6962a133282Smanojkiraneda } 6972a133282Smanojkiraneda else if (property.first == "HostNameEnabled") 6982a133282Smanojkiraneda { 6992a133282Smanojkiraneda DHCPConfigTypeJson["UseDomainName"] = *value; 7002a133282Smanojkiraneda } 7012a133282Smanojkiraneda else if (property.first == "NTPEnabled") 7022a133282Smanojkiraneda { 7032a133282Smanojkiraneda DHCPConfigTypeJson["UseNTPServers"] = *value; 7042a133282Smanojkiraneda } 7052a133282Smanojkiraneda } 7062a133282Smanojkiraneda }; 7072a133282Smanojkiraneda crow::connections::systemBus->async_method_call( 7082a133282Smanojkiraneda std::move(getConfig), "xyz.openbmc_project.Network", 7092a133282Smanojkiraneda "/xyz/openbmc_project/network/config/dhcp", 7102a133282Smanojkiraneda "org.freedesktop.DBus.Properties", "GetAll", 7112a133282Smanojkiraneda "xyz.openbmc_project.Network.DHCPConfiguration"); 7122a133282Smanojkiraneda } 713179db1d7SKowalski, Kamil 714179db1d7SKowalski, Kamil /** 715179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 716179db1d7SKowalski, Kamil * Object 717179db1d7SKowalski, Kamil * from EntityManager Network Manager 7184a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 719179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 720179db1d7SKowalski, Kamil * into JSON 721179db1d7SKowalski, Kamil */ 722179db1d7SKowalski, Kamil template <typename CallbackFunc> 7234a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 7241abe55efSEd Tanous CallbackFunc &&callback) 7251abe55efSEd Tanous { 72655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7274a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 7281abe55efSEd Tanous const boost::system::error_code error_code, 7294a0cb85cSEd Tanous const GetManagedObjects &resp) { 73055c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 7314a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 732179db1d7SKowalski, Kamil 7331abe55efSEd Tanous if (error_code) 7341abe55efSEd Tanous { 73555c7b7a2SEd Tanous callback(false, ethData, ipv4Data); 736179db1d7SKowalski, Kamil return; 737179db1d7SKowalski, Kamil } 738179db1d7SKowalski, Kamil 7394a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 7404a0cb85cSEd Tanous extractIPData(ethiface_id, resp, ipv4Data); 741179db1d7SKowalski, Kamil 742179db1d7SKowalski, Kamil // Fix global GW 7431abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 7441abe55efSEd Tanous { 7454a0cb85cSEd Tanous if ((ipv4.linktype == LinkType::Global) && 7464a0cb85cSEd Tanous (ipv4.gateway == "0.0.0.0")) 7471abe55efSEd Tanous { 7484a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 749179db1d7SKowalski, Kamil } 750179db1d7SKowalski, Kamil } 751179db1d7SKowalski, Kamil 7524a0cb85cSEd Tanous // Finally make a callback with usefull data 75355c7b7a2SEd Tanous callback(true, ethData, ipv4Data); 754179db1d7SKowalski, Kamil }, 755179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 756179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 757179db1d7SKowalski, Kamil }; 758179db1d7SKowalski, Kamil 759179db1d7SKowalski, Kamil /** 7609391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 7619391bb9cSRapkiewicz, Pawel * Manager 7621abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 7631abe55efSEd Tanous * into JSON. 7649391bb9cSRapkiewicz, Pawel */ 7659391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 7661abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 7671abe55efSEd Tanous { 76855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7694a0cb85cSEd Tanous [callback{std::move(callback)}]( 7709391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 7714a0cb85cSEd Tanous GetManagedObjects &resp) { 7721abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 7731abe55efSEd Tanous // ethernet interfaces 7744a0cb85cSEd Tanous std::vector<std::string> iface_list; 7754a0cb85cSEd Tanous iface_list.reserve(resp.size()); 7761abe55efSEd Tanous if (error_code) 7771abe55efSEd Tanous { 7784a0cb85cSEd Tanous callback(false, iface_list); 7799391bb9cSRapkiewicz, Pawel return; 7809391bb9cSRapkiewicz, Pawel } 7819391bb9cSRapkiewicz, Pawel 7829391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 7834a0cb85cSEd Tanous for (const auto &objpath : resp) 7841abe55efSEd Tanous { 7859391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 7864a0cb85cSEd Tanous for (const auto &interface : objpath.second) 7871abe55efSEd Tanous { 7881abe55efSEd Tanous // If interface is 7894a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 7904a0cb85cSEd Tanous // what we're looking for. 7919391bb9cSRapkiewicz, Pawel if (interface.first == 7921abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 7931abe55efSEd Tanous { 7944a0cb85cSEd Tanous // Cut out everyting until last "/", ... 7954a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 7964a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 7974a0cb85cSEd Tanous if (last_pos != std::string::npos) 7981abe55efSEd Tanous { 7999391bb9cSRapkiewicz, Pawel // and put it into output vector. 8004a0cb85cSEd Tanous iface_list.emplace_back( 8014a0cb85cSEd Tanous iface_id.substr(last_pos + 1)); 8029391bb9cSRapkiewicz, Pawel } 8039391bb9cSRapkiewicz, Pawel } 8049391bb9cSRapkiewicz, Pawel } 8059391bb9cSRapkiewicz, Pawel } 806a434f2bdSEd Tanous // Finally make a callback with useful data 8074a0cb85cSEd Tanous callback(true, iface_list); 8089391bb9cSRapkiewicz, Pawel }, 809aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 810aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 8119391bb9cSRapkiewicz, Pawel }; 8129391bb9cSRapkiewicz, Pawel 8139391bb9cSRapkiewicz, Pawel /** 8149391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 8159391bb9cSRapkiewicz, Pawel */ 8161abe55efSEd Tanous class EthernetCollection : public Node 8171abe55efSEd Tanous { 8189391bb9cSRapkiewicz, Pawel public: 8194a0cb85cSEd Tanous template <typename CrowApp> 8201abe55efSEd Tanous EthernetCollection(CrowApp &app) : 8214a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 8221abe55efSEd Tanous { 823588c3f0dSKowalski, Kamil entityPrivileges = { 824588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 825e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 826e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 827e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 828e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 829e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 8309391bb9cSRapkiewicz, Pawel } 8319391bb9cSRapkiewicz, Pawel 8329391bb9cSRapkiewicz, Pawel private: 8339391bb9cSRapkiewicz, Pawel /** 8349391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 8359391bb9cSRapkiewicz, Pawel */ 83655c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 8371abe55efSEd Tanous const std::vector<std::string> ¶ms) override 8381abe55efSEd Tanous { 8390f74e643SEd Tanous res.jsonValue["@odata.type"] = 8400f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 8410f74e643SEd Tanous res.jsonValue["@odata.context"] = 8420f74e643SEd Tanous "/redfish/v1/" 8430f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 8440f74e643SEd Tanous res.jsonValue["@odata.id"] = 8450f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 8460f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 8470f74e643SEd Tanous res.jsonValue["Description"] = 8480f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 8490f74e643SEd Tanous 8504a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 8511abe55efSEd Tanous // preparation 852f12894f8SJason M. Bills getEthernetIfaceList( 853f12894f8SJason M. Bills [&res](const bool &success, 8541abe55efSEd Tanous const std::vector<std::string> &iface_list) { 8554a0cb85cSEd Tanous if (!success) 8561abe55efSEd Tanous { 857f12894f8SJason M. Bills messages::internalError(res); 8584a0cb85cSEd Tanous res.end(); 8594a0cb85cSEd Tanous return; 8604a0cb85cSEd Tanous } 8614a0cb85cSEd Tanous 8624a0cb85cSEd Tanous nlohmann::json &iface_array = res.jsonValue["Members"]; 8634a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 864fda13ad2SSunitha Harish std::string tag = "_"; 8654a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 8661abe55efSEd Tanous { 867fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 868fda13ad2SSunitha Harish if (found == std::string::npos) 869fda13ad2SSunitha Harish { 8704a0cb85cSEd Tanous iface_array.push_back( 8714a0cb85cSEd Tanous {{"@odata.id", 8724a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 8734a0cb85cSEd Tanous iface_item}}); 8749391bb9cSRapkiewicz, Pawel } 875fda13ad2SSunitha Harish } 8764a0cb85cSEd Tanous 8774a0cb85cSEd Tanous res.jsonValue["Members@odata.count"] = iface_array.size(); 8784a0cb85cSEd Tanous res.jsonValue["@odata.id"] = 8794a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 8809391bb9cSRapkiewicz, Pawel res.end(); 8819391bb9cSRapkiewicz, Pawel }); 8829391bb9cSRapkiewicz, Pawel } 8839391bb9cSRapkiewicz, Pawel }; 8849391bb9cSRapkiewicz, Pawel 8859391bb9cSRapkiewicz, Pawel /** 8869391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 8879391bb9cSRapkiewicz, Pawel */ 8881abe55efSEd Tanous class EthernetInterface : public Node 8891abe55efSEd Tanous { 8909391bb9cSRapkiewicz, Pawel public: 8919391bb9cSRapkiewicz, Pawel /* 8929391bb9cSRapkiewicz, Pawel * Default Constructor 8939391bb9cSRapkiewicz, Pawel */ 8944a0cb85cSEd Tanous template <typename CrowApp> 8951abe55efSEd Tanous EthernetInterface(CrowApp &app) : 8964a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 8971abe55efSEd Tanous std::string()) 8981abe55efSEd Tanous { 899588c3f0dSKowalski, Kamil entityPrivileges = { 900588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 901e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 902e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 903e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 904e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 905e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9069391bb9cSRapkiewicz, Pawel } 9079391bb9cSRapkiewicz, Pawel 908e439f0f8SKowalski, Kamil private: 909bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 9104a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 9111abe55efSEd Tanous { 912bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 913bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 914bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 9154a0cb85cSEd Tanous if (ec) 9164a0cb85cSEd Tanous { 917a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 9181abe55efSEd Tanous } 919bc0bd6e0SEd Tanous }, 920bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 921bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 922bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 923bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 924abf2add6SEd Tanous std::variant<std::string>(hostname)); 925588c3f0dSKowalski, Kamil } 926588c3f0dSKowalski, Kamil 927d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 928d577665bSRatan Gupta const std::string &macAddress, 929d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 930d577665bSRatan Gupta { 931d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 932d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 933d577665bSRatan Gupta if (ec) 934d577665bSRatan Gupta { 935d577665bSRatan Gupta messages::internalError(asyncResp->res); 936d577665bSRatan Gupta return; 937d577665bSRatan Gupta } 938d577665bSRatan Gupta asyncResp->res.jsonValue["MACAddress"] = std::move(macAddress); 939d577665bSRatan Gupta }, 940d577665bSRatan Gupta "xyz.openbmc_project.Network", 941d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 942d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 943d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 944d577665bSRatan Gupta std::variant<std::string>(macAddress)); 945d577665bSRatan Gupta } 946d577665bSRatan Gupta 9474a0cb85cSEd Tanous void handleIPv4Patch( 948f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 9494a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data, 9504a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 9511abe55efSEd Tanous { 952f476acbfSRatan Gupta if (!input.is_array()) 953f476acbfSRatan Gupta { 954f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 955f476acbfSRatan Gupta "IPv4Addresses"); 956f476acbfSRatan Gupta return; 957f476acbfSRatan Gupta } 958f476acbfSRatan Gupta 9594a0cb85cSEd Tanous int entryIdx = 0; 9604a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::const_iterator thisData = 9614a0cb85cSEd Tanous ipv4Data.begin(); 962537174c4SEd Tanous for (nlohmann::json &thisJson : input) 9631abe55efSEd Tanous { 9644a0cb85cSEd Tanous std::string pathString = 965a08b46ccSJason M. Bills "IPv4Addresses/" + std::to_string(entryIdx); 966179db1d7SKowalski, Kamil 967f476acbfSRatan Gupta if (thisJson.is_null()) 968f476acbfSRatan Gupta { 969f476acbfSRatan Gupta if (thisData != ipv4Data.end()) 970f476acbfSRatan Gupta { 971f476acbfSRatan Gupta deleteIPv4(ifaceId, thisData->id, entryIdx, asyncResp); 972f476acbfSRatan Gupta thisData++; 973f476acbfSRatan Gupta } 974f476acbfSRatan Gupta else 975f476acbfSRatan Gupta { 976f476acbfSRatan Gupta messages::propertyValueFormatError( 977f476acbfSRatan Gupta asyncResp->res, input.dump(), pathString); 978f476acbfSRatan Gupta return; 979f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 980f476acbfSRatan Gupta // list and if unable to update one of the 981f476acbfSRatan Gupta // list value then should we proceed further or 982f476acbfSRatan Gupta // break there, would ask in the redfish forum 983f476acbfSRatan Gupta // till then we stop processing the next list item. 984f476acbfSRatan Gupta } 985f476acbfSRatan Gupta entryIdx++; 986f476acbfSRatan Gupta continue; // not an error as per the redfish spec. 987f476acbfSRatan Gupta } 988f476acbfSRatan Gupta 9899474b378SRatan Gupta if (thisJson.empty()) 9909474b378SRatan Gupta { 9919474b378SRatan Gupta if (thisData != ipv4Data.end()) 9929474b378SRatan Gupta { 9939474b378SRatan Gupta thisData++; 9949474b378SRatan Gupta } 9959474b378SRatan Gupta else 9969474b378SRatan Gupta { 9979474b378SRatan Gupta messages::propertyMissing(asyncResp->res, 9989474b378SRatan Gupta pathString + "/Address"); 9999474b378SRatan Gupta return; 1000f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 10019474b378SRatan Gupta // list and if unable to update one of the 10029474b378SRatan Gupta // list value then should we proceed further or 10039474b378SRatan Gupta // break there, would ask in the redfish forum 10049474b378SRatan Gupta // till then we stop processing the next list item. 10059474b378SRatan Gupta } 10069474b378SRatan Gupta entryIdx++; 10079474b378SRatan Gupta continue; // not an error as per the redfish spec. 10089474b378SRatan Gupta } 10099474b378SRatan Gupta 1010537174c4SEd Tanous std::optional<std::string> address; 1011537174c4SEd Tanous std::optional<std::string> addressOrigin; 1012537174c4SEd Tanous std::optional<std::string> subnetMask; 1013537174c4SEd Tanous std::optional<std::string> gateway; 1014537174c4SEd Tanous 1015537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1016537174c4SEd Tanous address, "AddressOrigin", addressOrigin, 1017537174c4SEd Tanous "SubnetMask", subnetMask, "Gateway", 1018537174c4SEd Tanous gateway)) 1019537174c4SEd Tanous { 1020537174c4SEd Tanous return; 1021179db1d7SKowalski, Kamil } 1022179db1d7SKowalski, Kamil 1023537174c4SEd Tanous if (address) 10241abe55efSEd Tanous { 1025537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*address)) 10261abe55efSEd Tanous { 1027537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 10284a0cb85cSEd Tanous pathString + "/Address"); 1029537174c4SEd Tanous return; 10304a0cb85cSEd Tanous } 10314a0cb85cSEd Tanous } 10324a0cb85cSEd Tanous 1033537174c4SEd Tanous uint8_t prefixLength = 0; 1034537174c4SEd Tanous if (subnetMask) 10354a0cb85cSEd Tanous { 1036537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 10374a0cb85cSEd Tanous { 1038f12894f8SJason M. Bills messages::propertyValueFormatError( 1039537174c4SEd Tanous asyncResp->res, *subnetMask, 10404a0cb85cSEd Tanous pathString + "/SubnetMask"); 1041537174c4SEd Tanous return; 10424a0cb85cSEd Tanous } 10434a0cb85cSEd Tanous } 10444a0cb85cSEd Tanous std::string addressOriginInDBusFormat; 1045537174c4SEd Tanous if (addressOrigin) 10464a0cb85cSEd Tanous { 10474a0cb85cSEd Tanous // Get Address origin in proper format 10484a0cb85cSEd Tanous addressOriginInDBusFormat = 1049537174c4SEd Tanous translateAddressOriginRedfishToDbus(*addressOrigin); 10504a0cb85cSEd Tanous if (addressOriginInDBusFormat.empty()) 10514a0cb85cSEd Tanous { 10524a0cb85cSEd Tanous messages::propertyValueNotInList( 1053537174c4SEd Tanous asyncResp->res, *addressOrigin, 1054a08b46ccSJason M. Bills pathString + "/AddressOrigin"); 1055537174c4SEd Tanous return; 10564a0cb85cSEd Tanous } 10574a0cb85cSEd Tanous } 10584a0cb85cSEd Tanous 1059537174c4SEd Tanous if (gateway) 10604a0cb85cSEd Tanous { 1061537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*gateway)) 10624a0cb85cSEd Tanous { 1063537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1064537174c4SEd Tanous pathString + "/Gateway"); 1065537174c4SEd Tanous return; 10664a0cb85cSEd Tanous } 10674a0cb85cSEd Tanous } 10684a0cb85cSEd Tanous 1069f476acbfSRatan Gupta // if IP address exist then modify it. 10704a0cb85cSEd Tanous if (thisData != ipv4Data.end()) 10714a0cb85cSEd Tanous { 1072179db1d7SKowalski, Kamil // Apply changes 1073537174c4SEd Tanous if (address) 10741abe55efSEd Tanous { 1075f476acbfSRatan Gupta auto callback = [asyncResp, entryIdx, 1076f476acbfSRatan Gupta address{std::string(*address)}]( 10774a0cb85cSEd Tanous const boost::system::error_code ec) { 10784a0cb85cSEd Tanous if (ec) 10791abe55efSEd Tanous { 1080a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10814a0cb85cSEd Tanous return; 10824a0cb85cSEd Tanous } 1083f476acbfSRatan Gupta asyncResp->res 1084f476acbfSRatan Gupta .jsonValue["IPv4Addresses"][entryIdx]["Address"] = 1085f476acbfSRatan Gupta std::move(address); 10864a0cb85cSEd Tanous }; 10874a0cb85cSEd Tanous 10884a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 10894a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1090f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1091f476acbfSRatan Gupta thisData->id, 10924a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 10934a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Address", 1094537174c4SEd Tanous std::variant<std::string>(*address)); 1095179db1d7SKowalski, Kamil } 1096179db1d7SKowalski, Kamil 1097537174c4SEd Tanous if (subnetMask) 10981abe55efSEd Tanous { 10994a0cb85cSEd Tanous changeIPv4SubnetMaskProperty(ifaceId, entryIdx, 1100537174c4SEd Tanous thisData->id, *subnetMask, 1101537174c4SEd Tanous prefixLength, asyncResp); 1102179db1d7SKowalski, Kamil } 1103179db1d7SKowalski, Kamil 1104537174c4SEd Tanous if (addressOrigin) 11051abe55efSEd Tanous { 11064a0cb85cSEd Tanous changeIPv4Origin(ifaceId, entryIdx, thisData->id, 1107f476acbfSRatan Gupta *addressOrigin, addressOriginInDBusFormat, 1108f476acbfSRatan Gupta asyncResp); 1109179db1d7SKowalski, Kamil } 1110179db1d7SKowalski, Kamil 1111537174c4SEd Tanous if (gateway) 11121abe55efSEd Tanous { 1113f476acbfSRatan Gupta auto callback = [asyncResp, entryIdx, 1114537174c4SEd Tanous gateway{std::string(*gateway)}]( 11154a0cb85cSEd Tanous const boost::system::error_code ec) { 11164a0cb85cSEd Tanous if (ec) 11171abe55efSEd Tanous { 1118a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 11194a0cb85cSEd Tanous return; 11204a0cb85cSEd Tanous } 1121f476acbfSRatan Gupta asyncResp->res 1122f476acbfSRatan Gupta .jsonValue["IPv4Addresses"][entryIdx]["Gateway"] = 1123537174c4SEd Tanous std::move(gateway); 11244a0cb85cSEd Tanous }; 11254a0cb85cSEd Tanous 11264a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 11274a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1128f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1129f476acbfSRatan Gupta thisData->id, 11304a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 11314a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Gateway", 1132537174c4SEd Tanous std::variant<std::string>(*gateway)); 11334a0cb85cSEd Tanous } 1134f476acbfSRatan Gupta 11354a0cb85cSEd Tanous thisData++; 11361abe55efSEd Tanous } 11371abe55efSEd Tanous else 11381abe55efSEd Tanous { 11394a0cb85cSEd Tanous // Create IPv4 with provided data 1140537174c4SEd Tanous if (!gateway) 11411abe55efSEd Tanous { 1142a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 11434a0cb85cSEd Tanous pathString + "/Gateway"); 11444a0cb85cSEd Tanous continue; 11454a0cb85cSEd Tanous } 11464a0cb85cSEd Tanous 1147537174c4SEd Tanous if (!address) 11481abe55efSEd Tanous { 1149a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 11504a0cb85cSEd Tanous pathString + "/Address"); 11514a0cb85cSEd Tanous continue; 11524a0cb85cSEd Tanous } 11534a0cb85cSEd Tanous 1154537174c4SEd Tanous if (!subnetMask) 11551abe55efSEd Tanous { 1156a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 11574a0cb85cSEd Tanous pathString + "/SubnetMask"); 11584a0cb85cSEd Tanous continue; 1159588c3f0dSKowalski, Kamil } 1160588c3f0dSKowalski, Kamil 1161b01bf299SEd Tanous createIPv4(ifaceId, entryIdx, prefixLength, *gateway, *address, 1162b01bf299SEd Tanous asyncResp); 116395897b20SRatan Gupta 116495897b20SRatan Gupta nlohmann::json &ipv4AddressJson = 116595897b20SRatan Gupta asyncResp->res.jsonValue["IPv4Addresses"][entryIdx]; 116695897b20SRatan Gupta ipv4AddressJson["Address"] = *address; 116795897b20SRatan Gupta ipv4AddressJson["SubnetMask"] = *subnetMask; 116895897b20SRatan Gupta ipv4AddressJson["Gateway"] = *gateway; 11694a0cb85cSEd Tanous } 11704a0cb85cSEd Tanous entryIdx++; 11714a0cb85cSEd Tanous } 11724a0cb85cSEd Tanous } 11734a0cb85cSEd Tanous 1174f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1175f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1176f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1177f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1178f85837bfSRAJESWARAN THILLAIGOVINDAN { 1179f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1180f85837bfSRAJESWARAN THILLAIGOVINDAN [asyncResp, 1181f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers](const boost::system::error_code ec) { 1182f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1183f85837bfSRAJESWARAN THILLAIGOVINDAN { 1184f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1185f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1186f85837bfSRAJESWARAN THILLAIGOVINDAN } 1187f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp->res.jsonValue["NameServers"] = 1188f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers; 1189f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp->res.jsonValue["StaticNameServers"] = 1190f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers; 1191f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1192f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1193f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1194f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1195f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1196f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1197f85837bfSRAJESWARAN THILLAIGOVINDAN } 1198f85837bfSRAJESWARAN THILLAIGOVINDAN 11990f74e643SEd Tanous void parseInterfaceData( 12000f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 12010f74e643SEd Tanous const EthernetInterfaceData ðData, 12024a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data) 12034a0cb85cSEd Tanous { 12044a0cb85cSEd Tanous json_response["Id"] = iface_id; 12054a0cb85cSEd Tanous json_response["@odata.id"] = 12064a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1207029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1208029573d4SEd Tanous if (ethData.speed == 0) 1209029573d4SEd Tanous { 1210029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1211029573d4SEd Tanous json_response["Status"] = { 1212029573d4SEd Tanous {"Health", "OK"}, 1213029573d4SEd Tanous {"State", "Disabled"}, 1214029573d4SEd Tanous }; 1215029573d4SEd Tanous } 1216029573d4SEd Tanous else 1217029573d4SEd Tanous { 1218029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1219029573d4SEd Tanous json_response["Status"] = { 1220029573d4SEd Tanous {"Health", "OK"}, 1221029573d4SEd Tanous {"State", "Enabled"}, 1222029573d4SEd Tanous }; 1223029573d4SEd Tanous } 12244a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 12254a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1226fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 12272a133282Smanojkiraneda 12284a0cb85cSEd Tanous if (!ethData.hostname.empty()) 12294a0cb85cSEd Tanous { 12304a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 12314a0cb85cSEd Tanous } 12324a0cb85cSEd Tanous 1233fda13ad2SSunitha Harish json_response["VLANs"] = { 1234fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1235fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1236fda13ad2SSunitha Harish 1237029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 1238f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 12394a0cb85cSEd Tanous 12404a0cb85cSEd Tanous if (ipv4Data.size() > 0) 12414a0cb85cSEd Tanous { 12424a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 12434a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 12444a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 12454a0cb85cSEd Tanous { 1246fa5053a6SGunnar Mills 1247fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1248fa5053a6SGunnar Mills if (gatewayStr.empty()) 1249fa5053a6SGunnar Mills { 1250fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1251fa5053a6SGunnar Mills } 1252fa5053a6SGunnar Mills 12534a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 12544a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1255029573d4SEd Tanous {"Address", ipv4_config.address}, 1256fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 12574a0cb85cSEd Tanous } 12584a0cb85cSEd Tanous } 1259*9a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1260588c3f0dSKowalski, Kamil } 1261588c3f0dSKowalski, Kamil 12629391bb9cSRapkiewicz, Pawel /** 12639391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 12649391bb9cSRapkiewicz, Pawel */ 126555c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 12661abe55efSEd Tanous const std::vector<std::string> ¶ms) override 12671abe55efSEd Tanous { 12684a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 12691abe55efSEd Tanous if (params.size() != 1) 12701abe55efSEd Tanous { 1271f12894f8SJason M. Bills messages::internalError(asyncResp->res); 12729391bb9cSRapkiewicz, Pawel return; 12739391bb9cSRapkiewicz, Pawel } 12749391bb9cSRapkiewicz, Pawel 12754a0cb85cSEd Tanous getEthernetIfaceData( 12764a0cb85cSEd Tanous params[0], 12774a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 12784a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 12794a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data) { 12804a0cb85cSEd Tanous if (!success) 12811abe55efSEd Tanous { 12821abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 12831abe55efSEd Tanous // object, and other errors 1284f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1285f12894f8SJason M. Bills "EthernetInterface", iface_id); 12864a0cb85cSEd Tanous return; 12879391bb9cSRapkiewicz, Pawel } 12880f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1289fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 12900f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 12910f74e643SEd Tanous "/redfish/v1/$metadata#EthernetInterface.EthernetInterface"; 12920f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 12930f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 12940f74e643SEd Tanous "Management Network Interface"; 12950f74e643SEd Tanous 12960f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 12970f74e643SEd Tanous ipv4Data); 12989391bb9cSRapkiewicz, Pawel }); 12992a133282Smanojkiraneda getDHCPConfigData(asyncResp); 13009391bb9cSRapkiewicz, Pawel } 13019391bb9cSRapkiewicz, Pawel 130255c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 13031abe55efSEd Tanous const std::vector<std::string> ¶ms) override 13041abe55efSEd Tanous { 13054a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 13061abe55efSEd Tanous if (params.size() != 1) 13071abe55efSEd Tanous { 1308f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1309588c3f0dSKowalski, Kamil return; 1310588c3f0dSKowalski, Kamil } 1311588c3f0dSKowalski, Kamil 13124a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1313588c3f0dSKowalski, Kamil 1314bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1315d577665bSRatan Gupta std::optional<std::string> macAddress; 1316*9a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1317f476acbfSRatan Gupta std::optional<nlohmann::json> ipv4Addresses; 1318f476acbfSRatan Gupta std::optional<nlohmann::json> ipv6Addresses; 1319f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 13200627a2c7SEd Tanous 1321fda13ad2SSunitha Harish if (!json_util::readJson( 1322fda13ad2SSunitha Harish req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses, 1323f85837bfSRAJESWARAN THILLAIGOVINDAN "IPv6Addresses", ipv6Addresses, "MACAddress", macAddress, 1324*9a6fc6feSRavi Teja "StaticNameServers", staticNameServers, "IPv6DefaultGateway", 1325*9a6fc6feSRavi Teja ipv6DefaultGateway)) 13261abe55efSEd Tanous { 1327588c3f0dSKowalski, Kamil return; 1328588c3f0dSKowalski, Kamil } 1329f15aad37SRatan Gupta 13304a0cb85cSEd Tanous // Get single eth interface data, and call the below callback for JSON 1331588c3f0dSKowalski, Kamil // preparation 13324a0cb85cSEd Tanous getEthernetIfaceData( 13334a0cb85cSEd Tanous iface_id, 1334fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1335fda13ad2SSunitha Harish macAddress = std::move(macAddress), 13360627a2c7SEd Tanous ipv4Addresses = std::move(ipv4Addresses), 1337f85837bfSRAJESWARAN THILLAIGOVINDAN ipv6Addresses = std::move(ipv6Addresses), 1338*9a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1339f85837bfSRAJESWARAN THILLAIGOVINDAN staticNameServers = std::move(staticNameServers)]( 13404a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 13414a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data) { 13421abe55efSEd Tanous if (!success) 13431abe55efSEd Tanous { 1344588c3f0dSKowalski, Kamil // ... otherwise return error 13451abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 13461abe55efSEd Tanous // object, and other errors 1347fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1348fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1349588c3f0dSKowalski, Kamil return; 1350588c3f0dSKowalski, Kamil } 1351588c3f0dSKowalski, Kamil 13520f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 13530f74e643SEd Tanous ipv4Data); 1354588c3f0dSKowalski, Kamil 13550627a2c7SEd Tanous if (hostname) 13561abe55efSEd Tanous { 13570627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 13581abe55efSEd Tanous } 13590627a2c7SEd Tanous 1360d577665bSRatan Gupta if (macAddress) 1361d577665bSRatan Gupta { 1362d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1363d577665bSRatan Gupta } 1364d577665bSRatan Gupta 13650627a2c7SEd Tanous if (ipv4Addresses) 13661abe55efSEd Tanous { 1367537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 1368537174c4SEd Tanous // above is returning a const value, not a non-const value. 1369537174c4SEd Tanous // This doesn't really work for us, as we need to be able to 1370537174c4SEd Tanous // efficiently move out the intermedia nlohmann::json 1371537174c4SEd Tanous // objects. This makes a copy of the structure, and operates 1372537174c4SEd Tanous // on that, but could be done more efficiently 1373f476acbfSRatan Gupta nlohmann::json ipv4 = std::move(*ipv4Addresses); 1374537174c4SEd Tanous handleIPv4Patch(iface_id, ipv4, ipv4Data, asyncResp); 13751abe55efSEd Tanous } 13760627a2c7SEd Tanous 13770627a2c7SEd Tanous if (ipv6Addresses) 13781abe55efSEd Tanous { 1379179db1d7SKowalski, Kamil // TODO(kkowalsk) IPv6 Not supported on D-Bus yet 1380a08b46ccSJason M. Bills messages::propertyNotWritable(asyncResp->res, 13810627a2c7SEd Tanous "IPv6Addresses"); 1382588c3f0dSKowalski, Kamil } 1383f85837bfSRAJESWARAN THILLAIGOVINDAN 1384f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1385f85837bfSRAJESWARAN THILLAIGOVINDAN { 1386f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1387f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1388f85837bfSRAJESWARAN THILLAIGOVINDAN } 1389*9a6fc6feSRavi Teja 1390*9a6fc6feSRavi Teja if (ipv6DefaultGateway) 1391*9a6fc6feSRavi Teja { 1392*9a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 1393*9a6fc6feSRavi Teja "IPv6DefaultGateway"); 1394*9a6fc6feSRavi Teja } 1395588c3f0dSKowalski, Kamil }); 1396588c3f0dSKowalski, Kamil } 13979391bb9cSRapkiewicz, Pawel }; 13989391bb9cSRapkiewicz, Pawel 1399e439f0f8SKowalski, Kamil /** 14004a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 14014a0cb85cSEd Tanous * Schema 1402e439f0f8SKowalski, Kamil */ 14031abe55efSEd Tanous class VlanNetworkInterface : public Node 14041abe55efSEd Tanous { 1405e439f0f8SKowalski, Kamil public: 1406e439f0f8SKowalski, Kamil /* 1407e439f0f8SKowalski, Kamil * Default Constructor 1408e439f0f8SKowalski, Kamil */ 1409e439f0f8SKowalski, Kamil template <typename CrowApp> 14101abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 14114a0cb85cSEd Tanous Node(app, 14120f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 14131abe55efSEd Tanous std::string(), std::string()) 14141abe55efSEd Tanous { 1415e439f0f8SKowalski, Kamil entityPrivileges = { 1416e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1417e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1418e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1419e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1420e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1421e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1422e439f0f8SKowalski, Kamil } 1423e439f0f8SKowalski, Kamil 1424e439f0f8SKowalski, Kamil private: 14250f74e643SEd Tanous void parseInterfaceData( 14260f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 14270f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 14284a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data) 14291abe55efSEd Tanous { 1430e439f0f8SKowalski, Kamil // Fill out obvious data... 14314a0cb85cSEd Tanous json_response["Id"] = iface_id; 14324a0cb85cSEd Tanous json_response["@odata.id"] = 14334a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 14344a0cb85cSEd Tanous "/VLANs/" + iface_id; 1435e439f0f8SKowalski, Kamil 14364a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1437fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 14384a0cb85cSEd Tanous { 1439fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 14404a0cb85cSEd Tanous } 1441e439f0f8SKowalski, Kamil } 1442e439f0f8SKowalski, Kamil 1443fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 14441abe55efSEd Tanous { 14451abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 14461abe55efSEd Tanous { 1447927a505aSKowalski, Kamil return false; 14481abe55efSEd Tanous } 14491abe55efSEd Tanous else 14501abe55efSEd Tanous { 1451927a505aSKowalski, Kamil return true; 1452927a505aSKowalski, Kamil } 1453927a505aSKowalski, Kamil } 1454927a505aSKowalski, Kamil 1455e439f0f8SKowalski, Kamil /** 1456e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1457e439f0f8SKowalski, Kamil */ 145855c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 14591abe55efSEd Tanous const std::vector<std::string> ¶ms) override 14601abe55efSEd Tanous { 14614a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 14624a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1463e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1464e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1465e439f0f8SKowalski, Kamil // impossible. 14661abe55efSEd Tanous if (params.size() != 2) 14671abe55efSEd Tanous { 1468f12894f8SJason M. Bills messages::internalError(res); 1469e439f0f8SKowalski, Kamil res.end(); 1470e439f0f8SKowalski, Kamil return; 1471e439f0f8SKowalski, Kamil } 1472e439f0f8SKowalski, Kamil 14734a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 14744a0cb85cSEd Tanous const std::string &iface_id = params[1]; 14750f74e643SEd Tanous res.jsonValue["@odata.type"] = 14760f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 14770f74e643SEd Tanous res.jsonValue["@odata.context"] = 14780f74e643SEd Tanous "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface"; 14790f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1480e439f0f8SKowalski, Kamil 1481fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 14821abe55efSEd Tanous { 1483a434f2bdSEd Tanous return; 1484a434f2bdSEd Tanous } 1485a434f2bdSEd Tanous 1486e439f0f8SKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1487e439f0f8SKowalski, Kamil // preparation 14884a0cb85cSEd Tanous getEthernetIfaceData( 1489fda13ad2SSunitha Harish params[1], 1490fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1491fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 14924a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 14934a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data) { 1494fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 14951abe55efSEd Tanous { 14960f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 14970f74e643SEd Tanous parent_iface_id, iface_id, ethData, 14980f74e643SEd Tanous ipv4Data); 14991abe55efSEd Tanous } 15001abe55efSEd Tanous else 15011abe55efSEd Tanous { 1502e439f0f8SKowalski, Kamil // ... otherwise return error 15031abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 15041abe55efSEd Tanous // object, and other errors 1505f12894f8SJason M. Bills messages::resourceNotFound( 1506f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1507e439f0f8SKowalski, Kamil } 1508e439f0f8SKowalski, Kamil }); 1509e439f0f8SKowalski, Kamil } 1510e439f0f8SKowalski, Kamil 151155c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 15121abe55efSEd Tanous const std::vector<std::string> ¶ms) override 15131abe55efSEd Tanous { 15144a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 15151abe55efSEd Tanous if (params.size() != 2) 15161abe55efSEd Tanous { 1517f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1518e439f0f8SKowalski, Kamil return; 1519e439f0f8SKowalski, Kamil } 1520e439f0f8SKowalski, Kamil 1521d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 152255c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1523927a505aSKowalski, Kamil 1524fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 15251abe55efSEd Tanous { 1526fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1527fda13ad2SSunitha Harish ifaceId); 1528927a505aSKowalski, Kamil return; 1529927a505aSKowalski, Kamil } 1530927a505aSKowalski, Kamil 15310627a2c7SEd Tanous bool vlanEnable = false; 15320627a2c7SEd Tanous uint64_t vlanId = 0; 15330627a2c7SEd Tanous 15340627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 15350627a2c7SEd Tanous vlanId)) 15361abe55efSEd Tanous { 1537927a505aSKowalski, Kamil return; 1538927a505aSKowalski, Kamil } 1539927a505aSKowalski, Kamil 1540927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1541927a505aSKowalski, Kamil // preparation 154208244d02SSunitha Harish getEthernetIfaceData(params[1], [this, asyncResp, 154308244d02SSunitha Harish parentIfaceId{std::string(params[0])}, 154408244d02SSunitha Harish ifaceId{std::string(params[1])}, 154508244d02SSunitha Harish &vlanEnable, &vlanId]( 154608244d02SSunitha Harish const bool &success, 154708244d02SSunitha Harish const EthernetInterfaceData 154808244d02SSunitha Harish ðData, 154908244d02SSunitha Harish const boost::container::flat_set< 155008244d02SSunitha Harish IPv4AddressData> &ipv4Data) { 155108244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 155208244d02SSunitha Harish { 155308244d02SSunitha Harish parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId, 155408244d02SSunitha Harish ifaceId, ethData, ipv4Data); 155508244d02SSunitha Harish auto callback = 155608244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 155708244d02SSunitha Harish if (ec) 155808244d02SSunitha Harish { 155908244d02SSunitha Harish messages::internalError(asyncResp->res); 156008244d02SSunitha Harish } 156108244d02SSunitha Harish }; 156208244d02SSunitha Harish 156308244d02SSunitha Harish if (vlanEnable == true) 156408244d02SSunitha Harish { 156508244d02SSunitha Harish crow::connections::systemBus->async_method_call( 156608244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 156708244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 156808244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 156908244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 157008244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 157108244d02SSunitha Harish } 157208244d02SSunitha Harish else 157308244d02SSunitha Harish { 157408244d02SSunitha Harish BMCWEB_LOG_DEBUG 157508244d02SSunitha Harish << "vlanEnable is false. Deleting the vlan interface"; 157608244d02SSunitha Harish crow::connections::systemBus->async_method_call( 157708244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 157808244d02SSunitha Harish std::string("/xyz/openbmc_project/network/") + ifaceId, 157908244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 158008244d02SSunitha Harish } 158108244d02SSunitha Harish } 158208244d02SSunitha Harish else 15831abe55efSEd Tanous { 15841abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 15851abe55efSEd Tanous // object, and other errors 158608244d02SSunitha Harish messages::resourceNotFound(asyncResp->res, 158708244d02SSunitha Harish "VLAN Network Interface", ifaceId); 1588927a505aSKowalski, Kamil return; 1589927a505aSKowalski, Kamil } 1590927a505aSKowalski, Kamil }); 1591e439f0f8SKowalski, Kamil } 1592e439f0f8SKowalski, Kamil 159355c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 15941abe55efSEd Tanous const std::vector<std::string> ¶ms) override 15951abe55efSEd Tanous { 15964a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 15971abe55efSEd Tanous if (params.size() != 2) 15981abe55efSEd Tanous { 1599f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1600e439f0f8SKowalski, Kamil return; 1601e439f0f8SKowalski, Kamil } 1602e439f0f8SKowalski, Kamil 1603d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 160455c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 1605927a505aSKowalski, Kamil 1606fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 16071abe55efSEd Tanous { 1608fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 1609fda13ad2SSunitha Harish ifaceId); 1610927a505aSKowalski, Kamil return; 1611927a505aSKowalski, Kamil } 1612927a505aSKowalski, Kamil 1613927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1614927a505aSKowalski, Kamil // preparation 1615f12894f8SJason M. Bills getEthernetIfaceData( 1616fda13ad2SSunitha Harish params[1], 1617fda13ad2SSunitha Harish [this, asyncResp, parentIfaceId{std::string(params[0])}, 1618fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 1619f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 1620f12894f8SJason M. Bills const boost::container::flat_set<IPv4AddressData> &ipv4Data) { 1621fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 16221abe55efSEd Tanous { 16230f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId, 16240f74e643SEd Tanous ifaceId, ethData, ipv4Data); 1625927a505aSKowalski, Kamil 1626f12894f8SJason M. Bills auto callback = 1627f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 16281abe55efSEd Tanous if (ec) 16291abe55efSEd Tanous { 1630f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1631927a505aSKowalski, Kamil } 16324a0cb85cSEd Tanous }; 16334a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 16344a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 16354a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 16364a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 16371abe55efSEd Tanous } 16381abe55efSEd Tanous else 16391abe55efSEd Tanous { 1640927a505aSKowalski, Kamil // ... otherwise return error 1641f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 1642f12894f8SJason M. Bills // object, and other errors 1643f12894f8SJason M. Bills messages::resourceNotFound( 1644f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 1645927a505aSKowalski, Kamil } 1646927a505aSKowalski, Kamil }); 1647e439f0f8SKowalski, Kamil } 1648e439f0f8SKowalski, Kamil }; 1649e439f0f8SKowalski, Kamil 1650e439f0f8SKowalski, Kamil /** 1651e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 1652e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 1653e439f0f8SKowalski, Kamil */ 16541abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 16551abe55efSEd Tanous { 1656e439f0f8SKowalski, Kamil public: 1657e439f0f8SKowalski, Kamil template <typename CrowApp> 16581abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 16594a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 16604a0cb85cSEd Tanous std::string()) 16611abe55efSEd Tanous { 1662e439f0f8SKowalski, Kamil entityPrivileges = { 1663e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1664e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1665e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1666e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1667e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1668e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1669e439f0f8SKowalski, Kamil } 1670e439f0f8SKowalski, Kamil 1671e439f0f8SKowalski, Kamil private: 1672e439f0f8SKowalski, Kamil /** 1673e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1674e439f0f8SKowalski, Kamil */ 167555c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 16761abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16771abe55efSEd Tanous { 16784a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16791abe55efSEd Tanous if (params.size() != 1) 16801abe55efSEd Tanous { 1681e439f0f8SKowalski, Kamil // This means there is a problem with the router 1682f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1683e439f0f8SKowalski, Kamil return; 1684e439f0f8SKowalski, Kamil } 1685e439f0f8SKowalski, Kamil 16864a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 1687e439f0f8SKowalski, Kamil 16884a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 16891abe55efSEd Tanous // preparation 1690f12894f8SJason M. Bills getEthernetIfaceList( 169143b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 16921abe55efSEd Tanous const bool &success, 16931abe55efSEd Tanous const std::vector<std::string> &iface_list) { 16944a0cb85cSEd Tanous if (!success) 16951abe55efSEd Tanous { 1696f12894f8SJason M. Bills messages::internalError(asyncResp->res); 16974a0cb85cSEd Tanous return; 16981abe55efSEd Tanous } 16990f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 17000f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 17010f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 17020f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 17030f74e643SEd Tanous "/redfish/v1/$metadata" 17040f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 17050f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 17060f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 17070f74e643SEd Tanous "VLAN Network Interface Collection"; 17084a0cb85cSEd Tanous 17094a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 17104a0cb85cSEd Tanous 17114a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 17121abe55efSEd Tanous { 17134a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 17144a0cb85cSEd Tanous { 17154a0cb85cSEd Tanous iface_array.push_back( 17164a0cb85cSEd Tanous {{"@odata.id", 17174a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 17184a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 1719e439f0f8SKowalski, Kamil } 1720e439f0f8SKowalski, Kamil } 1721e439f0f8SKowalski, Kamil 17224a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 17234a0cb85cSEd Tanous iface_array.size(); 17244a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 17254a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 17264a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 17274a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 1728e439f0f8SKowalski, Kamil }); 1729e439f0f8SKowalski, Kamil } 1730e439f0f8SKowalski, Kamil 173155c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 17321abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17331abe55efSEd Tanous { 17344a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17351abe55efSEd Tanous if (params.size() != 1) 17361abe55efSEd Tanous { 1737f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1738e439f0f8SKowalski, Kamil return; 1739e439f0f8SKowalski, Kamil } 1740fda13ad2SSunitha Harish bool vlanEnable = false; 17410627a2c7SEd Tanous uint32_t vlanId = 0; 1742fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 1743fda13ad2SSunitha Harish vlanEnable)) 17441abe55efSEd Tanous { 17454a0cb85cSEd Tanous return; 1746e439f0f8SKowalski, Kamil } 1747fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 1748fda13ad2SSunitha Harish if (!vlanId) 1749fda13ad2SSunitha Harish { 1750fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 1751fda13ad2SSunitha Harish } 1752fda13ad2SSunitha Harish if (!vlanEnable) 1753fda13ad2SSunitha Harish { 1754fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 1755fda13ad2SSunitha Harish } 1756fda13ad2SSunitha Harish if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) 1757fda13ad2SSunitha Harish { 1758fda13ad2SSunitha Harish return; 1759fda13ad2SSunitha Harish } 1760fda13ad2SSunitha Harish 17614a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 17624a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 17631abe55efSEd Tanous if (ec) 17641abe55efSEd Tanous { 17654a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 17664a0cb85cSEd Tanous // phosphor-network responses 1767f12894f8SJason M. Bills messages::internalError(asyncResp->res); 17684a0cb85cSEd Tanous return; 17691abe55efSEd Tanous } 1770f12894f8SJason M. Bills messages::created(asyncResp->res); 1771e439f0f8SKowalski, Kamil }; 17724a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 17734a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 17744a0cb85cSEd Tanous "/xyz/openbmc_project/network", 17754a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 17760627a2c7SEd Tanous rootInterfaceName, vlanId); 17774a0cb85cSEd Tanous } 17784a0cb85cSEd Tanous }; 17799391bb9cSRapkiewicz, Pawel } // namespace redfish 1780