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; 961f8c7b5dSJohnathan Mantey bool DNSEnabled; 971f8c7b5dSJohnathan Mantey bool NTPEnabled; 981f8c7b5dSJohnathan Mantey bool HostNameEnabled; 991f8c7b5dSJohnathan Mantey bool SendHostNameEnabled; 100aa05fb27SJohnathan Mantey bool linkUp; 101*eeedda23SJohnathan Mantey bool nicEnabled; 1021f8c7b5dSJohnathan Mantey std::string DHCPEnabled; 1031f8c7b5dSJohnathan Mantey std::string operatingMode; 1044a0cb85cSEd Tanous std::string hostname; 1054a0cb85cSEd Tanous std::string default_gateway; 1069a6fc6feSRavi Teja std::string ipv6_default_gateway; 1074a0cb85cSEd Tanous std::string mac_address; 108fda13ad2SSunitha Harish std::vector<std::uint32_t> vlan_id; 109029573d4SEd Tanous std::vector<std::string> nameservers; 110d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1119391bb9cSRapkiewicz, Pawel }; 1129391bb9cSRapkiewicz, Pawel 1131f8c7b5dSJohnathan Mantey struct DHCPParameters 1141f8c7b5dSJohnathan Mantey { 1151f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 1161f8c7b5dSJohnathan Mantey std::optional<bool> useDNSServers; 1171f8c7b5dSJohnathan Mantey std::optional<bool> useNTPServers; 1181f8c7b5dSJohnathan Mantey std::optional<bool> useUseDomainName; 1191f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1201f8c7b5dSJohnathan Mantey }; 1211f8c7b5dSJohnathan Mantey 1229391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1239391bb9cSRapkiewicz, Pawel // into full dot notation 1241abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1251abe55efSEd Tanous { 1269391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1279391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1289391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1299391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1309391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1319391bb9cSRapkiewicz, Pawel return netmask; 1329391bb9cSRapkiewicz, Pawel } 1339391bb9cSRapkiewicz, Pawel 1341f8c7b5dSJohnathan Mantey inline bool translateDHCPEnabledToBool(const std::string &inputDHCP, 1351f8c7b5dSJohnathan Mantey bool isIPv4) 1361f8c7b5dSJohnathan Mantey { 1371f8c7b5dSJohnathan Mantey if (isIPv4) 1381f8c7b5dSJohnathan Mantey { 1391f8c7b5dSJohnathan Mantey return ( 1401f8c7b5dSJohnathan Mantey (inputDHCP == 1411f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1421f8c7b5dSJohnathan Mantey (inputDHCP == 1431f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1441f8c7b5dSJohnathan Mantey } 1451f8c7b5dSJohnathan Mantey return ((inputDHCP == 1461f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1471f8c7b5dSJohnathan Mantey (inputDHCP == 1481f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1491f8c7b5dSJohnathan Mantey } 1501f8c7b5dSJohnathan Mantey 1511f8c7b5dSJohnathan Mantey inline std::string GetDHCPEnabledEnumeration(bool isIPv4, bool isIPv6) 1521f8c7b5dSJohnathan Mantey { 1531f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1541f8c7b5dSJohnathan Mantey { 1551f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1561f8c7b5dSJohnathan Mantey } 1571f8c7b5dSJohnathan Mantey else if (isIPv4) 1581f8c7b5dSJohnathan Mantey { 1591f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1601f8c7b5dSJohnathan Mantey } 1611f8c7b5dSJohnathan Mantey else if (isIPv6) 1621f8c7b5dSJohnathan Mantey { 1631f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1641f8c7b5dSJohnathan Mantey } 1651f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1661f8c7b5dSJohnathan Mantey } 1671f8c7b5dSJohnathan Mantey 1684a0cb85cSEd Tanous inline std::string 1694a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string &inputOrigin, 1704a0cb85cSEd Tanous bool isIPv4) 1711abe55efSEd Tanous { 1724a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1731abe55efSEd Tanous { 1744a0cb85cSEd Tanous return "Static"; 1759391bb9cSRapkiewicz, Pawel } 1764a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1771abe55efSEd Tanous { 1784a0cb85cSEd Tanous if (isIPv4) 1791abe55efSEd Tanous { 1804a0cb85cSEd Tanous return "IPv4LinkLocal"; 1811abe55efSEd Tanous } 1821abe55efSEd Tanous else 1831abe55efSEd Tanous { 1844a0cb85cSEd Tanous return "LinkLocal"; 1859391bb9cSRapkiewicz, Pawel } 1869391bb9cSRapkiewicz, Pawel } 1874a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1881abe55efSEd Tanous { 1894a0cb85cSEd Tanous if (isIPv4) 1904a0cb85cSEd Tanous { 1914a0cb85cSEd Tanous return "DHCP"; 1924a0cb85cSEd Tanous } 1934a0cb85cSEd Tanous else 1944a0cb85cSEd Tanous { 1954a0cb85cSEd Tanous return "DHCPv6"; 1964a0cb85cSEd Tanous } 1974a0cb85cSEd Tanous } 1984a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1994a0cb85cSEd Tanous { 2004a0cb85cSEd Tanous return "SLAAC"; 2014a0cb85cSEd Tanous } 2024a0cb85cSEd Tanous return ""; 2034a0cb85cSEd Tanous } 2044a0cb85cSEd Tanous 2054c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string ðiface_id, 2064a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 2074a0cb85cSEd Tanous EthernetInterfaceData ðData) 2084a0cb85cSEd Tanous { 2094c9afe43SEd Tanous bool idFound = false; 2104a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 2114a0cb85cSEd Tanous { 2124a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 2134a0cb85cSEd Tanous { 214029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 215029573d4SEd Tanous { 2164c9afe43SEd Tanous idFound = true; 2174a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2184a0cb85cSEd Tanous { 2194a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2204a0cb85cSEd Tanous { 2214a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2224a0cb85cSEd Tanous { 2234a0cb85cSEd Tanous const std::string *mac = 224abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2254a0cb85cSEd Tanous if (mac != nullptr) 2264a0cb85cSEd Tanous { 2274a0cb85cSEd Tanous ethData.mac_address = *mac; 2284a0cb85cSEd Tanous } 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous } 2314a0cb85cSEd Tanous } 2324a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2334a0cb85cSEd Tanous { 2344a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2354a0cb85cSEd Tanous { 2364a0cb85cSEd Tanous if (propertyPair.first == "Id") 2374a0cb85cSEd Tanous { 2381b6b96c5SEd Tanous const uint32_t *id = 239abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2404a0cb85cSEd Tanous if (id != nullptr) 2414a0cb85cSEd Tanous { 242fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 2434a0cb85cSEd Tanous } 2444a0cb85cSEd Tanous } 2454a0cb85cSEd Tanous } 2464a0cb85cSEd Tanous } 2474a0cb85cSEd Tanous else if (ifacePair.first == 2484a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2494a0cb85cSEd Tanous { 2504a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2514a0cb85cSEd Tanous { 2524a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2534a0cb85cSEd Tanous { 2544a0cb85cSEd Tanous const bool *auto_neg = 255abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2564a0cb85cSEd Tanous if (auto_neg != nullptr) 2574a0cb85cSEd Tanous { 2584a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2594a0cb85cSEd Tanous } 2604a0cb85cSEd Tanous } 2614a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2624a0cb85cSEd Tanous { 2634a0cb85cSEd Tanous const uint32_t *speed = 264abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2654a0cb85cSEd Tanous if (speed != nullptr) 2664a0cb85cSEd Tanous { 2674a0cb85cSEd Tanous ethData.speed = *speed; 2684a0cb85cSEd Tanous } 2694a0cb85cSEd Tanous } 270aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 271aa05fb27SJohnathan Mantey { 272aa05fb27SJohnathan Mantey const bool *linkUp = 273aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 274aa05fb27SJohnathan Mantey if (linkUp != nullptr) 275aa05fb27SJohnathan Mantey { 276aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 277aa05fb27SJohnathan Mantey } 278aa05fb27SJohnathan Mantey } 279*eeedda23SJohnathan Mantey else if (propertyPair.first == "NICEnabled") 280*eeedda23SJohnathan Mantey { 281*eeedda23SJohnathan Mantey const bool *nicEnabled = 282*eeedda23SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 283*eeedda23SJohnathan Mantey if (nicEnabled != nullptr) 284*eeedda23SJohnathan Mantey { 285*eeedda23SJohnathan Mantey ethData.nicEnabled = *nicEnabled; 286*eeedda23SJohnathan Mantey } 287*eeedda23SJohnathan Mantey } 288f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 289029573d4SEd Tanous { 290029573d4SEd Tanous const std::vector<std::string> *nameservers = 291029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 292029573d4SEd Tanous std::vector<std::string>>( 293029573d4SEd Tanous &propertyPair.second); 294029573d4SEd Tanous if (nameservers != nullptr) 295029573d4SEd Tanous { 296029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2974a0cb85cSEd Tanous } 2984a0cb85cSEd Tanous } 2992a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 3002a133282Smanojkiraneda { 3011f8c7b5dSJohnathan Mantey const std::string *DHCPEnabled = 3021f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 3032a133282Smanojkiraneda if (DHCPEnabled != nullptr) 3042a133282Smanojkiraneda { 3052a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 3062a133282Smanojkiraneda } 3072a133282Smanojkiraneda } 308d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 309d24bfc7aSJennifer Lee { 310d24bfc7aSJennifer Lee const std::vector<std::string> *domainNames = 311d24bfc7aSJennifer Lee sdbusplus::message::variant_ns::get_if< 312d24bfc7aSJennifer Lee std::vector<std::string>>( 313d24bfc7aSJennifer Lee &propertyPair.second); 314d24bfc7aSJennifer Lee if (domainNames != nullptr) 315d24bfc7aSJennifer Lee { 316d24bfc7aSJennifer Lee ethData.domainnames = std::move(*domainNames); 317d24bfc7aSJennifer Lee } 318d24bfc7aSJennifer Lee } 319029573d4SEd Tanous } 320029573d4SEd Tanous } 321029573d4SEd Tanous } 3221f8c7b5dSJohnathan Mantey 3231f8c7b5dSJohnathan Mantey if (objpath.first == "/xyz/openbmc_project/network/config/dhcp") 3241f8c7b5dSJohnathan Mantey { 3251f8c7b5dSJohnathan Mantey if (ifacePair.first == 3261f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 3271f8c7b5dSJohnathan Mantey { 3281f8c7b5dSJohnathan Mantey for (const auto &propertyPair : ifacePair.second) 3291f8c7b5dSJohnathan Mantey { 3301f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 3311f8c7b5dSJohnathan Mantey { 3321f8c7b5dSJohnathan Mantey const bool *DNSEnabled = 3331f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3341f8c7b5dSJohnathan Mantey if (DNSEnabled != nullptr) 3351f8c7b5dSJohnathan Mantey { 3361f8c7b5dSJohnathan Mantey ethData.DNSEnabled = *DNSEnabled; 3371f8c7b5dSJohnathan Mantey } 3381f8c7b5dSJohnathan Mantey } 3391f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 3401f8c7b5dSJohnathan Mantey { 3411f8c7b5dSJohnathan Mantey const bool *NTPEnabled = 3421f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3431f8c7b5dSJohnathan Mantey if (NTPEnabled != nullptr) 3441f8c7b5dSJohnathan Mantey { 3451f8c7b5dSJohnathan Mantey ethData.NTPEnabled = *NTPEnabled; 3461f8c7b5dSJohnathan Mantey } 3471f8c7b5dSJohnathan Mantey } 3481f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 3491f8c7b5dSJohnathan Mantey { 3501f8c7b5dSJohnathan Mantey const bool *HostNameEnabled = 3511f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3521f8c7b5dSJohnathan Mantey if (HostNameEnabled != nullptr) 3531f8c7b5dSJohnathan Mantey { 3541f8c7b5dSJohnathan Mantey ethData.HostNameEnabled = *HostNameEnabled; 3551f8c7b5dSJohnathan Mantey } 3561f8c7b5dSJohnathan Mantey } 3571f8c7b5dSJohnathan Mantey else if (propertyPair.first == "SendHostNameEnabled") 3581f8c7b5dSJohnathan Mantey { 3591f8c7b5dSJohnathan Mantey const bool *SendHostNameEnabled = 3601f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3611f8c7b5dSJohnathan Mantey if (SendHostNameEnabled != nullptr) 3621f8c7b5dSJohnathan Mantey { 3631f8c7b5dSJohnathan Mantey ethData.SendHostNameEnabled = 3641f8c7b5dSJohnathan Mantey *SendHostNameEnabled; 3651f8c7b5dSJohnathan Mantey } 3661f8c7b5dSJohnathan Mantey } 3671f8c7b5dSJohnathan Mantey } 3681f8c7b5dSJohnathan Mantey } 3691f8c7b5dSJohnathan Mantey } 370029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 371029573d4SEd Tanous // to check eth number 372029573d4SEd Tanous if (ifacePair.first == 3734a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 3744a0cb85cSEd Tanous { 3754a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 3764a0cb85cSEd Tanous { 3774a0cb85cSEd Tanous if (propertyPair.first == "HostName") 3784a0cb85cSEd Tanous { 3794a0cb85cSEd Tanous const std::string *hostname = 380029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 381029573d4SEd Tanous &propertyPair.second); 3824a0cb85cSEd Tanous if (hostname != nullptr) 3834a0cb85cSEd Tanous { 3844a0cb85cSEd Tanous ethData.hostname = *hostname; 3854a0cb85cSEd Tanous } 3864a0cb85cSEd Tanous } 3874a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 3884a0cb85cSEd Tanous { 3894a0cb85cSEd Tanous const std::string *defaultGateway = 390029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 391029573d4SEd Tanous &propertyPair.second); 3924a0cb85cSEd Tanous if (defaultGateway != nullptr) 3934a0cb85cSEd Tanous { 3944a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 3954a0cb85cSEd Tanous } 3964a0cb85cSEd Tanous } 3979a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3989a6fc6feSRavi Teja { 3999a6fc6feSRavi Teja const std::string *defaultGateway6 = 4009a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 4019a6fc6feSRavi Teja &propertyPair.second); 4029a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 4039a6fc6feSRavi Teja { 4049a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 4059a6fc6feSRavi Teja } 4069a6fc6feSRavi Teja } 4074a0cb85cSEd Tanous } 4084a0cb85cSEd Tanous } 4094a0cb85cSEd Tanous } 4104a0cb85cSEd Tanous } 4114c9afe43SEd Tanous return idFound; 4124a0cb85cSEd Tanous } 4134a0cb85cSEd Tanous 414e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 41501784826SJohnathan Mantey inline void 41601784826SJohnathan Mantey extractIPV6Data(const std::string ðiface_id, 41701784826SJohnathan Mantey const GetManagedObjects &dbus_data, 41801784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData> &ipv6_config) 419e48c0fc5SRavi Teja { 420e48c0fc5SRavi Teja const std::string ipv6PathStart = 421e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/"; 422e48c0fc5SRavi Teja 423e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 424e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 425e48c0fc5SRavi Teja for (const auto &objpath : dbus_data) 426e48c0fc5SRavi Teja { 427e48c0fc5SRavi Teja // Check if proper pattern for object path appears 428e48c0fc5SRavi Teja if (boost::starts_with(objpath.first.str, ipv6PathStart)) 429e48c0fc5SRavi Teja { 430e48c0fc5SRavi Teja for (auto &interface : objpath.second) 431e48c0fc5SRavi Teja { 432e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 433e48c0fc5SRavi Teja { 434e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 435e48c0fc5SRavi Teja // appropriate 436e48c0fc5SRavi Teja std::pair< 437e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::iterator, 438e48c0fc5SRavi Teja bool> 439271584abSEd Tanous it = ipv6_config.insert(IPv6AddressData{}); 440e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 441271584abSEd Tanous ipv6_address.id = 442271584abSEd Tanous objpath.first.str.substr(ipv6PathStart.size()); 443e48c0fc5SRavi Teja for (auto &property : interface.second) 444e48c0fc5SRavi Teja { 445e48c0fc5SRavi Teja if (property.first == "Address") 446e48c0fc5SRavi Teja { 447e48c0fc5SRavi Teja const std::string *address = 448e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 449e48c0fc5SRavi Teja if (address != nullptr) 450e48c0fc5SRavi Teja { 451e48c0fc5SRavi Teja ipv6_address.address = *address; 452e48c0fc5SRavi Teja } 453e48c0fc5SRavi Teja } 454e48c0fc5SRavi Teja else if (property.first == "Origin") 455e48c0fc5SRavi Teja { 456e48c0fc5SRavi Teja const std::string *origin = 457e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 458e48c0fc5SRavi Teja if (origin != nullptr) 459e48c0fc5SRavi Teja { 460e48c0fc5SRavi Teja ipv6_address.origin = 461e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 462e48c0fc5SRavi Teja false); 463e48c0fc5SRavi Teja } 464e48c0fc5SRavi Teja } 465e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 466e48c0fc5SRavi Teja { 467e48c0fc5SRavi Teja const uint8_t *prefix = 468e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 469e48c0fc5SRavi Teja if (prefix != nullptr) 470e48c0fc5SRavi Teja { 471e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 472e48c0fc5SRavi Teja } 473e48c0fc5SRavi Teja } 474e48c0fc5SRavi Teja else 475e48c0fc5SRavi Teja { 476e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 477e48c0fc5SRavi Teja << "Got extra property: " << property.first 478e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 479e48c0fc5SRavi Teja } 480e48c0fc5SRavi Teja } 481e48c0fc5SRavi Teja } 482e48c0fc5SRavi Teja } 483e48c0fc5SRavi Teja } 484e48c0fc5SRavi Teja } 485e48c0fc5SRavi Teja } 486e48c0fc5SRavi Teja 4874a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 48801784826SJohnathan Mantey inline void 48901784826SJohnathan Mantey extractIPData(const std::string ðiface_id, 49001784826SJohnathan Mantey const GetManagedObjects &dbus_data, 49101784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData> &ipv4_config) 4924a0cb85cSEd Tanous { 4934a0cb85cSEd Tanous const std::string ipv4PathStart = 4944a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 4954a0cb85cSEd Tanous 4964a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 4974a0cb85cSEd Tanous // single ethernet interface, loop over all of them 4984a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 4994a0cb85cSEd Tanous { 5004a0cb85cSEd Tanous // Check if proper pattern for object path appears 5014a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 5024a0cb85cSEd Tanous { 5034a0cb85cSEd Tanous for (auto &interface : objpath.second) 5044a0cb85cSEd Tanous { 5054a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 5064a0cb85cSEd Tanous { 5074a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 5084a0cb85cSEd Tanous // appropriate 5094a0cb85cSEd Tanous std::pair< 5104a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 5114a0cb85cSEd Tanous bool> 512271584abSEd Tanous it = ipv4_config.insert(IPv4AddressData{}); 5134a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 514271584abSEd Tanous ipv4_address.id = 515271584abSEd Tanous objpath.first.str.substr(ipv4PathStart.size()); 5164a0cb85cSEd Tanous for (auto &property : interface.second) 5174a0cb85cSEd Tanous { 5184a0cb85cSEd Tanous if (property.first == "Address") 5194a0cb85cSEd Tanous { 5204a0cb85cSEd Tanous const std::string *address = 521abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5224a0cb85cSEd Tanous if (address != nullptr) 5234a0cb85cSEd Tanous { 5244a0cb85cSEd Tanous ipv4_address.address = *address; 5254a0cb85cSEd Tanous } 5264a0cb85cSEd Tanous } 5274a0cb85cSEd Tanous else if (property.first == "Gateway") 5284a0cb85cSEd Tanous { 5294a0cb85cSEd Tanous const std::string *gateway = 530abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5314a0cb85cSEd Tanous if (gateway != nullptr) 5324a0cb85cSEd Tanous { 5334a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 5344a0cb85cSEd Tanous } 5354a0cb85cSEd Tanous } 5364a0cb85cSEd Tanous else if (property.first == "Origin") 5374a0cb85cSEd Tanous { 5384a0cb85cSEd Tanous const std::string *origin = 539abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5404a0cb85cSEd Tanous if (origin != nullptr) 5414a0cb85cSEd Tanous { 5424a0cb85cSEd Tanous ipv4_address.origin = 5434a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 5444a0cb85cSEd Tanous true); 5454a0cb85cSEd Tanous } 5464a0cb85cSEd Tanous } 5474a0cb85cSEd Tanous else if (property.first == "PrefixLength") 5484a0cb85cSEd Tanous { 5494a0cb85cSEd Tanous const uint8_t *mask = 550abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 5514a0cb85cSEd Tanous if (mask != nullptr) 5524a0cb85cSEd Tanous { 5534a0cb85cSEd Tanous // convert it to the string 5544a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 5554a0cb85cSEd Tanous } 5564a0cb85cSEd Tanous } 5574a0cb85cSEd Tanous else 5584a0cb85cSEd Tanous { 5594a0cb85cSEd Tanous BMCWEB_LOG_ERROR 5604a0cb85cSEd Tanous << "Got extra property: " << property.first 5614a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 5624a0cb85cSEd Tanous } 5634a0cb85cSEd Tanous } 5644a0cb85cSEd Tanous // Check if given address is local, or global 5654a0cb85cSEd Tanous ipv4_address.linktype = 5664a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 56718659d10SJohnathan Mantey ? LinkType::Local 56818659d10SJohnathan Mantey : LinkType::Global; 5694a0cb85cSEd Tanous } 5704a0cb85cSEd Tanous } 5714a0cb85cSEd Tanous } 5724a0cb85cSEd Tanous } 5734a0cb85cSEd Tanous } 574588c3f0dSKowalski, Kamil 575588c3f0dSKowalski, Kamil /** 576588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 577588c3f0dSKowalski, Kamil * 578588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 579588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 580588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 581588c3f0dSKowalski, Kamil * 582588c3f0dSKowalski, Kamil * @return None. 583588c3f0dSKowalski, Kamil */ 584588c3f0dSKowalski, Kamil template <typename CallbackFunc> 5854a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 5861abe55efSEd Tanous CallbackFunc &&callback) 5871abe55efSEd Tanous { 58855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 589588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 590588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 591588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 592588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 593abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 5944a0cb85cSEd Tanous } 595588c3f0dSKowalski, Kamil 596588c3f0dSKowalski, Kamil /** 597179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 598179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 599179db1d7SKowalski, Kamil * bit count for Subnet Mask. 600179db1d7SKowalski, Kamil * 601179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 602179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 603179db1d7SKowalski, Kamil * 604179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 605179db1d7SKowalski, Kamil */ 6064a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 6071abe55efSEd Tanous uint8_t *bits = nullptr) 6081abe55efSEd Tanous { 609179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 610179db1d7SKowalski, Kamil 611179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 612179db1d7SKowalski, Kamil 6134a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 6141abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 6151abe55efSEd Tanous { 616179db1d7SKowalski, Kamil return false; 617179db1d7SKowalski, Kamil } 618179db1d7SKowalski, Kamil 6191abe55efSEd Tanous if (bits != nullptr) 6201abe55efSEd Tanous { 621179db1d7SKowalski, Kamil *bits = 0; 622179db1d7SKowalski, Kamil } 623179db1d7SKowalski, Kamil 624179db1d7SKowalski, Kamil char *endPtr; 625179db1d7SKowalski, Kamil long previousValue = 255; 626179db1d7SKowalski, Kamil bool firstZeroInByteHit; 6271abe55efSEd Tanous for (const std::string &byte : bytesInMask) 6281abe55efSEd Tanous { 6291abe55efSEd Tanous if (byte.empty()) 6301abe55efSEd Tanous { 6311db9ca37SKowalski, Kamil return false; 6321db9ca37SKowalski, Kamil } 6331db9ca37SKowalski, Kamil 634179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 6351db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 636179db1d7SKowalski, Kamil 6374a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 6384a0cb85cSEd Tanous // is not 100% number 6391abe55efSEd Tanous if (*endPtr != '\0') 6401abe55efSEd Tanous { 641179db1d7SKowalski, Kamil return false; 642179db1d7SKowalski, Kamil } 643179db1d7SKowalski, Kamil 644179db1d7SKowalski, Kamil // Value should be contained in byte 6451abe55efSEd Tanous if (value < 0 || value > 255) 6461abe55efSEd Tanous { 647179db1d7SKowalski, Kamil return false; 648179db1d7SKowalski, Kamil } 649179db1d7SKowalski, Kamil 6501abe55efSEd Tanous if (bits != nullptr) 6511abe55efSEd Tanous { 652179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 6531abe55efSEd Tanous if (previousValue != 255 && value != 0) 6541abe55efSEd Tanous { 655179db1d7SKowalski, Kamil return false; 656179db1d7SKowalski, Kamil } 657179db1d7SKowalski, Kamil 658179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 659179db1d7SKowalski, Kamil firstZeroInByteHit = false; 660179db1d7SKowalski, Kamil 661179db1d7SKowalski, Kamil // Count bits 6621abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 6631abe55efSEd Tanous { 6641abe55efSEd Tanous if (value & (1 << bitIdx)) 6651abe55efSEd Tanous { 6661abe55efSEd Tanous if (firstZeroInByteHit) 6671abe55efSEd Tanous { 668179db1d7SKowalski, Kamil // Continuity not preserved 669179db1d7SKowalski, Kamil return false; 6701abe55efSEd Tanous } 6711abe55efSEd Tanous else 6721abe55efSEd Tanous { 673179db1d7SKowalski, Kamil (*bits)++; 674179db1d7SKowalski, Kamil } 6751abe55efSEd Tanous } 6761abe55efSEd Tanous else 6771abe55efSEd Tanous { 678179db1d7SKowalski, Kamil firstZeroInByteHit = true; 679179db1d7SKowalski, Kamil } 680179db1d7SKowalski, Kamil } 681179db1d7SKowalski, Kamil } 682179db1d7SKowalski, Kamil 683179db1d7SKowalski, Kamil previousValue = value; 684179db1d7SKowalski, Kamil } 685179db1d7SKowalski, Kamil 686179db1d7SKowalski, Kamil return true; 687179db1d7SKowalski, Kamil } 688179db1d7SKowalski, Kamil 689179db1d7SKowalski, Kamil /** 69001784826SJohnathan Mantey * @brief Deletes given IPv4 interface 691179db1d7SKowalski, Kamil * 692179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 693179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 694179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 695179db1d7SKowalski, Kamil * 696179db1d7SKowalski, Kamil * @return None 697179db1d7SKowalski, Kamil */ 6984a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 6994a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 7001abe55efSEd Tanous { 70155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 702286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 7031abe55efSEd Tanous if (ec) 7041abe55efSEd Tanous { 705a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 7061abe55efSEd Tanous } 707179db1d7SKowalski, Kamil }, 708179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 709179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 710179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 711179db1d7SKowalski, Kamil } 712179db1d7SKowalski, Kamil 713179db1d7SKowalski, Kamil /** 71401784826SJohnathan Mantey * @brief Creates a static IPv4 entry 715179db1d7SKowalski, Kamil * 71601784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 71701784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 71801784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 71901784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 720179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 721179db1d7SKowalski, Kamil * 722179db1d7SKowalski, Kamil * @return None 723179db1d7SKowalski, Kamil */ 724b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 72501784826SJohnathan Mantey uint8_t prefixLength, const std::string &gateway, 726b01bf299SEd Tanous const std::string &address, 7274a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 7281abe55efSEd Tanous { 72901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 73001784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 7311abe55efSEd Tanous if (ec) 7321abe55efSEd Tanous { 733a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 734179db1d7SKowalski, Kamil } 73501784826SJohnathan Mantey }, 73601784826SJohnathan Mantey "xyz.openbmc_project.Network", 737179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 738179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 73901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 740179db1d7SKowalski, Kamil gateway); 741179db1d7SKowalski, Kamil } 742e48c0fc5SRavi Teja 743e48c0fc5SRavi Teja /** 74401784826SJohnathan Mantey * @brief Deletes the IPv4 entry for this interface and creates a replacement 74501784826SJohnathan Mantey * static IPv4 entry 74601784826SJohnathan Mantey * 74701784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 74801784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 74901784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 75001784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 75101784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 75201784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 75301784826SJohnathan Mantey * 75401784826SJohnathan Mantey * @return None 75501784826SJohnathan Mantey */ 75601784826SJohnathan Mantey inline void deleteAndCreateIPv4(const std::string &ifaceId, 75701784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 75801784826SJohnathan Mantey const std::string &gateway, 75901784826SJohnathan Mantey const std::string &address, 76001784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 76101784826SJohnathan Mantey { 76201784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 76301784826SJohnathan Mantey [asyncResp, ifaceId, address, prefixLength, 76401784826SJohnathan Mantey gateway](const boost::system::error_code ec) { 76501784826SJohnathan Mantey if (ec) 76601784826SJohnathan Mantey { 76701784826SJohnathan Mantey messages::internalError(asyncResp->res); 76801784826SJohnathan Mantey } 76901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 77001784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 77101784826SJohnathan Mantey if (ec) 77201784826SJohnathan Mantey { 77301784826SJohnathan Mantey messages::internalError(asyncResp->res); 77401784826SJohnathan Mantey } 77501784826SJohnathan Mantey }, 77601784826SJohnathan Mantey "xyz.openbmc_project.Network", 77701784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 77801784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 77901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, 78001784826SJohnathan Mantey prefixLength, gateway); 78101784826SJohnathan Mantey }, 78201784826SJohnathan Mantey "xyz.openbmc_project.Network", 78301784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + id, 78401784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 78501784826SJohnathan Mantey } 78601784826SJohnathan Mantey 78701784826SJohnathan Mantey /** 788e48c0fc5SRavi Teja * @brief Deletes given IPv6 789e48c0fc5SRavi Teja * 790e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 791e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 792e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 793e48c0fc5SRavi Teja * 794e48c0fc5SRavi Teja * @return None 795e48c0fc5SRavi Teja */ 796e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 797e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 798e48c0fc5SRavi Teja { 799e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 800286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 801e48c0fc5SRavi Teja if (ec) 802e48c0fc5SRavi Teja { 803e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 804e48c0fc5SRavi Teja } 805e48c0fc5SRavi Teja }, 806e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 807e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 808e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 809e48c0fc5SRavi Teja } 810e48c0fc5SRavi Teja 811e48c0fc5SRavi Teja /** 81201784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 81301784826SJohnathan Mantey * static IPv6 entry 81401784826SJohnathan Mantey * 81501784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 81601784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 81701784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 81801784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 81901784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 82001784826SJohnathan Mantey * 82101784826SJohnathan Mantey * @return None 82201784826SJohnathan Mantey */ 82301784826SJohnathan Mantey inline void deleteAndCreateIPv6(const std::string &ifaceId, 82401784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 82501784826SJohnathan Mantey const std::string &address, 82601784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 82701784826SJohnathan Mantey { 82801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 82901784826SJohnathan Mantey [asyncResp, ifaceId, address, 83001784826SJohnathan Mantey prefixLength](const boost::system::error_code ec) { 83101784826SJohnathan Mantey if (ec) 83201784826SJohnathan Mantey { 83301784826SJohnathan Mantey messages::internalError(asyncResp->res); 83401784826SJohnathan Mantey } 83501784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 83601784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 83701784826SJohnathan Mantey if (ec) 83801784826SJohnathan Mantey { 83901784826SJohnathan Mantey messages::internalError(asyncResp->res); 84001784826SJohnathan Mantey } 84101784826SJohnathan Mantey }, 84201784826SJohnathan Mantey "xyz.openbmc_project.Network", 84301784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 84401784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 84501784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, 84601784826SJohnathan Mantey prefixLength, ""); 84701784826SJohnathan Mantey }, 84801784826SJohnathan Mantey "xyz.openbmc_project.Network", 84901784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + id, 85001784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 85101784826SJohnathan Mantey } 85201784826SJohnathan Mantey 85301784826SJohnathan Mantey /** 854e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 855e48c0fc5SRavi Teja * 856e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 857e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 858e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 859e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 860e48c0fc5SRavi Teja * 861e48c0fc5SRavi Teja * @return None 862e48c0fc5SRavi Teja */ 86301784826SJohnathan Mantey inline void createIPv6(const std::string &ifaceId, uint8_t prefixLength, 86401784826SJohnathan Mantey const std::string &address, 865e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 866e48c0fc5SRavi Teja { 867e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 868e48c0fc5SRavi Teja if (ec) 869e48c0fc5SRavi Teja { 870e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 871e48c0fc5SRavi Teja } 872e48c0fc5SRavi Teja }; 873e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 874e48c0fc5SRavi Teja // does not have assosiated gateway property 875e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 876e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 877e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 878e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 879e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 880e48c0fc5SRavi Teja ""); 881e48c0fc5SRavi Teja } 882e48c0fc5SRavi Teja 883179db1d7SKowalski, Kamil /** 884179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 885179db1d7SKowalski, Kamil * Object 886179db1d7SKowalski, Kamil * from EntityManager Network Manager 8874a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 888179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 889179db1d7SKowalski, Kamil * into JSON 890179db1d7SKowalski, Kamil */ 891179db1d7SKowalski, Kamil template <typename CallbackFunc> 8924a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8931abe55efSEd Tanous CallbackFunc &&callback) 8941abe55efSEd Tanous { 89555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8964a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8971abe55efSEd Tanous const boost::system::error_code error_code, 8984a0cb85cSEd Tanous const GetManagedObjects &resp) { 89955c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 9004a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 901e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 902179db1d7SKowalski, Kamil 9031abe55efSEd Tanous if (error_code) 9041abe55efSEd Tanous { 90501784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 906179db1d7SKowalski, Kamil return; 907179db1d7SKowalski, Kamil } 908179db1d7SKowalski, Kamil 9094c9afe43SEd Tanous bool found = 9104a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 9114c9afe43SEd Tanous if (!found) 9124c9afe43SEd Tanous { 91301784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 9144c9afe43SEd Tanous return; 9154c9afe43SEd Tanous } 9164c9afe43SEd Tanous 91701784826SJohnathan Mantey extractIPData(ethiface_id, resp, ipv4Data); 918179db1d7SKowalski, Kamil // Fix global GW 9191abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 9201abe55efSEd Tanous { 921c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 922c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 923c619141bSRavi Teja (ipv4.origin == "DHCP")) 9241abe55efSEd Tanous { 9254a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 926179db1d7SKowalski, Kamil } 927179db1d7SKowalski, Kamil } 928179db1d7SKowalski, Kamil 92901784826SJohnathan Mantey extractIPV6Data(ethiface_id, resp, ipv6Data); 9304a0cb85cSEd Tanous // Finally make a callback with usefull data 93101784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 932179db1d7SKowalski, Kamil }, 933179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 934179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 935271584abSEd Tanous } 936179db1d7SKowalski, Kamil 937179db1d7SKowalski, Kamil /** 9389391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 9399391bb9cSRapkiewicz, Pawel * Manager 9401abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 9411abe55efSEd Tanous * into JSON. 9429391bb9cSRapkiewicz, Pawel */ 9439391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 9441abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 9451abe55efSEd Tanous { 94655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 9474a0cb85cSEd Tanous [callback{std::move(callback)}]( 9489391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 9494a0cb85cSEd Tanous GetManagedObjects &resp) { 9501abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 9511abe55efSEd Tanous // ethernet interfaces 9524c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 9534a0cb85cSEd Tanous iface_list.reserve(resp.size()); 9541abe55efSEd Tanous if (error_code) 9551abe55efSEd Tanous { 9564a0cb85cSEd Tanous callback(false, iface_list); 9579391bb9cSRapkiewicz, Pawel return; 9589391bb9cSRapkiewicz, Pawel } 9599391bb9cSRapkiewicz, Pawel 9609391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 9614a0cb85cSEd Tanous for (const auto &objpath : resp) 9621abe55efSEd Tanous { 9639391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 9644a0cb85cSEd Tanous for (const auto &interface : objpath.second) 9651abe55efSEd Tanous { 9661abe55efSEd Tanous // If interface is 9674a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9684a0cb85cSEd Tanous // what we're looking for. 9699391bb9cSRapkiewicz, Pawel if (interface.first == 9701abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9711abe55efSEd Tanous { 9724a0cb85cSEd Tanous // Cut out everyting until last "/", ... 9734a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9744a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9754a0cb85cSEd Tanous if (last_pos != std::string::npos) 9761abe55efSEd Tanous { 9779391bb9cSRapkiewicz, Pawel // and put it into output vector. 9784c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9799391bb9cSRapkiewicz, Pawel } 9809391bb9cSRapkiewicz, Pawel } 9819391bb9cSRapkiewicz, Pawel } 9829391bb9cSRapkiewicz, Pawel } 983a434f2bdSEd Tanous // Finally make a callback with useful data 9844a0cb85cSEd Tanous callback(true, iface_list); 9859391bb9cSRapkiewicz, Pawel }, 986aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 987aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 988271584abSEd Tanous } 9899391bb9cSRapkiewicz, Pawel 9909391bb9cSRapkiewicz, Pawel /** 9919391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9929391bb9cSRapkiewicz, Pawel */ 9931abe55efSEd Tanous class EthernetCollection : public Node 9941abe55efSEd Tanous { 9959391bb9cSRapkiewicz, Pawel public: 9964a0cb85cSEd Tanous template <typename CrowApp> 9971abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9984a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9991abe55efSEd Tanous { 1000588c3f0dSKowalski, Kamil entityPrivileges = { 1001588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1002e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1003e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1004e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1005e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1006e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10079391bb9cSRapkiewicz, Pawel } 10089391bb9cSRapkiewicz, Pawel 10099391bb9cSRapkiewicz, Pawel private: 10109391bb9cSRapkiewicz, Pawel /** 10119391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 10129391bb9cSRapkiewicz, Pawel */ 101355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 10141abe55efSEd Tanous const std::vector<std::string> ¶ms) override 10151abe55efSEd Tanous { 10160f74e643SEd Tanous res.jsonValue["@odata.type"] = 10170f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 10180f74e643SEd Tanous res.jsonValue["@odata.id"] = 10190f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 10200f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 10210f74e643SEd Tanous res.jsonValue["Description"] = 10220f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 10234c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 10244a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 10251abe55efSEd Tanous // preparation 1026f12894f8SJason M. Bills getEthernetIfaceList( 10274c9afe43SEd Tanous [asyncResp]( 10284c9afe43SEd Tanous const bool &success, 10294c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 10304a0cb85cSEd Tanous if (!success) 10311abe55efSEd Tanous { 10324c9afe43SEd Tanous messages::internalError(asyncResp->res); 10334a0cb85cSEd Tanous return; 10344a0cb85cSEd Tanous } 10354a0cb85cSEd Tanous 10364c9afe43SEd Tanous nlohmann::json &iface_array = 10374c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 10384a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 1039fda13ad2SSunitha Harish std::string tag = "_"; 10404a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 10411abe55efSEd Tanous { 1042fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 1043fda13ad2SSunitha Harish if (found == std::string::npos) 1044fda13ad2SSunitha Harish { 10454a0cb85cSEd Tanous iface_array.push_back( 10464a0cb85cSEd Tanous {{"@odata.id", 10474a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 10484a0cb85cSEd Tanous iface_item}}); 10499391bb9cSRapkiewicz, Pawel } 1050fda13ad2SSunitha Harish } 10514a0cb85cSEd Tanous 10524c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 10534c9afe43SEd Tanous iface_array.size(); 10544c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10554a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 10569391bb9cSRapkiewicz, Pawel }); 10579391bb9cSRapkiewicz, Pawel } 10589391bb9cSRapkiewicz, Pawel }; 10599391bb9cSRapkiewicz, Pawel 10609391bb9cSRapkiewicz, Pawel /** 10619391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 10629391bb9cSRapkiewicz, Pawel */ 10631abe55efSEd Tanous class EthernetInterface : public Node 10641abe55efSEd Tanous { 10659391bb9cSRapkiewicz, Pawel public: 10669391bb9cSRapkiewicz, Pawel /* 10679391bb9cSRapkiewicz, Pawel * Default Constructor 10689391bb9cSRapkiewicz, Pawel */ 10694a0cb85cSEd Tanous template <typename CrowApp> 10701abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10714a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10721abe55efSEd Tanous std::string()) 10731abe55efSEd Tanous { 1074588c3f0dSKowalski, Kamil entityPrivileges = { 1075588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1076e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1077e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1078e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1079e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1080e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10819391bb9cSRapkiewicz, Pawel } 10829391bb9cSRapkiewicz, Pawel 1083e439f0f8SKowalski, Kamil private: 1084bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10854a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10861abe55efSEd Tanous { 1087bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1088bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1089bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10904a0cb85cSEd Tanous if (ec) 10914a0cb85cSEd Tanous { 1092a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10931abe55efSEd Tanous } 1094bc0bd6e0SEd Tanous }, 1095bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1096bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1097bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1098bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1099abf2add6SEd Tanous std::variant<std::string>(hostname)); 1100588c3f0dSKowalski, Kamil } 1101588c3f0dSKowalski, Kamil 1102d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1103d577665bSRatan Gupta const std::string &macAddress, 1104d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1105d577665bSRatan Gupta { 1106d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1107d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1108d577665bSRatan Gupta if (ec) 1109d577665bSRatan Gupta { 1110d577665bSRatan Gupta messages::internalError(asyncResp->res); 1111d577665bSRatan Gupta return; 1112d577665bSRatan Gupta } 1113d577665bSRatan Gupta }, 1114d577665bSRatan Gupta "xyz.openbmc_project.Network", 1115d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1116d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1117d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1118d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1119d577665bSRatan Gupta } 1120286b9118SJohnathan Mantey 1121da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 11221f8c7b5dSJohnathan Mantey const std::string &propertyName, const bool v4Value, 11231f8c7b5dSJohnathan Mantey const bool v6Value, 1124da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1125da131a9aSJennifer Lee { 11261f8c7b5dSJohnathan Mantey const std::string dhcp = GetDHCPEnabledEnumeration(v4Value, v6Value); 1127da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1128da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1129da131a9aSJennifer Lee if (ec) 1130da131a9aSJennifer Lee { 1131da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1132da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1133da131a9aSJennifer Lee return; 1134da131a9aSJennifer Lee } 1135da131a9aSJennifer Lee }, 1136da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1137da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1138da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1139da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 11401f8c7b5dSJohnathan Mantey std::variant<std::string>{dhcp}); 1141da131a9aSJennifer Lee } 11421f8c7b5dSJohnathan Mantey 1143*eeedda23SJohnathan Mantey void setEthernetInterfaceBoolProperty( 1144*eeedda23SJohnathan Mantey const std::string &ifaceId, const std::string &propertyName, 1145*eeedda23SJohnathan Mantey const bool &value, const std::shared_ptr<AsyncResp> asyncResp) 1146*eeedda23SJohnathan Mantey { 1147*eeedda23SJohnathan Mantey crow::connections::systemBus->async_method_call( 1148*eeedda23SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1149*eeedda23SJohnathan Mantey if (ec) 1150*eeedda23SJohnathan Mantey { 1151*eeedda23SJohnathan Mantey BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1152*eeedda23SJohnathan Mantey messages::internalError(asyncResp->res); 1153*eeedda23SJohnathan Mantey return; 1154*eeedda23SJohnathan Mantey } 1155*eeedda23SJohnathan Mantey }, 1156*eeedda23SJohnathan Mantey "xyz.openbmc_project.Network", 1157*eeedda23SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 1158*eeedda23SJohnathan Mantey "org.freedesktop.DBus.Properties", "Set", 1159*eeedda23SJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface", propertyName, 1160*eeedda23SJohnathan Mantey std::variant<bool>{value}); 1161*eeedda23SJohnathan Mantey } 1162*eeedda23SJohnathan Mantey 1163da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1164da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1165da131a9aSJennifer Lee { 1166da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1167da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1168da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1169da131a9aSJennifer Lee if (ec) 1170da131a9aSJennifer Lee { 1171da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1172da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1173da131a9aSJennifer Lee return; 1174da131a9aSJennifer Lee } 1175da131a9aSJennifer Lee }, 1176da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1177da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1178da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1179da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1180da131a9aSJennifer Lee std::variant<bool>{value}); 1181da131a9aSJennifer Lee } 1182d577665bSRatan Gupta 11831f8c7b5dSJohnathan Mantey void handleDHCPPatch(const std::string &ifaceId, 11841f8c7b5dSJohnathan Mantey const EthernetInterfaceData ðData, 11851f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms, DHCPParameters v6dhcpParms, 1186da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1187da131a9aSJennifer Lee { 11881f8c7b5dSJohnathan Mantey bool ipv4Active = translateDHCPEnabledToBool(ethData.DHCPEnabled, true); 11891f8c7b5dSJohnathan Mantey bool ipv6Active = 11901f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, false); 1191da131a9aSJennifer Lee 11921f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 11931f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 11941f8c7b5dSJohnathan Mantey 11951f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 11961f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1197da131a9aSJennifer Lee { 11981f8c7b5dSJohnathan Mantey if ((*v6dhcpParms.dhcpv6OperatingMode != "Stateful") && 11991f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Stateless") && 12001f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 12011f8c7b5dSJohnathan Mantey { 12021f8c7b5dSJohnathan Mantey messages::propertyValueFormatError( 12031f8c7b5dSJohnathan Mantey asyncResp->res, *v6dhcpParms.dhcpv6OperatingMode, 12041f8c7b5dSJohnathan Mantey "OperatingMode"); 1205da131a9aSJennifer Lee return; 1206da131a9aSJennifer Lee } 12071f8c7b5dSJohnathan Mantey nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Stateful"); 12081f8c7b5dSJohnathan Mantey } 12091f8c7b5dSJohnathan Mantey else 1210da131a9aSJennifer Lee { 12111f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 12121f8c7b5dSJohnathan Mantey } 12131f8c7b5dSJohnathan Mantey 12141f8c7b5dSJohnathan Mantey bool nextDNS{}; 12151f8c7b5dSJohnathan Mantey if (v4dhcpParms.useDNSServers && v6dhcpParms.useDNSServers) 12161f8c7b5dSJohnathan Mantey { 12171f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useDNSServers != *v6dhcpParms.useDNSServers) 12181f8c7b5dSJohnathan Mantey { 12191f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 12201f8c7b5dSJohnathan Mantey return; 12211f8c7b5dSJohnathan Mantey } 12221f8c7b5dSJohnathan Mantey nextDNS = *v4dhcpParms.useDNSServers; 12231f8c7b5dSJohnathan Mantey } 12241f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useDNSServers) 12251f8c7b5dSJohnathan Mantey { 12261f8c7b5dSJohnathan Mantey nextDNS = *v4dhcpParms.useDNSServers; 12271f8c7b5dSJohnathan Mantey } 12281f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useDNSServers) 12291f8c7b5dSJohnathan Mantey { 12301f8c7b5dSJohnathan Mantey nextDNS = *v6dhcpParms.useDNSServers; 12311f8c7b5dSJohnathan Mantey } 12321f8c7b5dSJohnathan Mantey else 12331f8c7b5dSJohnathan Mantey { 12341f8c7b5dSJohnathan Mantey nextDNS = ethData.DNSEnabled; 12351f8c7b5dSJohnathan Mantey } 12361f8c7b5dSJohnathan Mantey 12371f8c7b5dSJohnathan Mantey bool nextNTP{}; 12381f8c7b5dSJohnathan Mantey if (v4dhcpParms.useNTPServers && v6dhcpParms.useNTPServers) 12391f8c7b5dSJohnathan Mantey { 12401f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useNTPServers != *v6dhcpParms.useNTPServers) 12411f8c7b5dSJohnathan Mantey { 12421f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 12431f8c7b5dSJohnathan Mantey return; 12441f8c7b5dSJohnathan Mantey } 12451f8c7b5dSJohnathan Mantey nextNTP = *v4dhcpParms.useNTPServers; 12461f8c7b5dSJohnathan Mantey } 12471f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useNTPServers) 12481f8c7b5dSJohnathan Mantey { 12491f8c7b5dSJohnathan Mantey nextNTP = *v4dhcpParms.useNTPServers; 12501f8c7b5dSJohnathan Mantey } 12511f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useNTPServers) 12521f8c7b5dSJohnathan Mantey { 12531f8c7b5dSJohnathan Mantey nextNTP = *v6dhcpParms.useNTPServers; 12541f8c7b5dSJohnathan Mantey } 12551f8c7b5dSJohnathan Mantey else 12561f8c7b5dSJohnathan Mantey { 12571f8c7b5dSJohnathan Mantey nextNTP = ethData.NTPEnabled; 12581f8c7b5dSJohnathan Mantey } 12591f8c7b5dSJohnathan Mantey 12601f8c7b5dSJohnathan Mantey bool nextUseDomain{}; 12611f8c7b5dSJohnathan Mantey if (v4dhcpParms.useUseDomainName && v6dhcpParms.useUseDomainName) 12621f8c7b5dSJohnathan Mantey { 12631f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useUseDomainName != *v6dhcpParms.useUseDomainName) 12641f8c7b5dSJohnathan Mantey { 12651f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 12661f8c7b5dSJohnathan Mantey return; 12671f8c7b5dSJohnathan Mantey } 12681f8c7b5dSJohnathan Mantey nextUseDomain = *v4dhcpParms.useUseDomainName; 12691f8c7b5dSJohnathan Mantey } 12701f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useUseDomainName) 12711f8c7b5dSJohnathan Mantey { 12721f8c7b5dSJohnathan Mantey nextUseDomain = *v4dhcpParms.useUseDomainName; 12731f8c7b5dSJohnathan Mantey } 12741f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useUseDomainName) 12751f8c7b5dSJohnathan Mantey { 12761f8c7b5dSJohnathan Mantey nextUseDomain = *v6dhcpParms.useUseDomainName; 12771f8c7b5dSJohnathan Mantey } 12781f8c7b5dSJohnathan Mantey else 12791f8c7b5dSJohnathan Mantey { 12801f8c7b5dSJohnathan Mantey nextUseDomain = ethData.HostNameEnabled; 12811f8c7b5dSJohnathan Mantey } 12821f8c7b5dSJohnathan Mantey 1283da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 12841f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 12851f8c7b5dSJohnathan Mantey asyncResp); 1286da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 12871f8c7b5dSJohnathan Mantey setDHCPv4Config("DNSEnabled", nextDNS, asyncResp); 1288da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 12891f8c7b5dSJohnathan Mantey setDHCPv4Config("NTPEnabled", nextNTP, asyncResp); 12901f8c7b5dSJohnathan Mantey BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 12911f8c7b5dSJohnathan Mantey setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp); 1292da131a9aSJennifer Lee } 129301784826SJohnathan Mantey 129401784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator 129501784826SJohnathan Mantey GetNextStaticIPEntry( 129601784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator head, 129701784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator end) 129801784826SJohnathan Mantey { 129901784826SJohnathan Mantey for (; head != end; head++) 130001784826SJohnathan Mantey { 130101784826SJohnathan Mantey if (head->origin == "Static") 130201784826SJohnathan Mantey { 130301784826SJohnathan Mantey return head; 130401784826SJohnathan Mantey } 130501784826SJohnathan Mantey } 130601784826SJohnathan Mantey return end; 130701784826SJohnathan Mantey } 130801784826SJohnathan Mantey 130901784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator 131001784826SJohnathan Mantey GetNextStaticIPEntry( 131101784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator head, 131201784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator end) 131301784826SJohnathan Mantey { 131401784826SJohnathan Mantey for (; head != end; head++) 131501784826SJohnathan Mantey { 131601784826SJohnathan Mantey if (head->origin == "Static") 131701784826SJohnathan Mantey { 131801784826SJohnathan Mantey return head; 131901784826SJohnathan Mantey } 132001784826SJohnathan Mantey } 132101784826SJohnathan Mantey return end; 132201784826SJohnathan Mantey } 132301784826SJohnathan Mantey 1324d1d50814SRavi Teja void handleIPv4StaticPatch( 1325f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 132601784826SJohnathan Mantey const boost::container::flat_set<IPv4AddressData> &ipv4Data, 13274a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 13281abe55efSEd Tanous { 132901784826SJohnathan Mantey if ((!input.is_array()) || input.empty()) 1330f476acbfSRatan Gupta { 1331f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1332d1d50814SRavi Teja "IPv4StaticAddresses"); 1333f476acbfSRatan Gupta return; 1334f476acbfSRatan Gupta } 1335f476acbfSRatan Gupta 1336271584abSEd Tanous unsigned entryIdx = 1; 133701784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 133801784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 133901784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 134001784826SJohnathan Mantey // into the NIC. 134101784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator NICIPentry = 134201784826SJohnathan Mantey GetNextStaticIPEntry(ipv4Data.cbegin(), ipv4Data.cend()); 134301784826SJohnathan Mantey 1344537174c4SEd Tanous for (nlohmann::json &thisJson : input) 13451abe55efSEd Tanous { 13464a0cb85cSEd Tanous std::string pathString = 1347d1d50814SRavi Teja "IPv4StaticAddresses/" + std::to_string(entryIdx); 1348179db1d7SKowalski, Kamil 134901784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1350f476acbfSRatan Gupta { 1351537174c4SEd Tanous std::optional<std::string> address; 1352537174c4SEd Tanous std::optional<std::string> subnetMask; 1353537174c4SEd Tanous std::optional<std::string> gateway; 1354537174c4SEd Tanous 1355537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 13567e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 13577e27d832SJohnathan Mantey "Gateway", gateway)) 1358537174c4SEd Tanous { 135901784826SJohnathan Mantey messages::propertyValueFormatError( 136001784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1361537174c4SEd Tanous return; 1362179db1d7SKowalski, Kamil } 1363179db1d7SKowalski, Kamil 136401784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 136501784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 136601784826SJohnathan Mantey // current state of the interface. Merge existing state into the 136701784826SJohnathan Mantey // current request. 1368271584abSEd Tanous const std::string *addr = nullptr; 1369271584abSEd Tanous const std::string *gw = nullptr; 137001784826SJohnathan Mantey uint8_t prefixLength = 0; 137101784826SJohnathan Mantey bool errorInEntry = false; 1372537174c4SEd Tanous if (address) 13731abe55efSEd Tanous { 137401784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*address)) 13751abe55efSEd Tanous { 137601784826SJohnathan Mantey addr = &(*address); 13774a0cb85cSEd Tanous } 137801784826SJohnathan Mantey else 137901784826SJohnathan Mantey { 138001784826SJohnathan Mantey messages::propertyValueFormatError( 138101784826SJohnathan Mantey asyncResp->res, *address, pathString + "/Address"); 138201784826SJohnathan Mantey errorInEntry = true; 138301784826SJohnathan Mantey } 138401784826SJohnathan Mantey } 138501784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 138601784826SJohnathan Mantey { 138701784826SJohnathan Mantey addr = &(NICIPentry->address); 138801784826SJohnathan Mantey } 138901784826SJohnathan Mantey else 139001784826SJohnathan Mantey { 139101784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 139201784826SJohnathan Mantey pathString + "/Address"); 139301784826SJohnathan Mantey errorInEntry = true; 13944a0cb85cSEd Tanous } 13954a0cb85cSEd Tanous 1396537174c4SEd Tanous if (subnetMask) 13974a0cb85cSEd Tanous { 1398537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 13994a0cb85cSEd Tanous { 1400f12894f8SJason M. Bills messages::propertyValueFormatError( 1401537174c4SEd Tanous asyncResp->res, *subnetMask, 14024a0cb85cSEd Tanous pathString + "/SubnetMask"); 140301784826SJohnathan Mantey errorInEntry = true; 14044a0cb85cSEd Tanous } 14054a0cb85cSEd Tanous } 140601784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 14074a0cb85cSEd Tanous { 140801784826SJohnathan Mantey if (!ipv4VerifyIpAndGetBitcount(NICIPentry->netmask, 140901784826SJohnathan Mantey &prefixLength)) 14104a0cb85cSEd Tanous { 141101784826SJohnathan Mantey messages::propertyValueFormatError( 141201784826SJohnathan Mantey asyncResp->res, NICIPentry->netmask, 141301784826SJohnathan Mantey pathString + "/SubnetMask"); 141401784826SJohnathan Mantey errorInEntry = true; 14154a0cb85cSEd Tanous } 14164a0cb85cSEd Tanous } 14171abe55efSEd Tanous else 14181abe55efSEd Tanous { 141901784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 142001784826SJohnathan Mantey pathString + "/SubnetMask"); 142101784826SJohnathan Mantey errorInEntry = true; 142201784826SJohnathan Mantey } 142301784826SJohnathan Mantey 142401784826SJohnathan Mantey if (gateway) 142501784826SJohnathan Mantey { 142601784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*gateway)) 142701784826SJohnathan Mantey { 142801784826SJohnathan Mantey gw = &(*gateway); 142901784826SJohnathan Mantey } 143001784826SJohnathan Mantey else 143101784826SJohnathan Mantey { 143201784826SJohnathan Mantey messages::propertyValueFormatError( 143301784826SJohnathan Mantey asyncResp->res, *gateway, pathString + "/Gateway"); 143401784826SJohnathan Mantey errorInEntry = true; 143501784826SJohnathan Mantey } 143601784826SJohnathan Mantey } 143701784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 143801784826SJohnathan Mantey { 143901784826SJohnathan Mantey gw = &NICIPentry->gateway; 144001784826SJohnathan Mantey } 144101784826SJohnathan Mantey else 14421abe55efSEd Tanous { 1443a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 14444a0cb85cSEd Tanous pathString + "/Gateway"); 144501784826SJohnathan Mantey errorInEntry = true; 14464a0cb85cSEd Tanous } 14474a0cb85cSEd Tanous 144801784826SJohnathan Mantey if (errorInEntry) 14491abe55efSEd Tanous { 145001784826SJohnathan Mantey return; 14514a0cb85cSEd Tanous } 14524a0cb85cSEd Tanous 145301784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 14541abe55efSEd Tanous { 1455271584abSEd Tanous if (gw != nullptr || addr != nullptr) 1456271584abSEd Tanous { 1457271584abSEd Tanous // Shouldn't be possible based on errorInEntry, but 1458271584abSEd Tanous // it flags -wmaybe-uninitialized in the compiler, 1459271584abSEd Tanous // so defend against that 1460271584abSEd Tanous return; 1461271584abSEd Tanous } 146201784826SJohnathan Mantey deleteAndCreateIPv4(ifaceId, NICIPentry->id, prefixLength, 146301784826SJohnathan Mantey *gw, *addr, asyncResp); 146401784826SJohnathan Mantey NICIPentry = 146501784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 1466588c3f0dSKowalski, Kamil } 146701784826SJohnathan Mantey else 146801784826SJohnathan Mantey { 146901784826SJohnathan Mantey createIPv4(ifaceId, entryIdx, prefixLength, *gateway, 147001784826SJohnathan Mantey *address, asyncResp); 14714a0cb85cSEd Tanous } 14724a0cb85cSEd Tanous entryIdx++; 14734a0cb85cSEd Tanous } 147401784826SJohnathan Mantey else 147501784826SJohnathan Mantey { 147601784826SJohnathan Mantey if (NICIPentry == ipv4Data.cend()) 147701784826SJohnathan Mantey { 147801784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 147901784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 148001784826SJohnathan Mantey // in error, so bail out. 148101784826SJohnathan Mantey if (thisJson.is_null()) 148201784826SJohnathan Mantey { 148301784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 148401784826SJohnathan Mantey return; 148501784826SJohnathan Mantey } 148601784826SJohnathan Mantey else 148701784826SJohnathan Mantey { 148801784826SJohnathan Mantey messages::propertyValueFormatError( 148901784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 149001784826SJohnathan Mantey return; 149101784826SJohnathan Mantey } 149201784826SJohnathan Mantey } 149301784826SJohnathan Mantey 149401784826SJohnathan Mantey if (thisJson.is_null()) 149501784826SJohnathan Mantey { 149601784826SJohnathan Mantey deleteIPv4(ifaceId, NICIPentry->id, asyncResp); 149701784826SJohnathan Mantey } 149801784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 149901784826SJohnathan Mantey { 150001784826SJohnathan Mantey NICIPentry = 150101784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 150201784826SJohnathan Mantey } 150301784826SJohnathan Mantey entryIdx++; 150401784826SJohnathan Mantey } 150501784826SJohnathan Mantey } 15064a0cb85cSEd Tanous } 15074a0cb85cSEd Tanous 1508f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1509f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1510f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1511f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1512f85837bfSRAJESWARAN THILLAIGOVINDAN { 1513f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1514286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1515f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1516f85837bfSRAJESWARAN THILLAIGOVINDAN { 1517f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1518f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1519f85837bfSRAJESWARAN THILLAIGOVINDAN } 1520f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1521f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1522f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1523f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1524f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1525f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1526f85837bfSRAJESWARAN THILLAIGOVINDAN } 1527f85837bfSRAJESWARAN THILLAIGOVINDAN 1528e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1529e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 153001784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1531e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1532e48c0fc5SRavi Teja { 153301784826SJohnathan Mantey if (!input.is_array() || input.empty()) 1534e48c0fc5SRavi Teja { 1535e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1536e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1537e48c0fc5SRavi Teja return; 1538e48c0fc5SRavi Teja } 1539271584abSEd Tanous size_t entryIdx = 1; 154001784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator NICIPentry = 154101784826SJohnathan Mantey GetNextStaticIPEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1542e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1543e48c0fc5SRavi Teja { 1544e48c0fc5SRavi Teja std::string pathString = 1545e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1546e48c0fc5SRavi Teja 154701784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1548e48c0fc5SRavi Teja { 1549e48c0fc5SRavi Teja std::optional<std::string> address; 1550e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1551e48c0fc5SRavi Teja 1552e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1553e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1554e48c0fc5SRavi Teja { 155501784826SJohnathan Mantey messages::propertyValueFormatError( 155601784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1557e48c0fc5SRavi Teja return; 1558e48c0fc5SRavi Teja } 1559e48c0fc5SRavi Teja 156001784826SJohnathan Mantey const std::string *addr; 156101784826SJohnathan Mantey uint8_t prefix; 156201784826SJohnathan Mantey 156301784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 156401784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 156501784826SJohnathan Mantey // current state of the interface. Merge existing state into the 156601784826SJohnathan Mantey // current request. 1567e48c0fc5SRavi Teja if (address) 1568e48c0fc5SRavi Teja { 156901784826SJohnathan Mantey addr = &(*address); 1570e48c0fc5SRavi Teja } 157101784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 157201784826SJohnathan Mantey { 157301784826SJohnathan Mantey addr = &(NICIPentry->address); 157401784826SJohnathan Mantey } 157501784826SJohnathan Mantey else 157601784826SJohnathan Mantey { 157701784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 157801784826SJohnathan Mantey pathString + "/Address"); 157901784826SJohnathan Mantey return; 1580e48c0fc5SRavi Teja } 1581e48c0fc5SRavi Teja 1582e48c0fc5SRavi Teja if (prefixLength) 1583e48c0fc5SRavi Teja { 158401784826SJohnathan Mantey prefix = *prefixLength; 158501784826SJohnathan Mantey } 158601784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 1587e48c0fc5SRavi Teja { 158801784826SJohnathan Mantey prefix = NICIPentry->prefixLength; 1589e48c0fc5SRavi Teja } 1590e48c0fc5SRavi Teja else 1591e48c0fc5SRavi Teja { 1592e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1593e48c0fc5SRavi Teja pathString + "/PrefixLength"); 159401784826SJohnathan Mantey return; 1595e48c0fc5SRavi Teja } 1596e48c0fc5SRavi Teja 159701784826SJohnathan Mantey if (NICIPentry != ipv6Data.end()) 1598e48c0fc5SRavi Teja { 159901784826SJohnathan Mantey deleteAndCreateIPv6(ifaceId, NICIPentry->id, prefix, *addr, 1600e48c0fc5SRavi Teja asyncResp); 160101784826SJohnathan Mantey NICIPentry = 160201784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 160301784826SJohnathan Mantey } 160401784826SJohnathan Mantey else 160501784826SJohnathan Mantey { 160601784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1607e48c0fc5SRavi Teja } 1608e48c0fc5SRavi Teja entryIdx++; 1609e48c0fc5SRavi Teja } 161001784826SJohnathan Mantey else 161101784826SJohnathan Mantey { 161201784826SJohnathan Mantey if (NICIPentry == ipv6Data.end()) 161301784826SJohnathan Mantey { 161401784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 161501784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 161601784826SJohnathan Mantey // in error, so bail out. 161701784826SJohnathan Mantey if (thisJson.is_null()) 161801784826SJohnathan Mantey { 161901784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 162001784826SJohnathan Mantey return; 162101784826SJohnathan Mantey } 162201784826SJohnathan Mantey else 162301784826SJohnathan Mantey { 162401784826SJohnathan Mantey messages::propertyValueFormatError( 162501784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 162601784826SJohnathan Mantey return; 162701784826SJohnathan Mantey } 162801784826SJohnathan Mantey } 162901784826SJohnathan Mantey 163001784826SJohnathan Mantey if (thisJson.is_null()) 163101784826SJohnathan Mantey { 163201784826SJohnathan Mantey deleteIPv6(ifaceId, NICIPentry->id, asyncResp); 163301784826SJohnathan Mantey } 163401784826SJohnathan Mantey if (NICIPentry != ipv6Data.cend()) 163501784826SJohnathan Mantey { 163601784826SJohnathan Mantey NICIPentry = 163701784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 163801784826SJohnathan Mantey } 163901784826SJohnathan Mantey entryIdx++; 164001784826SJohnathan Mantey } 164101784826SJohnathan Mantey } 1642e48c0fc5SRavi Teja } 1643e48c0fc5SRavi Teja 16440f74e643SEd Tanous void parseInterfaceData( 1645*eeedda23SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp, const std::string &iface_id, 16460f74e643SEd Tanous const EthernetInterfaceData ðData, 1647e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 164801784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 16494a0cb85cSEd Tanous { 1650*eeedda23SJohnathan Mantey constexpr const std::array<const char *, 1> inventoryForEthernet = { 1651*eeedda23SJohnathan Mantey "xyz.openbmc_project.Inventory.Item.Ethernet"}; 1652*eeedda23SJohnathan Mantey 1653*eeedda23SJohnathan Mantey nlohmann::json &json_response = asyncResp->res.jsonValue; 16544a0cb85cSEd Tanous json_response["Id"] = iface_id; 16554a0cb85cSEd Tanous json_response["@odata.id"] = 16564a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1657*eeedda23SJohnathan Mantey json_response["InterfaceEnabled"] = ethData.nicEnabled; 1658*eeedda23SJohnathan Mantey 1659*eeedda23SJohnathan Mantey auto health = std::make_shared<HealthPopulate>(asyncResp); 1660*eeedda23SJohnathan Mantey 1661*eeedda23SJohnathan Mantey crow::connections::systemBus->async_method_call( 1662*eeedda23SJohnathan Mantey [health](const boost::system::error_code ec, 1663*eeedda23SJohnathan Mantey std::vector<std::string> &resp) { 1664*eeedda23SJohnathan Mantey if (ec) 1665029573d4SEd Tanous { 1666*eeedda23SJohnathan Mantey return; 1667*eeedda23SJohnathan Mantey } 1668*eeedda23SJohnathan Mantey 1669*eeedda23SJohnathan Mantey health->inventory = std::move(resp); 1670*eeedda23SJohnathan Mantey }, 1671*eeedda23SJohnathan Mantey "xyz.openbmc_project.ObjectMapper", 1672*eeedda23SJohnathan Mantey "/xyz/openbmc_project/object_mapper", 1673*eeedda23SJohnathan Mantey "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", "/", 1674*eeedda23SJohnathan Mantey int32_t(0), inventoryForEthernet); 1675*eeedda23SJohnathan Mantey 1676*eeedda23SJohnathan Mantey health->populate(); 1677*eeedda23SJohnathan Mantey 1678*eeedda23SJohnathan Mantey if (ethData.nicEnabled) 1679*eeedda23SJohnathan Mantey { 1680*eeedda23SJohnathan Mantey json_response["LinkStatus"] = "LinkUp"; 1681*eeedda23SJohnathan Mantey json_response["Status"]["State"] = "Enabled"; 1682029573d4SEd Tanous } 1683029573d4SEd Tanous else 1684029573d4SEd Tanous { 1685*eeedda23SJohnathan Mantey json_response["LinkStatus"] = "NoLink"; 1686*eeedda23SJohnathan Mantey json_response["Status"]["State"] = "Disabled"; 1687029573d4SEd Tanous } 1688aa05fb27SJohnathan Mantey 1689aa05fb27SJohnathan Mantey json_response["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 16904a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 16914a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 16921f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["DHCPEnabled"] = 16931f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, true); 16941f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseNTPServers"] = ethData.NTPEnabled; 16951f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseDNSServers"] = ethData.DNSEnabled; 16961f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseDomainName"] = ethData.HostNameEnabled; 16971f8c7b5dSJohnathan Mantey 16981f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["OperatingMode"] = 16991f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, false) ? "Stateful" 17001f8c7b5dSJohnathan Mantey : "Disabled"; 17011f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseNTPServers"] = ethData.NTPEnabled; 17021f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseDNSServers"] = ethData.DNSEnabled; 17031f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseDomainName"] = ethData.HostNameEnabled; 17042a133282Smanojkiraneda 17054a0cb85cSEd Tanous if (!ethData.hostname.empty()) 17064a0cb85cSEd Tanous { 17074a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 1708d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1709d24bfc7aSJennifer Lee { 1710d24bfc7aSJennifer Lee json_response["FQDN"] = 1711d24bfc7aSJennifer Lee ethData.hostname + "." + ethData.domainnames[0]; 1712d24bfc7aSJennifer Lee } 17134a0cb85cSEd Tanous } 17144a0cb85cSEd Tanous 1715fda13ad2SSunitha Harish json_response["VLANs"] = { 1716fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1717fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1718fda13ad2SSunitha Harish 17191f8c7b5dSJohnathan Mantey if (translateDHCPEnabledToBool(ethData.DHCPEnabled, true) && 17201f8c7b5dSJohnathan Mantey ethData.DNSEnabled) 172195f8646eSManojkiran Eda { 17221f8c7b5dSJohnathan Mantey json_response["StaticNameServers"] = nlohmann::json::array(); 172395f8646eSManojkiran Eda } 172495f8646eSManojkiran Eda else 172595f8646eSManojkiran Eda { 17261f8c7b5dSJohnathan Mantey json_response["StaticNameServers"] = ethData.nameservers; 172795f8646eSManojkiran Eda } 17284a0cb85cSEd Tanous 17294a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 173001784826SJohnathan Mantey nlohmann::json &ipv4_static_array = 173101784826SJohnathan Mantey json_response["IPv4StaticAddresses"]; 17324a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 173301784826SJohnathan Mantey ipv4_static_array = nlohmann::json::array(); 17344a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 17354a0cb85cSEd Tanous { 1736fa5053a6SGunnar Mills 1737fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1738fa5053a6SGunnar Mills if (gatewayStr.empty()) 1739fa5053a6SGunnar Mills { 1740fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1741fa5053a6SGunnar Mills } 1742fa5053a6SGunnar Mills 17434a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 17444a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1745029573d4SEd Tanous {"Address", ipv4_config.address}, 1746fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 174701784826SJohnathan Mantey if (ipv4_config.origin == "Static") 1748d1d50814SRavi Teja { 1749d1d50814SRavi Teja ipv4_static_array.push_back( 175001784826SJohnathan Mantey {{"AddressOrigin", ipv4_config.origin}, 175101784826SJohnathan Mantey {"SubnetMask", ipv4_config.netmask}, 175201784826SJohnathan Mantey {"Address", ipv4_config.address}, 1753d1d50814SRavi Teja {"Gateway", gatewayStr}}); 1754d1d50814SRavi Teja } 175501784826SJohnathan Mantey } 1756d1d50814SRavi Teja 17579a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1758e48c0fc5SRavi Teja 1759e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 176001784826SJohnathan Mantey nlohmann::json &ipv6_static_array = 176101784826SJohnathan Mantey json_response["IPv6StaticAddresses"]; 1762e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 176301784826SJohnathan Mantey ipv6_static_array = nlohmann::json::array(); 1764e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1765e48c0fc5SRavi Teja { 1766e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1767e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1768e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 176901784826SJohnathan Mantey if (ipv6_config.origin == "Static") 1770e48c0fc5SRavi Teja { 1771e48c0fc5SRavi Teja ipv6_static_array.push_back( 177201784826SJohnathan Mantey {{"Address", ipv6_config.address}, 177301784826SJohnathan Mantey {"PrefixLength", ipv6_config.prefixLength}, 177401784826SJohnathan Mantey {"AddressOrigin", ipv6_config.origin}}); 177501784826SJohnathan Mantey } 1776e48c0fc5SRavi Teja } 1777588c3f0dSKowalski, Kamil } 1778588c3f0dSKowalski, Kamil 17799391bb9cSRapkiewicz, Pawel /** 17809391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 17819391bb9cSRapkiewicz, Pawel */ 178255c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 17831abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17841abe55efSEd Tanous { 17854a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17861abe55efSEd Tanous if (params.size() != 1) 17871abe55efSEd Tanous { 1788f12894f8SJason M. Bills messages::internalError(asyncResp->res); 17899391bb9cSRapkiewicz, Pawel return; 17909391bb9cSRapkiewicz, Pawel } 17919391bb9cSRapkiewicz, Pawel 17924a0cb85cSEd Tanous getEthernetIfaceData( 17934a0cb85cSEd Tanous params[0], 17944a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 17954a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1796e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 179701784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 17984a0cb85cSEd Tanous if (!success) 17991abe55efSEd Tanous { 18001abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18011abe55efSEd Tanous // object, and other errors 1802f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1803f12894f8SJason M. Bills "EthernetInterface", iface_id); 18044a0cb85cSEd Tanous return; 18059391bb9cSRapkiewicz, Pawel } 18064c9afe43SEd Tanous 18070f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1808fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 18090f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 18100f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 18110f74e643SEd Tanous "Management Network Interface"; 18120f74e643SEd Tanous 1813*eeedda23SJohnathan Mantey parseInterfaceData(asyncResp, iface_id, ethData, ipv4Data, 1814*eeedda23SJohnathan Mantey ipv6Data); 18159391bb9cSRapkiewicz, Pawel }); 18169391bb9cSRapkiewicz, Pawel } 18179391bb9cSRapkiewicz, Pawel 181855c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 18191abe55efSEd Tanous const std::vector<std::string> ¶ms) override 18201abe55efSEd Tanous { 18214a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 18221abe55efSEd Tanous if (params.size() != 1) 18231abe55efSEd Tanous { 1824f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1825588c3f0dSKowalski, Kamil return; 1826588c3f0dSKowalski, Kamil } 1827588c3f0dSKowalski, Kamil 18284a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1829588c3f0dSKowalski, Kamil 1830bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1831d577665bSRatan Gupta std::optional<std::string> macAddress; 18329a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1833d1d50814SRavi Teja std::optional<nlohmann::json> ipv4StaticAddresses; 1834e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1835f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 1836da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 18371f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 1838*eeedda23SJohnathan Mantey std::optional<bool> interfaceEnabled; 18391f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 18401f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 18410627a2c7SEd Tanous 18421f8c7b5dSJohnathan Mantey if (!json_util::readJson( 18431f8c7b5dSJohnathan Mantey req, res, "HostName", hostname, "IPv4StaticAddresses", 18441f8c7b5dSJohnathan Mantey ipv4StaticAddresses, "MACAddress", macAddress, 18451f8c7b5dSJohnathan Mantey "StaticNameServers", staticNameServers, "IPv6DefaultGateway", 18461f8c7b5dSJohnathan Mantey ipv6DefaultGateway, "IPv6StaticAddresses", ipv6StaticAddresses, 1847*eeedda23SJohnathan Mantey "DHCPv4", dhcpv4, "DHCPv6", dhcpv6, "InterfaceEnabled", 1848*eeedda23SJohnathan Mantey interfaceEnabled)) 18491abe55efSEd Tanous { 1850588c3f0dSKowalski, Kamil return; 1851588c3f0dSKowalski, Kamil } 1852da131a9aSJennifer Lee if (dhcpv4) 1853da131a9aSJennifer Lee { 18541f8c7b5dSJohnathan Mantey if (!json_util::readJson(*dhcpv4, res, "DHCPEnabled", 18551f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 18561f8c7b5dSJohnathan Mantey v4dhcpParms.useDNSServers, "UseNTPServers", 18571f8c7b5dSJohnathan Mantey v4dhcpParms.useNTPServers, "UseDomainName", 18581f8c7b5dSJohnathan Mantey v4dhcpParms.useUseDomainName)) 18591f8c7b5dSJohnathan Mantey { 18601f8c7b5dSJohnathan Mantey return; 18611f8c7b5dSJohnathan Mantey } 18621f8c7b5dSJohnathan Mantey } 18631f8c7b5dSJohnathan Mantey 18641f8c7b5dSJohnathan Mantey if (dhcpv6) 18651f8c7b5dSJohnathan Mantey { 18661f8c7b5dSJohnathan Mantey if (!json_util::readJson(*dhcpv6, res, "OperatingMode", 18671f8c7b5dSJohnathan Mantey v6dhcpParms.dhcpv6OperatingMode, 18681f8c7b5dSJohnathan Mantey "UseDNSServers", v6dhcpParms.useDNSServers, 18691f8c7b5dSJohnathan Mantey "UseNTPServers", v6dhcpParms.useNTPServers, 18701f8c7b5dSJohnathan Mantey "UseDomainName", 18711f8c7b5dSJohnathan Mantey v6dhcpParms.useUseDomainName)) 18721f8c7b5dSJohnathan Mantey { 18731f8c7b5dSJohnathan Mantey return; 18741f8c7b5dSJohnathan Mantey } 1875da131a9aSJennifer Lee } 1876da131a9aSJennifer Lee 187701784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 187801784826SJohnathan Mantey // JSON preparation 18794a0cb85cSEd Tanous getEthernetIfaceData( 18804a0cb85cSEd Tanous iface_id, 1881fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1882fda13ad2SSunitha Harish macAddress = std::move(macAddress), 1883d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 18849a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1885e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 18861f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 18871f8c7b5dSJohnathan Mantey dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), 18881f8c7b5dSJohnathan Mantey v4dhcpParms = std::move(v4dhcpParms), 1889*eeedda23SJohnathan Mantey v6dhcpParms = std::move(v6dhcpParms), 1890*eeedda23SJohnathan Mantey interfaceEnabled = std::move(interfaceEnabled)]( 18914a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1892e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 189301784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 18941abe55efSEd Tanous if (!success) 18951abe55efSEd Tanous { 1896588c3f0dSKowalski, Kamil // ... otherwise return error 18971abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18981abe55efSEd Tanous // object, and other errors 1899fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1900fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1901588c3f0dSKowalski, Kamil return; 1902588c3f0dSKowalski, Kamil } 1903588c3f0dSKowalski, Kamil 19041f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 19051f8c7b5dSJohnathan Mantey { 19061f8c7b5dSJohnathan Mantey handleDHCPPatch(iface_id, ethData, std::move(v4dhcpParms), 19071f8c7b5dSJohnathan Mantey std::move(v6dhcpParms), asyncResp); 19081f8c7b5dSJohnathan Mantey } 19091f8c7b5dSJohnathan Mantey 19100627a2c7SEd Tanous if (hostname) 19111abe55efSEd Tanous { 19120627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 19131abe55efSEd Tanous } 19140627a2c7SEd Tanous 1915d577665bSRatan Gupta if (macAddress) 1916d577665bSRatan Gupta { 1917d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1918d577665bSRatan Gupta } 1919d577665bSRatan Gupta 1920d1d50814SRavi Teja if (ipv4StaticAddresses) 1921d1d50814SRavi Teja { 1922537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 192301784826SJohnathan Mantey // above is returning a const value, not a non-const 192401784826SJohnathan Mantey // value. This doesn't really work for us, as we need to 192501784826SJohnathan Mantey // be able to efficiently move out the intermedia 192601784826SJohnathan Mantey // nlohmann::json objects. This makes a copy of the 192701784826SJohnathan Mantey // structure, and operates on that, but could be done 192801784826SJohnathan Mantey // more efficiently 1929d1d50814SRavi Teja nlohmann::json ipv4Static = std::move(*ipv4StaticAddresses); 193001784826SJohnathan Mantey handleIPv4StaticPatch(iface_id, ipv4Static, ipv4Data, 1931d1d50814SRavi Teja asyncResp); 19321abe55efSEd Tanous } 19330627a2c7SEd Tanous 1934f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1935f85837bfSRAJESWARAN THILLAIGOVINDAN { 1936f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1937f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1938f85837bfSRAJESWARAN THILLAIGOVINDAN } 19399a6fc6feSRavi Teja 19409a6fc6feSRavi Teja if (ipv6DefaultGateway) 19419a6fc6feSRavi Teja { 19429a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 19439a6fc6feSRavi Teja "IPv6DefaultGateway"); 19449a6fc6feSRavi Teja } 1945e48c0fc5SRavi Teja 1946e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1947e48c0fc5SRavi Teja { 1948e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1949e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 195001784826SJohnathan Mantey ipv6Data, asyncResp); 1951e48c0fc5SRavi Teja } 1952*eeedda23SJohnathan Mantey 1953*eeedda23SJohnathan Mantey if (interfaceEnabled) 1954*eeedda23SJohnathan Mantey { 1955*eeedda23SJohnathan Mantey setEthernetInterfaceBoolProperty( 1956*eeedda23SJohnathan Mantey iface_id, "NICEnabled", *interfaceEnabled, asyncResp); 1957*eeedda23SJohnathan Mantey } 1958588c3f0dSKowalski, Kamil }); 1959588c3f0dSKowalski, Kamil } 19609391bb9cSRapkiewicz, Pawel }; 19619391bb9cSRapkiewicz, Pawel 1962e439f0f8SKowalski, Kamil /** 19634a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 19644a0cb85cSEd Tanous * Schema 1965e439f0f8SKowalski, Kamil */ 19661abe55efSEd Tanous class VlanNetworkInterface : public Node 19671abe55efSEd Tanous { 1968e439f0f8SKowalski, Kamil public: 1969e439f0f8SKowalski, Kamil /* 1970e439f0f8SKowalski, Kamil * Default Constructor 1971e439f0f8SKowalski, Kamil */ 1972e439f0f8SKowalski, Kamil template <typename CrowApp> 19731abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 19744a0cb85cSEd Tanous Node(app, 19750f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 19761abe55efSEd Tanous std::string(), std::string()) 19771abe55efSEd Tanous { 1978e439f0f8SKowalski, Kamil entityPrivileges = { 1979e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1980e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1981e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1982e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1983e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1984e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1985e439f0f8SKowalski, Kamil } 1986e439f0f8SKowalski, Kamil 1987e439f0f8SKowalski, Kamil private: 19880f74e643SEd Tanous void parseInterfaceData( 19890f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 19900f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1991e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 199201784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 19931abe55efSEd Tanous { 1994e439f0f8SKowalski, Kamil // Fill out obvious data... 19954a0cb85cSEd Tanous json_response["Id"] = iface_id; 19964a0cb85cSEd Tanous json_response["@odata.id"] = 19974a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 19984a0cb85cSEd Tanous "/VLANs/" + iface_id; 1999e439f0f8SKowalski, Kamil 20004a0cb85cSEd Tanous json_response["VLANEnable"] = true; 2001fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 20024a0cb85cSEd Tanous { 2003fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 20044a0cb85cSEd Tanous } 2005e439f0f8SKowalski, Kamil } 2006e439f0f8SKowalski, Kamil 2007fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 20081abe55efSEd Tanous { 20091abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 20101abe55efSEd Tanous { 2011927a505aSKowalski, Kamil return false; 20121abe55efSEd Tanous } 20131abe55efSEd Tanous else 20141abe55efSEd Tanous { 2015927a505aSKowalski, Kamil return true; 2016927a505aSKowalski, Kamil } 2017927a505aSKowalski, Kamil } 2018927a505aSKowalski, Kamil 2019e439f0f8SKowalski, Kamil /** 2020e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2021e439f0f8SKowalski, Kamil */ 202255c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 20231abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20241abe55efSEd Tanous { 20254a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20264a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 2027e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 2028e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 2029e439f0f8SKowalski, Kamil // impossible. 20301abe55efSEd Tanous if (params.size() != 2) 20311abe55efSEd Tanous { 2032f12894f8SJason M. Bills messages::internalError(res); 2033e439f0f8SKowalski, Kamil res.end(); 2034e439f0f8SKowalski, Kamil return; 2035e439f0f8SKowalski, Kamil } 2036e439f0f8SKowalski, Kamil 20374a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 20384a0cb85cSEd Tanous const std::string &iface_id = params[1]; 20390f74e643SEd Tanous res.jsonValue["@odata.type"] = 20400f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 20410f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 2042e439f0f8SKowalski, Kamil 2043fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 20441abe55efSEd Tanous { 2045a434f2bdSEd Tanous return; 2046a434f2bdSEd Tanous } 2047a434f2bdSEd Tanous 204801784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 204901784826SJohnathan Mantey // JSON preparation 20504a0cb85cSEd Tanous getEthernetIfaceData( 2051fda13ad2SSunitha Harish params[1], 2052fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 2053fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 20544a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 2055e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 205601784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 2057fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 20581abe55efSEd Tanous { 20590f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 20600f74e643SEd Tanous parent_iface_id, iface_id, ethData, 206101784826SJohnathan Mantey ipv4Data, ipv6Data); 20621abe55efSEd Tanous } 20631abe55efSEd Tanous else 20641abe55efSEd Tanous { 2065e439f0f8SKowalski, Kamil // ... otherwise return error 20661abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 20671abe55efSEd Tanous // object, and other errors 2068f12894f8SJason M. Bills messages::resourceNotFound( 2069f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 2070e439f0f8SKowalski, Kamil } 2071e439f0f8SKowalski, Kamil }); 2072e439f0f8SKowalski, Kamil } 2073e439f0f8SKowalski, Kamil 207455c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 20751abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20761abe55efSEd Tanous { 20774a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20781abe55efSEd Tanous if (params.size() != 2) 20791abe55efSEd Tanous { 2080f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2081e439f0f8SKowalski, Kamil return; 2082e439f0f8SKowalski, Kamil } 2083e439f0f8SKowalski, Kamil 2084d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 208555c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2086927a505aSKowalski, Kamil 2087fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 20881abe55efSEd Tanous { 2089fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2090fda13ad2SSunitha Harish ifaceId); 2091927a505aSKowalski, Kamil return; 2092927a505aSKowalski, Kamil } 2093927a505aSKowalski, Kamil 20940627a2c7SEd Tanous bool vlanEnable = false; 20950627a2c7SEd Tanous uint64_t vlanId = 0; 20960627a2c7SEd Tanous 20970627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 20980627a2c7SEd Tanous vlanId)) 20991abe55efSEd Tanous { 2100927a505aSKowalski, Kamil return; 2101927a505aSKowalski, Kamil } 2102927a505aSKowalski, Kamil 210301784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 210401784826SJohnathan Mantey // JSON preparation 2105e48c0fc5SRavi Teja getEthernetIfaceData( 2106e48c0fc5SRavi Teja params[1], 2107271584abSEd Tanous [asyncResp, parentIfaceId{std::string(params[0])}, 2108e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 2109e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 2110e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 211101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 211208244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 211308244d02SSunitha Harish { 211408244d02SSunitha Harish auto callback = 211508244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 211608244d02SSunitha Harish if (ec) 211708244d02SSunitha Harish { 211808244d02SSunitha Harish messages::internalError(asyncResp->res); 211908244d02SSunitha Harish } 212008244d02SSunitha Harish }; 212108244d02SSunitha Harish 212208244d02SSunitha Harish if (vlanEnable == true) 212308244d02SSunitha Harish { 212408244d02SSunitha Harish crow::connections::systemBus->async_method_call( 212508244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 212608244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 212708244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 212808244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 212908244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 213008244d02SSunitha Harish } 213108244d02SSunitha Harish else 213208244d02SSunitha Harish { 2133e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 2134e48c0fc5SRavi Teja "vlan interface"; 213508244d02SSunitha Harish crow::connections::systemBus->async_method_call( 213608244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 2137e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 2138e48c0fc5SRavi Teja ifaceId, 213908244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 214008244d02SSunitha Harish } 214108244d02SSunitha Harish } 214208244d02SSunitha Harish else 21431abe55efSEd Tanous { 21441abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 21451abe55efSEd Tanous // object, and other errors 2146e48c0fc5SRavi Teja messages::resourceNotFound( 2147e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 2148927a505aSKowalski, Kamil return; 2149927a505aSKowalski, Kamil } 2150927a505aSKowalski, Kamil }); 2151e439f0f8SKowalski, Kamil } 2152e439f0f8SKowalski, Kamil 215355c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 21541abe55efSEd Tanous const std::vector<std::string> ¶ms) override 21551abe55efSEd Tanous { 21564a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 21571abe55efSEd Tanous if (params.size() != 2) 21581abe55efSEd Tanous { 2159f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2160e439f0f8SKowalski, Kamil return; 2161e439f0f8SKowalski, Kamil } 2162e439f0f8SKowalski, Kamil 2163d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 216455c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2165927a505aSKowalski, Kamil 2166fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 21671abe55efSEd Tanous { 2168fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2169fda13ad2SSunitha Harish ifaceId); 2170927a505aSKowalski, Kamil return; 2171927a505aSKowalski, Kamil } 2172927a505aSKowalski, Kamil 217301784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 217401784826SJohnathan Mantey // JSON preparation 2175f12894f8SJason M. Bills getEthernetIfaceData( 2176fda13ad2SSunitha Harish params[1], 2177271584abSEd Tanous [asyncResp, parentIfaceId{std::string(params[0])}, 2178fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 2179f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 2180e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 218101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 2182fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 21831abe55efSEd Tanous { 2184f12894f8SJason M. Bills auto callback = 2185f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 21861abe55efSEd Tanous if (ec) 21871abe55efSEd Tanous { 2188f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2189927a505aSKowalski, Kamil } 21904a0cb85cSEd Tanous }; 21914a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21924a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21934a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 21944a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 21951abe55efSEd Tanous } 21961abe55efSEd Tanous else 21971abe55efSEd Tanous { 2198927a505aSKowalski, Kamil // ... otherwise return error 2199f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 2200f12894f8SJason M. Bills // object, and other errors 2201f12894f8SJason M. Bills messages::resourceNotFound( 2202f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 2203927a505aSKowalski, Kamil } 2204927a505aSKowalski, Kamil }); 2205e439f0f8SKowalski, Kamil } 2206e439f0f8SKowalski, Kamil }; 2207e439f0f8SKowalski, Kamil 2208e439f0f8SKowalski, Kamil /** 2209e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 2210e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 2211e439f0f8SKowalski, Kamil */ 22121abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 22131abe55efSEd Tanous { 2214e439f0f8SKowalski, Kamil public: 2215e439f0f8SKowalski, Kamil template <typename CrowApp> 22161abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 22174a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 22184a0cb85cSEd Tanous std::string()) 22191abe55efSEd Tanous { 2220e439f0f8SKowalski, Kamil entityPrivileges = { 2221e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 2222e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2223e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2224e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2225e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2226e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2227e439f0f8SKowalski, Kamil } 2228e439f0f8SKowalski, Kamil 2229e439f0f8SKowalski, Kamil private: 2230e439f0f8SKowalski, Kamil /** 2231e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2232e439f0f8SKowalski, Kamil */ 223355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 22341abe55efSEd Tanous const std::vector<std::string> ¶ms) override 22351abe55efSEd Tanous { 22364a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 22371abe55efSEd Tanous if (params.size() != 1) 22381abe55efSEd Tanous { 2239e439f0f8SKowalski, Kamil // This means there is a problem with the router 2240f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2241e439f0f8SKowalski, Kamil return; 2242e439f0f8SKowalski, Kamil } 2243e439f0f8SKowalski, Kamil 22444a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2245e439f0f8SKowalski, Kamil 22464a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 22471abe55efSEd Tanous // preparation 2248f12894f8SJason M. Bills getEthernetIfaceList( 224943b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 22501abe55efSEd Tanous const bool &success, 22514c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 22524a0cb85cSEd Tanous if (!success) 22531abe55efSEd Tanous { 2254f12894f8SJason M. Bills messages::internalError(asyncResp->res); 22554a0cb85cSEd Tanous return; 22561abe55efSEd Tanous } 22574c9afe43SEd Tanous 22584c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 22594c9afe43SEd Tanous { 22604c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 22614c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 22624c9afe43SEd Tanous rootInterfaceName); 22634c9afe43SEd Tanous return; 22644c9afe43SEd Tanous } 22654c9afe43SEd Tanous 22660f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 22670f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 22680f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 22690f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 22700f74e643SEd Tanous "VLAN Network Interface Collection"; 22714a0cb85cSEd Tanous 22724a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 22734a0cb85cSEd Tanous 22744a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 22751abe55efSEd Tanous { 22764a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 22774a0cb85cSEd Tanous { 22784a0cb85cSEd Tanous iface_array.push_back( 22794a0cb85cSEd Tanous {{"@odata.id", 22804a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 22814a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2282e439f0f8SKowalski, Kamil } 2283e439f0f8SKowalski, Kamil } 2284e439f0f8SKowalski, Kamil 22854a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 22864a0cb85cSEd Tanous iface_array.size(); 22874a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 22884a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 22894a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 22904a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2291e439f0f8SKowalski, Kamil }); 2292e439f0f8SKowalski, Kamil } 2293e439f0f8SKowalski, Kamil 229455c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 22951abe55efSEd Tanous const std::vector<std::string> ¶ms) override 22961abe55efSEd Tanous { 22974a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 22981abe55efSEd Tanous if (params.size() != 1) 22991abe55efSEd Tanous { 2300f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2301e439f0f8SKowalski, Kamil return; 2302e439f0f8SKowalski, Kamil } 2303fda13ad2SSunitha Harish bool vlanEnable = false; 23040627a2c7SEd Tanous uint32_t vlanId = 0; 2305fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2306fda13ad2SSunitha Harish vlanEnable)) 23071abe55efSEd Tanous { 23084a0cb85cSEd Tanous return; 2309e439f0f8SKowalski, Kamil } 2310fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2311fda13ad2SSunitha Harish if (!vlanId) 2312fda13ad2SSunitha Harish { 2313fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2314fda13ad2SSunitha Harish } 2315fda13ad2SSunitha Harish if (!vlanEnable) 2316fda13ad2SSunitha Harish { 2317fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2318fda13ad2SSunitha Harish } 2319271584abSEd Tanous if (static_cast<bool>(vlanId) ^ vlanEnable) 2320fda13ad2SSunitha Harish { 2321fda13ad2SSunitha Harish return; 2322fda13ad2SSunitha Harish } 2323fda13ad2SSunitha Harish 23244a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 23254a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 23261abe55efSEd Tanous if (ec) 23271abe55efSEd Tanous { 23284a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 23294a0cb85cSEd Tanous // phosphor-network responses 2330f12894f8SJason M. Bills messages::internalError(asyncResp->res); 23314a0cb85cSEd Tanous return; 23321abe55efSEd Tanous } 2333f12894f8SJason M. Bills messages::created(asyncResp->res); 2334e439f0f8SKowalski, Kamil }; 23354a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 23364a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 23374a0cb85cSEd Tanous "/xyz/openbmc_project/network", 23384a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 23390627a2c7SEd Tanous rootInterfaceName, vlanId); 23404a0cb85cSEd Tanous } 23414a0cb85cSEd Tanous }; 23429391bb9cSRapkiewicz, Pawel } // namespace redfish 2343