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 1544a0cb85cSEd Tanous inline std::string 1554a0cb85cSEd Tanous translateAddressOriginRedfishToDbus(const std::string &inputOrigin) 1564a0cb85cSEd Tanous { 1574a0cb85cSEd Tanous if (inputOrigin == "Static") 1584a0cb85cSEd Tanous { 1594a0cb85cSEd Tanous return "xyz.openbmc_project.Network.IP.AddressOrigin.Static"; 1604a0cb85cSEd Tanous } 1614a0cb85cSEd Tanous if (inputOrigin == "DHCP" || inputOrigin == "DHCPv6") 1624a0cb85cSEd Tanous { 1634a0cb85cSEd Tanous return "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP"; 1644a0cb85cSEd Tanous } 1654a0cb85cSEd Tanous if (inputOrigin == "IPv4LinkLocal" || inputOrigin == "LinkLocal") 1664a0cb85cSEd Tanous { 1674a0cb85cSEd Tanous return "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal"; 1684a0cb85cSEd Tanous } 1694a0cb85cSEd Tanous if (inputOrigin == "SLAAC") 1704a0cb85cSEd Tanous { 1714a0cb85cSEd Tanous return "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC"; 1724a0cb85cSEd Tanous } 1734a0cb85cSEd Tanous return ""; 1744a0cb85cSEd Tanous } 1754a0cb85cSEd Tanous 1764c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string ðiface_id, 1774a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 1784a0cb85cSEd Tanous EthernetInterfaceData ðData) 1794a0cb85cSEd Tanous { 1804c9afe43SEd Tanous bool idFound = false; 1814a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 1824a0cb85cSEd Tanous { 1834a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 1844a0cb85cSEd Tanous { 185029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 186029573d4SEd Tanous { 1874c9afe43SEd Tanous idFound = true; 1884a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 1894a0cb85cSEd Tanous { 1904a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 1914a0cb85cSEd Tanous { 1924a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 1934a0cb85cSEd Tanous { 1944a0cb85cSEd Tanous const std::string *mac = 195abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 1964a0cb85cSEd Tanous if (mac != nullptr) 1974a0cb85cSEd Tanous { 1984a0cb85cSEd Tanous ethData.mac_address = *mac; 1994a0cb85cSEd Tanous } 2004a0cb85cSEd Tanous } 2014a0cb85cSEd Tanous } 2024a0cb85cSEd Tanous } 2034a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2044a0cb85cSEd Tanous { 2054a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2064a0cb85cSEd Tanous { 2074a0cb85cSEd Tanous if (propertyPair.first == "Id") 2084a0cb85cSEd Tanous { 2091b6b96c5SEd Tanous const uint32_t *id = 210abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2114a0cb85cSEd Tanous if (id != nullptr) 2124a0cb85cSEd Tanous { 213fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 2144a0cb85cSEd Tanous } 2154a0cb85cSEd Tanous } 2164a0cb85cSEd Tanous } 2174a0cb85cSEd Tanous } 2184a0cb85cSEd Tanous else if (ifacePair.first == 2194a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2204a0cb85cSEd Tanous { 2214a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2224a0cb85cSEd Tanous { 2234a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2244a0cb85cSEd Tanous { 2254a0cb85cSEd Tanous const bool *auto_neg = 226abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2274a0cb85cSEd Tanous if (auto_neg != nullptr) 2284a0cb85cSEd Tanous { 2294a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2304a0cb85cSEd Tanous } 2314a0cb85cSEd Tanous } 2324a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2334a0cb85cSEd Tanous { 2344a0cb85cSEd Tanous const uint32_t *speed = 235abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2364a0cb85cSEd Tanous if (speed != nullptr) 2374a0cb85cSEd Tanous { 2384a0cb85cSEd Tanous ethData.speed = *speed; 2394a0cb85cSEd Tanous } 2404a0cb85cSEd Tanous } 241f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 242029573d4SEd Tanous { 243029573d4SEd Tanous const std::vector<std::string> *nameservers = 244029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 245029573d4SEd Tanous std::vector<std::string>>( 246029573d4SEd Tanous &propertyPair.second); 247029573d4SEd Tanous if (nameservers != nullptr) 248029573d4SEd Tanous { 249029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2504a0cb85cSEd Tanous } 2514a0cb85cSEd Tanous } 2522a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 2532a133282Smanojkiraneda { 2542a133282Smanojkiraneda const bool *DHCPEnabled = 2552a133282Smanojkiraneda std::get_if<bool>(&propertyPair.second); 2562a133282Smanojkiraneda if (DHCPEnabled != nullptr) 2572a133282Smanojkiraneda { 2582a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 2592a133282Smanojkiraneda } 2602a133282Smanojkiraneda } 261029573d4SEd Tanous } 262029573d4SEd Tanous } 263029573d4SEd Tanous } 264029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 265029573d4SEd Tanous // to check eth number 266029573d4SEd Tanous if (ifacePair.first == 2674a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 2684a0cb85cSEd Tanous { 2694a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2704a0cb85cSEd Tanous { 2714a0cb85cSEd Tanous if (propertyPair.first == "HostName") 2724a0cb85cSEd Tanous { 2734a0cb85cSEd Tanous const std::string *hostname = 274029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 275029573d4SEd Tanous &propertyPair.second); 2764a0cb85cSEd Tanous if (hostname != nullptr) 2774a0cb85cSEd Tanous { 2784a0cb85cSEd Tanous ethData.hostname = *hostname; 2794a0cb85cSEd Tanous } 2804a0cb85cSEd Tanous } 2814a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 2824a0cb85cSEd Tanous { 2834a0cb85cSEd Tanous const std::string *defaultGateway = 284029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 285029573d4SEd Tanous &propertyPair.second); 2864a0cb85cSEd Tanous if (defaultGateway != nullptr) 2874a0cb85cSEd Tanous { 2884a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 2894a0cb85cSEd Tanous } 2904a0cb85cSEd Tanous } 2919a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 2929a6fc6feSRavi Teja { 2939a6fc6feSRavi Teja const std::string *defaultGateway6 = 2949a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 2959a6fc6feSRavi Teja &propertyPair.second); 2969a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 2979a6fc6feSRavi Teja { 2989a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 2999a6fc6feSRavi Teja } 3009a6fc6feSRavi Teja } 3014a0cb85cSEd Tanous } 3024a0cb85cSEd Tanous } 3034a0cb85cSEd Tanous } 3044a0cb85cSEd Tanous } 3054c9afe43SEd Tanous return idFound; 3064a0cb85cSEd Tanous } 3074a0cb85cSEd Tanous 308e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 309e48c0fc5SRavi Teja inline void extractIPV6Data( 310e48c0fc5SRavi Teja const std::string ðiface_id, const GetManagedObjects &dbus_data, 311e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> &ipv6_config, 312e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> &ipv6_static_config) 313e48c0fc5SRavi Teja { 314e48c0fc5SRavi Teja const std::string ipv6PathStart = 315e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/"; 316e48c0fc5SRavi Teja 317e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 318e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 319e48c0fc5SRavi Teja for (const auto &objpath : dbus_data) 320e48c0fc5SRavi Teja { 321e48c0fc5SRavi Teja // Check if proper pattern for object path appears 322e48c0fc5SRavi Teja if (boost::starts_with(objpath.first.str, ipv6PathStart)) 323e48c0fc5SRavi Teja { 324e48c0fc5SRavi Teja for (auto &interface : objpath.second) 325e48c0fc5SRavi Teja { 326e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 327e48c0fc5SRavi Teja { 328e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 329e48c0fc5SRavi Teja // appropriate 330e48c0fc5SRavi Teja std::pair< 331e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::iterator, 332e48c0fc5SRavi Teja bool> 333e48c0fc5SRavi Teja it = ipv6_config.insert( 334e48c0fc5SRavi Teja {objpath.first.str.substr(ipv6PathStart.size())}); 335e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 336e48c0fc5SRavi Teja for (auto &property : interface.second) 337e48c0fc5SRavi Teja { 338e48c0fc5SRavi Teja if (property.first == "Address") 339e48c0fc5SRavi Teja { 340e48c0fc5SRavi Teja const std::string *address = 341e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 342e48c0fc5SRavi Teja if (address != nullptr) 343e48c0fc5SRavi Teja { 344e48c0fc5SRavi Teja ipv6_address.address = *address; 345e48c0fc5SRavi Teja } 346e48c0fc5SRavi Teja } 347e48c0fc5SRavi Teja else if (property.first == "Origin") 348e48c0fc5SRavi Teja { 349e48c0fc5SRavi Teja const std::string *origin = 350e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 351e48c0fc5SRavi Teja if (origin != nullptr) 352e48c0fc5SRavi Teja { 353e48c0fc5SRavi Teja ipv6_address.origin = 354e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 355e48c0fc5SRavi Teja false); 356e48c0fc5SRavi Teja } 357e48c0fc5SRavi Teja } 358e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 359e48c0fc5SRavi Teja { 360e48c0fc5SRavi Teja const uint8_t *prefix = 361e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 362e48c0fc5SRavi Teja if (prefix != nullptr) 363e48c0fc5SRavi Teja { 364e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 365e48c0fc5SRavi Teja } 366e48c0fc5SRavi Teja } 367e48c0fc5SRavi Teja else 368e48c0fc5SRavi Teja { 369e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 370e48c0fc5SRavi Teja << "Got extra property: " << property.first 371e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 372e48c0fc5SRavi Teja } 373e48c0fc5SRavi Teja } 374e48c0fc5SRavi Teja if (ipv6_address.origin == "Static") 375e48c0fc5SRavi Teja { 376e48c0fc5SRavi Teja std::pair<boost::container::flat_set< 377e48c0fc5SRavi Teja IPv6AddressData>::iterator, 378e48c0fc5SRavi Teja bool> 379e48c0fc5SRavi Teja iter = ipv6_static_config.insert( 380e48c0fc5SRavi Teja {objpath.first.str.substr( 381e48c0fc5SRavi Teja ipv6PathStart.size())}); 382e48c0fc5SRavi Teja IPv6AddressData &ipv6_static_address = *iter.first; 383e48c0fc5SRavi Teja 384e48c0fc5SRavi Teja ipv6_static_address.address = ipv6_address.address; 385e48c0fc5SRavi Teja ipv6_static_address.prefixLength = 386e48c0fc5SRavi Teja ipv6_address.prefixLength; 387e48c0fc5SRavi Teja } 388e48c0fc5SRavi Teja } 389e48c0fc5SRavi Teja } 390e48c0fc5SRavi Teja } 391e48c0fc5SRavi Teja } 392e48c0fc5SRavi Teja } 393e48c0fc5SRavi Teja 3944a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 3954a0cb85cSEd Tanous inline void 3964a0cb85cSEd Tanous extractIPData(const std::string ðiface_id, 3974a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 3984a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> &ipv4_config) 3994a0cb85cSEd Tanous { 4004a0cb85cSEd Tanous const std::string ipv4PathStart = 4014a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 4024a0cb85cSEd Tanous 4034a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 4044a0cb85cSEd Tanous // single ethernet interface, loop over all of them 4054a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 4064a0cb85cSEd Tanous { 4074a0cb85cSEd Tanous // Check if proper pattern for object path appears 4084a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 4094a0cb85cSEd Tanous { 4104a0cb85cSEd Tanous for (auto &interface : objpath.second) 4114a0cb85cSEd Tanous { 4124a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 4134a0cb85cSEd Tanous { 4144a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 4154a0cb85cSEd Tanous // appropriate 4164a0cb85cSEd Tanous std::pair< 4174a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 4184a0cb85cSEd Tanous bool> 4194a0cb85cSEd Tanous it = ipv4_config.insert( 420b01bf299SEd Tanous {objpath.first.str.substr(ipv4PathStart.size())}); 4214a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 4224a0cb85cSEd Tanous for (auto &property : interface.second) 4234a0cb85cSEd Tanous { 4244a0cb85cSEd Tanous if (property.first == "Address") 4254a0cb85cSEd Tanous { 4264a0cb85cSEd Tanous const std::string *address = 427abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4284a0cb85cSEd Tanous if (address != nullptr) 4294a0cb85cSEd Tanous { 4304a0cb85cSEd Tanous ipv4_address.address = *address; 4314a0cb85cSEd Tanous } 4324a0cb85cSEd Tanous } 4334a0cb85cSEd Tanous else if (property.first == "Gateway") 4344a0cb85cSEd Tanous { 4354a0cb85cSEd Tanous const std::string *gateway = 436abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4374a0cb85cSEd Tanous if (gateway != nullptr) 4384a0cb85cSEd Tanous { 4394a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 4404a0cb85cSEd Tanous } 4414a0cb85cSEd Tanous } 4424a0cb85cSEd Tanous else if (property.first == "Origin") 4434a0cb85cSEd Tanous { 4444a0cb85cSEd Tanous const std::string *origin = 445abf2add6SEd Tanous std::get_if<std::string>(&property.second); 4464a0cb85cSEd Tanous if (origin != nullptr) 4474a0cb85cSEd Tanous { 4484a0cb85cSEd Tanous ipv4_address.origin = 4494a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 4504a0cb85cSEd Tanous true); 4514a0cb85cSEd Tanous } 4524a0cb85cSEd Tanous } 4534a0cb85cSEd Tanous else if (property.first == "PrefixLength") 4544a0cb85cSEd Tanous { 4554a0cb85cSEd Tanous const uint8_t *mask = 456abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 4574a0cb85cSEd Tanous if (mask != nullptr) 4584a0cb85cSEd Tanous { 4594a0cb85cSEd Tanous // convert it to the string 4604a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 4614a0cb85cSEd Tanous } 4624a0cb85cSEd Tanous } 4634a0cb85cSEd Tanous else 4644a0cb85cSEd Tanous { 4654a0cb85cSEd Tanous BMCWEB_LOG_ERROR 4664a0cb85cSEd Tanous << "Got extra property: " << property.first 4674a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 4684a0cb85cSEd Tanous } 4694a0cb85cSEd Tanous } 4704a0cb85cSEd Tanous // Check if given address is local, or global 4714a0cb85cSEd Tanous ipv4_address.linktype = 4724a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 473*18659d10SJohnathan Mantey ? LinkType::Local 474*18659d10SJohnathan Mantey : LinkType::Global; 4754a0cb85cSEd Tanous } 4764a0cb85cSEd Tanous } 4774a0cb85cSEd Tanous } 4784a0cb85cSEd Tanous } 4794a0cb85cSEd Tanous } 480588c3f0dSKowalski, Kamil 481588c3f0dSKowalski, Kamil /** 482588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 483588c3f0dSKowalski, Kamil * 484588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 485588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 486588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 487588c3f0dSKowalski, Kamil * 488588c3f0dSKowalski, Kamil * @return None. 489588c3f0dSKowalski, Kamil */ 490588c3f0dSKowalski, Kamil template <typename CallbackFunc> 4914a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 4921abe55efSEd Tanous CallbackFunc &&callback) 4931abe55efSEd Tanous { 49455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 495588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 496588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 497588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 498588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 499abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 5004a0cb85cSEd Tanous } 501588c3f0dSKowalski, Kamil 502588c3f0dSKowalski, Kamil /** 503179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 504179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 505179db1d7SKowalski, Kamil * bit count for Subnet Mask. 506179db1d7SKowalski, Kamil * 507179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 508179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 509179db1d7SKowalski, Kamil * 510179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 511179db1d7SKowalski, Kamil */ 5124a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 5131abe55efSEd Tanous uint8_t *bits = nullptr) 5141abe55efSEd Tanous { 515179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 516179db1d7SKowalski, Kamil 517179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 518179db1d7SKowalski, Kamil 5194a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 5201abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 5211abe55efSEd Tanous { 522179db1d7SKowalski, Kamil return false; 523179db1d7SKowalski, Kamil } 524179db1d7SKowalski, Kamil 5251abe55efSEd Tanous if (bits != nullptr) 5261abe55efSEd Tanous { 527179db1d7SKowalski, Kamil *bits = 0; 528179db1d7SKowalski, Kamil } 529179db1d7SKowalski, Kamil 530179db1d7SKowalski, Kamil char *endPtr; 531179db1d7SKowalski, Kamil long previousValue = 255; 532179db1d7SKowalski, Kamil bool firstZeroInByteHit; 5331abe55efSEd Tanous for (const std::string &byte : bytesInMask) 5341abe55efSEd Tanous { 5351abe55efSEd Tanous if (byte.empty()) 5361abe55efSEd Tanous { 5371db9ca37SKowalski, Kamil return false; 5381db9ca37SKowalski, Kamil } 5391db9ca37SKowalski, Kamil 540179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 5411db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 542179db1d7SKowalski, Kamil 5434a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 5444a0cb85cSEd Tanous // is not 100% number 5451abe55efSEd Tanous if (*endPtr != '\0') 5461abe55efSEd Tanous { 547179db1d7SKowalski, Kamil return false; 548179db1d7SKowalski, Kamil } 549179db1d7SKowalski, Kamil 550179db1d7SKowalski, Kamil // Value should be contained in byte 5511abe55efSEd Tanous if (value < 0 || value > 255) 5521abe55efSEd Tanous { 553179db1d7SKowalski, Kamil return false; 554179db1d7SKowalski, Kamil } 555179db1d7SKowalski, Kamil 5561abe55efSEd Tanous if (bits != nullptr) 5571abe55efSEd Tanous { 558179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 5591abe55efSEd Tanous if (previousValue != 255 && value != 0) 5601abe55efSEd Tanous { 561179db1d7SKowalski, Kamil return false; 562179db1d7SKowalski, Kamil } 563179db1d7SKowalski, Kamil 564179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 565179db1d7SKowalski, Kamil firstZeroInByteHit = false; 566179db1d7SKowalski, Kamil 567179db1d7SKowalski, Kamil // Count bits 5681abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 5691abe55efSEd Tanous { 5701abe55efSEd Tanous if (value & (1 << bitIdx)) 5711abe55efSEd Tanous { 5721abe55efSEd Tanous if (firstZeroInByteHit) 5731abe55efSEd Tanous { 574179db1d7SKowalski, Kamil // Continuity not preserved 575179db1d7SKowalski, Kamil return false; 5761abe55efSEd Tanous } 5771abe55efSEd Tanous else 5781abe55efSEd Tanous { 579179db1d7SKowalski, Kamil (*bits)++; 580179db1d7SKowalski, Kamil } 5811abe55efSEd Tanous } 5821abe55efSEd Tanous else 5831abe55efSEd Tanous { 584179db1d7SKowalski, Kamil firstZeroInByteHit = true; 585179db1d7SKowalski, Kamil } 586179db1d7SKowalski, Kamil } 587179db1d7SKowalski, Kamil } 588179db1d7SKowalski, Kamil 589179db1d7SKowalski, Kamil previousValue = value; 590179db1d7SKowalski, Kamil } 591179db1d7SKowalski, Kamil 592179db1d7SKowalski, Kamil return true; 593179db1d7SKowalski, Kamil } 594179db1d7SKowalski, Kamil 595179db1d7SKowalski, Kamil /** 596b01bf299SEd Tanous * @brief Changes IPv4 address type property (Address, Gateway) 597b01bf299SEd Tanous * 598b01bf299SEd Tanous * @param[in] ifaceId Id of interface whose IP should be modified 599b01bf299SEd Tanous * @param[in] ipIdx Index of IP in input array that should be modified 600b01bf299SEd Tanous * @param[in] ipHash DBus Hash id of modified IP 601b01bf299SEd Tanous * @param[in] name Name of field in JSON representation 602b01bf299SEd Tanous * @param[in] newValue New value that should be written 603b01bf299SEd Tanous * @param[io] asyncResp Response object that will be returned to client 604b01bf299SEd Tanous * 605b01bf299SEd Tanous * @return true if give IP is valid and has been sent do D-Bus, false 606b01bf299SEd Tanous * otherwise 607b01bf299SEd Tanous */ 608b01bf299SEd Tanous inline void changeIPv4AddressProperty( 609b01bf299SEd Tanous const std::string &ifaceId, int ipIdx, const std::string &ipHash, 610b01bf299SEd Tanous const std::string &name, const std::string &newValue, 611b01bf299SEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 612b01bf299SEd Tanous { 613b01bf299SEd Tanous auto callback = [asyncResp, ipIdx, name{std::string(name)}, 614b01bf299SEd Tanous newValue{std::move(newValue)}]( 615b01bf299SEd Tanous const boost::system::error_code ec) { 616b01bf299SEd Tanous if (ec) 617b01bf299SEd Tanous { 618b01bf299SEd Tanous messages::internalError(asyncResp->res); 619b01bf299SEd Tanous } 620b01bf299SEd Tanous else 621b01bf299SEd Tanous { 622b01bf299SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx][name] = newValue; 623b01bf299SEd Tanous } 624b01bf299SEd Tanous }; 625b01bf299SEd Tanous 626b01bf299SEd Tanous crow::connections::systemBus->async_method_call( 627b01bf299SEd Tanous std::move(callback), "xyz.openbmc_project.Network", 628b01bf299SEd Tanous "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 629b01bf299SEd Tanous "org.freedesktop.DBus.Properties", "Set", 630b01bf299SEd Tanous "xyz.openbmc_project.Network.IP", name, 631b01bf299SEd Tanous std::variant<std::string>(newValue)); 632b01bf299SEd Tanous } 633b01bf299SEd Tanous 634b01bf299SEd Tanous /** 635179db1d7SKowalski, Kamil * @brief Changes IPv4 address origin property 636179db1d7SKowalski, Kamil * 637179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be modified 6384a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be 6391abe55efSEd Tanous * modified 640179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of modified IP 641179db1d7SKowalski, Kamil * @param[in] newValue New value in Redfish format 642179db1d7SKowalski, Kamil * @param[in] newValueDbus New value in D-Bus format 643179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 644179db1d7SKowalski, Kamil * 645179db1d7SKowalski, Kamil * @return true if give IP is valid and has been sent do D-Bus, false 646179db1d7SKowalski, Kamil * otherwise 647179db1d7SKowalski, Kamil */ 648b01bf299SEd Tanous inline void changeIPv4Origin(const std::string &ifaceId, int ipIdx, 6491abe55efSEd Tanous const std::string &ipHash, 6501abe55efSEd Tanous const std::string &newValue, 651179db1d7SKowalski, Kamil const std::string &newValueDbus, 6524a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 6531abe55efSEd Tanous { 6544a0cb85cSEd Tanous auto callback = [asyncResp, ipIdx, newValue{std::move(newValue)}]( 6551abe55efSEd Tanous const boost::system::error_code ec) { 6561abe55efSEd Tanous if (ec) 6571abe55efSEd Tanous { 658a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6591abe55efSEd Tanous } 6601abe55efSEd Tanous else 6611abe55efSEd Tanous { 6624a0cb85cSEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["AddressOrigin"] = 663179db1d7SKowalski, Kamil newValue; 664179db1d7SKowalski, Kamil } 665179db1d7SKowalski, Kamil }; 666179db1d7SKowalski, Kamil 66755c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 668179db1d7SKowalski, Kamil std::move(callback), "xyz.openbmc_project.Network", 669179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 670179db1d7SKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 671179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP", "Origin", 672abf2add6SEd Tanous std::variant<std::string>(newValueDbus)); 6734a0cb85cSEd Tanous } 674179db1d7SKowalski, Kamil 675179db1d7SKowalski, Kamil /** 676179db1d7SKowalski, Kamil * @brief Modifies SubnetMask for given IP 677179db1d7SKowalski, Kamil * 678179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be modified 6794a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be 6801abe55efSEd Tanous * modified 681179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of modified IP 682179db1d7SKowalski, Kamil * @param[in] newValueStr Mask in dot notation as string 683179db1d7SKowalski, Kamil * @param[in] newValue Mask as PrefixLength in bitcount 684179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 685179db1d7SKowalski, Kamil * 686179db1d7SKowalski, Kamil * @return None 687179db1d7SKowalski, Kamil */ 688b01bf299SEd Tanous inline void changeIPv4SubnetMaskProperty(const std::string &ifaceId, int ipIdx, 6894a0cb85cSEd Tanous const std::string &ipHash, 6904a0cb85cSEd Tanous const std::string &newValueStr, 6914a0cb85cSEd Tanous uint8_t &newValue, 6924a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 6931abe55efSEd Tanous { 6944a0cb85cSEd Tanous auto callback = [asyncResp, ipIdx, newValueStr{std::move(newValueStr)}]( 6951abe55efSEd Tanous const boost::system::error_code ec) { 6961abe55efSEd Tanous if (ec) 6971abe55efSEd Tanous { 698a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6991abe55efSEd Tanous } 7001abe55efSEd Tanous else 7011abe55efSEd Tanous { 70255c7b7a2SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["SubnetMask"] = 703179db1d7SKowalski, Kamil newValueStr; 704179db1d7SKowalski, Kamil } 705179db1d7SKowalski, Kamil }; 706179db1d7SKowalski, Kamil 70755c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 708179db1d7SKowalski, Kamil std::move(callback), "xyz.openbmc_project.Network", 709179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 710179db1d7SKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 711179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP", "PrefixLength", 712abf2add6SEd Tanous std::variant<uint8_t>(newValue)); 7134a0cb85cSEd Tanous } 714588c3f0dSKowalski, Kamil 715588c3f0dSKowalski, Kamil /** 716179db1d7SKowalski, Kamil * @brief Deletes given IPv4 717179db1d7SKowalski, Kamil * 718179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 7194a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 720179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 721179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 722179db1d7SKowalski, Kamil * 723179db1d7SKowalski, Kamil * @return None 724179db1d7SKowalski, Kamil */ 7254a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 726179db1d7SKowalski, Kamil unsigned int ipIdx, 7274a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 7281abe55efSEd Tanous { 72955c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 7304a0cb85cSEd Tanous [ipIdx, asyncResp](const boost::system::error_code ec) { 7311abe55efSEd Tanous if (ec) 7321abe55efSEd Tanous { 733a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7341abe55efSEd Tanous } 7351abe55efSEd Tanous else 7361abe55efSEd Tanous { 73755c7b7a2SEd Tanous asyncResp->res.jsonValue["IPv4Addresses"][ipIdx] = nullptr; 738179db1d7SKowalski, Kamil } 739179db1d7SKowalski, Kamil }, 740179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 741179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 742179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 743179db1d7SKowalski, Kamil } 744179db1d7SKowalski, Kamil 745179db1d7SKowalski, Kamil /** 746179db1d7SKowalski, Kamil * @brief Creates IPv4 with given data 747179db1d7SKowalski, Kamil * 748179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 7494a0cb85cSEd Tanous * @param[in] ipIdx Index of IP in input array that should be deleted 750179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 751179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 752179db1d7SKowalski, Kamil * 753179db1d7SKowalski, Kamil * @return None 754179db1d7SKowalski, Kamil */ 755b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 756b01bf299SEd Tanous uint8_t subnetMask, const std::string &gateway, 757b01bf299SEd Tanous const std::string &address, 7584a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 7591abe55efSEd Tanous { 76043b761d0SEd Tanous auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 7611abe55efSEd Tanous if (ec) 7621abe55efSEd Tanous { 763a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 764179db1d7SKowalski, Kamil } 765179db1d7SKowalski, Kamil }; 766179db1d7SKowalski, Kamil 76755c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 768179db1d7SKowalski, Kamil std::move(createIpHandler), "xyz.openbmc_project.Network", 769179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 770179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 771179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask, 772179db1d7SKowalski, Kamil gateway); 773179db1d7SKowalski, Kamil } 774e48c0fc5SRavi Teja 775e48c0fc5SRavi Teja /** 776e48c0fc5SRavi Teja * @brief Deletes given IPv6 777e48c0fc5SRavi Teja * 778e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 779e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 780e48c0fc5SRavi Teja * @param[in] ipIdx Index of IP in input array that should be deleted 781e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 782e48c0fc5SRavi Teja * 783e48c0fc5SRavi Teja * @return None 784e48c0fc5SRavi Teja */ 785e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 786e48c0fc5SRavi Teja unsigned int ipIdx, 787e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 788e48c0fc5SRavi Teja { 789e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 790e48c0fc5SRavi Teja [ipIdx, asyncResp](const boost::system::error_code ec) { 791e48c0fc5SRavi Teja if (ec) 792e48c0fc5SRavi Teja { 793e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 794e48c0fc5SRavi Teja } 795e48c0fc5SRavi Teja else 796e48c0fc5SRavi Teja { 797e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"][ipIdx] = 798e48c0fc5SRavi Teja nullptr; 799e48c0fc5SRavi Teja } 800e48c0fc5SRavi Teja }, 801e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 802e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 803e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 804e48c0fc5SRavi Teja } 805e48c0fc5SRavi Teja 806e48c0fc5SRavi Teja /** 807e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 808e48c0fc5SRavi Teja * 809e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 810e48c0fc5SRavi Teja * @param[in] ipIdx Index of IP in input array that should be added 811e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 812e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 813e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 814e48c0fc5SRavi Teja * 815e48c0fc5SRavi Teja * @return None 816e48c0fc5SRavi Teja */ 817e48c0fc5SRavi Teja inline void createIPv6(const std::string &ifaceId, unsigned int ipIdx, 818e48c0fc5SRavi Teja uint8_t prefixLength, const std::string &address, 819e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 820e48c0fc5SRavi Teja { 821e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 822e48c0fc5SRavi Teja if (ec) 823e48c0fc5SRavi Teja { 824e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 825e48c0fc5SRavi Teja } 826e48c0fc5SRavi Teja }; 827e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 828e48c0fc5SRavi Teja // does not have assosiated gateway property 829e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 830e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 831e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 832e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 833e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 834e48c0fc5SRavi Teja ""); 835e48c0fc5SRavi Teja } 836e48c0fc5SRavi Teja 8372a133282Smanojkiraneda using GetAllPropertiesType = 8382a133282Smanojkiraneda boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>; 8392a133282Smanojkiraneda 8402a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp) 8412a133282Smanojkiraneda { 8422a133282Smanojkiraneda auto getConfig = [asyncResp](const boost::system::error_code error_code, 8432a133282Smanojkiraneda const GetAllPropertiesType &dbus_data) { 8442a133282Smanojkiraneda if (error_code) 8452a133282Smanojkiraneda { 8462a133282Smanojkiraneda BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code; 8472a133282Smanojkiraneda messages::internalError(asyncResp->res); 8482a133282Smanojkiraneda return; 8492a133282Smanojkiraneda } 850fda13ad2SSunitha Harish nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"]; 8512a133282Smanojkiraneda for (const auto &property : dbus_data) 8522a133282Smanojkiraneda { 8532a133282Smanojkiraneda auto value = 8542a133282Smanojkiraneda sdbusplus::message::variant_ns::get_if<bool>(&property.second); 8552a133282Smanojkiraneda 8562a133282Smanojkiraneda if (value == nullptr) 8572a133282Smanojkiraneda { 8582a133282Smanojkiraneda continue; 8592a133282Smanojkiraneda } 8602a133282Smanojkiraneda if (property.first == "DNSEnabled") 8612a133282Smanojkiraneda { 8622a133282Smanojkiraneda DHCPConfigTypeJson["UseDNSServers"] = *value; 8632a133282Smanojkiraneda } 8642a133282Smanojkiraneda else if (property.first == "HostNameEnabled") 8652a133282Smanojkiraneda { 8662a133282Smanojkiraneda DHCPConfigTypeJson["UseDomainName"] = *value; 8672a133282Smanojkiraneda } 8682a133282Smanojkiraneda else if (property.first == "NTPEnabled") 8692a133282Smanojkiraneda { 8702a133282Smanojkiraneda DHCPConfigTypeJson["UseNTPServers"] = *value; 8712a133282Smanojkiraneda } 8722a133282Smanojkiraneda } 8732a133282Smanojkiraneda }; 8742a133282Smanojkiraneda crow::connections::systemBus->async_method_call( 8752a133282Smanojkiraneda std::move(getConfig), "xyz.openbmc_project.Network", 8762a133282Smanojkiraneda "/xyz/openbmc_project/network/config/dhcp", 8772a133282Smanojkiraneda "org.freedesktop.DBus.Properties", "GetAll", 8782a133282Smanojkiraneda "xyz.openbmc_project.Network.DHCPConfiguration"); 8792a133282Smanojkiraneda } 880179db1d7SKowalski, Kamil 881179db1d7SKowalski, Kamil /** 882179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 883179db1d7SKowalski, Kamil * Object 884179db1d7SKowalski, Kamil * from EntityManager Network Manager 8854a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 886179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 887179db1d7SKowalski, Kamil * into JSON 888179db1d7SKowalski, Kamil */ 889179db1d7SKowalski, Kamil template <typename CallbackFunc> 8904a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8911abe55efSEd Tanous CallbackFunc &&callback) 8921abe55efSEd Tanous { 89355c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8944a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8951abe55efSEd Tanous const boost::system::error_code error_code, 8964a0cb85cSEd Tanous const GetManagedObjects &resp) { 89755c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8984a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 899e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 900e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6StaticData; 901179db1d7SKowalski, Kamil 9021abe55efSEd Tanous if (error_code) 9031abe55efSEd Tanous { 904e48c0fc5SRavi Teja callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData); 905179db1d7SKowalski, Kamil return; 906179db1d7SKowalski, Kamil } 907179db1d7SKowalski, Kamil 9084c9afe43SEd Tanous bool found = 9094a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 9104c9afe43SEd Tanous if (!found) 9114c9afe43SEd Tanous { 912e48c0fc5SRavi Teja callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData); 9134c9afe43SEd Tanous return; 9144c9afe43SEd Tanous } 9154c9afe43SEd Tanous 9164a0cb85cSEd Tanous extractIPData(ethiface_id, resp, ipv4Data); 917179db1d7SKowalski, Kamil // Fix global GW 9181abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 9191abe55efSEd Tanous { 9204a0cb85cSEd Tanous if ((ipv4.linktype == LinkType::Global) && 9214a0cb85cSEd Tanous (ipv4.gateway == "0.0.0.0")) 9221abe55efSEd Tanous { 9234a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 924179db1d7SKowalski, Kamil } 925179db1d7SKowalski, Kamil } 926179db1d7SKowalski, Kamil 927e48c0fc5SRavi Teja extractIPV6Data(ethiface_id, resp, ipv6Data, ipv6StaticData); 9284a0cb85cSEd Tanous // Finally make a callback with usefull data 929e48c0fc5SRavi Teja callback(true, ethData, ipv4Data, ipv6Data, ipv6StaticData); 930179db1d7SKowalski, Kamil }, 931179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 932179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 933179db1d7SKowalski, Kamil }; 934179db1d7SKowalski, Kamil 935179db1d7SKowalski, Kamil /** 9369391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 9379391bb9cSRapkiewicz, Pawel * Manager 9381abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 9391abe55efSEd Tanous * into JSON. 9409391bb9cSRapkiewicz, Pawel */ 9419391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 9421abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 9431abe55efSEd Tanous { 94455c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 9454a0cb85cSEd Tanous [callback{std::move(callback)}]( 9469391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 9474a0cb85cSEd Tanous GetManagedObjects &resp) { 9481abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 9491abe55efSEd Tanous // ethernet interfaces 9504c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 9514a0cb85cSEd Tanous iface_list.reserve(resp.size()); 9521abe55efSEd Tanous if (error_code) 9531abe55efSEd Tanous { 9544a0cb85cSEd Tanous callback(false, iface_list); 9559391bb9cSRapkiewicz, Pawel return; 9569391bb9cSRapkiewicz, Pawel } 9579391bb9cSRapkiewicz, Pawel 9589391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 9594a0cb85cSEd Tanous for (const auto &objpath : resp) 9601abe55efSEd Tanous { 9619391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 9624a0cb85cSEd Tanous for (const auto &interface : objpath.second) 9631abe55efSEd Tanous { 9641abe55efSEd Tanous // If interface is 9654a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9664a0cb85cSEd Tanous // what we're looking for. 9679391bb9cSRapkiewicz, Pawel if (interface.first == 9681abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9691abe55efSEd Tanous { 9704a0cb85cSEd Tanous // Cut out everyting until last "/", ... 9714a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9724a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9734a0cb85cSEd Tanous if (last_pos != std::string::npos) 9741abe55efSEd Tanous { 9759391bb9cSRapkiewicz, Pawel // and put it into output vector. 9764c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9779391bb9cSRapkiewicz, Pawel } 9789391bb9cSRapkiewicz, Pawel } 9799391bb9cSRapkiewicz, Pawel } 9809391bb9cSRapkiewicz, Pawel } 981a434f2bdSEd Tanous // Finally make a callback with useful data 9824a0cb85cSEd Tanous callback(true, iface_list); 9839391bb9cSRapkiewicz, Pawel }, 984aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 985aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 9869391bb9cSRapkiewicz, Pawel }; 9879391bb9cSRapkiewicz, Pawel 9889391bb9cSRapkiewicz, Pawel /** 9899391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9909391bb9cSRapkiewicz, Pawel */ 9911abe55efSEd Tanous class EthernetCollection : public Node 9921abe55efSEd Tanous { 9939391bb9cSRapkiewicz, Pawel public: 9944a0cb85cSEd Tanous template <typename CrowApp> 9951abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9964a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9971abe55efSEd Tanous { 998588c3f0dSKowalski, Kamil entityPrivileges = { 999588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1000e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1001e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1002e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1003e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1004e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10059391bb9cSRapkiewicz, Pawel } 10069391bb9cSRapkiewicz, Pawel 10079391bb9cSRapkiewicz, Pawel private: 10089391bb9cSRapkiewicz, Pawel /** 10099391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 10109391bb9cSRapkiewicz, Pawel */ 101155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 10121abe55efSEd Tanous const std::vector<std::string> ¶ms) override 10131abe55efSEd Tanous { 10140f74e643SEd Tanous res.jsonValue["@odata.type"] = 10150f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 10160f74e643SEd Tanous res.jsonValue["@odata.context"] = 10170f74e643SEd Tanous "/redfish/v1/" 10180f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 10190f74e643SEd Tanous res.jsonValue["@odata.id"] = 10200f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 10210f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 10220f74e643SEd Tanous res.jsonValue["Description"] = 10230f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 10244c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 10254a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 10261abe55efSEd Tanous // preparation 1027f12894f8SJason M. Bills getEthernetIfaceList( 10284c9afe43SEd Tanous [asyncResp]( 10294c9afe43SEd Tanous const bool &success, 10304c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 10314a0cb85cSEd Tanous if (!success) 10321abe55efSEd Tanous { 10334c9afe43SEd Tanous messages::internalError(asyncResp->res); 10344a0cb85cSEd Tanous return; 10354a0cb85cSEd Tanous } 10364a0cb85cSEd Tanous 10374c9afe43SEd Tanous nlohmann::json &iface_array = 10384c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 10394a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 1040fda13ad2SSunitha Harish std::string tag = "_"; 10414a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 10421abe55efSEd Tanous { 1043fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 1044fda13ad2SSunitha Harish if (found == std::string::npos) 1045fda13ad2SSunitha Harish { 10464a0cb85cSEd Tanous iface_array.push_back( 10474a0cb85cSEd Tanous {{"@odata.id", 10484a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 10494a0cb85cSEd Tanous iface_item}}); 10509391bb9cSRapkiewicz, Pawel } 1051fda13ad2SSunitha Harish } 10524a0cb85cSEd Tanous 10534c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 10544c9afe43SEd Tanous iface_array.size(); 10554c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10564a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 10579391bb9cSRapkiewicz, Pawel }); 10589391bb9cSRapkiewicz, Pawel } 10599391bb9cSRapkiewicz, Pawel }; 10609391bb9cSRapkiewicz, Pawel 10619391bb9cSRapkiewicz, Pawel /** 10629391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 10639391bb9cSRapkiewicz, Pawel */ 10641abe55efSEd Tanous class EthernetInterface : public Node 10651abe55efSEd Tanous { 10669391bb9cSRapkiewicz, Pawel public: 10679391bb9cSRapkiewicz, Pawel /* 10689391bb9cSRapkiewicz, Pawel * Default Constructor 10699391bb9cSRapkiewicz, Pawel */ 10704a0cb85cSEd Tanous template <typename CrowApp> 10711abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10724a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10731abe55efSEd Tanous std::string()) 10741abe55efSEd Tanous { 1075588c3f0dSKowalski, Kamil entityPrivileges = { 1076588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1077e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1078e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1079e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1080e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1081e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10829391bb9cSRapkiewicz, Pawel } 10839391bb9cSRapkiewicz, Pawel 1084e439f0f8SKowalski, Kamil private: 1085bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10864a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10871abe55efSEd Tanous { 1088bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1089bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1090bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10914a0cb85cSEd Tanous if (ec) 10924a0cb85cSEd Tanous { 1093a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10941abe55efSEd Tanous } 1095bc0bd6e0SEd Tanous }, 1096bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1097bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1098bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1099bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1100abf2add6SEd Tanous std::variant<std::string>(hostname)); 1101588c3f0dSKowalski, Kamil } 1102588c3f0dSKowalski, Kamil 1103d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1104d577665bSRatan Gupta const std::string &macAddress, 1105d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1106d577665bSRatan Gupta { 1107d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1108d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1109d577665bSRatan Gupta if (ec) 1110d577665bSRatan Gupta { 1111d577665bSRatan Gupta messages::internalError(asyncResp->res); 1112d577665bSRatan Gupta return; 1113d577665bSRatan Gupta } 1114d577665bSRatan Gupta asyncResp->res.jsonValue["MACAddress"] = std::move(macAddress); 1115d577665bSRatan Gupta }, 1116d577665bSRatan Gupta "xyz.openbmc_project.Network", 1117d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1118d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1119d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1120d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1121d577665bSRatan Gupta } 1122da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 1123da131a9aSJennifer Lee const std::string &propertyName, const bool &value, 1124da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1125da131a9aSJennifer Lee { 1126da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1127da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1128da131a9aSJennifer Lee if (ec) 1129da131a9aSJennifer Lee { 1130da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1131da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1132da131a9aSJennifer Lee return; 1133da131a9aSJennifer Lee } 1134da131a9aSJennifer Lee }, 1135da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1136da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1137da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1138da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1139da131a9aSJennifer Lee std::variant<bool>{value}); 1140da131a9aSJennifer Lee } 1141da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1142da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1143da131a9aSJennifer Lee { 1144da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1145da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1146da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1147da131a9aSJennifer Lee if (ec) 1148da131a9aSJennifer Lee { 1149da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1150da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1151da131a9aSJennifer Lee return; 1152da131a9aSJennifer Lee } 1153da131a9aSJennifer Lee }, 1154da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1155da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1156da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1157da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1158da131a9aSJennifer Lee std::variant<bool>{value}); 1159da131a9aSJennifer Lee } 1160d577665bSRatan Gupta 1161da131a9aSJennifer Lee void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input, 1162da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1163da131a9aSJennifer Lee { 1164da131a9aSJennifer Lee std::optional<bool> dhcpEnabled; 1165da131a9aSJennifer Lee std::optional<bool> useDNSServers; 1166da131a9aSJennifer Lee std::optional<bool> useDomainName; 1167da131a9aSJennifer Lee std::optional<bool> useNTPServers; 1168da131a9aSJennifer Lee 1169da131a9aSJennifer Lee if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled", 1170da131a9aSJennifer Lee dhcpEnabled, "UseDNSServers", useDNSServers, 1171da131a9aSJennifer Lee "UseDomainName", useDomainName, 1172da131a9aSJennifer Lee "UseNTPServers", useNTPServers)) 1173da131a9aSJennifer Lee { 1174da131a9aSJennifer Lee return; 1175da131a9aSJennifer Lee } 1176da131a9aSJennifer Lee 1177da131a9aSJennifer Lee if (dhcpEnabled) 1178da131a9aSJennifer Lee { 1179da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 1180da131a9aSJennifer Lee setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp); 1181da131a9aSJennifer Lee } 1182da131a9aSJennifer Lee 1183da131a9aSJennifer Lee if (useDNSServers) 1184da131a9aSJennifer Lee { 1185da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 1186da131a9aSJennifer Lee setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp); 1187da131a9aSJennifer Lee } 1188da131a9aSJennifer Lee 1189da131a9aSJennifer Lee if (useDomainName) 1190da131a9aSJennifer Lee { 1191da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 1192da131a9aSJennifer Lee setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp); 1193da131a9aSJennifer Lee } 1194da131a9aSJennifer Lee 1195da131a9aSJennifer Lee if (useNTPServers) 1196da131a9aSJennifer Lee { 1197da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 1198da131a9aSJennifer Lee setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp); 1199da131a9aSJennifer Lee } 1200da131a9aSJennifer Lee } 12014a0cb85cSEd Tanous void handleIPv4Patch( 1202f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 12034a0cb85cSEd Tanous const boost::container::flat_set<IPv4AddressData> &ipv4Data, 12044a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 12051abe55efSEd Tanous { 1206f476acbfSRatan Gupta if (!input.is_array()) 1207f476acbfSRatan Gupta { 1208f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1209f476acbfSRatan Gupta "IPv4Addresses"); 1210f476acbfSRatan Gupta return; 1211f476acbfSRatan Gupta } 1212f476acbfSRatan Gupta 12134a0cb85cSEd Tanous int entryIdx = 0; 12144a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::const_iterator thisData = 12154a0cb85cSEd Tanous ipv4Data.begin(); 1216537174c4SEd Tanous for (nlohmann::json &thisJson : input) 12171abe55efSEd Tanous { 12184a0cb85cSEd Tanous std::string pathString = 1219a08b46ccSJason M. Bills "IPv4Addresses/" + std::to_string(entryIdx); 1220179db1d7SKowalski, Kamil 1221f476acbfSRatan Gupta if (thisJson.is_null()) 1222f476acbfSRatan Gupta { 1223f476acbfSRatan Gupta if (thisData != ipv4Data.end()) 1224f476acbfSRatan Gupta { 1225f476acbfSRatan Gupta deleteIPv4(ifaceId, thisData->id, entryIdx, asyncResp); 1226f476acbfSRatan Gupta thisData++; 1227f476acbfSRatan Gupta } 1228f476acbfSRatan Gupta else 1229f476acbfSRatan Gupta { 1230f476acbfSRatan Gupta messages::propertyValueFormatError( 1231f476acbfSRatan Gupta asyncResp->res, input.dump(), pathString); 1232f476acbfSRatan Gupta return; 1233f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 1234f476acbfSRatan Gupta // list and if unable to update one of the 1235f476acbfSRatan Gupta // list value then should we proceed further or 1236f476acbfSRatan Gupta // break there, would ask in the redfish forum 1237f476acbfSRatan Gupta // till then we stop processing the next list item. 1238f476acbfSRatan Gupta } 1239f476acbfSRatan Gupta entryIdx++; 1240f476acbfSRatan Gupta continue; // not an error as per the redfish spec. 1241f476acbfSRatan Gupta } 1242f476acbfSRatan Gupta 12439474b378SRatan Gupta if (thisJson.empty()) 12449474b378SRatan Gupta { 12459474b378SRatan Gupta if (thisData != ipv4Data.end()) 12469474b378SRatan Gupta { 12479474b378SRatan Gupta thisData++; 12489474b378SRatan Gupta } 12499474b378SRatan Gupta else 12509474b378SRatan Gupta { 12519474b378SRatan Gupta messages::propertyMissing(asyncResp->res, 12529474b378SRatan Gupta pathString + "/Address"); 12539474b378SRatan Gupta return; 1254f476acbfSRatan Gupta // TODO(ratagupt) Not sure about the property where value is 12559474b378SRatan Gupta // list and if unable to update one of the 12569474b378SRatan Gupta // list value then should we proceed further or 12579474b378SRatan Gupta // break there, would ask in the redfish forum 12589474b378SRatan Gupta // till then we stop processing the next list item. 12599474b378SRatan Gupta } 12609474b378SRatan Gupta entryIdx++; 12619474b378SRatan Gupta continue; // not an error as per the redfish spec. 12629474b378SRatan Gupta } 12639474b378SRatan Gupta 1264537174c4SEd Tanous std::optional<std::string> address; 1265537174c4SEd Tanous std::optional<std::string> addressOrigin; 1266537174c4SEd Tanous std::optional<std::string> subnetMask; 1267537174c4SEd Tanous std::optional<std::string> gateway; 1268537174c4SEd Tanous 1269537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1270537174c4SEd Tanous address, "AddressOrigin", addressOrigin, 1271537174c4SEd Tanous "SubnetMask", subnetMask, "Gateway", 1272537174c4SEd Tanous gateway)) 1273537174c4SEd Tanous { 1274537174c4SEd Tanous return; 1275179db1d7SKowalski, Kamil } 1276179db1d7SKowalski, Kamil 1277537174c4SEd Tanous if (address) 12781abe55efSEd Tanous { 1279537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*address)) 12801abe55efSEd Tanous { 1281537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *address, 12824a0cb85cSEd Tanous pathString + "/Address"); 1283537174c4SEd Tanous return; 12844a0cb85cSEd Tanous } 12854a0cb85cSEd Tanous } 12864a0cb85cSEd Tanous 1287537174c4SEd Tanous uint8_t prefixLength = 0; 1288537174c4SEd Tanous if (subnetMask) 12894a0cb85cSEd Tanous { 1290537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 12914a0cb85cSEd Tanous { 1292f12894f8SJason M. Bills messages::propertyValueFormatError( 1293537174c4SEd Tanous asyncResp->res, *subnetMask, 12944a0cb85cSEd Tanous pathString + "/SubnetMask"); 1295537174c4SEd Tanous return; 12964a0cb85cSEd Tanous } 12974a0cb85cSEd Tanous } 12984a0cb85cSEd Tanous std::string addressOriginInDBusFormat; 1299537174c4SEd Tanous if (addressOrigin) 13004a0cb85cSEd Tanous { 13014a0cb85cSEd Tanous // Get Address origin in proper format 13024a0cb85cSEd Tanous addressOriginInDBusFormat = 1303537174c4SEd Tanous translateAddressOriginRedfishToDbus(*addressOrigin); 13044a0cb85cSEd Tanous if (addressOriginInDBusFormat.empty()) 13054a0cb85cSEd Tanous { 13064a0cb85cSEd Tanous messages::propertyValueNotInList( 1307537174c4SEd Tanous asyncResp->res, *addressOrigin, 1308a08b46ccSJason M. Bills pathString + "/AddressOrigin"); 1309537174c4SEd Tanous return; 13104a0cb85cSEd Tanous } 13114a0cb85cSEd Tanous } 13124a0cb85cSEd Tanous 1313537174c4SEd Tanous if (gateway) 13144a0cb85cSEd Tanous { 1315537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*gateway)) 13164a0cb85cSEd Tanous { 1317537174c4SEd Tanous messages::propertyValueFormatError(asyncResp->res, *gateway, 1318537174c4SEd Tanous pathString + "/Gateway"); 1319537174c4SEd Tanous return; 13204a0cb85cSEd Tanous } 13214a0cb85cSEd Tanous } 13224a0cb85cSEd Tanous 1323f476acbfSRatan Gupta // if IP address exist then modify it. 13244a0cb85cSEd Tanous if (thisData != ipv4Data.end()) 13254a0cb85cSEd Tanous { 1326179db1d7SKowalski, Kamil // Apply changes 1327537174c4SEd Tanous if (address) 13281abe55efSEd Tanous { 1329f476acbfSRatan Gupta auto callback = [asyncResp, entryIdx, 1330f476acbfSRatan Gupta address{std::string(*address)}]( 13314a0cb85cSEd Tanous const boost::system::error_code ec) { 13324a0cb85cSEd Tanous if (ec) 13331abe55efSEd Tanous { 1334a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 13354a0cb85cSEd Tanous return; 13364a0cb85cSEd Tanous } 1337f476acbfSRatan Gupta asyncResp->res 1338f476acbfSRatan Gupta .jsonValue["IPv4Addresses"][entryIdx]["Address"] = 1339f476acbfSRatan Gupta std::move(address); 13404a0cb85cSEd Tanous }; 13414a0cb85cSEd Tanous 13424a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 13434a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1344f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1345f476acbfSRatan Gupta thisData->id, 13464a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 13474a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Address", 1348537174c4SEd Tanous std::variant<std::string>(*address)); 1349179db1d7SKowalski, Kamil } 1350179db1d7SKowalski, Kamil 1351537174c4SEd Tanous if (subnetMask) 13521abe55efSEd Tanous { 13534a0cb85cSEd Tanous changeIPv4SubnetMaskProperty(ifaceId, entryIdx, 1354537174c4SEd Tanous thisData->id, *subnetMask, 1355537174c4SEd Tanous prefixLength, asyncResp); 1356179db1d7SKowalski, Kamil } 1357179db1d7SKowalski, Kamil 1358537174c4SEd Tanous if (addressOrigin) 13591abe55efSEd Tanous { 13604a0cb85cSEd Tanous changeIPv4Origin(ifaceId, entryIdx, thisData->id, 1361f476acbfSRatan Gupta *addressOrigin, addressOriginInDBusFormat, 1362f476acbfSRatan Gupta asyncResp); 1363179db1d7SKowalski, Kamil } 1364179db1d7SKowalski, Kamil 1365537174c4SEd Tanous if (gateway) 13661abe55efSEd Tanous { 1367f476acbfSRatan Gupta auto callback = [asyncResp, entryIdx, 1368537174c4SEd Tanous gateway{std::string(*gateway)}]( 13694a0cb85cSEd Tanous const boost::system::error_code ec) { 13704a0cb85cSEd Tanous if (ec) 13711abe55efSEd Tanous { 1372a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 13734a0cb85cSEd Tanous return; 13744a0cb85cSEd Tanous } 1375f476acbfSRatan Gupta asyncResp->res 1376f476acbfSRatan Gupta .jsonValue["IPv4Addresses"][entryIdx]["Gateway"] = 1377537174c4SEd Tanous std::move(gateway); 13784a0cb85cSEd Tanous }; 13794a0cb85cSEd Tanous 13804a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 13814a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 1382f476acbfSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + 1383f476acbfSRatan Gupta thisData->id, 13844a0cb85cSEd Tanous "org.freedesktop.DBus.Properties", "Set", 13854a0cb85cSEd Tanous "xyz.openbmc_project.Network.IP", "Gateway", 1386537174c4SEd Tanous std::variant<std::string>(*gateway)); 13874a0cb85cSEd Tanous } 1388f476acbfSRatan Gupta 13894a0cb85cSEd Tanous thisData++; 13901abe55efSEd Tanous } 13911abe55efSEd Tanous else 13921abe55efSEd Tanous { 13934a0cb85cSEd Tanous // Create IPv4 with provided data 1394537174c4SEd Tanous if (!gateway) 13951abe55efSEd Tanous { 1396a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 13974a0cb85cSEd Tanous pathString + "/Gateway"); 13984a0cb85cSEd Tanous continue; 13994a0cb85cSEd Tanous } 14004a0cb85cSEd Tanous 1401537174c4SEd Tanous if (!address) 14021abe55efSEd Tanous { 1403a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 14044a0cb85cSEd Tanous pathString + "/Address"); 14054a0cb85cSEd Tanous continue; 14064a0cb85cSEd Tanous } 14074a0cb85cSEd Tanous 1408537174c4SEd Tanous if (!subnetMask) 14091abe55efSEd Tanous { 1410a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 14114a0cb85cSEd Tanous pathString + "/SubnetMask"); 14124a0cb85cSEd Tanous continue; 1413588c3f0dSKowalski, Kamil } 1414588c3f0dSKowalski, Kamil 1415b01bf299SEd Tanous createIPv4(ifaceId, entryIdx, prefixLength, *gateway, *address, 1416b01bf299SEd Tanous asyncResp); 141795897b20SRatan Gupta 141895897b20SRatan Gupta nlohmann::json &ipv4AddressJson = 141995897b20SRatan Gupta asyncResp->res.jsonValue["IPv4Addresses"][entryIdx]; 142095897b20SRatan Gupta ipv4AddressJson["Address"] = *address; 142195897b20SRatan Gupta ipv4AddressJson["SubnetMask"] = *subnetMask; 142295897b20SRatan Gupta ipv4AddressJson["Gateway"] = *gateway; 14234a0cb85cSEd Tanous } 14244a0cb85cSEd Tanous entryIdx++; 14254a0cb85cSEd Tanous } 14264a0cb85cSEd Tanous } 14274a0cb85cSEd Tanous 1428f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1429f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1430f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1431f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1432f85837bfSRAJESWARAN THILLAIGOVINDAN { 1433f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1434f85837bfSRAJESWARAN THILLAIGOVINDAN [asyncResp, 1435f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers](const boost::system::error_code ec) { 1436f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1437f85837bfSRAJESWARAN THILLAIGOVINDAN { 1438f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1439f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1440f85837bfSRAJESWARAN THILLAIGOVINDAN } 1441f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp->res.jsonValue["NameServers"] = 1442f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers; 1443f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp->res.jsonValue["StaticNameServers"] = 1444f85837bfSRAJESWARAN THILLAIGOVINDAN updatedStaticNameServers; 1445f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1446f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1447f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1448f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1449f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1450f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1451f85837bfSRAJESWARAN THILLAIGOVINDAN } 1452f85837bfSRAJESWARAN THILLAIGOVINDAN 1453e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1454e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 1455e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData, 1456e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1457e48c0fc5SRavi Teja { 1458e48c0fc5SRavi Teja if (!input.is_array()) 1459e48c0fc5SRavi Teja { 1460e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1461e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1462e48c0fc5SRavi Teja return; 1463e48c0fc5SRavi Teja } 1464e48c0fc5SRavi Teja 1465e48c0fc5SRavi Teja int entryIdx = 0; 1466e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::const_iterator thisData = 1467e48c0fc5SRavi Teja ipv6StaticData.begin(); 1468e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1469e48c0fc5SRavi Teja { 1470e48c0fc5SRavi Teja std::string pathString = 1471e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1472e48c0fc5SRavi Teja 1473e48c0fc5SRavi Teja if (thisJson.is_null()) 1474e48c0fc5SRavi Teja { 1475e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1476e48c0fc5SRavi Teja { 1477e48c0fc5SRavi Teja deleteIPv6(ifaceId, thisData->id, entryIdx, asyncResp); 1478e48c0fc5SRavi Teja thisData++; 1479e48c0fc5SRavi Teja } 1480e48c0fc5SRavi Teja else 1481e48c0fc5SRavi Teja { 1482e48c0fc5SRavi Teja messages::propertyValueFormatError( 1483e48c0fc5SRavi Teja asyncResp->res, input.dump(), pathString); 1484e48c0fc5SRavi Teja return; 1485e48c0fc5SRavi Teja } 1486e48c0fc5SRavi Teja entryIdx++; 1487e48c0fc5SRavi Teja continue; 1488e48c0fc5SRavi Teja } 1489e48c0fc5SRavi Teja 1490e48c0fc5SRavi Teja if (thisJson.empty()) 1491e48c0fc5SRavi Teja { 1492e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1493e48c0fc5SRavi Teja { 1494e48c0fc5SRavi Teja thisData++; 1495e48c0fc5SRavi Teja } 1496e48c0fc5SRavi Teja else 1497e48c0fc5SRavi Teja { 1498e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1499e48c0fc5SRavi Teja pathString + "/Address"); 1500e48c0fc5SRavi Teja return; 1501e48c0fc5SRavi Teja } 1502e48c0fc5SRavi Teja entryIdx++; 1503e48c0fc5SRavi Teja continue; 1504e48c0fc5SRavi Teja } 1505e48c0fc5SRavi Teja 1506e48c0fc5SRavi Teja std::optional<std::string> address; 1507e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1508e48c0fc5SRavi Teja 1509e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1510e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1511e48c0fc5SRavi Teja { 1512e48c0fc5SRavi Teja return; 1513e48c0fc5SRavi Teja } 1514e48c0fc5SRavi Teja 1515e48c0fc5SRavi Teja // if IP address exist then modify it. 1516e48c0fc5SRavi Teja if (thisData != ipv6StaticData.end()) 1517e48c0fc5SRavi Teja { 1518e48c0fc5SRavi Teja // Apply changes 1519e48c0fc5SRavi Teja if (address) 1520e48c0fc5SRavi Teja { 1521e48c0fc5SRavi Teja auto callback = [asyncResp, entryIdx, 1522e48c0fc5SRavi Teja address{std::string(*address)}]( 1523e48c0fc5SRavi Teja const boost::system::error_code ec) { 1524e48c0fc5SRavi Teja if (ec) 1525e48c0fc5SRavi Teja { 1526e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1527e48c0fc5SRavi Teja return; 1528e48c0fc5SRavi Teja } 1529e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"] 1530e48c0fc5SRavi Teja [entryIdx]["Address"] = 1531e48c0fc5SRavi Teja std::move(address); 1532e48c0fc5SRavi Teja }; 1533e48c0fc5SRavi Teja 1534e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1535e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1536e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1537e48c0fc5SRavi Teja thisData->id, 1538e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1539e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "Address", 1540e48c0fc5SRavi Teja std::variant<std::string>(*address)); 1541e48c0fc5SRavi Teja } 1542e48c0fc5SRavi Teja 1543e48c0fc5SRavi Teja if (prefixLength) 1544e48c0fc5SRavi Teja { 1545e48c0fc5SRavi Teja auto callback = [asyncResp, entryIdx, 1546e48c0fc5SRavi Teja prefixLength{uint8_t(*prefixLength)}]( 1547e48c0fc5SRavi Teja const boost::system::error_code ec) { 1548e48c0fc5SRavi Teja if (ec) 1549e48c0fc5SRavi Teja { 1550e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 1551e48c0fc5SRavi Teja return; 1552e48c0fc5SRavi Teja } 1553e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"] 1554e48c0fc5SRavi Teja [entryIdx]["PrefixLength"] = 1555e48c0fc5SRavi Teja std::move(prefixLength); 1556e48c0fc5SRavi Teja }; 1557e48c0fc5SRavi Teja 1558e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 1559e48c0fc5SRavi Teja std::move(callback), "xyz.openbmc_project.Network", 1560e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + 1561e48c0fc5SRavi Teja thisData->id, 1562e48c0fc5SRavi Teja "org.freedesktop.DBus.Properties", "Set", 1563e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP", "PrefixLength", 1564e48c0fc5SRavi Teja std::variant<uint8_t>(*prefixLength)); 1565e48c0fc5SRavi Teja } 1566e48c0fc5SRavi Teja 1567e48c0fc5SRavi Teja thisData++; 1568e48c0fc5SRavi Teja } 1569e48c0fc5SRavi Teja else 1570e48c0fc5SRavi Teja { 1571e48c0fc5SRavi Teja // Create IPv6 with provided data 1572e48c0fc5SRavi Teja 1573e48c0fc5SRavi Teja if (!prefixLength) 1574e48c0fc5SRavi Teja { 1575e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1576e48c0fc5SRavi Teja pathString + "/PrefixLength"); 1577e48c0fc5SRavi Teja continue; 1578e48c0fc5SRavi Teja } 1579e48c0fc5SRavi Teja 1580e48c0fc5SRavi Teja if (!address) 1581e48c0fc5SRavi Teja { 1582e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1583e48c0fc5SRavi Teja pathString + "/Address"); 1584e48c0fc5SRavi Teja continue; 1585e48c0fc5SRavi Teja } 1586e48c0fc5SRavi Teja 1587e48c0fc5SRavi Teja createIPv6(ifaceId, entryIdx, *prefixLength, *address, 1588e48c0fc5SRavi Teja asyncResp); 1589e48c0fc5SRavi Teja 1590e48c0fc5SRavi Teja nlohmann::json &ipv6StaticAddressJson = 1591e48c0fc5SRavi Teja asyncResp->res.jsonValue["IPv6StaticAddresses"][entryIdx]; 1592e48c0fc5SRavi Teja ipv6StaticAddressJson["Address"] = *address; 1593e48c0fc5SRavi Teja ipv6StaticAddressJson["PrefixLength"] = *prefixLength; 1594e48c0fc5SRavi Teja } 1595e48c0fc5SRavi Teja entryIdx++; 1596e48c0fc5SRavi Teja } 1597e48c0fc5SRavi Teja } 1598e48c0fc5SRavi Teja 15990f74e643SEd Tanous void parseInterfaceData( 16000f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 16010f74e643SEd Tanous const EthernetInterfaceData ðData, 1602e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1603e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1604e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 16054a0cb85cSEd Tanous { 16064a0cb85cSEd Tanous json_response["Id"] = iface_id; 16074a0cb85cSEd Tanous json_response["@odata.id"] = 16084a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1609029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1610029573d4SEd Tanous if (ethData.speed == 0) 1611029573d4SEd Tanous { 1612029573d4SEd Tanous json_response["LinkStatus"] = "NoLink"; 1613029573d4SEd Tanous json_response["Status"] = { 1614029573d4SEd Tanous {"Health", "OK"}, 1615029573d4SEd Tanous {"State", "Disabled"}, 1616029573d4SEd Tanous }; 1617029573d4SEd Tanous } 1618029573d4SEd Tanous else 1619029573d4SEd Tanous { 1620029573d4SEd Tanous json_response["LinkStatus"] = "LinkUp"; 1621029573d4SEd Tanous json_response["Status"] = { 1622029573d4SEd Tanous {"Health", "OK"}, 1623029573d4SEd Tanous {"State", "Enabled"}, 1624029573d4SEd Tanous }; 1625029573d4SEd Tanous } 16264a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 16274a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 1628fda13ad2SSunitha Harish json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled; 16292a133282Smanojkiraneda 16304a0cb85cSEd Tanous if (!ethData.hostname.empty()) 16314a0cb85cSEd Tanous { 16324a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 16334a0cb85cSEd Tanous } 16344a0cb85cSEd Tanous 1635fda13ad2SSunitha Harish json_response["VLANs"] = { 1636fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1637fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1638fda13ad2SSunitha Harish 1639029573d4SEd Tanous json_response["NameServers"] = ethData.nameservers; 1640f85837bfSRAJESWARAN THILLAIGOVINDAN json_response["StaticNameServers"] = ethData.nameservers; 16414a0cb85cSEd Tanous 16424a0cb85cSEd Tanous if (ipv4Data.size() > 0) 16434a0cb85cSEd Tanous { 16444a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 16454a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 16464a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 16474a0cb85cSEd Tanous { 1648fa5053a6SGunnar Mills 1649fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1650fa5053a6SGunnar Mills if (gatewayStr.empty()) 1651fa5053a6SGunnar Mills { 1652fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1653fa5053a6SGunnar Mills } 1654fa5053a6SGunnar Mills 16554a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 16564a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1657029573d4SEd Tanous {"Address", ipv4_config.address}, 1658fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 16594a0cb85cSEd Tanous } 16604a0cb85cSEd Tanous } 16619a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1662e48c0fc5SRavi Teja 1663e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 1664e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 1665e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1666e48c0fc5SRavi Teja { 1667e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1668e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1669e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 1670e48c0fc5SRavi Teja } 1671e48c0fc5SRavi Teja 1672e48c0fc5SRavi Teja nlohmann::json &ipv6_static_array = 1673e48c0fc5SRavi Teja json_response["IPv6StaticAddresses"]; 1674e48c0fc5SRavi Teja ipv6_static_array = nlohmann::json::array(); 1675e48c0fc5SRavi Teja for (auto &ipv6_static_config : ipv6StaticData) 1676e48c0fc5SRavi Teja { 1677e48c0fc5SRavi Teja ipv6_static_array.push_back( 1678e48c0fc5SRavi Teja {{"Address", ipv6_static_config.address}, 1679e48c0fc5SRavi Teja {"PrefixLength", ipv6_static_config.prefixLength}}); 1680e48c0fc5SRavi Teja } 1681588c3f0dSKowalski, Kamil } 1682588c3f0dSKowalski, Kamil 16839391bb9cSRapkiewicz, Pawel /** 16849391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 16859391bb9cSRapkiewicz, Pawel */ 168655c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 16871abe55efSEd Tanous const std::vector<std::string> ¶ms) override 16881abe55efSEd Tanous { 16894a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 16901abe55efSEd Tanous if (params.size() != 1) 16911abe55efSEd Tanous { 1692f12894f8SJason M. Bills messages::internalError(asyncResp->res); 16939391bb9cSRapkiewicz, Pawel return; 16949391bb9cSRapkiewicz, Pawel } 16959391bb9cSRapkiewicz, Pawel 16964a0cb85cSEd Tanous getEthernetIfaceData( 16974a0cb85cSEd Tanous params[0], 16984a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 16994a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1700e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1701e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1702e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1703e48c0fc5SRavi Teja &ipv6StaticData) { 17044a0cb85cSEd Tanous if (!success) 17051abe55efSEd Tanous { 17061abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 17071abe55efSEd Tanous // object, and other errors 1708f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1709f12894f8SJason M. Bills "EthernetInterface", iface_id); 17104a0cb85cSEd Tanous return; 17119391bb9cSRapkiewicz, Pawel } 17124c9afe43SEd Tanous 17134c9afe43SEd Tanous // because this has no dependence on the interface at this 17144c9afe43SEd Tanous // point, it needs to be done after we know the interface 17154c9afe43SEd Tanous // exists, not before. 17164c9afe43SEd Tanous getDHCPConfigData(asyncResp); 17174c9afe43SEd Tanous 17180f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1719fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 17200f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 17210f74e643SEd Tanous "/redfish/v1/$metadata#EthernetInterface.EthernetInterface"; 17220f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 17230f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 17240f74e643SEd Tanous "Management Network Interface"; 17250f74e643SEd Tanous 17260f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1727e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 17289391bb9cSRapkiewicz, Pawel }); 17299391bb9cSRapkiewicz, Pawel } 17309391bb9cSRapkiewicz, Pawel 173155c7b7a2SEd Tanous void doPatch(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); 1738588c3f0dSKowalski, Kamil return; 1739588c3f0dSKowalski, Kamil } 1740588c3f0dSKowalski, Kamil 17414a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1742588c3f0dSKowalski, Kamil 1743bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1744d577665bSRatan Gupta std::optional<std::string> macAddress; 17459a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1746f476acbfSRatan Gupta std::optional<nlohmann::json> ipv4Addresses; 1747f476acbfSRatan Gupta std::optional<nlohmann::json> ipv6Addresses; 1748e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1749f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 17505112e9b4SRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> nameServers; 1751da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 17520627a2c7SEd Tanous 1753fda13ad2SSunitha Harish if (!json_util::readJson( 1754fda13ad2SSunitha Harish req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses, 17556ca6ac12SJohnathan Mantey "MACAddress", macAddress, "StaticNameServers", 17566ca6ac12SJohnathan Mantey staticNameServers, "IPv6DefaultGateway", ipv6DefaultGateway, 17576ca6ac12SJohnathan Mantey "IPv6StaticAddresses", ipv6StaticAddresses, "NameServers", 17586ca6ac12SJohnathan Mantey nameServers, "DHCPv4", dhcpv4)) 17591abe55efSEd Tanous { 1760588c3f0dSKowalski, Kamil return; 1761588c3f0dSKowalski, Kamil } 1762f15aad37SRatan Gupta 1763da131a9aSJennifer Lee if (dhcpv4) 1764da131a9aSJennifer Lee { 1765da131a9aSJennifer Lee handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp); 1766da131a9aSJennifer Lee } 1767da131a9aSJennifer Lee 17684a0cb85cSEd Tanous // Get single eth interface data, and call the below callback for JSON 1769588c3f0dSKowalski, Kamil // preparation 17704a0cb85cSEd Tanous getEthernetIfaceData( 17714a0cb85cSEd Tanous iface_id, 1772fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1773fda13ad2SSunitha Harish macAddress = std::move(macAddress), 17740627a2c7SEd Tanous ipv4Addresses = std::move(ipv4Addresses), 17759a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1776e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 17775112e9b4SRAJESWARAN THILLAIGOVINDAN staticNameServers = std::move(staticNameServers), 17785112e9b4SRAJESWARAN THILLAIGOVINDAN nameServers = std::move(nameServers)]( 17794a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1780e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1781e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1782e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1783e48c0fc5SRavi Teja &ipv6StaticData) { 17841abe55efSEd Tanous if (!success) 17851abe55efSEd Tanous { 1786588c3f0dSKowalski, Kamil // ... otherwise return error 17871abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 17881abe55efSEd Tanous // object, and other errors 1789fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1790fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1791588c3f0dSKowalski, Kamil return; 1792588c3f0dSKowalski, Kamil } 1793588c3f0dSKowalski, Kamil 17940f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 1795e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 1796588c3f0dSKowalski, Kamil 17970627a2c7SEd Tanous if (hostname) 17981abe55efSEd Tanous { 17990627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 18001abe55efSEd Tanous } 18010627a2c7SEd Tanous 1802d577665bSRatan Gupta if (macAddress) 1803d577665bSRatan Gupta { 1804d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1805d577665bSRatan Gupta } 1806d577665bSRatan Gupta 18070627a2c7SEd Tanous if (ipv4Addresses) 18081abe55efSEd Tanous { 1809537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 1810537174c4SEd Tanous // above is returning a const value, not a non-const value. 1811537174c4SEd Tanous // This doesn't really work for us, as we need to be able to 1812537174c4SEd Tanous // efficiently move out the intermedia nlohmann::json 1813537174c4SEd Tanous // objects. This makes a copy of the structure, and operates 1814537174c4SEd Tanous // on that, but could be done more efficiently 1815f476acbfSRatan Gupta nlohmann::json ipv4 = std::move(*ipv4Addresses); 1816537174c4SEd Tanous handleIPv4Patch(iface_id, ipv4, ipv4Data, asyncResp); 18171abe55efSEd Tanous } 18180627a2c7SEd Tanous 18195112e9b4SRAJESWARAN THILLAIGOVINDAN if (nameServers) 18205112e9b4SRAJESWARAN THILLAIGOVINDAN { 18215112e9b4SRAJESWARAN THILLAIGOVINDAN // Data.Permissions is read-only 18225112e9b4SRAJESWARAN THILLAIGOVINDAN messages::propertyNotWritable(asyncResp->res, 18235112e9b4SRAJESWARAN THILLAIGOVINDAN "NameServers"); 18245112e9b4SRAJESWARAN THILLAIGOVINDAN } 18255112e9b4SRAJESWARAN THILLAIGOVINDAN 1826f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1827f85837bfSRAJESWARAN THILLAIGOVINDAN { 1828f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1829f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1830f85837bfSRAJESWARAN THILLAIGOVINDAN } 18319a6fc6feSRavi Teja 18329a6fc6feSRavi Teja if (ipv6DefaultGateway) 18339a6fc6feSRavi Teja { 18349a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 18359a6fc6feSRavi Teja "IPv6DefaultGateway"); 18369a6fc6feSRavi Teja } 1837e48c0fc5SRavi Teja 1838e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1839e48c0fc5SRavi Teja { 1840e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1841e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 1842e48c0fc5SRavi Teja ipv6StaticData, asyncResp); 1843e48c0fc5SRavi Teja 1844e48c0fc5SRavi Teja // call getEthernetIfaceData to populate updated static 1845e48c0fc5SRavi Teja // addresses data to "IPv6Addresses" json collection 1846e48c0fc5SRavi Teja getEthernetIfaceData( 1847e48c0fc5SRavi Teja iface_id, 1848e48c0fc5SRavi Teja [this, asyncResp, iface_id]( 1849e48c0fc5SRavi Teja const bool &success, 1850e48c0fc5SRavi Teja const EthernetInterfaceData ðData, 1851e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> 1852e48c0fc5SRavi Teja &ipv4Data, 1853e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1854e48c0fc5SRavi Teja &ipv6Data, 1855e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1856e48c0fc5SRavi Teja &ipv6StaticData) { 1857e48c0fc5SRavi Teja if (!success) 1858e48c0fc5SRavi Teja { 1859e48c0fc5SRavi Teja messages::resourceNotFound(asyncResp->res, 1860e48c0fc5SRavi Teja "Ethernet Interface", 1861e48c0fc5SRavi Teja iface_id); 1862e48c0fc5SRavi Teja return; 1863e48c0fc5SRavi Teja } 1864e48c0fc5SRavi Teja 1865e48c0fc5SRavi Teja parseInterfaceData(asyncResp->res.jsonValue, 1866e48c0fc5SRavi Teja iface_id, ethData, ipv4Data, 1867e48c0fc5SRavi Teja ipv6Data, ipv6StaticData); 1868e48c0fc5SRavi Teja }); 1869e48c0fc5SRavi Teja } 1870588c3f0dSKowalski, Kamil }); 1871588c3f0dSKowalski, Kamil } 18729391bb9cSRapkiewicz, Pawel }; 18739391bb9cSRapkiewicz, Pawel 1874e439f0f8SKowalski, Kamil /** 18754a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 18764a0cb85cSEd Tanous * Schema 1877e439f0f8SKowalski, Kamil */ 18781abe55efSEd Tanous class VlanNetworkInterface : public Node 18791abe55efSEd Tanous { 1880e439f0f8SKowalski, Kamil public: 1881e439f0f8SKowalski, Kamil /* 1882e439f0f8SKowalski, Kamil * Default Constructor 1883e439f0f8SKowalski, Kamil */ 1884e439f0f8SKowalski, Kamil template <typename CrowApp> 18851abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 18864a0cb85cSEd Tanous Node(app, 18870f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 18881abe55efSEd Tanous std::string(), std::string()) 18891abe55efSEd Tanous { 1890e439f0f8SKowalski, Kamil entityPrivileges = { 1891e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1892e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1893e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1894e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1895e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1896e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1897e439f0f8SKowalski, Kamil } 1898e439f0f8SKowalski, Kamil 1899e439f0f8SKowalski, Kamil private: 19000f74e643SEd Tanous void parseInterfaceData( 19010f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 19020f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1903e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1904e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1905e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6StaticData) 19061abe55efSEd Tanous { 1907e439f0f8SKowalski, Kamil // Fill out obvious data... 19084a0cb85cSEd Tanous json_response["Id"] = iface_id; 19094a0cb85cSEd Tanous json_response["@odata.id"] = 19104a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 19114a0cb85cSEd Tanous "/VLANs/" + iface_id; 1912e439f0f8SKowalski, Kamil 19134a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1914fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 19154a0cb85cSEd Tanous { 1916fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 19174a0cb85cSEd Tanous } 1918e439f0f8SKowalski, Kamil } 1919e439f0f8SKowalski, Kamil 1920fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 19211abe55efSEd Tanous { 19221abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 19231abe55efSEd Tanous { 1924927a505aSKowalski, Kamil return false; 19251abe55efSEd Tanous } 19261abe55efSEd Tanous else 19271abe55efSEd Tanous { 1928927a505aSKowalski, Kamil return true; 1929927a505aSKowalski, Kamil } 1930927a505aSKowalski, Kamil } 1931927a505aSKowalski, Kamil 1932e439f0f8SKowalski, Kamil /** 1933e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1934e439f0f8SKowalski, Kamil */ 193555c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 19361abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19371abe55efSEd Tanous { 19384a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19394a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1940e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1941e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1942e439f0f8SKowalski, Kamil // impossible. 19431abe55efSEd Tanous if (params.size() != 2) 19441abe55efSEd Tanous { 1945f12894f8SJason M. Bills messages::internalError(res); 1946e439f0f8SKowalski, Kamil res.end(); 1947e439f0f8SKowalski, Kamil return; 1948e439f0f8SKowalski, Kamil } 1949e439f0f8SKowalski, Kamil 19504a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 19514a0cb85cSEd Tanous const std::string &iface_id = params[1]; 19520f74e643SEd Tanous res.jsonValue["@odata.type"] = 19530f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 19540f74e643SEd Tanous res.jsonValue["@odata.context"] = 19550f74e643SEd Tanous "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface"; 19560f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1957e439f0f8SKowalski, Kamil 1958fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 19591abe55efSEd Tanous { 1960a434f2bdSEd Tanous return; 1961a434f2bdSEd Tanous } 1962a434f2bdSEd Tanous 1963e439f0f8SKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 1964e439f0f8SKowalski, Kamil // preparation 19654a0cb85cSEd Tanous getEthernetIfaceData( 1966fda13ad2SSunitha Harish params[1], 1967fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 1968fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 19694a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1970e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 1971e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1972e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 1973e48c0fc5SRavi Teja &ipv6StaticData) { 1974fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 19751abe55efSEd Tanous { 19760f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 19770f74e643SEd Tanous parent_iface_id, iface_id, ethData, 1978e48c0fc5SRavi Teja ipv4Data, ipv6Data, ipv6StaticData); 19791abe55efSEd Tanous } 19801abe55efSEd Tanous else 19811abe55efSEd Tanous { 1982e439f0f8SKowalski, Kamil // ... otherwise return error 19831abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 19841abe55efSEd Tanous // object, and other errors 1985f12894f8SJason M. Bills messages::resourceNotFound( 1986f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 1987e439f0f8SKowalski, Kamil } 1988e439f0f8SKowalski, Kamil }); 1989e439f0f8SKowalski, Kamil } 1990e439f0f8SKowalski, Kamil 199155c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 19921abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19931abe55efSEd Tanous { 19944a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19951abe55efSEd Tanous if (params.size() != 2) 19961abe55efSEd Tanous { 1997f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1998e439f0f8SKowalski, Kamil return; 1999e439f0f8SKowalski, Kamil } 2000e439f0f8SKowalski, Kamil 2001d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 200255c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2003927a505aSKowalski, Kamil 2004fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 20051abe55efSEd Tanous { 2006fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2007fda13ad2SSunitha Harish ifaceId); 2008927a505aSKowalski, Kamil return; 2009927a505aSKowalski, Kamil } 2010927a505aSKowalski, Kamil 20110627a2c7SEd Tanous bool vlanEnable = false; 20120627a2c7SEd Tanous uint64_t vlanId = 0; 20130627a2c7SEd Tanous 20140627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 20150627a2c7SEd Tanous vlanId)) 20161abe55efSEd Tanous { 2017927a505aSKowalski, Kamil return; 2018927a505aSKowalski, Kamil } 2019927a505aSKowalski, Kamil 2020927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 2021927a505aSKowalski, Kamil // preparation 2022e48c0fc5SRavi Teja getEthernetIfaceData( 2023e48c0fc5SRavi Teja params[1], 2024e48c0fc5SRavi Teja [this, asyncResp, parentIfaceId{std::string(params[0])}, 2025e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 2026e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 2027e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 2028e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 2029e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 2030e48c0fc5SRavi Teja &ipv6StaticData) { 203108244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 203208244d02SSunitha Harish { 203308244d02SSunitha Harish parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId, 2034e48c0fc5SRavi Teja ifaceId, ethData, ipv4Data, ipv6Data, 2035e48c0fc5SRavi Teja ipv6StaticData); 203608244d02SSunitha Harish auto callback = 203708244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 203808244d02SSunitha Harish if (ec) 203908244d02SSunitha Harish { 204008244d02SSunitha Harish messages::internalError(asyncResp->res); 204108244d02SSunitha Harish } 204208244d02SSunitha Harish }; 204308244d02SSunitha Harish 204408244d02SSunitha Harish if (vlanEnable == true) 204508244d02SSunitha Harish { 204608244d02SSunitha Harish crow::connections::systemBus->async_method_call( 204708244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 204808244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 204908244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 205008244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 205108244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 205208244d02SSunitha Harish } 205308244d02SSunitha Harish else 205408244d02SSunitha Harish { 2055e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 2056e48c0fc5SRavi Teja "vlan interface"; 205708244d02SSunitha Harish crow::connections::systemBus->async_method_call( 205808244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 2059e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 2060e48c0fc5SRavi Teja ifaceId, 206108244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 206208244d02SSunitha Harish } 206308244d02SSunitha Harish } 206408244d02SSunitha Harish else 20651abe55efSEd Tanous { 20661abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 20671abe55efSEd Tanous // object, and other errors 2068e48c0fc5SRavi Teja messages::resourceNotFound( 2069e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 2070927a505aSKowalski, Kamil return; 2071927a505aSKowalski, Kamil } 2072927a505aSKowalski, Kamil }); 2073e439f0f8SKowalski, Kamil } 2074e439f0f8SKowalski, Kamil 207555c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 20761abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20771abe55efSEd Tanous { 20784a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20791abe55efSEd Tanous if (params.size() != 2) 20801abe55efSEd Tanous { 2081f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2082e439f0f8SKowalski, Kamil return; 2083e439f0f8SKowalski, Kamil } 2084e439f0f8SKowalski, Kamil 2085d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 208655c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2087927a505aSKowalski, Kamil 2088fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 20891abe55efSEd Tanous { 2090fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2091fda13ad2SSunitha Harish ifaceId); 2092927a505aSKowalski, Kamil return; 2093927a505aSKowalski, Kamil } 2094927a505aSKowalski, Kamil 2095927a505aSKowalski, Kamil // Get single eth interface data, and call the below callback for JSON 2096927a505aSKowalski, Kamil // preparation 2097f12894f8SJason M. Bills getEthernetIfaceData( 2098fda13ad2SSunitha Harish params[1], 2099fda13ad2SSunitha Harish [this, asyncResp, parentIfaceId{std::string(params[0])}, 2100fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 2101f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 2102e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 2103e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> &ipv6Data, 2104e48c0fc5SRavi Teja const boost::container::flat_set<IPv6AddressData> 2105e48c0fc5SRavi Teja &ipv6StaticData) { 2106fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 21071abe55efSEd Tanous { 21080f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId, 2109e48c0fc5SRavi Teja ifaceId, ethData, ipv4Data, ipv6Data, 2110e48c0fc5SRavi Teja ipv6StaticData); 2111927a505aSKowalski, Kamil 2112f12894f8SJason M. Bills auto callback = 2113f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 21141abe55efSEd Tanous if (ec) 21151abe55efSEd Tanous { 2116f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2117927a505aSKowalski, Kamil } 21184a0cb85cSEd Tanous }; 21194a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21204a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21214a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 21224a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 21231abe55efSEd Tanous } 21241abe55efSEd Tanous else 21251abe55efSEd Tanous { 2126927a505aSKowalski, Kamil // ... otherwise return error 2127f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 2128f12894f8SJason M. Bills // object, and other errors 2129f12894f8SJason M. Bills messages::resourceNotFound( 2130f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 2131927a505aSKowalski, Kamil } 2132927a505aSKowalski, Kamil }); 2133e439f0f8SKowalski, Kamil } 2134e439f0f8SKowalski, Kamil }; 2135e439f0f8SKowalski, Kamil 2136e439f0f8SKowalski, Kamil /** 2137e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 2138e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 2139e439f0f8SKowalski, Kamil */ 21401abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 21411abe55efSEd Tanous { 2142e439f0f8SKowalski, Kamil public: 2143e439f0f8SKowalski, Kamil template <typename CrowApp> 21441abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 21454a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 21464a0cb85cSEd Tanous std::string()) 21471abe55efSEd Tanous { 2148e439f0f8SKowalski, Kamil entityPrivileges = { 2149e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 2150e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2151e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2152e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2153e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2154e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2155e439f0f8SKowalski, Kamil } 2156e439f0f8SKowalski, Kamil 2157e439f0f8SKowalski, Kamil private: 2158e439f0f8SKowalski, Kamil /** 2159e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2160e439f0f8SKowalski, Kamil */ 216155c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 21621abe55efSEd Tanous const std::vector<std::string> ¶ms) override 21631abe55efSEd Tanous { 21644a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 21651abe55efSEd Tanous if (params.size() != 1) 21661abe55efSEd Tanous { 2167e439f0f8SKowalski, Kamil // This means there is a problem with the router 2168f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2169e439f0f8SKowalski, Kamil return; 2170e439f0f8SKowalski, Kamil } 2171e439f0f8SKowalski, Kamil 21724a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2173e439f0f8SKowalski, Kamil 21744a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 21751abe55efSEd Tanous // preparation 2176f12894f8SJason M. Bills getEthernetIfaceList( 217743b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 21781abe55efSEd Tanous const bool &success, 21794c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 21804a0cb85cSEd Tanous if (!success) 21811abe55efSEd Tanous { 2182f12894f8SJason M. Bills messages::internalError(asyncResp->res); 21834a0cb85cSEd Tanous return; 21841abe55efSEd Tanous } 21854c9afe43SEd Tanous 21864c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 21874c9afe43SEd Tanous { 21884c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 21894c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 21904c9afe43SEd Tanous rootInterfaceName); 21914c9afe43SEd Tanous return; 21924c9afe43SEd Tanous } 21934c9afe43SEd Tanous 21940f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 21950f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 21960f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 21970f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 21980f74e643SEd Tanous "/redfish/v1/$metadata" 21990f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 22000f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 22010f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 22020f74e643SEd Tanous "VLAN Network Interface Collection"; 22034a0cb85cSEd Tanous 22044a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 22054a0cb85cSEd Tanous 22064a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 22071abe55efSEd Tanous { 22084a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 22094a0cb85cSEd Tanous { 22104a0cb85cSEd Tanous iface_array.push_back( 22114a0cb85cSEd Tanous {{"@odata.id", 22124a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 22134a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2214e439f0f8SKowalski, Kamil } 2215e439f0f8SKowalski, Kamil } 2216e439f0f8SKowalski, Kamil 22174a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 22184a0cb85cSEd Tanous iface_array.size(); 22194a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 22204a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 22214a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 22224a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2223e439f0f8SKowalski, Kamil }); 2224e439f0f8SKowalski, Kamil } 2225e439f0f8SKowalski, Kamil 222655c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 22271abe55efSEd Tanous const std::vector<std::string> ¶ms) override 22281abe55efSEd Tanous { 22294a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 22301abe55efSEd Tanous if (params.size() != 1) 22311abe55efSEd Tanous { 2232f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2233e439f0f8SKowalski, Kamil return; 2234e439f0f8SKowalski, Kamil } 2235fda13ad2SSunitha Harish bool vlanEnable = false; 22360627a2c7SEd Tanous uint32_t vlanId = 0; 2237fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2238fda13ad2SSunitha Harish vlanEnable)) 22391abe55efSEd Tanous { 22404a0cb85cSEd Tanous return; 2241e439f0f8SKowalski, Kamil } 2242fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2243fda13ad2SSunitha Harish if (!vlanId) 2244fda13ad2SSunitha Harish { 2245fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2246fda13ad2SSunitha Harish } 2247fda13ad2SSunitha Harish if (!vlanEnable) 2248fda13ad2SSunitha Harish { 2249fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2250fda13ad2SSunitha Harish } 2251fda13ad2SSunitha Harish if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable)) 2252fda13ad2SSunitha Harish { 2253fda13ad2SSunitha Harish return; 2254fda13ad2SSunitha Harish } 2255fda13ad2SSunitha Harish 22564a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 22574a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 22581abe55efSEd Tanous if (ec) 22591abe55efSEd Tanous { 22604a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 22614a0cb85cSEd Tanous // phosphor-network responses 2262f12894f8SJason M. Bills messages::internalError(asyncResp->res); 22634a0cb85cSEd Tanous return; 22641abe55efSEd Tanous } 2265f12894f8SJason M. Bills messages::created(asyncResp->res); 2266e439f0f8SKowalski, Kamil }; 22674a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 22684a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 22694a0cb85cSEd Tanous "/xyz/openbmc_project/network", 22704a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 22710627a2c7SEd Tanous rootInterfaceName, vlanId); 22724a0cb85cSEd Tanous } 22734a0cb85cSEd Tanous }; 22749391bb9cSRapkiewicz, Pawel } // namespace redfish 2275