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; 100*aa05fb27SJohnathan Mantey bool linkUp; 1011f8c7b5dSJohnathan Mantey std::string DHCPEnabled; 1021f8c7b5dSJohnathan Mantey std::string operatingMode; 1034a0cb85cSEd Tanous std::string hostname; 1044a0cb85cSEd Tanous std::string default_gateway; 1059a6fc6feSRavi Teja std::string ipv6_default_gateway; 1064a0cb85cSEd Tanous std::string mac_address; 107fda13ad2SSunitha Harish std::vector<std::uint32_t> vlan_id; 108029573d4SEd Tanous std::vector<std::string> nameservers; 109d24bfc7aSJennifer Lee std::vector<std::string> domainnames; 1109391bb9cSRapkiewicz, Pawel }; 1119391bb9cSRapkiewicz, Pawel 1121f8c7b5dSJohnathan Mantey struct DHCPParameters 1131f8c7b5dSJohnathan Mantey { 1141f8c7b5dSJohnathan Mantey std::optional<bool> dhcpv4Enabled; 1151f8c7b5dSJohnathan Mantey std::optional<bool> useDNSServers; 1161f8c7b5dSJohnathan Mantey std::optional<bool> useNTPServers; 1171f8c7b5dSJohnathan Mantey std::optional<bool> useUseDomainName; 1181f8c7b5dSJohnathan Mantey std::optional<std::string> dhcpv6OperatingMode; 1191f8c7b5dSJohnathan Mantey }; 1201f8c7b5dSJohnathan Mantey 1219391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24) 1229391bb9cSRapkiewicz, Pawel // into full dot notation 1231abe55efSEd Tanous inline std::string getNetmask(unsigned int bits) 1241abe55efSEd Tanous { 1259391bb9cSRapkiewicz, Pawel uint32_t value = 0xffffffff << (32 - bits); 1269391bb9cSRapkiewicz, Pawel std::string netmask = std::to_string((value >> 24) & 0xff) + "." + 1279391bb9cSRapkiewicz, Pawel std::to_string((value >> 16) & 0xff) + "." + 1289391bb9cSRapkiewicz, Pawel std::to_string((value >> 8) & 0xff) + "." + 1299391bb9cSRapkiewicz, Pawel std::to_string(value & 0xff); 1309391bb9cSRapkiewicz, Pawel return netmask; 1319391bb9cSRapkiewicz, Pawel } 1329391bb9cSRapkiewicz, Pawel 1331f8c7b5dSJohnathan Mantey inline bool translateDHCPEnabledToBool(const std::string &inputDHCP, 1341f8c7b5dSJohnathan Mantey bool isIPv4) 1351f8c7b5dSJohnathan Mantey { 1361f8c7b5dSJohnathan Mantey if (isIPv4) 1371f8c7b5dSJohnathan Mantey { 1381f8c7b5dSJohnathan Mantey return ( 1391f8c7b5dSJohnathan Mantey (inputDHCP == 1401f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") || 1411f8c7b5dSJohnathan Mantey (inputDHCP == 1421f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1431f8c7b5dSJohnathan Mantey } 1441f8c7b5dSJohnathan Mantey return ((inputDHCP == 1451f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") || 1461f8c7b5dSJohnathan Mantey (inputDHCP == 1471f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both")); 1481f8c7b5dSJohnathan Mantey } 1491f8c7b5dSJohnathan Mantey 1501f8c7b5dSJohnathan Mantey inline std::string GetDHCPEnabledEnumeration(bool isIPv4, bool isIPv6) 1511f8c7b5dSJohnathan Mantey { 1521f8c7b5dSJohnathan Mantey if (isIPv4 && isIPv6) 1531f8c7b5dSJohnathan Mantey { 1541f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"; 1551f8c7b5dSJohnathan Mantey } 1561f8c7b5dSJohnathan Mantey else if (isIPv4) 1571f8c7b5dSJohnathan Mantey { 1581f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4"; 1591f8c7b5dSJohnathan Mantey } 1601f8c7b5dSJohnathan Mantey else if (isIPv6) 1611f8c7b5dSJohnathan Mantey { 1621f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6"; 1631f8c7b5dSJohnathan Mantey } 1641f8c7b5dSJohnathan Mantey return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none"; 1651f8c7b5dSJohnathan Mantey } 1661f8c7b5dSJohnathan Mantey 1674a0cb85cSEd Tanous inline std::string 1684a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(const std::string &inputOrigin, 1694a0cb85cSEd Tanous bool isIPv4) 1701abe55efSEd Tanous { 1714a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static") 1721abe55efSEd Tanous { 1734a0cb85cSEd Tanous return "Static"; 1749391bb9cSRapkiewicz, Pawel } 1754a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal") 1761abe55efSEd Tanous { 1774a0cb85cSEd Tanous if (isIPv4) 1781abe55efSEd Tanous { 1794a0cb85cSEd Tanous return "IPv4LinkLocal"; 1801abe55efSEd Tanous } 1811abe55efSEd Tanous else 1821abe55efSEd Tanous { 1834a0cb85cSEd Tanous return "LinkLocal"; 1849391bb9cSRapkiewicz, Pawel } 1859391bb9cSRapkiewicz, Pawel } 1864a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 1871abe55efSEd Tanous { 1884a0cb85cSEd Tanous if (isIPv4) 1894a0cb85cSEd Tanous { 1904a0cb85cSEd Tanous return "DHCP"; 1914a0cb85cSEd Tanous } 1924a0cb85cSEd Tanous else 1934a0cb85cSEd Tanous { 1944a0cb85cSEd Tanous return "DHCPv6"; 1954a0cb85cSEd Tanous } 1964a0cb85cSEd Tanous } 1974a0cb85cSEd Tanous if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC") 1984a0cb85cSEd Tanous { 1994a0cb85cSEd Tanous return "SLAAC"; 2004a0cb85cSEd Tanous } 2014a0cb85cSEd Tanous return ""; 2024a0cb85cSEd Tanous } 2034a0cb85cSEd Tanous 2044c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string ðiface_id, 2054a0cb85cSEd Tanous const GetManagedObjects &dbus_data, 2064a0cb85cSEd Tanous EthernetInterfaceData ðData) 2074a0cb85cSEd Tanous { 2084c9afe43SEd Tanous bool idFound = false; 2094a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 2104a0cb85cSEd Tanous { 2114a0cb85cSEd Tanous for (const auto &ifacePair : objpath.second) 2124a0cb85cSEd Tanous { 213029573d4SEd Tanous if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id) 214029573d4SEd Tanous { 2154c9afe43SEd Tanous idFound = true; 2164a0cb85cSEd Tanous if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress") 2174a0cb85cSEd Tanous { 2184a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2194a0cb85cSEd Tanous { 2204a0cb85cSEd Tanous if (propertyPair.first == "MACAddress") 2214a0cb85cSEd Tanous { 2224a0cb85cSEd Tanous const std::string *mac = 223abf2add6SEd Tanous std::get_if<std::string>(&propertyPair.second); 2244a0cb85cSEd Tanous if (mac != nullptr) 2254a0cb85cSEd Tanous { 2264a0cb85cSEd Tanous ethData.mac_address = *mac; 2274a0cb85cSEd Tanous } 2284a0cb85cSEd Tanous } 2294a0cb85cSEd Tanous } 2304a0cb85cSEd Tanous } 2314a0cb85cSEd Tanous else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN") 2324a0cb85cSEd Tanous { 2334a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2344a0cb85cSEd Tanous { 2354a0cb85cSEd Tanous if (propertyPair.first == "Id") 2364a0cb85cSEd Tanous { 2371b6b96c5SEd Tanous const uint32_t *id = 238abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2394a0cb85cSEd Tanous if (id != nullptr) 2404a0cb85cSEd Tanous { 241fda13ad2SSunitha Harish ethData.vlan_id.push_back(*id); 2424a0cb85cSEd Tanous } 2434a0cb85cSEd Tanous } 2444a0cb85cSEd Tanous } 2454a0cb85cSEd Tanous } 2464a0cb85cSEd Tanous else if (ifacePair.first == 2474a0cb85cSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 2484a0cb85cSEd Tanous { 2494a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 2504a0cb85cSEd Tanous { 2514a0cb85cSEd Tanous if (propertyPair.first == "AutoNeg") 2524a0cb85cSEd Tanous { 2534a0cb85cSEd Tanous const bool *auto_neg = 254abf2add6SEd Tanous std::get_if<bool>(&propertyPair.second); 2554a0cb85cSEd Tanous if (auto_neg != nullptr) 2564a0cb85cSEd Tanous { 2574a0cb85cSEd Tanous ethData.auto_neg = *auto_neg; 2584a0cb85cSEd Tanous } 2594a0cb85cSEd Tanous } 2604a0cb85cSEd Tanous else if (propertyPair.first == "Speed") 2614a0cb85cSEd Tanous { 2624a0cb85cSEd Tanous const uint32_t *speed = 263abf2add6SEd Tanous std::get_if<uint32_t>(&propertyPair.second); 2644a0cb85cSEd Tanous if (speed != nullptr) 2654a0cb85cSEd Tanous { 2664a0cb85cSEd Tanous ethData.speed = *speed; 2674a0cb85cSEd Tanous } 2684a0cb85cSEd Tanous } 269*aa05fb27SJohnathan Mantey else if (propertyPair.first == "LinkUp") 270*aa05fb27SJohnathan Mantey { 271*aa05fb27SJohnathan Mantey const bool *linkUp = 272*aa05fb27SJohnathan Mantey std::get_if<bool>(&propertyPair.second); 273*aa05fb27SJohnathan Mantey if (linkUp != nullptr) 274*aa05fb27SJohnathan Mantey { 275*aa05fb27SJohnathan Mantey ethData.linkUp = *linkUp; 276*aa05fb27SJohnathan Mantey } 277*aa05fb27SJohnathan Mantey } 278f85837bfSRAJESWARAN THILLAIGOVINDAN else if (propertyPair.first == "Nameservers") 279029573d4SEd Tanous { 280029573d4SEd Tanous const std::vector<std::string> *nameservers = 281029573d4SEd Tanous sdbusplus::message::variant_ns::get_if< 282029573d4SEd Tanous std::vector<std::string>>( 283029573d4SEd Tanous &propertyPair.second); 284029573d4SEd Tanous if (nameservers != nullptr) 285029573d4SEd Tanous { 286029573d4SEd Tanous ethData.nameservers = std::move(*nameservers); 2874a0cb85cSEd Tanous } 2884a0cb85cSEd Tanous } 2892a133282Smanojkiraneda else if (propertyPair.first == "DHCPEnabled") 2902a133282Smanojkiraneda { 2911f8c7b5dSJohnathan Mantey const std::string *DHCPEnabled = 2921f8c7b5dSJohnathan Mantey std::get_if<std::string>(&propertyPair.second); 2932a133282Smanojkiraneda if (DHCPEnabled != nullptr) 2942a133282Smanojkiraneda { 2952a133282Smanojkiraneda ethData.DHCPEnabled = *DHCPEnabled; 2962a133282Smanojkiraneda } 2972a133282Smanojkiraneda } 298d24bfc7aSJennifer Lee else if (propertyPair.first == "DomainName") 299d24bfc7aSJennifer Lee { 300d24bfc7aSJennifer Lee const std::vector<std::string> *domainNames = 301d24bfc7aSJennifer Lee sdbusplus::message::variant_ns::get_if< 302d24bfc7aSJennifer Lee std::vector<std::string>>( 303d24bfc7aSJennifer Lee &propertyPair.second); 304d24bfc7aSJennifer Lee if (domainNames != nullptr) 305d24bfc7aSJennifer Lee { 306d24bfc7aSJennifer Lee ethData.domainnames = std::move(*domainNames); 307d24bfc7aSJennifer Lee } 308d24bfc7aSJennifer Lee } 309029573d4SEd Tanous } 310029573d4SEd Tanous } 311029573d4SEd Tanous } 3121f8c7b5dSJohnathan Mantey 3131f8c7b5dSJohnathan Mantey if (objpath.first == "/xyz/openbmc_project/network/config/dhcp") 3141f8c7b5dSJohnathan Mantey { 3151f8c7b5dSJohnathan Mantey if (ifacePair.first == 3161f8c7b5dSJohnathan Mantey "xyz.openbmc_project.Network.DHCPConfiguration") 3171f8c7b5dSJohnathan Mantey { 3181f8c7b5dSJohnathan Mantey for (const auto &propertyPair : ifacePair.second) 3191f8c7b5dSJohnathan Mantey { 3201f8c7b5dSJohnathan Mantey if (propertyPair.first == "DNSEnabled") 3211f8c7b5dSJohnathan Mantey { 3221f8c7b5dSJohnathan Mantey const bool *DNSEnabled = 3231f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3241f8c7b5dSJohnathan Mantey if (DNSEnabled != nullptr) 3251f8c7b5dSJohnathan Mantey { 3261f8c7b5dSJohnathan Mantey ethData.DNSEnabled = *DNSEnabled; 3271f8c7b5dSJohnathan Mantey } 3281f8c7b5dSJohnathan Mantey } 3291f8c7b5dSJohnathan Mantey else if (propertyPair.first == "NTPEnabled") 3301f8c7b5dSJohnathan Mantey { 3311f8c7b5dSJohnathan Mantey const bool *NTPEnabled = 3321f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3331f8c7b5dSJohnathan Mantey if (NTPEnabled != nullptr) 3341f8c7b5dSJohnathan Mantey { 3351f8c7b5dSJohnathan Mantey ethData.NTPEnabled = *NTPEnabled; 3361f8c7b5dSJohnathan Mantey } 3371f8c7b5dSJohnathan Mantey } 3381f8c7b5dSJohnathan Mantey else if (propertyPair.first == "HostNameEnabled") 3391f8c7b5dSJohnathan Mantey { 3401f8c7b5dSJohnathan Mantey const bool *HostNameEnabled = 3411f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3421f8c7b5dSJohnathan Mantey if (HostNameEnabled != nullptr) 3431f8c7b5dSJohnathan Mantey { 3441f8c7b5dSJohnathan Mantey ethData.HostNameEnabled = *HostNameEnabled; 3451f8c7b5dSJohnathan Mantey } 3461f8c7b5dSJohnathan Mantey } 3471f8c7b5dSJohnathan Mantey else if (propertyPair.first == "SendHostNameEnabled") 3481f8c7b5dSJohnathan Mantey { 3491f8c7b5dSJohnathan Mantey const bool *SendHostNameEnabled = 3501f8c7b5dSJohnathan Mantey std::get_if<bool>(&propertyPair.second); 3511f8c7b5dSJohnathan Mantey if (SendHostNameEnabled != nullptr) 3521f8c7b5dSJohnathan Mantey { 3531f8c7b5dSJohnathan Mantey ethData.SendHostNameEnabled = 3541f8c7b5dSJohnathan Mantey *SendHostNameEnabled; 3551f8c7b5dSJohnathan Mantey } 3561f8c7b5dSJohnathan Mantey } 3571f8c7b5dSJohnathan Mantey } 3581f8c7b5dSJohnathan Mantey } 3591f8c7b5dSJohnathan Mantey } 360029573d4SEd Tanous // System configuration shows up in the global namespace, so no need 361029573d4SEd Tanous // to check eth number 362029573d4SEd Tanous if (ifacePair.first == 3634a0cb85cSEd Tanous "xyz.openbmc_project.Network.SystemConfiguration") 3644a0cb85cSEd Tanous { 3654a0cb85cSEd Tanous for (const auto &propertyPair : ifacePair.second) 3664a0cb85cSEd Tanous { 3674a0cb85cSEd Tanous if (propertyPair.first == "HostName") 3684a0cb85cSEd Tanous { 3694a0cb85cSEd Tanous const std::string *hostname = 370029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 371029573d4SEd Tanous &propertyPair.second); 3724a0cb85cSEd Tanous if (hostname != nullptr) 3734a0cb85cSEd Tanous { 3744a0cb85cSEd Tanous ethData.hostname = *hostname; 3754a0cb85cSEd Tanous } 3764a0cb85cSEd Tanous } 3774a0cb85cSEd Tanous else if (propertyPair.first == "DefaultGateway") 3784a0cb85cSEd Tanous { 3794a0cb85cSEd Tanous const std::string *defaultGateway = 380029573d4SEd Tanous sdbusplus::message::variant_ns::get_if<std::string>( 381029573d4SEd Tanous &propertyPair.second); 3824a0cb85cSEd Tanous if (defaultGateway != nullptr) 3834a0cb85cSEd Tanous { 3844a0cb85cSEd Tanous ethData.default_gateway = *defaultGateway; 3854a0cb85cSEd Tanous } 3864a0cb85cSEd Tanous } 3879a6fc6feSRavi Teja else if (propertyPair.first == "DefaultGateway6") 3889a6fc6feSRavi Teja { 3899a6fc6feSRavi Teja const std::string *defaultGateway6 = 3909a6fc6feSRavi Teja sdbusplus::message::variant_ns::get_if<std::string>( 3919a6fc6feSRavi Teja &propertyPair.second); 3929a6fc6feSRavi Teja if (defaultGateway6 != nullptr) 3939a6fc6feSRavi Teja { 3949a6fc6feSRavi Teja ethData.ipv6_default_gateway = *defaultGateway6; 3959a6fc6feSRavi Teja } 3969a6fc6feSRavi Teja } 3974a0cb85cSEd Tanous } 3984a0cb85cSEd Tanous } 3994a0cb85cSEd Tanous } 4004a0cb85cSEd Tanous } 4014c9afe43SEd Tanous return idFound; 4024a0cb85cSEd Tanous } 4034a0cb85cSEd Tanous 404e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address 40501784826SJohnathan Mantey inline void 40601784826SJohnathan Mantey extractIPV6Data(const std::string ðiface_id, 40701784826SJohnathan Mantey const GetManagedObjects &dbus_data, 40801784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData> &ipv6_config) 409e48c0fc5SRavi Teja { 410e48c0fc5SRavi Teja const std::string ipv6PathStart = 411e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/"; 412e48c0fc5SRavi Teja 413e48c0fc5SRavi Teja // Since there might be several IPv6 configurations aligned with 414e48c0fc5SRavi Teja // single ethernet interface, loop over all of them 415e48c0fc5SRavi Teja for (const auto &objpath : dbus_data) 416e48c0fc5SRavi Teja { 417e48c0fc5SRavi Teja // Check if proper pattern for object path appears 418e48c0fc5SRavi Teja if (boost::starts_with(objpath.first.str, ipv6PathStart)) 419e48c0fc5SRavi Teja { 420e48c0fc5SRavi Teja for (auto &interface : objpath.second) 421e48c0fc5SRavi Teja { 422e48c0fc5SRavi Teja if (interface.first == "xyz.openbmc_project.Network.IP") 423e48c0fc5SRavi Teja { 424e48c0fc5SRavi Teja // Instance IPv6AddressData structure, and set as 425e48c0fc5SRavi Teja // appropriate 426e48c0fc5SRavi Teja std::pair< 427e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData>::iterator, 428e48c0fc5SRavi Teja bool> 429271584abSEd Tanous it = ipv6_config.insert(IPv6AddressData{}); 430e48c0fc5SRavi Teja IPv6AddressData &ipv6_address = *it.first; 431271584abSEd Tanous ipv6_address.id = 432271584abSEd Tanous objpath.first.str.substr(ipv6PathStart.size()); 433e48c0fc5SRavi Teja for (auto &property : interface.second) 434e48c0fc5SRavi Teja { 435e48c0fc5SRavi Teja if (property.first == "Address") 436e48c0fc5SRavi Teja { 437e48c0fc5SRavi Teja const std::string *address = 438e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 439e48c0fc5SRavi Teja if (address != nullptr) 440e48c0fc5SRavi Teja { 441e48c0fc5SRavi Teja ipv6_address.address = *address; 442e48c0fc5SRavi Teja } 443e48c0fc5SRavi Teja } 444e48c0fc5SRavi Teja else if (property.first == "Origin") 445e48c0fc5SRavi Teja { 446e48c0fc5SRavi Teja const std::string *origin = 447e48c0fc5SRavi Teja std::get_if<std::string>(&property.second); 448e48c0fc5SRavi Teja if (origin != nullptr) 449e48c0fc5SRavi Teja { 450e48c0fc5SRavi Teja ipv6_address.origin = 451e48c0fc5SRavi Teja translateAddressOriginDbusToRedfish(*origin, 452e48c0fc5SRavi Teja false); 453e48c0fc5SRavi Teja } 454e48c0fc5SRavi Teja } 455e48c0fc5SRavi Teja else if (property.first == "PrefixLength") 456e48c0fc5SRavi Teja { 457e48c0fc5SRavi Teja const uint8_t *prefix = 458e48c0fc5SRavi Teja std::get_if<uint8_t>(&property.second); 459e48c0fc5SRavi Teja if (prefix != nullptr) 460e48c0fc5SRavi Teja { 461e48c0fc5SRavi Teja ipv6_address.prefixLength = *prefix; 462e48c0fc5SRavi Teja } 463e48c0fc5SRavi Teja } 464e48c0fc5SRavi Teja else 465e48c0fc5SRavi Teja { 466e48c0fc5SRavi Teja BMCWEB_LOG_ERROR 467e48c0fc5SRavi Teja << "Got extra property: " << property.first 468e48c0fc5SRavi Teja << " on the " << objpath.first.str << " object"; 469e48c0fc5SRavi Teja } 470e48c0fc5SRavi Teja } 471e48c0fc5SRavi Teja } 472e48c0fc5SRavi Teja } 473e48c0fc5SRavi Teja } 474e48c0fc5SRavi Teja } 475e48c0fc5SRavi Teja } 476e48c0fc5SRavi Teja 4774a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address 47801784826SJohnathan Mantey inline void 47901784826SJohnathan Mantey extractIPData(const std::string ðiface_id, 48001784826SJohnathan Mantey const GetManagedObjects &dbus_data, 48101784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData> &ipv4_config) 4824a0cb85cSEd Tanous { 4834a0cb85cSEd Tanous const std::string ipv4PathStart = 4844a0cb85cSEd Tanous "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/"; 4854a0cb85cSEd Tanous 4864a0cb85cSEd Tanous // Since there might be several IPv4 configurations aligned with 4874a0cb85cSEd Tanous // single ethernet interface, loop over all of them 4884a0cb85cSEd Tanous for (const auto &objpath : dbus_data) 4894a0cb85cSEd Tanous { 4904a0cb85cSEd Tanous // Check if proper pattern for object path appears 4914a0cb85cSEd Tanous if (boost::starts_with(objpath.first.str, ipv4PathStart)) 4924a0cb85cSEd Tanous { 4934a0cb85cSEd Tanous for (auto &interface : objpath.second) 4944a0cb85cSEd Tanous { 4954a0cb85cSEd Tanous if (interface.first == "xyz.openbmc_project.Network.IP") 4964a0cb85cSEd Tanous { 4974a0cb85cSEd Tanous // Instance IPv4AddressData structure, and set as 4984a0cb85cSEd Tanous // appropriate 4994a0cb85cSEd Tanous std::pair< 5004a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData>::iterator, 5014a0cb85cSEd Tanous bool> 502271584abSEd Tanous it = ipv4_config.insert(IPv4AddressData{}); 5034a0cb85cSEd Tanous IPv4AddressData &ipv4_address = *it.first; 504271584abSEd Tanous ipv4_address.id = 505271584abSEd Tanous objpath.first.str.substr(ipv4PathStart.size()); 5064a0cb85cSEd Tanous for (auto &property : interface.second) 5074a0cb85cSEd Tanous { 5084a0cb85cSEd Tanous if (property.first == "Address") 5094a0cb85cSEd Tanous { 5104a0cb85cSEd Tanous const std::string *address = 511abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5124a0cb85cSEd Tanous if (address != nullptr) 5134a0cb85cSEd Tanous { 5144a0cb85cSEd Tanous ipv4_address.address = *address; 5154a0cb85cSEd Tanous } 5164a0cb85cSEd Tanous } 5174a0cb85cSEd Tanous else if (property.first == "Gateway") 5184a0cb85cSEd Tanous { 5194a0cb85cSEd Tanous const std::string *gateway = 520abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5214a0cb85cSEd Tanous if (gateway != nullptr) 5224a0cb85cSEd Tanous { 5234a0cb85cSEd Tanous ipv4_address.gateway = *gateway; 5244a0cb85cSEd Tanous } 5254a0cb85cSEd Tanous } 5264a0cb85cSEd Tanous else if (property.first == "Origin") 5274a0cb85cSEd Tanous { 5284a0cb85cSEd Tanous const std::string *origin = 529abf2add6SEd Tanous std::get_if<std::string>(&property.second); 5304a0cb85cSEd Tanous if (origin != nullptr) 5314a0cb85cSEd Tanous { 5324a0cb85cSEd Tanous ipv4_address.origin = 5334a0cb85cSEd Tanous translateAddressOriginDbusToRedfish(*origin, 5344a0cb85cSEd Tanous true); 5354a0cb85cSEd Tanous } 5364a0cb85cSEd Tanous } 5374a0cb85cSEd Tanous else if (property.first == "PrefixLength") 5384a0cb85cSEd Tanous { 5394a0cb85cSEd Tanous const uint8_t *mask = 540abf2add6SEd Tanous std::get_if<uint8_t>(&property.second); 5414a0cb85cSEd Tanous if (mask != nullptr) 5424a0cb85cSEd Tanous { 5434a0cb85cSEd Tanous // convert it to the string 5444a0cb85cSEd Tanous ipv4_address.netmask = getNetmask(*mask); 5454a0cb85cSEd Tanous } 5464a0cb85cSEd Tanous } 5474a0cb85cSEd Tanous else 5484a0cb85cSEd Tanous { 5494a0cb85cSEd Tanous BMCWEB_LOG_ERROR 5504a0cb85cSEd Tanous << "Got extra property: " << property.first 5514a0cb85cSEd Tanous << " on the " << objpath.first.str << " object"; 5524a0cb85cSEd Tanous } 5534a0cb85cSEd Tanous } 5544a0cb85cSEd Tanous // Check if given address is local, or global 5554a0cb85cSEd Tanous ipv4_address.linktype = 5564a0cb85cSEd Tanous boost::starts_with(ipv4_address.address, "169.254.") 55718659d10SJohnathan Mantey ? LinkType::Local 55818659d10SJohnathan Mantey : LinkType::Global; 5594a0cb85cSEd Tanous } 5604a0cb85cSEd Tanous } 5614a0cb85cSEd Tanous } 5624a0cb85cSEd Tanous } 5634a0cb85cSEd Tanous } 564588c3f0dSKowalski, Kamil 565588c3f0dSKowalski, Kamil /** 566588c3f0dSKowalski, Kamil * @brief Sets given Id on the given VLAN interface through D-Bus 567588c3f0dSKowalski, Kamil * 568588c3f0dSKowalski, Kamil * @param[in] ifaceId Id of VLAN interface that should be modified 569588c3f0dSKowalski, Kamil * @param[in] inputVlanId New ID of the VLAN 570588c3f0dSKowalski, Kamil * @param[in] callback Function that will be called after the operation 571588c3f0dSKowalski, Kamil * 572588c3f0dSKowalski, Kamil * @return None. 573588c3f0dSKowalski, Kamil */ 574588c3f0dSKowalski, Kamil template <typename CallbackFunc> 5754a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId, 5761abe55efSEd Tanous CallbackFunc &&callback) 5771abe55efSEd Tanous { 57855c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 579588c3f0dSKowalski, Kamil callback, "xyz.openbmc_project.Network", 580588c3f0dSKowalski, Kamil std::string("/xyz/openbmc_project/network/") + ifaceId, 581588c3f0dSKowalski, Kamil "org.freedesktop.DBus.Properties", "Set", 582588c3f0dSKowalski, Kamil "xyz.openbmc_project.Network.VLAN", "Id", 583abf2add6SEd Tanous std::variant<uint32_t>(inputVlanId)); 5844a0cb85cSEd Tanous } 585588c3f0dSKowalski, Kamil 586588c3f0dSKowalski, Kamil /** 587179db1d7SKowalski, Kamil * @brief Helper function that verifies IP address to check if it is in 588179db1d7SKowalski, Kamil * proper format. If bits pointer is provided, also calculates active 589179db1d7SKowalski, Kamil * bit count for Subnet Mask. 590179db1d7SKowalski, Kamil * 591179db1d7SKowalski, Kamil * @param[in] ip IP that will be verified 592179db1d7SKowalski, Kamil * @param[out] bits Calculated mask in bits notation 593179db1d7SKowalski, Kamil * 594179db1d7SKowalski, Kamil * @return true in case of success, false otherwise 595179db1d7SKowalski, Kamil */ 5964a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip, 5971abe55efSEd Tanous uint8_t *bits = nullptr) 5981abe55efSEd Tanous { 599179db1d7SKowalski, Kamil std::vector<std::string> bytesInMask; 600179db1d7SKowalski, Kamil 601179db1d7SKowalski, Kamil boost::split(bytesInMask, ip, boost::is_any_of(".")); 602179db1d7SKowalski, Kamil 6034a0cb85cSEd Tanous static const constexpr int ipV4AddressSectionsCount = 4; 6041abe55efSEd Tanous if (bytesInMask.size() != ipV4AddressSectionsCount) 6051abe55efSEd Tanous { 606179db1d7SKowalski, Kamil return false; 607179db1d7SKowalski, Kamil } 608179db1d7SKowalski, Kamil 6091abe55efSEd Tanous if (bits != nullptr) 6101abe55efSEd Tanous { 611179db1d7SKowalski, Kamil *bits = 0; 612179db1d7SKowalski, Kamil } 613179db1d7SKowalski, Kamil 614179db1d7SKowalski, Kamil char *endPtr; 615179db1d7SKowalski, Kamil long previousValue = 255; 616179db1d7SKowalski, Kamil bool firstZeroInByteHit; 6171abe55efSEd Tanous for (const std::string &byte : bytesInMask) 6181abe55efSEd Tanous { 6191abe55efSEd Tanous if (byte.empty()) 6201abe55efSEd Tanous { 6211db9ca37SKowalski, Kamil return false; 6221db9ca37SKowalski, Kamil } 6231db9ca37SKowalski, Kamil 624179db1d7SKowalski, Kamil // Use strtol instead of stroi to avoid exceptions 6251db9ca37SKowalski, Kamil long value = std::strtol(byte.c_str(), &endPtr, 10); 626179db1d7SKowalski, Kamil 6274a0cb85cSEd Tanous // endPtr should point to the end of the string, otherwise given string 6284a0cb85cSEd Tanous // is not 100% number 6291abe55efSEd Tanous if (*endPtr != '\0') 6301abe55efSEd Tanous { 631179db1d7SKowalski, Kamil return false; 632179db1d7SKowalski, Kamil } 633179db1d7SKowalski, Kamil 634179db1d7SKowalski, Kamil // Value should be contained in byte 6351abe55efSEd Tanous if (value < 0 || value > 255) 6361abe55efSEd Tanous { 637179db1d7SKowalski, Kamil return false; 638179db1d7SKowalski, Kamil } 639179db1d7SKowalski, Kamil 6401abe55efSEd Tanous if (bits != nullptr) 6411abe55efSEd Tanous { 642179db1d7SKowalski, Kamil // Mask has to be continuous between bytes 6431abe55efSEd Tanous if (previousValue != 255 && value != 0) 6441abe55efSEd Tanous { 645179db1d7SKowalski, Kamil return false; 646179db1d7SKowalski, Kamil } 647179db1d7SKowalski, Kamil 648179db1d7SKowalski, Kamil // Mask has to be continuous inside bytes 649179db1d7SKowalski, Kamil firstZeroInByteHit = false; 650179db1d7SKowalski, Kamil 651179db1d7SKowalski, Kamil // Count bits 6521abe55efSEd Tanous for (int bitIdx = 7; bitIdx >= 0; bitIdx--) 6531abe55efSEd Tanous { 6541abe55efSEd Tanous if (value & (1 << bitIdx)) 6551abe55efSEd Tanous { 6561abe55efSEd Tanous if (firstZeroInByteHit) 6571abe55efSEd Tanous { 658179db1d7SKowalski, Kamil // Continuity not preserved 659179db1d7SKowalski, Kamil return false; 6601abe55efSEd Tanous } 6611abe55efSEd Tanous else 6621abe55efSEd Tanous { 663179db1d7SKowalski, Kamil (*bits)++; 664179db1d7SKowalski, Kamil } 6651abe55efSEd Tanous } 6661abe55efSEd Tanous else 6671abe55efSEd Tanous { 668179db1d7SKowalski, Kamil firstZeroInByteHit = true; 669179db1d7SKowalski, Kamil } 670179db1d7SKowalski, Kamil } 671179db1d7SKowalski, Kamil } 672179db1d7SKowalski, Kamil 673179db1d7SKowalski, Kamil previousValue = value; 674179db1d7SKowalski, Kamil } 675179db1d7SKowalski, Kamil 676179db1d7SKowalski, Kamil return true; 677179db1d7SKowalski, Kamil } 678179db1d7SKowalski, Kamil 679179db1d7SKowalski, Kamil /** 68001784826SJohnathan Mantey * @brief Deletes given IPv4 interface 681179db1d7SKowalski, Kamil * 682179db1d7SKowalski, Kamil * @param[in] ifaceId Id of interface whose IP should be deleted 683179db1d7SKowalski, Kamil * @param[in] ipHash DBus Hash id of IP that should be deleted 684179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 685179db1d7SKowalski, Kamil * 686179db1d7SKowalski, Kamil * @return None 687179db1d7SKowalski, Kamil */ 6884a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash, 6894a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 6901abe55efSEd Tanous { 69155c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 692286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 6931abe55efSEd Tanous if (ec) 6941abe55efSEd Tanous { 695a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 6961abe55efSEd Tanous } 697179db1d7SKowalski, Kamil }, 698179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", 699179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash, 700179db1d7SKowalski, Kamil "xyz.openbmc_project.Object.Delete", "Delete"); 701179db1d7SKowalski, Kamil } 702179db1d7SKowalski, Kamil 703179db1d7SKowalski, Kamil /** 70401784826SJohnathan Mantey * @brief Creates a static IPv4 entry 705179db1d7SKowalski, Kamil * 70601784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 70701784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 70801784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 70901784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 710179db1d7SKowalski, Kamil * @param[io] asyncResp Response object that will be returned to client 711179db1d7SKowalski, Kamil * 712179db1d7SKowalski, Kamil * @return None 713179db1d7SKowalski, Kamil */ 714b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx, 71501784826SJohnathan Mantey uint8_t prefixLength, const std::string &gateway, 716b01bf299SEd Tanous const std::string &address, 7174a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp) 7181abe55efSEd Tanous { 71901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 72001784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 7211abe55efSEd Tanous if (ec) 7221abe55efSEd Tanous { 723a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 724179db1d7SKowalski, Kamil } 72501784826SJohnathan Mantey }, 72601784826SJohnathan Mantey "xyz.openbmc_project.Network", 727179db1d7SKowalski, Kamil "/xyz/openbmc_project/network/" + ifaceId, 728179db1d7SKowalski, Kamil "xyz.openbmc_project.Network.IP.Create", "IP", 72901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength, 730179db1d7SKowalski, Kamil gateway); 731179db1d7SKowalski, Kamil } 732e48c0fc5SRavi Teja 733e48c0fc5SRavi Teja /** 73401784826SJohnathan Mantey * @brief Deletes the IPv4 entry for this interface and creates a replacement 73501784826SJohnathan Mantey * static IPv4 entry 73601784826SJohnathan Mantey * 73701784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv4 entry 73801784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 73901784826SJohnathan Mantey * @param[in] prefixLength IPv4 prefix syntax for the subnet mask 74001784826SJohnathan Mantey * @param[in] gateway IPv4 address of this interfaces gateway 74101784826SJohnathan Mantey * @param[in] address IPv4 address to assign to this interface 74201784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 74301784826SJohnathan Mantey * 74401784826SJohnathan Mantey * @return None 74501784826SJohnathan Mantey */ 74601784826SJohnathan Mantey inline void deleteAndCreateIPv4(const std::string &ifaceId, 74701784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 74801784826SJohnathan Mantey const std::string &gateway, 74901784826SJohnathan Mantey const std::string &address, 75001784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 75101784826SJohnathan Mantey { 75201784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 75301784826SJohnathan Mantey [asyncResp, ifaceId, address, prefixLength, 75401784826SJohnathan Mantey gateway](const boost::system::error_code ec) { 75501784826SJohnathan Mantey if (ec) 75601784826SJohnathan Mantey { 75701784826SJohnathan Mantey messages::internalError(asyncResp->res); 75801784826SJohnathan Mantey } 75901784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 76001784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 76101784826SJohnathan Mantey if (ec) 76201784826SJohnathan Mantey { 76301784826SJohnathan Mantey messages::internalError(asyncResp->res); 76401784826SJohnathan Mantey } 76501784826SJohnathan Mantey }, 76601784826SJohnathan Mantey "xyz.openbmc_project.Network", 76701784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 76801784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 76901784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, 77001784826SJohnathan Mantey prefixLength, gateway); 77101784826SJohnathan Mantey }, 77201784826SJohnathan Mantey "xyz.openbmc_project.Network", 77301784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + id, 77401784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 77501784826SJohnathan Mantey } 77601784826SJohnathan Mantey 77701784826SJohnathan Mantey /** 778e48c0fc5SRavi Teja * @brief Deletes given IPv6 779e48c0fc5SRavi Teja * 780e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be deleted 781e48c0fc5SRavi Teja * @param[in] ipHash DBus Hash id of IP that should be deleted 782e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 783e48c0fc5SRavi Teja * 784e48c0fc5SRavi Teja * @return None 785e48c0fc5SRavi Teja */ 786e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash, 787e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 788e48c0fc5SRavi Teja { 789e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 790286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 791e48c0fc5SRavi Teja if (ec) 792e48c0fc5SRavi Teja { 793e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 794e48c0fc5SRavi Teja } 795e48c0fc5SRavi Teja }, 796e48c0fc5SRavi Teja "xyz.openbmc_project.Network", 797e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash, 798e48c0fc5SRavi Teja "xyz.openbmc_project.Object.Delete", "Delete"); 799e48c0fc5SRavi Teja } 800e48c0fc5SRavi Teja 801e48c0fc5SRavi Teja /** 80201784826SJohnathan Mantey * @brief Deletes the IPv6 entry for this interface and creates a replacement 80301784826SJohnathan Mantey * static IPv6 entry 80401784826SJohnathan Mantey * 80501784826SJohnathan Mantey * @param[in] ifaceId Id of interface upon which to create the IPv6 entry 80601784826SJohnathan Mantey * @param[in] id The unique hash entry identifying the DBus entry 80701784826SJohnathan Mantey * @param[in] prefixLength IPv6 prefix syntax for the subnet mask 80801784826SJohnathan Mantey * @param[in] address IPv6 address to assign to this interface 80901784826SJohnathan Mantey * @param[io] asyncResp Response object that will be returned to client 81001784826SJohnathan Mantey * 81101784826SJohnathan Mantey * @return None 81201784826SJohnathan Mantey */ 81301784826SJohnathan Mantey inline void deleteAndCreateIPv6(const std::string &ifaceId, 81401784826SJohnathan Mantey const std::string &id, uint8_t prefixLength, 81501784826SJohnathan Mantey const std::string &address, 81601784826SJohnathan Mantey std::shared_ptr<AsyncResp> asyncResp) 81701784826SJohnathan Mantey { 81801784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 81901784826SJohnathan Mantey [asyncResp, ifaceId, address, 82001784826SJohnathan Mantey prefixLength](const boost::system::error_code ec) { 82101784826SJohnathan Mantey if (ec) 82201784826SJohnathan Mantey { 82301784826SJohnathan Mantey messages::internalError(asyncResp->res); 82401784826SJohnathan Mantey } 82501784826SJohnathan Mantey crow::connections::systemBus->async_method_call( 82601784826SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 82701784826SJohnathan Mantey if (ec) 82801784826SJohnathan Mantey { 82901784826SJohnathan Mantey messages::internalError(asyncResp->res); 83001784826SJohnathan Mantey } 83101784826SJohnathan Mantey }, 83201784826SJohnathan Mantey "xyz.openbmc_project.Network", 83301784826SJohnathan Mantey "/xyz/openbmc_project/network/" + ifaceId, 83401784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Create", "IP", 83501784826SJohnathan Mantey "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, 83601784826SJohnathan Mantey prefixLength, ""); 83701784826SJohnathan Mantey }, 83801784826SJohnathan Mantey "xyz.openbmc_project.Network", 83901784826SJohnathan Mantey +"/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + id, 84001784826SJohnathan Mantey "xyz.openbmc_project.Object.Delete", "Delete"); 84101784826SJohnathan Mantey } 84201784826SJohnathan Mantey 84301784826SJohnathan Mantey /** 844e48c0fc5SRavi Teja * @brief Creates IPv6 with given data 845e48c0fc5SRavi Teja * 846e48c0fc5SRavi Teja * @param[in] ifaceId Id of interface whose IP should be added 847e48c0fc5SRavi Teja * @param[in] prefixLength Prefix length that needs to be added 848e48c0fc5SRavi Teja * @param[in] address IP address that needs to be added 849e48c0fc5SRavi Teja * @param[io] asyncResp Response object that will be returned to client 850e48c0fc5SRavi Teja * 851e48c0fc5SRavi Teja * @return None 852e48c0fc5SRavi Teja */ 85301784826SJohnathan Mantey inline void createIPv6(const std::string &ifaceId, uint8_t prefixLength, 85401784826SJohnathan Mantey const std::string &address, 855e48c0fc5SRavi Teja std::shared_ptr<AsyncResp> asyncResp) 856e48c0fc5SRavi Teja { 857e48c0fc5SRavi Teja auto createIpHandler = [asyncResp](const boost::system::error_code ec) { 858e48c0fc5SRavi Teja if (ec) 859e48c0fc5SRavi Teja { 860e48c0fc5SRavi Teja messages::internalError(asyncResp->res); 861e48c0fc5SRavi Teja } 862e48c0fc5SRavi Teja }; 863e48c0fc5SRavi Teja // Passing null for gateway, as per redfish spec IPv6StaticAddresses object 864e48c0fc5SRavi Teja // does not have assosiated gateway property 865e48c0fc5SRavi Teja crow::connections::systemBus->async_method_call( 866e48c0fc5SRavi Teja std::move(createIpHandler), "xyz.openbmc_project.Network", 867e48c0fc5SRavi Teja "/xyz/openbmc_project/network/" + ifaceId, 868e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Create", "IP", 869e48c0fc5SRavi Teja "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength, 870e48c0fc5SRavi Teja ""); 871e48c0fc5SRavi Teja } 872e48c0fc5SRavi Teja 873179db1d7SKowalski, Kamil /** 874179db1d7SKowalski, Kamil * Function that retrieves all properties for given Ethernet Interface 875179db1d7SKowalski, Kamil * Object 876179db1d7SKowalski, Kamil * from EntityManager Network Manager 8774a0cb85cSEd Tanous * @param ethiface_id a eth interface id to query on DBus 878179db1d7SKowalski, Kamil * @param callback a function that shall be called to convert Dbus output 879179db1d7SKowalski, Kamil * into JSON 880179db1d7SKowalski, Kamil */ 881179db1d7SKowalski, Kamil template <typename CallbackFunc> 8824a0cb85cSEd Tanous void getEthernetIfaceData(const std::string ðiface_id, 8831abe55efSEd Tanous CallbackFunc &&callback) 8841abe55efSEd Tanous { 88555c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 8864a0cb85cSEd Tanous [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}]( 8871abe55efSEd Tanous const boost::system::error_code error_code, 8884a0cb85cSEd Tanous const GetManagedObjects &resp) { 88955c7b7a2SEd Tanous EthernetInterfaceData ethData{}; 8904a0cb85cSEd Tanous boost::container::flat_set<IPv4AddressData> ipv4Data; 891e48c0fc5SRavi Teja boost::container::flat_set<IPv6AddressData> ipv6Data; 892179db1d7SKowalski, Kamil 8931abe55efSEd Tanous if (error_code) 8941abe55efSEd Tanous { 89501784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 896179db1d7SKowalski, Kamil return; 897179db1d7SKowalski, Kamil } 898179db1d7SKowalski, Kamil 8994c9afe43SEd Tanous bool found = 9004a0cb85cSEd Tanous extractEthernetInterfaceData(ethiface_id, resp, ethData); 9014c9afe43SEd Tanous if (!found) 9024c9afe43SEd Tanous { 90301784826SJohnathan Mantey callback(false, ethData, ipv4Data, ipv6Data); 9044c9afe43SEd Tanous return; 9054c9afe43SEd Tanous } 9064c9afe43SEd Tanous 90701784826SJohnathan Mantey extractIPData(ethiface_id, resp, ipv4Data); 908179db1d7SKowalski, Kamil // Fix global GW 9091abe55efSEd Tanous for (IPv4AddressData &ipv4 : ipv4Data) 9101abe55efSEd Tanous { 911c619141bSRavi Teja if (((ipv4.linktype == LinkType::Global) && 912c619141bSRavi Teja (ipv4.gateway == "0.0.0.0")) || 913c619141bSRavi Teja (ipv4.origin == "DHCP")) 9141abe55efSEd Tanous { 9154a0cb85cSEd Tanous ipv4.gateway = ethData.default_gateway; 916179db1d7SKowalski, Kamil } 917179db1d7SKowalski, Kamil } 918179db1d7SKowalski, Kamil 91901784826SJohnathan Mantey extractIPV6Data(ethiface_id, resp, ipv6Data); 9204a0cb85cSEd Tanous // Finally make a callback with usefull data 92101784826SJohnathan Mantey callback(true, ethData, ipv4Data, ipv6Data); 922179db1d7SKowalski, Kamil }, 923179db1d7SKowalski, Kamil "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 924179db1d7SKowalski, Kamil "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 925271584abSEd Tanous } 926179db1d7SKowalski, Kamil 927179db1d7SKowalski, Kamil /** 9289391bb9cSRapkiewicz, Pawel * Function that retrieves all Ethernet Interfaces available through Network 9299391bb9cSRapkiewicz, Pawel * Manager 9301abe55efSEd Tanous * @param callback a function that shall be called to convert Dbus output 9311abe55efSEd Tanous * into JSON. 9329391bb9cSRapkiewicz, Pawel */ 9339391bb9cSRapkiewicz, Pawel template <typename CallbackFunc> 9341abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback) 9351abe55efSEd Tanous { 93655c7b7a2SEd Tanous crow::connections::systemBus->async_method_call( 9374a0cb85cSEd Tanous [callback{std::move(callback)}]( 9389391bb9cSRapkiewicz, Pawel const boost::system::error_code error_code, 9394a0cb85cSEd Tanous GetManagedObjects &resp) { 9401abe55efSEd Tanous // Callback requires vector<string> to retrieve all available 9411abe55efSEd Tanous // ethernet interfaces 9424c9afe43SEd Tanous boost::container::flat_set<std::string> iface_list; 9434a0cb85cSEd Tanous iface_list.reserve(resp.size()); 9441abe55efSEd Tanous if (error_code) 9451abe55efSEd Tanous { 9464a0cb85cSEd Tanous callback(false, iface_list); 9479391bb9cSRapkiewicz, Pawel return; 9489391bb9cSRapkiewicz, Pawel } 9499391bb9cSRapkiewicz, Pawel 9509391bb9cSRapkiewicz, Pawel // Iterate over all retrieved ObjectPaths. 9514a0cb85cSEd Tanous for (const auto &objpath : resp) 9521abe55efSEd Tanous { 9539391bb9cSRapkiewicz, Pawel // And all interfaces available for certain ObjectPath. 9544a0cb85cSEd Tanous for (const auto &interface : objpath.second) 9551abe55efSEd Tanous { 9561abe55efSEd Tanous // If interface is 9574a0cb85cSEd Tanous // xyz.openbmc_project.Network.EthernetInterface, this is 9584a0cb85cSEd Tanous // what we're looking for. 9599391bb9cSRapkiewicz, Pawel if (interface.first == 9601abe55efSEd Tanous "xyz.openbmc_project.Network.EthernetInterface") 9611abe55efSEd Tanous { 9624a0cb85cSEd Tanous // Cut out everyting until last "/", ... 9634a0cb85cSEd Tanous const std::string &iface_id = objpath.first.str; 9644a0cb85cSEd Tanous std::size_t last_pos = iface_id.rfind("/"); 9654a0cb85cSEd Tanous if (last_pos != std::string::npos) 9661abe55efSEd Tanous { 9679391bb9cSRapkiewicz, Pawel // and put it into output vector. 9684c9afe43SEd Tanous iface_list.emplace(iface_id.substr(last_pos + 1)); 9699391bb9cSRapkiewicz, Pawel } 9709391bb9cSRapkiewicz, Pawel } 9719391bb9cSRapkiewicz, Pawel } 9729391bb9cSRapkiewicz, Pawel } 973a434f2bdSEd Tanous // Finally make a callback with useful data 9744a0cb85cSEd Tanous callback(true, iface_list); 9759391bb9cSRapkiewicz, Pawel }, 976aa2e59c1SEd Tanous "xyz.openbmc_project.Network", "/xyz/openbmc_project/network", 977aa2e59c1SEd Tanous "org.freedesktop.DBus.ObjectManager", "GetManagedObjects"); 978271584abSEd Tanous } 9799391bb9cSRapkiewicz, Pawel 9809391bb9cSRapkiewicz, Pawel /** 9819391bb9cSRapkiewicz, Pawel * EthernetCollection derived class for delivering Ethernet Collection Schema 9829391bb9cSRapkiewicz, Pawel */ 9831abe55efSEd Tanous class EthernetCollection : public Node 9841abe55efSEd Tanous { 9859391bb9cSRapkiewicz, Pawel public: 9864a0cb85cSEd Tanous template <typename CrowApp> 9871abe55efSEd Tanous EthernetCollection(CrowApp &app) : 9884a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/") 9891abe55efSEd Tanous { 990588c3f0dSKowalski, Kamil entityPrivileges = { 991588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 992e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 993e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 994e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 995e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 996e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 9979391bb9cSRapkiewicz, Pawel } 9989391bb9cSRapkiewicz, Pawel 9999391bb9cSRapkiewicz, Pawel private: 10009391bb9cSRapkiewicz, Pawel /** 10019391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 10029391bb9cSRapkiewicz, Pawel */ 100355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 10041abe55efSEd Tanous const std::vector<std::string> ¶ms) override 10051abe55efSEd Tanous { 10060f74e643SEd Tanous res.jsonValue["@odata.type"] = 10070f74e643SEd Tanous "#EthernetInterfaceCollection.EthernetInterfaceCollection"; 10080f74e643SEd Tanous res.jsonValue["@odata.context"] = 10090f74e643SEd Tanous "/redfish/v1/" 10100f74e643SEd Tanous "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection"; 10110f74e643SEd Tanous res.jsonValue["@odata.id"] = 10120f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 10130f74e643SEd Tanous res.jsonValue["Name"] = "Ethernet Network Interface Collection"; 10140f74e643SEd Tanous res.jsonValue["Description"] = 10150f74e643SEd Tanous "Collection of EthernetInterfaces for this Manager"; 10164c9afe43SEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 10174a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 10181abe55efSEd Tanous // preparation 1019f12894f8SJason M. Bills getEthernetIfaceList( 10204c9afe43SEd Tanous [asyncResp]( 10214c9afe43SEd Tanous const bool &success, 10224c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 10234a0cb85cSEd Tanous if (!success) 10241abe55efSEd Tanous { 10254c9afe43SEd Tanous messages::internalError(asyncResp->res); 10264a0cb85cSEd Tanous return; 10274a0cb85cSEd Tanous } 10284a0cb85cSEd Tanous 10294c9afe43SEd Tanous nlohmann::json &iface_array = 10304c9afe43SEd Tanous asyncResp->res.jsonValue["Members"]; 10314a0cb85cSEd Tanous iface_array = nlohmann::json::array(); 1032fda13ad2SSunitha Harish std::string tag = "_"; 10334a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 10341abe55efSEd Tanous { 1035fda13ad2SSunitha Harish std::size_t found = iface_item.find(tag); 1036fda13ad2SSunitha Harish if (found == std::string::npos) 1037fda13ad2SSunitha Harish { 10384a0cb85cSEd Tanous iface_array.push_back( 10394a0cb85cSEd Tanous {{"@odata.id", 10404a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 10414a0cb85cSEd Tanous iface_item}}); 10429391bb9cSRapkiewicz, Pawel } 1043fda13ad2SSunitha Harish } 10444a0cb85cSEd Tanous 10454c9afe43SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 10464c9afe43SEd Tanous iface_array.size(); 10474c9afe43SEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10484a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces"; 10499391bb9cSRapkiewicz, Pawel }); 10509391bb9cSRapkiewicz, Pawel } 10519391bb9cSRapkiewicz, Pawel }; 10529391bb9cSRapkiewicz, Pawel 10539391bb9cSRapkiewicz, Pawel /** 10549391bb9cSRapkiewicz, Pawel * EthernetInterface derived class for delivering Ethernet Schema 10559391bb9cSRapkiewicz, Pawel */ 10561abe55efSEd Tanous class EthernetInterface : public Node 10571abe55efSEd Tanous { 10589391bb9cSRapkiewicz, Pawel public: 10599391bb9cSRapkiewicz, Pawel /* 10609391bb9cSRapkiewicz, Pawel * Default Constructor 10619391bb9cSRapkiewicz, Pawel */ 10624a0cb85cSEd Tanous template <typename CrowApp> 10631abe55efSEd Tanous EthernetInterface(CrowApp &app) : 10644a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/", 10651abe55efSEd Tanous std::string()) 10661abe55efSEd Tanous { 1067588c3f0dSKowalski, Kamil entityPrivileges = { 1068588c3f0dSKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1069e0d918bcSEd Tanous {boost::beast::http::verb::head, {{"Login"}}}, 1070e0d918bcSEd Tanous {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1071e0d918bcSEd Tanous {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1072e0d918bcSEd Tanous {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1073e0d918bcSEd Tanous {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 10749391bb9cSRapkiewicz, Pawel } 10759391bb9cSRapkiewicz, Pawel 1076e439f0f8SKowalski, Kamil private: 1077bc0bd6e0SEd Tanous void handleHostnamePatch(const std::string &hostname, 10784a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 10791abe55efSEd Tanous { 1080bc0bd6e0SEd Tanous asyncResp->res.jsonValue["HostName"] = hostname; 1081bc0bd6e0SEd Tanous crow::connections::systemBus->async_method_call( 1082bc0bd6e0SEd Tanous [asyncResp](const boost::system::error_code ec) { 10834a0cb85cSEd Tanous if (ec) 10844a0cb85cSEd Tanous { 1085a08b46ccSJason M. Bills messages::internalError(asyncResp->res); 10861abe55efSEd Tanous } 1087bc0bd6e0SEd Tanous }, 1088bc0bd6e0SEd Tanous "xyz.openbmc_project.Network", 1089bc0bd6e0SEd Tanous "/xyz/openbmc_project/network/config", 1090bc0bd6e0SEd Tanous "org.freedesktop.DBus.Properties", "Set", 1091bc0bd6e0SEd Tanous "xyz.openbmc_project.Network.SystemConfiguration", "HostName", 1092abf2add6SEd Tanous std::variant<std::string>(hostname)); 1093588c3f0dSKowalski, Kamil } 1094588c3f0dSKowalski, Kamil 1095d577665bSRatan Gupta void handleMACAddressPatch(const std::string &ifaceId, 1096d577665bSRatan Gupta const std::string &macAddress, 1097d577665bSRatan Gupta const std::shared_ptr<AsyncResp> &asyncResp) 1098d577665bSRatan Gupta { 1099d577665bSRatan Gupta crow::connections::systemBus->async_method_call( 1100d577665bSRatan Gupta [asyncResp, macAddress](const boost::system::error_code ec) { 1101d577665bSRatan Gupta if (ec) 1102d577665bSRatan Gupta { 1103d577665bSRatan Gupta messages::internalError(asyncResp->res); 1104d577665bSRatan Gupta return; 1105d577665bSRatan Gupta } 1106d577665bSRatan Gupta }, 1107d577665bSRatan Gupta "xyz.openbmc_project.Network", 1108d577665bSRatan Gupta "/xyz/openbmc_project/network/" + ifaceId, 1109d577665bSRatan Gupta "org.freedesktop.DBus.Properties", "Set", 1110d577665bSRatan Gupta "xyz.openbmc_project.Network.MACAddress", "MACAddress", 1111d577665bSRatan Gupta std::variant<std::string>(macAddress)); 1112d577665bSRatan Gupta } 1113286b9118SJohnathan Mantey 1114da131a9aSJennifer Lee void setDHCPEnabled(const std::string &ifaceId, 11151f8c7b5dSJohnathan Mantey const std::string &propertyName, const bool v4Value, 11161f8c7b5dSJohnathan Mantey const bool v6Value, 1117da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1118da131a9aSJennifer Lee { 11191f8c7b5dSJohnathan Mantey const std::string dhcp = GetDHCPEnabledEnumeration(v4Value, v6Value); 1120da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1121da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1122da131a9aSJennifer Lee if (ec) 1123da131a9aSJennifer Lee { 1124da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1125da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1126da131a9aSJennifer Lee return; 1127da131a9aSJennifer Lee } 1128da131a9aSJennifer Lee }, 1129da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1130da131a9aSJennifer Lee "/xyz/openbmc_project/network/" + ifaceId, 1131da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1132da131a9aSJennifer Lee "xyz.openbmc_project.Network.EthernetInterface", propertyName, 11331f8c7b5dSJohnathan Mantey std::variant<std::string>{dhcp}); 1134da131a9aSJennifer Lee } 11351f8c7b5dSJohnathan Mantey 1136da131a9aSJennifer Lee void setDHCPv4Config(const std::string &propertyName, const bool &value, 1137da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1138da131a9aSJennifer Lee { 1139da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << propertyName << " = " << value; 1140da131a9aSJennifer Lee crow::connections::systemBus->async_method_call( 1141da131a9aSJennifer Lee [asyncResp](const boost::system::error_code ec) { 1142da131a9aSJennifer Lee if (ec) 1143da131a9aSJennifer Lee { 1144da131a9aSJennifer Lee BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec; 1145da131a9aSJennifer Lee messages::internalError(asyncResp->res); 1146da131a9aSJennifer Lee return; 1147da131a9aSJennifer Lee } 1148da131a9aSJennifer Lee }, 1149da131a9aSJennifer Lee "xyz.openbmc_project.Network", 1150da131a9aSJennifer Lee "/xyz/openbmc_project/network/config/dhcp", 1151da131a9aSJennifer Lee "org.freedesktop.DBus.Properties", "Set", 1152da131a9aSJennifer Lee "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, 1153da131a9aSJennifer Lee std::variant<bool>{value}); 1154da131a9aSJennifer Lee } 1155d577665bSRatan Gupta 11561f8c7b5dSJohnathan Mantey void handleDHCPPatch(const std::string &ifaceId, 11571f8c7b5dSJohnathan Mantey const EthernetInterfaceData ðData, 11581f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms, DHCPParameters v6dhcpParms, 1159da131a9aSJennifer Lee const std::shared_ptr<AsyncResp> asyncResp) 1160da131a9aSJennifer Lee { 11611f8c7b5dSJohnathan Mantey bool ipv4Active = translateDHCPEnabledToBool(ethData.DHCPEnabled, true); 11621f8c7b5dSJohnathan Mantey bool ipv6Active = 11631f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, false); 1164da131a9aSJennifer Lee 11651f8c7b5dSJohnathan Mantey bool nextv4DHCPState = 11661f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active; 11671f8c7b5dSJohnathan Mantey 11681f8c7b5dSJohnathan Mantey bool nextv6DHCPState{}; 11691f8c7b5dSJohnathan Mantey if (v6dhcpParms.dhcpv6OperatingMode) 1170da131a9aSJennifer Lee { 11711f8c7b5dSJohnathan Mantey if ((*v6dhcpParms.dhcpv6OperatingMode != "Stateful") && 11721f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Stateless") && 11731f8c7b5dSJohnathan Mantey (*v6dhcpParms.dhcpv6OperatingMode != "Disabled")) 11741f8c7b5dSJohnathan Mantey { 11751f8c7b5dSJohnathan Mantey messages::propertyValueFormatError( 11761f8c7b5dSJohnathan Mantey asyncResp->res, *v6dhcpParms.dhcpv6OperatingMode, 11771f8c7b5dSJohnathan Mantey "OperatingMode"); 1178da131a9aSJennifer Lee return; 1179da131a9aSJennifer Lee } 11801f8c7b5dSJohnathan Mantey nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Stateful"); 11811f8c7b5dSJohnathan Mantey } 11821f8c7b5dSJohnathan Mantey else 1183da131a9aSJennifer Lee { 11841f8c7b5dSJohnathan Mantey nextv6DHCPState = ipv6Active; 11851f8c7b5dSJohnathan Mantey } 11861f8c7b5dSJohnathan Mantey 11871f8c7b5dSJohnathan Mantey bool nextDNS{}; 11881f8c7b5dSJohnathan Mantey if (v4dhcpParms.useDNSServers && v6dhcpParms.useDNSServers) 11891f8c7b5dSJohnathan Mantey { 11901f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useDNSServers != *v6dhcpParms.useDNSServers) 11911f8c7b5dSJohnathan Mantey { 11921f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 11931f8c7b5dSJohnathan Mantey return; 11941f8c7b5dSJohnathan Mantey } 11951f8c7b5dSJohnathan Mantey nextDNS = *v4dhcpParms.useDNSServers; 11961f8c7b5dSJohnathan Mantey } 11971f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useDNSServers) 11981f8c7b5dSJohnathan Mantey { 11991f8c7b5dSJohnathan Mantey nextDNS = *v4dhcpParms.useDNSServers; 12001f8c7b5dSJohnathan Mantey } 12011f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useDNSServers) 12021f8c7b5dSJohnathan Mantey { 12031f8c7b5dSJohnathan Mantey nextDNS = *v6dhcpParms.useDNSServers; 12041f8c7b5dSJohnathan Mantey } 12051f8c7b5dSJohnathan Mantey else 12061f8c7b5dSJohnathan Mantey { 12071f8c7b5dSJohnathan Mantey nextDNS = ethData.DNSEnabled; 12081f8c7b5dSJohnathan Mantey } 12091f8c7b5dSJohnathan Mantey 12101f8c7b5dSJohnathan Mantey bool nextNTP{}; 12111f8c7b5dSJohnathan Mantey if (v4dhcpParms.useNTPServers && v6dhcpParms.useNTPServers) 12121f8c7b5dSJohnathan Mantey { 12131f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useNTPServers != *v6dhcpParms.useNTPServers) 12141f8c7b5dSJohnathan Mantey { 12151f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 12161f8c7b5dSJohnathan Mantey return; 12171f8c7b5dSJohnathan Mantey } 12181f8c7b5dSJohnathan Mantey nextNTP = *v4dhcpParms.useNTPServers; 12191f8c7b5dSJohnathan Mantey } 12201f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useNTPServers) 12211f8c7b5dSJohnathan Mantey { 12221f8c7b5dSJohnathan Mantey nextNTP = *v4dhcpParms.useNTPServers; 12231f8c7b5dSJohnathan Mantey } 12241f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useNTPServers) 12251f8c7b5dSJohnathan Mantey { 12261f8c7b5dSJohnathan Mantey nextNTP = *v6dhcpParms.useNTPServers; 12271f8c7b5dSJohnathan Mantey } 12281f8c7b5dSJohnathan Mantey else 12291f8c7b5dSJohnathan Mantey { 12301f8c7b5dSJohnathan Mantey nextNTP = ethData.NTPEnabled; 12311f8c7b5dSJohnathan Mantey } 12321f8c7b5dSJohnathan Mantey 12331f8c7b5dSJohnathan Mantey bool nextUseDomain{}; 12341f8c7b5dSJohnathan Mantey if (v4dhcpParms.useUseDomainName && v6dhcpParms.useUseDomainName) 12351f8c7b5dSJohnathan Mantey { 12361f8c7b5dSJohnathan Mantey if (*v4dhcpParms.useUseDomainName != *v6dhcpParms.useUseDomainName) 12371f8c7b5dSJohnathan Mantey { 12381f8c7b5dSJohnathan Mantey messages::generalError(asyncResp->res); 12391f8c7b5dSJohnathan Mantey return; 12401f8c7b5dSJohnathan Mantey } 12411f8c7b5dSJohnathan Mantey nextUseDomain = *v4dhcpParms.useUseDomainName; 12421f8c7b5dSJohnathan Mantey } 12431f8c7b5dSJohnathan Mantey else if (v4dhcpParms.useUseDomainName) 12441f8c7b5dSJohnathan Mantey { 12451f8c7b5dSJohnathan Mantey nextUseDomain = *v4dhcpParms.useUseDomainName; 12461f8c7b5dSJohnathan Mantey } 12471f8c7b5dSJohnathan Mantey else if (v6dhcpParms.useUseDomainName) 12481f8c7b5dSJohnathan Mantey { 12491f8c7b5dSJohnathan Mantey nextUseDomain = *v6dhcpParms.useUseDomainName; 12501f8c7b5dSJohnathan Mantey } 12511f8c7b5dSJohnathan Mantey else 12521f8c7b5dSJohnathan Mantey { 12531f8c7b5dSJohnathan Mantey nextUseDomain = ethData.HostNameEnabled; 12541f8c7b5dSJohnathan Mantey } 12551f8c7b5dSJohnathan Mantey 1256da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DHCPEnabled..."; 12571f8c7b5dSJohnathan Mantey setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState, 12581f8c7b5dSJohnathan Mantey asyncResp); 1259da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set DNSEnabled..."; 12601f8c7b5dSJohnathan Mantey setDHCPv4Config("DNSEnabled", nextDNS, asyncResp); 1261da131a9aSJennifer Lee BMCWEB_LOG_DEBUG << "set NTPEnabled..."; 12621f8c7b5dSJohnathan Mantey setDHCPv4Config("NTPEnabled", nextNTP, asyncResp); 12631f8c7b5dSJohnathan Mantey BMCWEB_LOG_DEBUG << "set HostNameEnabled..."; 12641f8c7b5dSJohnathan Mantey setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp); 1265da131a9aSJennifer Lee } 126601784826SJohnathan Mantey 126701784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator 126801784826SJohnathan Mantey GetNextStaticIPEntry( 126901784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator head, 127001784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator end) 127101784826SJohnathan Mantey { 127201784826SJohnathan Mantey for (; head != end; head++) 127301784826SJohnathan Mantey { 127401784826SJohnathan Mantey if (head->origin == "Static") 127501784826SJohnathan Mantey { 127601784826SJohnathan Mantey return head; 127701784826SJohnathan Mantey } 127801784826SJohnathan Mantey } 127901784826SJohnathan Mantey return end; 128001784826SJohnathan Mantey } 128101784826SJohnathan Mantey 128201784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator 128301784826SJohnathan Mantey GetNextStaticIPEntry( 128401784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator head, 128501784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator end) 128601784826SJohnathan Mantey { 128701784826SJohnathan Mantey for (; head != end; head++) 128801784826SJohnathan Mantey { 128901784826SJohnathan Mantey if (head->origin == "Static") 129001784826SJohnathan Mantey { 129101784826SJohnathan Mantey return head; 129201784826SJohnathan Mantey } 129301784826SJohnathan Mantey } 129401784826SJohnathan Mantey return end; 129501784826SJohnathan Mantey } 129601784826SJohnathan Mantey 1297d1d50814SRavi Teja void handleIPv4StaticPatch( 1298f476acbfSRatan Gupta const std::string &ifaceId, nlohmann::json &input, 129901784826SJohnathan Mantey const boost::container::flat_set<IPv4AddressData> &ipv4Data, 13004a0cb85cSEd Tanous const std::shared_ptr<AsyncResp> asyncResp) 13011abe55efSEd Tanous { 130201784826SJohnathan Mantey if ((!input.is_array()) || input.empty()) 1303f476acbfSRatan Gupta { 1304f476acbfSRatan Gupta messages::propertyValueTypeError(asyncResp->res, input.dump(), 1305d1d50814SRavi Teja "IPv4StaticAddresses"); 1306f476acbfSRatan Gupta return; 1307f476acbfSRatan Gupta } 1308f476acbfSRatan Gupta 1309271584abSEd Tanous unsigned entryIdx = 1; 131001784826SJohnathan Mantey // Find the first static IP address currently active on the NIC and 131101784826SJohnathan Mantey // match it to the first JSON element in the IPv4StaticAddresses array. 131201784826SJohnathan Mantey // Match each subsequent JSON element to the next static IP programmed 131301784826SJohnathan Mantey // into the NIC. 131401784826SJohnathan Mantey boost::container::flat_set<IPv4AddressData>::const_iterator NICIPentry = 131501784826SJohnathan Mantey GetNextStaticIPEntry(ipv4Data.cbegin(), ipv4Data.cend()); 131601784826SJohnathan Mantey 1317537174c4SEd Tanous for (nlohmann::json &thisJson : input) 13181abe55efSEd Tanous { 13194a0cb85cSEd Tanous std::string pathString = 1320d1d50814SRavi Teja "IPv4StaticAddresses/" + std::to_string(entryIdx); 1321179db1d7SKowalski, Kamil 132201784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1323f476acbfSRatan Gupta { 1324537174c4SEd Tanous std::optional<std::string> address; 1325537174c4SEd Tanous std::optional<std::string> subnetMask; 1326537174c4SEd Tanous std::optional<std::string> gateway; 1327537174c4SEd Tanous 1328537174c4SEd Tanous if (!json_util::readJson(thisJson, asyncResp->res, "Address", 13297e27d832SJohnathan Mantey address, "SubnetMask", subnetMask, 13307e27d832SJohnathan Mantey "Gateway", gateway)) 1331537174c4SEd Tanous { 133201784826SJohnathan Mantey messages::propertyValueFormatError( 133301784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1334537174c4SEd Tanous return; 1335179db1d7SKowalski, Kamil } 1336179db1d7SKowalski, Kamil 133701784826SJohnathan Mantey // Find the address/subnet/gateway values. Any values that are 133801784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 133901784826SJohnathan Mantey // current state of the interface. Merge existing state into the 134001784826SJohnathan Mantey // current request. 1341271584abSEd Tanous const std::string *addr = nullptr; 1342271584abSEd Tanous const std::string *gw = nullptr; 134301784826SJohnathan Mantey uint8_t prefixLength = 0; 134401784826SJohnathan Mantey bool errorInEntry = false; 1345537174c4SEd Tanous if (address) 13461abe55efSEd Tanous { 134701784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*address)) 13481abe55efSEd Tanous { 134901784826SJohnathan Mantey addr = &(*address); 13504a0cb85cSEd Tanous } 135101784826SJohnathan Mantey else 135201784826SJohnathan Mantey { 135301784826SJohnathan Mantey messages::propertyValueFormatError( 135401784826SJohnathan Mantey asyncResp->res, *address, pathString + "/Address"); 135501784826SJohnathan Mantey errorInEntry = true; 135601784826SJohnathan Mantey } 135701784826SJohnathan Mantey } 135801784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 135901784826SJohnathan Mantey { 136001784826SJohnathan Mantey addr = &(NICIPentry->address); 136101784826SJohnathan Mantey } 136201784826SJohnathan Mantey else 136301784826SJohnathan Mantey { 136401784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 136501784826SJohnathan Mantey pathString + "/Address"); 136601784826SJohnathan Mantey errorInEntry = true; 13674a0cb85cSEd Tanous } 13684a0cb85cSEd Tanous 1369537174c4SEd Tanous if (subnetMask) 13704a0cb85cSEd Tanous { 1371537174c4SEd Tanous if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength)) 13724a0cb85cSEd Tanous { 1373f12894f8SJason M. Bills messages::propertyValueFormatError( 1374537174c4SEd Tanous asyncResp->res, *subnetMask, 13754a0cb85cSEd Tanous pathString + "/SubnetMask"); 137601784826SJohnathan Mantey errorInEntry = true; 13774a0cb85cSEd Tanous } 13784a0cb85cSEd Tanous } 137901784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 13804a0cb85cSEd Tanous { 138101784826SJohnathan Mantey if (!ipv4VerifyIpAndGetBitcount(NICIPentry->netmask, 138201784826SJohnathan Mantey &prefixLength)) 13834a0cb85cSEd Tanous { 138401784826SJohnathan Mantey messages::propertyValueFormatError( 138501784826SJohnathan Mantey asyncResp->res, NICIPentry->netmask, 138601784826SJohnathan Mantey pathString + "/SubnetMask"); 138701784826SJohnathan Mantey errorInEntry = true; 13884a0cb85cSEd Tanous } 13894a0cb85cSEd Tanous } 13901abe55efSEd Tanous else 13911abe55efSEd Tanous { 139201784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 139301784826SJohnathan Mantey pathString + "/SubnetMask"); 139401784826SJohnathan Mantey errorInEntry = true; 139501784826SJohnathan Mantey } 139601784826SJohnathan Mantey 139701784826SJohnathan Mantey if (gateway) 139801784826SJohnathan Mantey { 139901784826SJohnathan Mantey if (ipv4VerifyIpAndGetBitcount(*gateway)) 140001784826SJohnathan Mantey { 140101784826SJohnathan Mantey gw = &(*gateway); 140201784826SJohnathan Mantey } 140301784826SJohnathan Mantey else 140401784826SJohnathan Mantey { 140501784826SJohnathan Mantey messages::propertyValueFormatError( 140601784826SJohnathan Mantey asyncResp->res, *gateway, pathString + "/Gateway"); 140701784826SJohnathan Mantey errorInEntry = true; 140801784826SJohnathan Mantey } 140901784826SJohnathan Mantey } 141001784826SJohnathan Mantey else if (NICIPentry != ipv4Data.cend()) 141101784826SJohnathan Mantey { 141201784826SJohnathan Mantey gw = &NICIPentry->gateway; 141301784826SJohnathan Mantey } 141401784826SJohnathan Mantey else 14151abe55efSEd Tanous { 1416a08b46ccSJason M. Bills messages::propertyMissing(asyncResp->res, 14174a0cb85cSEd Tanous pathString + "/Gateway"); 141801784826SJohnathan Mantey errorInEntry = true; 14194a0cb85cSEd Tanous } 14204a0cb85cSEd Tanous 142101784826SJohnathan Mantey if (errorInEntry) 14221abe55efSEd Tanous { 142301784826SJohnathan Mantey return; 14244a0cb85cSEd Tanous } 14254a0cb85cSEd Tanous 142601784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 14271abe55efSEd Tanous { 1428271584abSEd Tanous if (gw != nullptr || addr != nullptr) 1429271584abSEd Tanous { 1430271584abSEd Tanous // Shouldn't be possible based on errorInEntry, but 1431271584abSEd Tanous // it flags -wmaybe-uninitialized in the compiler, 1432271584abSEd Tanous // so defend against that 1433271584abSEd Tanous return; 1434271584abSEd Tanous } 143501784826SJohnathan Mantey deleteAndCreateIPv4(ifaceId, NICIPentry->id, prefixLength, 143601784826SJohnathan Mantey *gw, *addr, asyncResp); 143701784826SJohnathan Mantey NICIPentry = 143801784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 1439588c3f0dSKowalski, Kamil } 144001784826SJohnathan Mantey else 144101784826SJohnathan Mantey { 144201784826SJohnathan Mantey createIPv4(ifaceId, entryIdx, prefixLength, *gateway, 144301784826SJohnathan Mantey *address, asyncResp); 14444a0cb85cSEd Tanous } 14454a0cb85cSEd Tanous entryIdx++; 14464a0cb85cSEd Tanous } 144701784826SJohnathan Mantey else 144801784826SJohnathan Mantey { 144901784826SJohnathan Mantey if (NICIPentry == ipv4Data.cend()) 145001784826SJohnathan Mantey { 145101784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 145201784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 145301784826SJohnathan Mantey // in error, so bail out. 145401784826SJohnathan Mantey if (thisJson.is_null()) 145501784826SJohnathan Mantey { 145601784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 145701784826SJohnathan Mantey return; 145801784826SJohnathan Mantey } 145901784826SJohnathan Mantey else 146001784826SJohnathan Mantey { 146101784826SJohnathan Mantey messages::propertyValueFormatError( 146201784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 146301784826SJohnathan Mantey return; 146401784826SJohnathan Mantey } 146501784826SJohnathan Mantey } 146601784826SJohnathan Mantey 146701784826SJohnathan Mantey if (thisJson.is_null()) 146801784826SJohnathan Mantey { 146901784826SJohnathan Mantey deleteIPv4(ifaceId, NICIPentry->id, asyncResp); 147001784826SJohnathan Mantey } 147101784826SJohnathan Mantey if (NICIPentry != ipv4Data.cend()) 147201784826SJohnathan Mantey { 147301784826SJohnathan Mantey NICIPentry = 147401784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv4Data.cend()); 147501784826SJohnathan Mantey } 147601784826SJohnathan Mantey entryIdx++; 147701784826SJohnathan Mantey } 147801784826SJohnathan Mantey } 14794a0cb85cSEd Tanous } 14804a0cb85cSEd Tanous 1481f85837bfSRAJESWARAN THILLAIGOVINDAN void handleStaticNameServersPatch( 1482f85837bfSRAJESWARAN THILLAIGOVINDAN const std::string &ifaceId, 1483f85837bfSRAJESWARAN THILLAIGOVINDAN const std::vector<std::string> &updatedStaticNameServers, 1484f85837bfSRAJESWARAN THILLAIGOVINDAN const std::shared_ptr<AsyncResp> &asyncResp) 1485f85837bfSRAJESWARAN THILLAIGOVINDAN { 1486f85837bfSRAJESWARAN THILLAIGOVINDAN crow::connections::systemBus->async_method_call( 1487286b9118SJohnathan Mantey [asyncResp](const boost::system::error_code ec) { 1488f85837bfSRAJESWARAN THILLAIGOVINDAN if (ec) 1489f85837bfSRAJESWARAN THILLAIGOVINDAN { 1490f85837bfSRAJESWARAN THILLAIGOVINDAN messages::internalError(asyncResp->res); 1491f85837bfSRAJESWARAN THILLAIGOVINDAN return; 1492f85837bfSRAJESWARAN THILLAIGOVINDAN } 1493f85837bfSRAJESWARAN THILLAIGOVINDAN }, 1494f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network", 1495f85837bfSRAJESWARAN THILLAIGOVINDAN "/xyz/openbmc_project/network/" + ifaceId, 1496f85837bfSRAJESWARAN THILLAIGOVINDAN "org.freedesktop.DBus.Properties", "Set", 1497f85837bfSRAJESWARAN THILLAIGOVINDAN "xyz.openbmc_project.Network.EthernetInterface", "Nameservers", 1498f85837bfSRAJESWARAN THILLAIGOVINDAN std::variant<std::vector<std::string>>{updatedStaticNameServers}); 1499f85837bfSRAJESWARAN THILLAIGOVINDAN } 1500f85837bfSRAJESWARAN THILLAIGOVINDAN 1501e48c0fc5SRavi Teja void handleIPv6StaticAddressesPatch( 1502e48c0fc5SRavi Teja const std::string &ifaceId, nlohmann::json &input, 150301784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data, 1504e48c0fc5SRavi Teja const std::shared_ptr<AsyncResp> asyncResp) 1505e48c0fc5SRavi Teja { 150601784826SJohnathan Mantey if (!input.is_array() || input.empty()) 1507e48c0fc5SRavi Teja { 1508e48c0fc5SRavi Teja messages::propertyValueTypeError(asyncResp->res, input.dump(), 1509e48c0fc5SRavi Teja "IPv6StaticAddresses"); 1510e48c0fc5SRavi Teja return; 1511e48c0fc5SRavi Teja } 1512271584abSEd Tanous size_t entryIdx = 1; 151301784826SJohnathan Mantey boost::container::flat_set<IPv6AddressData>::const_iterator NICIPentry = 151401784826SJohnathan Mantey GetNextStaticIPEntry(ipv6Data.cbegin(), ipv6Data.cend()); 1515e48c0fc5SRavi Teja for (nlohmann::json &thisJson : input) 1516e48c0fc5SRavi Teja { 1517e48c0fc5SRavi Teja std::string pathString = 1518e48c0fc5SRavi Teja "IPv6StaticAddresses/" + std::to_string(entryIdx); 1519e48c0fc5SRavi Teja 152001784826SJohnathan Mantey if (!thisJson.is_null() && !thisJson.empty()) 1521e48c0fc5SRavi Teja { 1522e48c0fc5SRavi Teja std::optional<std::string> address; 1523e48c0fc5SRavi Teja std::optional<uint8_t> prefixLength; 1524e48c0fc5SRavi Teja 1525e48c0fc5SRavi Teja if (!json_util::readJson(thisJson, asyncResp->res, "Address", 1526e48c0fc5SRavi Teja address, "PrefixLength", prefixLength)) 1527e48c0fc5SRavi Teja { 152801784826SJohnathan Mantey messages::propertyValueFormatError( 152901784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 1530e48c0fc5SRavi Teja return; 1531e48c0fc5SRavi Teja } 1532e48c0fc5SRavi Teja 153301784826SJohnathan Mantey const std::string *addr; 153401784826SJohnathan Mantey uint8_t prefix; 153501784826SJohnathan Mantey 153601784826SJohnathan Mantey // Find the address and prefixLength values. Any values that are 153701784826SJohnathan Mantey // not explicitly provided are assumed to be unmodified from the 153801784826SJohnathan Mantey // current state of the interface. Merge existing state into the 153901784826SJohnathan Mantey // current request. 1540e48c0fc5SRavi Teja if (address) 1541e48c0fc5SRavi Teja { 154201784826SJohnathan Mantey addr = &(*address); 1543e48c0fc5SRavi Teja } 154401784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 154501784826SJohnathan Mantey { 154601784826SJohnathan Mantey addr = &(NICIPentry->address); 154701784826SJohnathan Mantey } 154801784826SJohnathan Mantey else 154901784826SJohnathan Mantey { 155001784826SJohnathan Mantey messages::propertyMissing(asyncResp->res, 155101784826SJohnathan Mantey pathString + "/Address"); 155201784826SJohnathan Mantey return; 1553e48c0fc5SRavi Teja } 1554e48c0fc5SRavi Teja 1555e48c0fc5SRavi Teja if (prefixLength) 1556e48c0fc5SRavi Teja { 155701784826SJohnathan Mantey prefix = *prefixLength; 155801784826SJohnathan Mantey } 155901784826SJohnathan Mantey else if (NICIPentry != ipv6Data.end()) 1560e48c0fc5SRavi Teja { 156101784826SJohnathan Mantey prefix = NICIPentry->prefixLength; 1562e48c0fc5SRavi Teja } 1563e48c0fc5SRavi Teja else 1564e48c0fc5SRavi Teja { 1565e48c0fc5SRavi Teja messages::propertyMissing(asyncResp->res, 1566e48c0fc5SRavi Teja pathString + "/PrefixLength"); 156701784826SJohnathan Mantey return; 1568e48c0fc5SRavi Teja } 1569e48c0fc5SRavi Teja 157001784826SJohnathan Mantey if (NICIPentry != ipv6Data.end()) 1571e48c0fc5SRavi Teja { 157201784826SJohnathan Mantey deleteAndCreateIPv6(ifaceId, NICIPentry->id, prefix, *addr, 1573e48c0fc5SRavi Teja asyncResp); 157401784826SJohnathan Mantey NICIPentry = 157501784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 157601784826SJohnathan Mantey } 157701784826SJohnathan Mantey else 157801784826SJohnathan Mantey { 157901784826SJohnathan Mantey createIPv6(ifaceId, *prefixLength, *addr, asyncResp); 1580e48c0fc5SRavi Teja } 1581e48c0fc5SRavi Teja entryIdx++; 1582e48c0fc5SRavi Teja } 158301784826SJohnathan Mantey else 158401784826SJohnathan Mantey { 158501784826SJohnathan Mantey if (NICIPentry == ipv6Data.end()) 158601784826SJohnathan Mantey { 158701784826SJohnathan Mantey // Requesting a DELETE/DO NOT MODIFY action for an item 158801784826SJohnathan Mantey // that isn't present on the eth(n) interface. Input JSON is 158901784826SJohnathan Mantey // in error, so bail out. 159001784826SJohnathan Mantey if (thisJson.is_null()) 159101784826SJohnathan Mantey { 159201784826SJohnathan Mantey messages::resourceCannotBeDeleted(asyncResp->res); 159301784826SJohnathan Mantey return; 159401784826SJohnathan Mantey } 159501784826SJohnathan Mantey else 159601784826SJohnathan Mantey { 159701784826SJohnathan Mantey messages::propertyValueFormatError( 159801784826SJohnathan Mantey asyncResp->res, thisJson.dump(), pathString); 159901784826SJohnathan Mantey return; 160001784826SJohnathan Mantey } 160101784826SJohnathan Mantey } 160201784826SJohnathan Mantey 160301784826SJohnathan Mantey if (thisJson.is_null()) 160401784826SJohnathan Mantey { 160501784826SJohnathan Mantey deleteIPv6(ifaceId, NICIPentry->id, asyncResp); 160601784826SJohnathan Mantey } 160701784826SJohnathan Mantey if (NICIPentry != ipv6Data.cend()) 160801784826SJohnathan Mantey { 160901784826SJohnathan Mantey NICIPentry = 161001784826SJohnathan Mantey GetNextStaticIPEntry(++NICIPentry, ipv6Data.cend()); 161101784826SJohnathan Mantey } 161201784826SJohnathan Mantey entryIdx++; 161301784826SJohnathan Mantey } 161401784826SJohnathan Mantey } 1615e48c0fc5SRavi Teja } 1616e48c0fc5SRavi Teja 16170f74e643SEd Tanous void parseInterfaceData( 16180f74e643SEd Tanous nlohmann::json &json_response, const std::string &iface_id, 16190f74e643SEd Tanous const EthernetInterfaceData ðData, 1620e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 162101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 16224a0cb85cSEd Tanous { 16234a0cb85cSEd Tanous json_response["Id"] = iface_id; 16244a0cb85cSEd Tanous json_response["@odata.id"] = 16254a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id; 1626029573d4SEd Tanous json_response["InterfaceEnabled"] = true; 1627029573d4SEd Tanous if (ethData.speed == 0) 1628029573d4SEd Tanous { 1629029573d4SEd Tanous json_response["Status"] = { 1630029573d4SEd Tanous {"Health", "OK"}, 1631029573d4SEd Tanous {"State", "Disabled"}, 1632029573d4SEd Tanous }; 1633029573d4SEd Tanous } 1634029573d4SEd Tanous else 1635029573d4SEd Tanous { 1636029573d4SEd Tanous json_response["Status"] = { 1637029573d4SEd Tanous {"Health", "OK"}, 1638029573d4SEd Tanous {"State", "Enabled"}, 1639029573d4SEd Tanous }; 1640029573d4SEd Tanous } 1641*aa05fb27SJohnathan Mantey 1642*aa05fb27SJohnathan Mantey json_response["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown"; 16434a0cb85cSEd Tanous json_response["SpeedMbps"] = ethData.speed; 16444a0cb85cSEd Tanous json_response["MACAddress"] = ethData.mac_address; 16451f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["DHCPEnabled"] = 16461f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, true); 16471f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseNTPServers"] = ethData.NTPEnabled; 16481f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseDNSServers"] = ethData.DNSEnabled; 16491f8c7b5dSJohnathan Mantey json_response["DHCPv4"]["UseDomainName"] = ethData.HostNameEnabled; 16501f8c7b5dSJohnathan Mantey 16511f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["OperatingMode"] = 16521f8c7b5dSJohnathan Mantey translateDHCPEnabledToBool(ethData.DHCPEnabled, false) ? "Stateful" 16531f8c7b5dSJohnathan Mantey : "Disabled"; 16541f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseNTPServers"] = ethData.NTPEnabled; 16551f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseDNSServers"] = ethData.DNSEnabled; 16561f8c7b5dSJohnathan Mantey json_response["DHCPv6"]["UseDomainName"] = ethData.HostNameEnabled; 16572a133282Smanojkiraneda 16584a0cb85cSEd Tanous if (!ethData.hostname.empty()) 16594a0cb85cSEd Tanous { 16604a0cb85cSEd Tanous json_response["HostName"] = ethData.hostname; 1661d24bfc7aSJennifer Lee if (!ethData.domainnames.empty()) 1662d24bfc7aSJennifer Lee { 1663d24bfc7aSJennifer Lee json_response["FQDN"] = 1664d24bfc7aSJennifer Lee ethData.hostname + "." + ethData.domainnames[0]; 1665d24bfc7aSJennifer Lee } 16664a0cb85cSEd Tanous } 16674a0cb85cSEd Tanous 1668fda13ad2SSunitha Harish json_response["VLANs"] = { 1669fda13ad2SSunitha Harish {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 1670fda13ad2SSunitha Harish iface_id + "/VLANs"}}; 1671fda13ad2SSunitha Harish 16721f8c7b5dSJohnathan Mantey if (translateDHCPEnabledToBool(ethData.DHCPEnabled, true) && 16731f8c7b5dSJohnathan Mantey ethData.DNSEnabled) 167495f8646eSManojkiran Eda { 16751f8c7b5dSJohnathan Mantey json_response["StaticNameServers"] = nlohmann::json::array(); 167695f8646eSManojkiran Eda } 167795f8646eSManojkiran Eda else 167895f8646eSManojkiran Eda { 16791f8c7b5dSJohnathan Mantey json_response["StaticNameServers"] = ethData.nameservers; 168095f8646eSManojkiran Eda } 16814a0cb85cSEd Tanous 16824a0cb85cSEd Tanous nlohmann::json &ipv4_array = json_response["IPv4Addresses"]; 168301784826SJohnathan Mantey nlohmann::json &ipv4_static_array = 168401784826SJohnathan Mantey json_response["IPv4StaticAddresses"]; 16854a0cb85cSEd Tanous ipv4_array = nlohmann::json::array(); 168601784826SJohnathan Mantey ipv4_static_array = nlohmann::json::array(); 16874a0cb85cSEd Tanous for (auto &ipv4_config : ipv4Data) 16884a0cb85cSEd Tanous { 1689fa5053a6SGunnar Mills 1690fa5053a6SGunnar Mills std::string gatewayStr = ipv4_config.gateway; 1691fa5053a6SGunnar Mills if (gatewayStr.empty()) 1692fa5053a6SGunnar Mills { 1693fa5053a6SGunnar Mills gatewayStr = "0.0.0.0"; 1694fa5053a6SGunnar Mills } 1695fa5053a6SGunnar Mills 16964a0cb85cSEd Tanous ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin}, 16974a0cb85cSEd Tanous {"SubnetMask", ipv4_config.netmask}, 1698029573d4SEd Tanous {"Address", ipv4_config.address}, 1699fa5053a6SGunnar Mills {"Gateway", gatewayStr}}); 170001784826SJohnathan Mantey if (ipv4_config.origin == "Static") 1701d1d50814SRavi Teja { 1702d1d50814SRavi Teja ipv4_static_array.push_back( 170301784826SJohnathan Mantey {{"AddressOrigin", ipv4_config.origin}, 170401784826SJohnathan Mantey {"SubnetMask", ipv4_config.netmask}, 170501784826SJohnathan Mantey {"Address", ipv4_config.address}, 1706d1d50814SRavi Teja {"Gateway", gatewayStr}}); 1707d1d50814SRavi Teja } 170801784826SJohnathan Mantey } 1709d1d50814SRavi Teja 17109a6fc6feSRavi Teja json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway; 1711e48c0fc5SRavi Teja 1712e48c0fc5SRavi Teja nlohmann::json &ipv6_array = json_response["IPv6Addresses"]; 171301784826SJohnathan Mantey nlohmann::json &ipv6_static_array = 171401784826SJohnathan Mantey json_response["IPv6StaticAddresses"]; 1715e48c0fc5SRavi Teja ipv6_array = nlohmann::json::array(); 171601784826SJohnathan Mantey ipv6_static_array = nlohmann::json::array(); 1717e48c0fc5SRavi Teja for (auto &ipv6_config : ipv6Data) 1718e48c0fc5SRavi Teja { 1719e48c0fc5SRavi Teja ipv6_array.push_back({{"Address", ipv6_config.address}, 1720e48c0fc5SRavi Teja {"PrefixLength", ipv6_config.prefixLength}, 1721e48c0fc5SRavi Teja {"AddressOrigin", ipv6_config.origin}}); 172201784826SJohnathan Mantey if (ipv6_config.origin == "Static") 1723e48c0fc5SRavi Teja { 1724e48c0fc5SRavi Teja ipv6_static_array.push_back( 172501784826SJohnathan Mantey {{"Address", ipv6_config.address}, 172601784826SJohnathan Mantey {"PrefixLength", ipv6_config.prefixLength}, 172701784826SJohnathan Mantey {"AddressOrigin", ipv6_config.origin}}); 172801784826SJohnathan Mantey } 1729e48c0fc5SRavi Teja } 1730588c3f0dSKowalski, Kamil } 1731588c3f0dSKowalski, Kamil 17329391bb9cSRapkiewicz, Pawel /** 17339391bb9cSRapkiewicz, Pawel * Functions triggers appropriate requests on DBus 17349391bb9cSRapkiewicz, Pawel */ 173555c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 17361abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17371abe55efSEd Tanous { 17384a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17391abe55efSEd Tanous if (params.size() != 1) 17401abe55efSEd Tanous { 1741f12894f8SJason M. Bills messages::internalError(asyncResp->res); 17429391bb9cSRapkiewicz, Pawel return; 17439391bb9cSRapkiewicz, Pawel } 17449391bb9cSRapkiewicz, Pawel 17454a0cb85cSEd Tanous getEthernetIfaceData( 17464a0cb85cSEd Tanous params[0], 17474a0cb85cSEd Tanous [this, asyncResp, iface_id{std::string(params[0])}]( 17484a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1749e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 175001784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 17514a0cb85cSEd Tanous if (!success) 17521abe55efSEd Tanous { 17531abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 17541abe55efSEd Tanous // object, and other errors 1755f12894f8SJason M. Bills messages::resourceNotFound(asyncResp->res, 1756f12894f8SJason M. Bills "EthernetInterface", iface_id); 17574a0cb85cSEd Tanous return; 17589391bb9cSRapkiewicz, Pawel } 17594c9afe43SEd Tanous 17600f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 1761fda13ad2SSunitha Harish "#EthernetInterface.v1_4_1.EthernetInterface"; 17620f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 176301784826SJohnathan Mantey "/redfish/v1/" 176401784826SJohnathan Mantey "$metadata#EthernetInterface.EthernetInterface"; 17650f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface"; 17660f74e643SEd Tanous asyncResp->res.jsonValue["Description"] = 17670f74e643SEd Tanous "Management Network Interface"; 17680f74e643SEd Tanous 17690f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData, 177001784826SJohnathan Mantey ipv4Data, ipv6Data); 17719391bb9cSRapkiewicz, Pawel }); 17729391bb9cSRapkiewicz, Pawel } 17739391bb9cSRapkiewicz, Pawel 177455c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 17751abe55efSEd Tanous const std::vector<std::string> ¶ms) override 17761abe55efSEd Tanous { 17774a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 17781abe55efSEd Tanous if (params.size() != 1) 17791abe55efSEd Tanous { 1780f12894f8SJason M. Bills messages::internalError(asyncResp->res); 1781588c3f0dSKowalski, Kamil return; 1782588c3f0dSKowalski, Kamil } 1783588c3f0dSKowalski, Kamil 17844a0cb85cSEd Tanous const std::string &iface_id = params[0]; 1785588c3f0dSKowalski, Kamil 1786bc0bd6e0SEd Tanous std::optional<std::string> hostname; 1787d577665bSRatan Gupta std::optional<std::string> macAddress; 17889a6fc6feSRavi Teja std::optional<std::string> ipv6DefaultGateway; 1789d1d50814SRavi Teja std::optional<nlohmann::json> ipv4StaticAddresses; 1790e48c0fc5SRavi Teja std::optional<nlohmann::json> ipv6StaticAddresses; 1791f85837bfSRAJESWARAN THILLAIGOVINDAN std::optional<std::vector<std::string>> staticNameServers; 1792da131a9aSJennifer Lee std::optional<nlohmann::json> dhcpv4; 17931f8c7b5dSJohnathan Mantey std::optional<nlohmann::json> dhcpv6; 17941f8c7b5dSJohnathan Mantey DHCPParameters v4dhcpParms; 17951f8c7b5dSJohnathan Mantey DHCPParameters v6dhcpParms; 17960627a2c7SEd Tanous 17971f8c7b5dSJohnathan Mantey if (!json_util::readJson( 17981f8c7b5dSJohnathan Mantey req, res, "HostName", hostname, "IPv4StaticAddresses", 17991f8c7b5dSJohnathan Mantey ipv4StaticAddresses, "MACAddress", macAddress, 18001f8c7b5dSJohnathan Mantey "StaticNameServers", staticNameServers, "IPv6DefaultGateway", 18011f8c7b5dSJohnathan Mantey ipv6DefaultGateway, "IPv6StaticAddresses", ipv6StaticAddresses, 18021f8c7b5dSJohnathan Mantey "DHCPv4", dhcpv4, "DHCPv6", dhcpv6)) 18031abe55efSEd Tanous { 1804588c3f0dSKowalski, Kamil return; 1805588c3f0dSKowalski, Kamil } 1806da131a9aSJennifer Lee if (dhcpv4) 1807da131a9aSJennifer Lee { 18081f8c7b5dSJohnathan Mantey if (!json_util::readJson(*dhcpv4, res, "DHCPEnabled", 18091f8c7b5dSJohnathan Mantey v4dhcpParms.dhcpv4Enabled, "UseDNSServers", 18101f8c7b5dSJohnathan Mantey v4dhcpParms.useDNSServers, "UseNTPServers", 18111f8c7b5dSJohnathan Mantey v4dhcpParms.useNTPServers, "UseDomainName", 18121f8c7b5dSJohnathan Mantey v4dhcpParms.useUseDomainName)) 18131f8c7b5dSJohnathan Mantey { 18141f8c7b5dSJohnathan Mantey return; 18151f8c7b5dSJohnathan Mantey } 18161f8c7b5dSJohnathan Mantey } 18171f8c7b5dSJohnathan Mantey 18181f8c7b5dSJohnathan Mantey if (dhcpv6) 18191f8c7b5dSJohnathan Mantey { 18201f8c7b5dSJohnathan Mantey if (!json_util::readJson(*dhcpv6, res, "OperatingMode", 18211f8c7b5dSJohnathan Mantey v6dhcpParms.dhcpv6OperatingMode, 18221f8c7b5dSJohnathan Mantey "UseDNSServers", v6dhcpParms.useDNSServers, 18231f8c7b5dSJohnathan Mantey "UseNTPServers", v6dhcpParms.useNTPServers, 18241f8c7b5dSJohnathan Mantey "UseDomainName", 18251f8c7b5dSJohnathan Mantey v6dhcpParms.useUseDomainName)) 18261f8c7b5dSJohnathan Mantey { 18271f8c7b5dSJohnathan Mantey return; 18281f8c7b5dSJohnathan Mantey } 1829da131a9aSJennifer Lee } 1830da131a9aSJennifer Lee 183101784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 183201784826SJohnathan Mantey // JSON preparation 18334a0cb85cSEd Tanous getEthernetIfaceData( 18344a0cb85cSEd Tanous iface_id, 1835fda13ad2SSunitha Harish [this, asyncResp, iface_id, hostname = std::move(hostname), 1836fda13ad2SSunitha Harish macAddress = std::move(macAddress), 1837d1d50814SRavi Teja ipv4StaticAddresses = std::move(ipv4StaticAddresses), 18389a6fc6feSRavi Teja ipv6DefaultGateway = std::move(ipv6DefaultGateway), 1839e48c0fc5SRavi Teja ipv6StaticAddresses = std::move(ipv6StaticAddresses), 18401f8c7b5dSJohnathan Mantey staticNameServers = std::move(staticNameServers), 18411f8c7b5dSJohnathan Mantey dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), 18421f8c7b5dSJohnathan Mantey v4dhcpParms = std::move(v4dhcpParms), 18431f8c7b5dSJohnathan Mantey v6dhcpParms = std::move(v6dhcpParms)]( 18444a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 1845e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 184601784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 18471abe55efSEd Tanous if (!success) 18481abe55efSEd Tanous { 1849588c3f0dSKowalski, Kamil // ... otherwise return error 18501abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 18511abe55efSEd Tanous // object, and other errors 1852fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, 1853fda13ad2SSunitha Harish "Ethernet Interface", iface_id); 1854588c3f0dSKowalski, Kamil return; 1855588c3f0dSKowalski, Kamil } 1856588c3f0dSKowalski, Kamil 18571f8c7b5dSJohnathan Mantey if (dhcpv4 || dhcpv6) 18581f8c7b5dSJohnathan Mantey { 18591f8c7b5dSJohnathan Mantey handleDHCPPatch(iface_id, ethData, std::move(v4dhcpParms), 18601f8c7b5dSJohnathan Mantey std::move(v6dhcpParms), asyncResp); 18611f8c7b5dSJohnathan Mantey } 18621f8c7b5dSJohnathan Mantey 18630627a2c7SEd Tanous if (hostname) 18641abe55efSEd Tanous { 18650627a2c7SEd Tanous handleHostnamePatch(*hostname, asyncResp); 18661abe55efSEd Tanous } 18670627a2c7SEd Tanous 1868d577665bSRatan Gupta if (macAddress) 1869d577665bSRatan Gupta { 1870d577665bSRatan Gupta handleMACAddressPatch(iface_id, *macAddress, asyncResp); 1871d577665bSRatan Gupta } 1872d577665bSRatan Gupta 1873d1d50814SRavi Teja if (ipv4StaticAddresses) 1874d1d50814SRavi Teja { 1875537174c4SEd Tanous // TODO(ed) for some reason the capture of ipv4Addresses 187601784826SJohnathan Mantey // above is returning a const value, not a non-const 187701784826SJohnathan Mantey // value. This doesn't really work for us, as we need to 187801784826SJohnathan Mantey // be able to efficiently move out the intermedia 187901784826SJohnathan Mantey // nlohmann::json objects. This makes a copy of the 188001784826SJohnathan Mantey // structure, and operates on that, but could be done 188101784826SJohnathan Mantey // more efficiently 1882d1d50814SRavi Teja nlohmann::json ipv4Static = std::move(*ipv4StaticAddresses); 188301784826SJohnathan Mantey handleIPv4StaticPatch(iface_id, ipv4Static, ipv4Data, 1884d1d50814SRavi Teja asyncResp); 18851abe55efSEd Tanous } 18860627a2c7SEd Tanous 1887f85837bfSRAJESWARAN THILLAIGOVINDAN if (staticNameServers) 1888f85837bfSRAJESWARAN THILLAIGOVINDAN { 1889f85837bfSRAJESWARAN THILLAIGOVINDAN handleStaticNameServersPatch(iface_id, *staticNameServers, 1890f85837bfSRAJESWARAN THILLAIGOVINDAN asyncResp); 1891f85837bfSRAJESWARAN THILLAIGOVINDAN } 18929a6fc6feSRavi Teja 18939a6fc6feSRavi Teja if (ipv6DefaultGateway) 18949a6fc6feSRavi Teja { 18959a6fc6feSRavi Teja messages::propertyNotWritable(asyncResp->res, 18969a6fc6feSRavi Teja "IPv6DefaultGateway"); 18979a6fc6feSRavi Teja } 1898e48c0fc5SRavi Teja 1899e48c0fc5SRavi Teja if (ipv6StaticAddresses) 1900e48c0fc5SRavi Teja { 1901e48c0fc5SRavi Teja nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses); 1902e48c0fc5SRavi Teja handleIPv6StaticAddressesPatch(iface_id, ipv6Static, 190301784826SJohnathan Mantey ipv6Data, asyncResp); 1904e48c0fc5SRavi Teja } 1905588c3f0dSKowalski, Kamil }); 1906588c3f0dSKowalski, Kamil } 19079391bb9cSRapkiewicz, Pawel }; 19089391bb9cSRapkiewicz, Pawel 1909e439f0f8SKowalski, Kamil /** 19104a0cb85cSEd Tanous * VlanNetworkInterface derived class for delivering VLANNetworkInterface 19114a0cb85cSEd Tanous * Schema 1912e439f0f8SKowalski, Kamil */ 19131abe55efSEd Tanous class VlanNetworkInterface : public Node 19141abe55efSEd Tanous { 1915e439f0f8SKowalski, Kamil public: 1916e439f0f8SKowalski, Kamil /* 1917e439f0f8SKowalski, Kamil * Default Constructor 1918e439f0f8SKowalski, Kamil */ 1919e439f0f8SKowalski, Kamil template <typename CrowApp> 19201abe55efSEd Tanous VlanNetworkInterface(CrowApp &app) : 19214a0cb85cSEd Tanous Node(app, 19220f74e643SEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>", 19231abe55efSEd Tanous std::string(), std::string()) 19241abe55efSEd Tanous { 1925e439f0f8SKowalski, Kamil entityPrivileges = { 1926e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 1927e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 1928e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 1929e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 1930e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 1931e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 1932e439f0f8SKowalski, Kamil } 1933e439f0f8SKowalski, Kamil 1934e439f0f8SKowalski, Kamil private: 19350f74e643SEd Tanous void parseInterfaceData( 19360f74e643SEd Tanous nlohmann::json &json_response, const std::string &parent_iface_id, 19370f74e643SEd Tanous const std::string &iface_id, const EthernetInterfaceData ðData, 1938e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 193901784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) 19401abe55efSEd Tanous { 1941e439f0f8SKowalski, Kamil // Fill out obvious data... 19424a0cb85cSEd Tanous json_response["Id"] = iface_id; 19434a0cb85cSEd Tanous json_response["@odata.id"] = 19444a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id + 19454a0cb85cSEd Tanous "/VLANs/" + iface_id; 1946e439f0f8SKowalski, Kamil 19474a0cb85cSEd Tanous json_response["VLANEnable"] = true; 1948fda13ad2SSunitha Harish if (!ethData.vlan_id.empty()) 19494a0cb85cSEd Tanous { 1950fda13ad2SSunitha Harish json_response["VLANId"] = ethData.vlan_id.back(); 19514a0cb85cSEd Tanous } 1952e439f0f8SKowalski, Kamil } 1953e439f0f8SKowalski, Kamil 1954fda13ad2SSunitha Harish bool verifyNames(const std::string &parent, const std::string &iface) 19551abe55efSEd Tanous { 19561abe55efSEd Tanous if (!boost::starts_with(iface, parent + "_")) 19571abe55efSEd Tanous { 1958927a505aSKowalski, Kamil return false; 19591abe55efSEd Tanous } 19601abe55efSEd Tanous else 19611abe55efSEd Tanous { 1962927a505aSKowalski, Kamil return true; 1963927a505aSKowalski, Kamil } 1964927a505aSKowalski, Kamil } 1965927a505aSKowalski, Kamil 1966e439f0f8SKowalski, Kamil /** 1967e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 1968e439f0f8SKowalski, Kamil */ 196955c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 19701abe55efSEd Tanous const std::vector<std::string> ¶ms) override 19711abe55efSEd Tanous { 19724a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 19734a0cb85cSEd Tanous // TODO(Pawel) this shall be parameterized call (two params) to get 1974e439f0f8SKowalski, Kamil // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'. 1975e439f0f8SKowalski, Kamil // Check if there is required param, truly entering this shall be 1976e439f0f8SKowalski, Kamil // impossible. 19771abe55efSEd Tanous if (params.size() != 2) 19781abe55efSEd Tanous { 1979f12894f8SJason M. Bills messages::internalError(res); 1980e439f0f8SKowalski, Kamil res.end(); 1981e439f0f8SKowalski, Kamil return; 1982e439f0f8SKowalski, Kamil } 1983e439f0f8SKowalski, Kamil 19844a0cb85cSEd Tanous const std::string &parent_iface_id = params[0]; 19854a0cb85cSEd Tanous const std::string &iface_id = params[1]; 19860f74e643SEd Tanous res.jsonValue["@odata.type"] = 19870f74e643SEd Tanous "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface"; 19880f74e643SEd Tanous res.jsonValue["@odata.context"] = 198901784826SJohnathan Mantey "/redfish/v1/" 199001784826SJohnathan Mantey "$metadata#VLanNetworkInterface.VLanNetworkInterface"; 19910f74e643SEd Tanous res.jsonValue["Name"] = "VLAN Network Interface"; 1992e439f0f8SKowalski, Kamil 1993fda13ad2SSunitha Harish if (!verifyNames(parent_iface_id, iface_id)) 19941abe55efSEd Tanous { 1995a434f2bdSEd Tanous return; 1996a434f2bdSEd Tanous } 1997a434f2bdSEd Tanous 199801784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 199901784826SJohnathan Mantey // JSON preparation 20004a0cb85cSEd Tanous getEthernetIfaceData( 2001fda13ad2SSunitha Harish params[1], 2002fda13ad2SSunitha Harish [this, asyncResp, parent_iface_id{std::string(params[0])}, 2003fda13ad2SSunitha Harish iface_id{std::string(params[1])}]( 20044a0cb85cSEd Tanous const bool &success, const EthernetInterfaceData ðData, 2005e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 200601784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 2007fda13ad2SSunitha Harish if (success && ethData.vlan_id.size() != 0) 20081abe55efSEd Tanous { 20090f74e643SEd Tanous parseInterfaceData(asyncResp->res.jsonValue, 20100f74e643SEd Tanous parent_iface_id, iface_id, ethData, 201101784826SJohnathan Mantey ipv4Data, ipv6Data); 20121abe55efSEd Tanous } 20131abe55efSEd Tanous else 20141abe55efSEd Tanous { 2015e439f0f8SKowalski, Kamil // ... otherwise return error 20161abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 20171abe55efSEd Tanous // object, and other errors 2018f12894f8SJason M. Bills messages::resourceNotFound( 2019f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", iface_id); 2020e439f0f8SKowalski, Kamil } 2021e439f0f8SKowalski, Kamil }); 2022e439f0f8SKowalski, Kamil } 2023e439f0f8SKowalski, Kamil 202455c7b7a2SEd Tanous void doPatch(crow::Response &res, const crow::Request &req, 20251abe55efSEd Tanous const std::vector<std::string> ¶ms) override 20261abe55efSEd Tanous { 20274a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 20281abe55efSEd Tanous if (params.size() != 2) 20291abe55efSEd Tanous { 2030f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2031e439f0f8SKowalski, Kamil return; 2032e439f0f8SKowalski, Kamil } 2033e439f0f8SKowalski, Kamil 2034d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 203555c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2036927a505aSKowalski, Kamil 2037fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 20381abe55efSEd Tanous { 2039fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2040fda13ad2SSunitha Harish ifaceId); 2041927a505aSKowalski, Kamil return; 2042927a505aSKowalski, Kamil } 2043927a505aSKowalski, Kamil 20440627a2c7SEd Tanous bool vlanEnable = false; 20450627a2c7SEd Tanous uint64_t vlanId = 0; 20460627a2c7SEd Tanous 20470627a2c7SEd Tanous if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId", 20480627a2c7SEd Tanous vlanId)) 20491abe55efSEd Tanous { 2050927a505aSKowalski, Kamil return; 2051927a505aSKowalski, Kamil } 2052927a505aSKowalski, Kamil 205301784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 205401784826SJohnathan Mantey // JSON preparation 2055e48c0fc5SRavi Teja getEthernetIfaceData( 2056e48c0fc5SRavi Teja params[1], 2057271584abSEd Tanous [asyncResp, parentIfaceId{std::string(params[0])}, 2058e48c0fc5SRavi Teja ifaceId{std::string(params[1])}, &vlanEnable, &vlanId]( 2059e48c0fc5SRavi Teja const bool &success, const EthernetInterfaceData ðData, 2060e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 206101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 206208244d02SSunitha Harish if (success && !ethData.vlan_id.empty()) 206308244d02SSunitha Harish { 206408244d02SSunitha Harish auto callback = 206508244d02SSunitha Harish [asyncResp](const boost::system::error_code ec) { 206608244d02SSunitha Harish if (ec) 206708244d02SSunitha Harish { 206808244d02SSunitha Harish messages::internalError(asyncResp->res); 206908244d02SSunitha Harish } 207008244d02SSunitha Harish }; 207108244d02SSunitha Harish 207208244d02SSunitha Harish if (vlanEnable == true) 207308244d02SSunitha Harish { 207408244d02SSunitha Harish crow::connections::systemBus->async_method_call( 207508244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 207608244d02SSunitha Harish "/xyz/openbmc_project/network/" + ifaceId, 207708244d02SSunitha Harish "org.freedesktop.DBus.Properties", "Set", 207808244d02SSunitha Harish "xyz.openbmc_project.Network.VLAN", "Id", 207908244d02SSunitha Harish std::variant<uint32_t>(vlanId)); 208008244d02SSunitha Harish } 208108244d02SSunitha Harish else 208208244d02SSunitha Harish { 2083e48c0fc5SRavi Teja BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the " 2084e48c0fc5SRavi Teja "vlan interface"; 208508244d02SSunitha Harish crow::connections::systemBus->async_method_call( 208608244d02SSunitha Harish std::move(callback), "xyz.openbmc_project.Network", 2087e48c0fc5SRavi Teja std::string("/xyz/openbmc_project/network/") + 2088e48c0fc5SRavi Teja ifaceId, 208908244d02SSunitha Harish "xyz.openbmc_project.Object.Delete", "Delete"); 209008244d02SSunitha Harish } 209108244d02SSunitha Harish } 209208244d02SSunitha Harish else 20931abe55efSEd Tanous { 20941abe55efSEd Tanous // TODO(Pawel)consider distinguish between non existing 20951abe55efSEd Tanous // object, and other errors 2096e48c0fc5SRavi Teja messages::resourceNotFound( 2097e48c0fc5SRavi Teja asyncResp->res, "VLAN Network Interface", ifaceId); 2098927a505aSKowalski, Kamil return; 2099927a505aSKowalski, Kamil } 2100927a505aSKowalski, Kamil }); 2101e439f0f8SKowalski, Kamil } 2102e439f0f8SKowalski, Kamil 210355c7b7a2SEd Tanous void doDelete(crow::Response &res, const crow::Request &req, 21041abe55efSEd Tanous const std::vector<std::string> ¶ms) override 21051abe55efSEd Tanous { 21064a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 21071abe55efSEd Tanous if (params.size() != 2) 21081abe55efSEd Tanous { 2109f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2110e439f0f8SKowalski, Kamil return; 2111e439f0f8SKowalski, Kamil } 2112e439f0f8SKowalski, Kamil 2113d76323e5SEd Tanous const std::string &parentIfaceId = params[0]; 211455c7b7a2SEd Tanous const std::string &ifaceId = params[1]; 2115927a505aSKowalski, Kamil 2116fda13ad2SSunitha Harish if (!verifyNames(parentIfaceId, ifaceId)) 21171abe55efSEd Tanous { 2118fda13ad2SSunitha Harish messages::resourceNotFound(asyncResp->res, "VLAN Network Interface", 2119fda13ad2SSunitha Harish ifaceId); 2120927a505aSKowalski, Kamil return; 2121927a505aSKowalski, Kamil } 2122927a505aSKowalski, Kamil 212301784826SJohnathan Mantey // Get single eth interface data, and call the below callback for 212401784826SJohnathan Mantey // JSON preparation 2125f12894f8SJason M. Bills getEthernetIfaceData( 2126fda13ad2SSunitha Harish params[1], 2127271584abSEd Tanous [asyncResp, parentIfaceId{std::string(params[0])}, 2128fda13ad2SSunitha Harish ifaceId{std::string(params[1])}]( 2129f12894f8SJason M. Bills const bool &success, const EthernetInterfaceData ðData, 2130e48c0fc5SRavi Teja const boost::container::flat_set<IPv4AddressData> &ipv4Data, 213101784826SJohnathan Mantey const boost::container::flat_set<IPv6AddressData> &ipv6Data) { 2132fda13ad2SSunitha Harish if (success && !ethData.vlan_id.empty()) 21331abe55efSEd Tanous { 2134f12894f8SJason M. Bills auto callback = 2135f12894f8SJason M. Bills [asyncResp](const boost::system::error_code ec) { 21361abe55efSEd Tanous if (ec) 21371abe55efSEd Tanous { 2138f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2139927a505aSKowalski, Kamil } 21404a0cb85cSEd Tanous }; 21414a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 21424a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 21434a0cb85cSEd Tanous std::string("/xyz/openbmc_project/network/") + ifaceId, 21444a0cb85cSEd Tanous "xyz.openbmc_project.Object.Delete", "Delete"); 21451abe55efSEd Tanous } 21461abe55efSEd Tanous else 21471abe55efSEd Tanous { 2148927a505aSKowalski, Kamil // ... otherwise return error 2149f12894f8SJason M. Bills // TODO(Pawel)consider distinguish between non existing 2150f12894f8SJason M. Bills // object, and other errors 2151f12894f8SJason M. Bills messages::resourceNotFound( 2152f12894f8SJason M. Bills asyncResp->res, "VLAN Network Interface", ifaceId); 2153927a505aSKowalski, Kamil } 2154927a505aSKowalski, Kamil }); 2155e439f0f8SKowalski, Kamil } 2156e439f0f8SKowalski, Kamil }; 2157e439f0f8SKowalski, Kamil 2158e439f0f8SKowalski, Kamil /** 2159e439f0f8SKowalski, Kamil * VlanNetworkInterfaceCollection derived class for delivering 2160e439f0f8SKowalski, Kamil * VLANNetworkInterface Collection Schema 2161e439f0f8SKowalski, Kamil */ 21621abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node 21631abe55efSEd Tanous { 2164e439f0f8SKowalski, Kamil public: 2165e439f0f8SKowalski, Kamil template <typename CrowApp> 21661abe55efSEd Tanous VlanNetworkInterfaceCollection(CrowApp &app) : 21674a0cb85cSEd Tanous Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/", 21684a0cb85cSEd Tanous std::string()) 21691abe55efSEd Tanous { 2170e439f0f8SKowalski, Kamil entityPrivileges = { 2171e439f0f8SKowalski, Kamil {boost::beast::http::verb::get, {{"Login"}}}, 2172e439f0f8SKowalski, Kamil {boost::beast::http::verb::head, {{"Login"}}}, 2173e439f0f8SKowalski, Kamil {boost::beast::http::verb::patch, {{"ConfigureComponents"}}}, 2174e439f0f8SKowalski, Kamil {boost::beast::http::verb::put, {{"ConfigureComponents"}}}, 2175e439f0f8SKowalski, Kamil {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}}, 2176e439f0f8SKowalski, Kamil {boost::beast::http::verb::post, {{"ConfigureComponents"}}}}; 2177e439f0f8SKowalski, Kamil } 2178e439f0f8SKowalski, Kamil 2179e439f0f8SKowalski, Kamil private: 2180e439f0f8SKowalski, Kamil /** 2181e439f0f8SKowalski, Kamil * Functions triggers appropriate requests on DBus 2182e439f0f8SKowalski, Kamil */ 218355c7b7a2SEd Tanous void doGet(crow::Response &res, const crow::Request &req, 21841abe55efSEd Tanous const std::vector<std::string> ¶ms) override 21851abe55efSEd Tanous { 21864a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 21871abe55efSEd Tanous if (params.size() != 1) 21881abe55efSEd Tanous { 2189e439f0f8SKowalski, Kamil // This means there is a problem with the router 2190f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2191e439f0f8SKowalski, Kamil return; 2192e439f0f8SKowalski, Kamil } 2193e439f0f8SKowalski, Kamil 21944a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 2195e439f0f8SKowalski, Kamil 21964a0cb85cSEd Tanous // Get eth interface list, and call the below callback for JSON 21971abe55efSEd Tanous // preparation 2198f12894f8SJason M. Bills getEthernetIfaceList( 219943b761d0SEd Tanous [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}]( 22001abe55efSEd Tanous const bool &success, 22014c9afe43SEd Tanous const boost::container::flat_set<std::string> &iface_list) { 22024a0cb85cSEd Tanous if (!success) 22031abe55efSEd Tanous { 2204f12894f8SJason M. Bills messages::internalError(asyncResp->res); 22054a0cb85cSEd Tanous return; 22061abe55efSEd Tanous } 22074c9afe43SEd Tanous 22084c9afe43SEd Tanous if (iface_list.find(rootInterfaceName) == iface_list.end()) 22094c9afe43SEd Tanous { 22104c9afe43SEd Tanous messages::resourceNotFound(asyncResp->res, 22114c9afe43SEd Tanous "VLanNetworkInterfaceCollection", 22124c9afe43SEd Tanous rootInterfaceName); 22134c9afe43SEd Tanous return; 22144c9afe43SEd Tanous } 22154c9afe43SEd Tanous 22160f74e643SEd Tanous asyncResp->res.jsonValue["@odata.type"] = 22170f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 22180f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 22190f74e643SEd Tanous asyncResp->res.jsonValue["@odata.context"] = 22200f74e643SEd Tanous "/redfish/v1/$metadata" 22210f74e643SEd Tanous "#VLanNetworkInterfaceCollection." 22220f74e643SEd Tanous "VLanNetworkInterfaceCollection"; 22230f74e643SEd Tanous asyncResp->res.jsonValue["Name"] = 22240f74e643SEd Tanous "VLAN Network Interface Collection"; 22254a0cb85cSEd Tanous 22264a0cb85cSEd Tanous nlohmann::json iface_array = nlohmann::json::array(); 22274a0cb85cSEd Tanous 22284a0cb85cSEd Tanous for (const std::string &iface_item : iface_list) 22291abe55efSEd Tanous { 22304a0cb85cSEd Tanous if (boost::starts_with(iface_item, rootInterfaceName + "_")) 22314a0cb85cSEd Tanous { 22324a0cb85cSEd Tanous iface_array.push_back( 22334a0cb85cSEd Tanous {{"@odata.id", 22344a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 22354a0cb85cSEd Tanous rootInterfaceName + "/VLANs/" + iface_item}}); 2236e439f0f8SKowalski, Kamil } 2237e439f0f8SKowalski, Kamil } 2238e439f0f8SKowalski, Kamil 22394a0cb85cSEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = 22404a0cb85cSEd Tanous iface_array.size(); 22414a0cb85cSEd Tanous asyncResp->res.jsonValue["Members"] = std::move(iface_array); 22424a0cb85cSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 22434a0cb85cSEd Tanous "/redfish/v1/Managers/bmc/EthernetInterfaces/" + 22444a0cb85cSEd Tanous rootInterfaceName + "/VLANs"; 2245e439f0f8SKowalski, Kamil }); 2246e439f0f8SKowalski, Kamil } 2247e439f0f8SKowalski, Kamil 224855c7b7a2SEd Tanous void doPost(crow::Response &res, const crow::Request &req, 22491abe55efSEd Tanous const std::vector<std::string> ¶ms) override 22501abe55efSEd Tanous { 22514a0cb85cSEd Tanous std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res); 22521abe55efSEd Tanous if (params.size() != 1) 22531abe55efSEd Tanous { 2254f12894f8SJason M. Bills messages::internalError(asyncResp->res); 2255e439f0f8SKowalski, Kamil return; 2256e439f0f8SKowalski, Kamil } 2257fda13ad2SSunitha Harish bool vlanEnable = false; 22580627a2c7SEd Tanous uint32_t vlanId = 0; 2259fda13ad2SSunitha Harish if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable", 2260fda13ad2SSunitha Harish vlanEnable)) 22611abe55efSEd Tanous { 22624a0cb85cSEd Tanous return; 2263e439f0f8SKowalski, Kamil } 2264fda13ad2SSunitha Harish // Need both vlanId and vlanEnable to service this request 2265fda13ad2SSunitha Harish if (!vlanId) 2266fda13ad2SSunitha Harish { 2267fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANId"); 2268fda13ad2SSunitha Harish } 2269fda13ad2SSunitha Harish if (!vlanEnable) 2270fda13ad2SSunitha Harish { 2271fda13ad2SSunitha Harish messages::propertyMissing(asyncResp->res, "VLANEnable"); 2272fda13ad2SSunitha Harish } 2273271584abSEd Tanous if (static_cast<bool>(vlanId) ^ vlanEnable) 2274fda13ad2SSunitha Harish { 2275fda13ad2SSunitha Harish return; 2276fda13ad2SSunitha Harish } 2277fda13ad2SSunitha Harish 22784a0cb85cSEd Tanous const std::string &rootInterfaceName = params[0]; 22794a0cb85cSEd Tanous auto callback = [asyncResp](const boost::system::error_code ec) { 22801abe55efSEd Tanous if (ec) 22811abe55efSEd Tanous { 22824a0cb85cSEd Tanous // TODO(ed) make more consistent error messages based on 22834a0cb85cSEd Tanous // phosphor-network responses 2284f12894f8SJason M. Bills messages::internalError(asyncResp->res); 22854a0cb85cSEd Tanous return; 22861abe55efSEd Tanous } 2287f12894f8SJason M. Bills messages::created(asyncResp->res); 2288e439f0f8SKowalski, Kamil }; 22894a0cb85cSEd Tanous crow::connections::systemBus->async_method_call( 22904a0cb85cSEd Tanous std::move(callback), "xyz.openbmc_project.Network", 22914a0cb85cSEd Tanous "/xyz/openbmc_project/network", 22924a0cb85cSEd Tanous "xyz.openbmc_project.Network.VLAN.Create", "VLAN", 22930627a2c7SEd Tanous rootInterfaceName, vlanId); 22944a0cb85cSEd Tanous } 22954a0cb85cSEd Tanous }; 22969391bb9cSRapkiewicz, Pawel } // namespace redfish 2297