xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision e48c0fc5fcdfebb8f70f4d176f2b1f8490cb94df)
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 /**
74*e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
75*e48c0fc5SRavi Teja  */
76*e48c0fc5SRavi Teja struct IPv6AddressData
77*e48c0fc5SRavi Teja {
78*e48c0fc5SRavi Teja     std::string id;
79*e48c0fc5SRavi Teja     std::string address;
80*e48c0fc5SRavi Teja     std::string origin;
81*e48c0fc5SRavi Teja     uint8_t prefixLength;
82*e48c0fc5SRavi Teja 
83*e48c0fc5SRavi Teja     bool operator<(const IPv6AddressData &obj) const
84*e48c0fc5SRavi Teja     {
85*e48c0fc5SRavi Teja         return id < obj.id;
86*e48c0fc5SRavi Teja     }
87*e48c0fc5SRavi Teja };
88*e48c0fc5SRavi Teja /**
899391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
909391bb9cSRapkiewicz, Pawel  * available from DBus
919391bb9cSRapkiewicz, Pawel  */
921abe55efSEd Tanous struct EthernetInterfaceData
931abe55efSEd Tanous {
944a0cb85cSEd Tanous     uint32_t speed;
954a0cb85cSEd Tanous     bool auto_neg;
962a133282Smanojkiraneda     bool DHCPEnabled;
974a0cb85cSEd Tanous     std::string hostname;
984a0cb85cSEd Tanous     std::string default_gateway;
999a6fc6feSRavi Teja     std::string ipv6_default_gateway;
1004a0cb85cSEd Tanous     std::string mac_address;
101fda13ad2SSunitha Harish     std::vector<std::uint32_t> vlan_id;
102029573d4SEd Tanous     std::vector<std::string> nameservers;
1039391bb9cSRapkiewicz, Pawel };
1049391bb9cSRapkiewicz, Pawel 
1059391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1069391bb9cSRapkiewicz, Pawel // into full dot notation
1071abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1081abe55efSEd Tanous {
1099391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1109391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1119391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1129391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1139391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1149391bb9cSRapkiewicz, Pawel     return netmask;
1159391bb9cSRapkiewicz, Pawel }
1169391bb9cSRapkiewicz, Pawel 
1174a0cb85cSEd Tanous inline std::string
1184a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string &inputOrigin,
1194a0cb85cSEd Tanous                                         bool isIPv4)
1201abe55efSEd Tanous {
1214a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1221abe55efSEd Tanous     {
1234a0cb85cSEd Tanous         return "Static";
1249391bb9cSRapkiewicz, Pawel     }
1254a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1261abe55efSEd Tanous     {
1274a0cb85cSEd Tanous         if (isIPv4)
1281abe55efSEd Tanous         {
1294a0cb85cSEd Tanous             return "IPv4LinkLocal";
1301abe55efSEd Tanous         }
1311abe55efSEd Tanous         else
1321abe55efSEd Tanous         {
1334a0cb85cSEd Tanous             return "LinkLocal";
1349391bb9cSRapkiewicz, Pawel         }
1359391bb9cSRapkiewicz, Pawel     }
1364a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1371abe55efSEd Tanous     {
1384a0cb85cSEd Tanous         if (isIPv4)
1394a0cb85cSEd Tanous         {
1404a0cb85cSEd Tanous             return "DHCP";
1414a0cb85cSEd Tanous         }
1424a0cb85cSEd Tanous         else
1434a0cb85cSEd Tanous         {
1444a0cb85cSEd Tanous             return "DHCPv6";
1454a0cb85cSEd Tanous         }
1464a0cb85cSEd Tanous     }
1474a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
1484a0cb85cSEd Tanous     {
1494a0cb85cSEd Tanous         return "SLAAC";
1504a0cb85cSEd Tanous     }
1514a0cb85cSEd Tanous     return "";
1524a0cb85cSEd Tanous }
1534a0cb85cSEd Tanous 
1544a0cb85cSEd Tanous inline std::string
1554a0cb85cSEd Tanous     translateAddressOriginRedfishToDbus(const std::string &inputOrigin)
1564a0cb85cSEd Tanous {
1574a0cb85cSEd Tanous     if (inputOrigin == "Static")
1584a0cb85cSEd Tanous     {
1594a0cb85cSEd Tanous         return "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
1604a0cb85cSEd Tanous     }
1614a0cb85cSEd Tanous     if (inputOrigin == "DHCP" || inputOrigin == "DHCPv6")
1624a0cb85cSEd Tanous     {
1634a0cb85cSEd Tanous         return "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
1644a0cb85cSEd Tanous     }
1654a0cb85cSEd Tanous     if (inputOrigin == "IPv4LinkLocal" || inputOrigin == "LinkLocal")
1664a0cb85cSEd Tanous     {
1674a0cb85cSEd Tanous         return "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal";
1684a0cb85cSEd Tanous     }
1694a0cb85cSEd Tanous     if (inputOrigin == "SLAAC")
1704a0cb85cSEd Tanous     {
1714a0cb85cSEd Tanous         return "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC";
1724a0cb85cSEd Tanous     }
1734a0cb85cSEd Tanous     return "";
1744a0cb85cSEd Tanous }
1754a0cb85cSEd Tanous 
1764c9afe43SEd Tanous inline bool extractEthernetInterfaceData(const std::string &ethiface_id,
1774a0cb85cSEd Tanous                                          const GetManagedObjects &dbus_data,
1784a0cb85cSEd Tanous                                          EthernetInterfaceData &ethData)
1794a0cb85cSEd Tanous {
1804c9afe43SEd Tanous     bool idFound = false;
1814a0cb85cSEd Tanous     for (const auto &objpath : dbus_data)
1824a0cb85cSEd Tanous     {
1834a0cb85cSEd Tanous         for (const auto &ifacePair : objpath.second)
1844a0cb85cSEd Tanous         {
185029573d4SEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethiface_id)
186029573d4SEd Tanous             {
1874c9afe43SEd Tanous                 idFound = true;
1884a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
1894a0cb85cSEd Tanous                 {
1904a0cb85cSEd Tanous                     for (const auto &propertyPair : ifacePair.second)
1914a0cb85cSEd Tanous                     {
1924a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
1934a0cb85cSEd Tanous                         {
1944a0cb85cSEd Tanous                             const std::string *mac =
195abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
1964a0cb85cSEd Tanous                             if (mac != nullptr)
1974a0cb85cSEd Tanous                             {
1984a0cb85cSEd Tanous                                 ethData.mac_address = *mac;
1994a0cb85cSEd Tanous                             }
2004a0cb85cSEd Tanous                         }
2014a0cb85cSEd Tanous                     }
2024a0cb85cSEd Tanous                 }
2034a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2044a0cb85cSEd Tanous                 {
2054a0cb85cSEd Tanous                     for (const auto &propertyPair : ifacePair.second)
2064a0cb85cSEd Tanous                     {
2074a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2084a0cb85cSEd Tanous                         {
2091b6b96c5SEd Tanous                             const uint32_t *id =
210abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2114a0cb85cSEd Tanous                             if (id != nullptr)
2124a0cb85cSEd Tanous                             {
213fda13ad2SSunitha Harish                                 ethData.vlan_id.push_back(*id);
2144a0cb85cSEd Tanous                             }
2154a0cb85cSEd Tanous                         }
2164a0cb85cSEd Tanous                     }
2174a0cb85cSEd Tanous                 }
2184a0cb85cSEd Tanous                 else if (ifacePair.first ==
2194a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2204a0cb85cSEd Tanous                 {
2214a0cb85cSEd Tanous                     for (const auto &propertyPair : ifacePair.second)
2224a0cb85cSEd Tanous                     {
2234a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2244a0cb85cSEd Tanous                         {
2254a0cb85cSEd Tanous                             const bool *auto_neg =
226abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2274a0cb85cSEd Tanous                             if (auto_neg != nullptr)
2284a0cb85cSEd Tanous                             {
2294a0cb85cSEd Tanous                                 ethData.auto_neg = *auto_neg;
2304a0cb85cSEd Tanous                             }
2314a0cb85cSEd Tanous                         }
2324a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2334a0cb85cSEd Tanous                         {
2344a0cb85cSEd Tanous                             const uint32_t *speed =
235abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2364a0cb85cSEd Tanous                             if (speed != nullptr)
2374a0cb85cSEd Tanous                             {
2384a0cb85cSEd Tanous                                 ethData.speed = *speed;
2394a0cb85cSEd Tanous                             }
2404a0cb85cSEd Tanous                         }
241f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
242029573d4SEd Tanous                         {
243029573d4SEd Tanous                             const std::vector<std::string> *nameservers =
244029573d4SEd Tanous                                 sdbusplus::message::variant_ns::get_if<
245029573d4SEd Tanous                                     std::vector<std::string>>(
246029573d4SEd Tanous                                     &propertyPair.second);
247029573d4SEd Tanous                             if (nameservers != nullptr)
248029573d4SEd Tanous                             {
249029573d4SEd Tanous                                 ethData.nameservers = std::move(*nameservers);
2504a0cb85cSEd Tanous                             }
2514a0cb85cSEd Tanous                         }
2522a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
2532a133282Smanojkiraneda                         {
2542a133282Smanojkiraneda                             const bool *DHCPEnabled =
2552a133282Smanojkiraneda                                 std::get_if<bool>(&propertyPair.second);
2562a133282Smanojkiraneda                             if (DHCPEnabled != nullptr)
2572a133282Smanojkiraneda                             {
2582a133282Smanojkiraneda                                 ethData.DHCPEnabled = *DHCPEnabled;
2592a133282Smanojkiraneda                             }
2602a133282Smanojkiraneda                         }
261029573d4SEd Tanous                     }
262029573d4SEd Tanous                 }
263029573d4SEd Tanous             }
264029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
265029573d4SEd Tanous             // to check eth number
266029573d4SEd Tanous             if (ifacePair.first ==
2674a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
2684a0cb85cSEd Tanous             {
2694a0cb85cSEd Tanous                 for (const auto &propertyPair : ifacePair.second)
2704a0cb85cSEd Tanous                 {
2714a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
2724a0cb85cSEd Tanous                     {
2734a0cb85cSEd Tanous                         const std::string *hostname =
274029573d4SEd Tanous                             sdbusplus::message::variant_ns::get_if<std::string>(
275029573d4SEd Tanous                                 &propertyPair.second);
2764a0cb85cSEd Tanous                         if (hostname != nullptr)
2774a0cb85cSEd Tanous                         {
2784a0cb85cSEd Tanous                             ethData.hostname = *hostname;
2794a0cb85cSEd Tanous                         }
2804a0cb85cSEd Tanous                     }
2814a0cb85cSEd Tanous                     else if (propertyPair.first == "DefaultGateway")
2824a0cb85cSEd Tanous                     {
2834a0cb85cSEd Tanous                         const std::string *defaultGateway =
284029573d4SEd Tanous                             sdbusplus::message::variant_ns::get_if<std::string>(
285029573d4SEd Tanous                                 &propertyPair.second);
2864a0cb85cSEd Tanous                         if (defaultGateway != nullptr)
2874a0cb85cSEd Tanous                         {
2884a0cb85cSEd Tanous                             ethData.default_gateway = *defaultGateway;
2894a0cb85cSEd Tanous                         }
2904a0cb85cSEd Tanous                     }
2919a6fc6feSRavi Teja                     else if (propertyPair.first == "DefaultGateway6")
2929a6fc6feSRavi Teja                     {
2939a6fc6feSRavi Teja                         const std::string *defaultGateway6 =
2949a6fc6feSRavi Teja                             sdbusplus::message::variant_ns::get_if<std::string>(
2959a6fc6feSRavi Teja                                 &propertyPair.second);
2969a6fc6feSRavi Teja                         if (defaultGateway6 != nullptr)
2979a6fc6feSRavi Teja                         {
2989a6fc6feSRavi Teja                             ethData.ipv6_default_gateway = *defaultGateway6;
2999a6fc6feSRavi Teja                         }
3009a6fc6feSRavi Teja                     }
3014a0cb85cSEd Tanous                 }
3024a0cb85cSEd Tanous             }
3034a0cb85cSEd Tanous         }
3044a0cb85cSEd Tanous     }
3054c9afe43SEd Tanous     return idFound;
3064a0cb85cSEd Tanous }
3074a0cb85cSEd Tanous 
308*e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
309*e48c0fc5SRavi Teja inline void extractIPV6Data(
310*e48c0fc5SRavi Teja     const std::string &ethiface_id, const GetManagedObjects &dbus_data,
311*e48c0fc5SRavi Teja     boost::container::flat_set<IPv6AddressData> &ipv6_config,
312*e48c0fc5SRavi Teja     boost::container::flat_set<IPv6AddressData> &ipv6_static_config)
313*e48c0fc5SRavi Teja {
314*e48c0fc5SRavi Teja     const std::string ipv6PathStart =
315*e48c0fc5SRavi Teja         "/xyz/openbmc_project/network/" + ethiface_id + "/ipv6/";
316*e48c0fc5SRavi Teja 
317*e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
318*e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
319*e48c0fc5SRavi Teja     for (const auto &objpath : dbus_data)
320*e48c0fc5SRavi Teja     {
321*e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
322*e48c0fc5SRavi Teja         if (boost::starts_with(objpath.first.str, ipv6PathStart))
323*e48c0fc5SRavi Teja         {
324*e48c0fc5SRavi Teja             for (auto &interface : objpath.second)
325*e48c0fc5SRavi Teja             {
326*e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
327*e48c0fc5SRavi Teja                 {
328*e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
329*e48c0fc5SRavi Teja                     // appropriate
330*e48c0fc5SRavi Teja                     std::pair<
331*e48c0fc5SRavi Teja                         boost::container::flat_set<IPv6AddressData>::iterator,
332*e48c0fc5SRavi Teja                         bool>
333*e48c0fc5SRavi Teja                         it = ipv6_config.insert(
334*e48c0fc5SRavi Teja                             {objpath.first.str.substr(ipv6PathStart.size())});
335*e48c0fc5SRavi Teja                     IPv6AddressData &ipv6_address = *it.first;
336*e48c0fc5SRavi Teja                     for (auto &property : interface.second)
337*e48c0fc5SRavi Teja                     {
338*e48c0fc5SRavi Teja                         if (property.first == "Address")
339*e48c0fc5SRavi Teja                         {
340*e48c0fc5SRavi Teja                             const std::string *address =
341*e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
342*e48c0fc5SRavi Teja                             if (address != nullptr)
343*e48c0fc5SRavi Teja                             {
344*e48c0fc5SRavi Teja                                 ipv6_address.address = *address;
345*e48c0fc5SRavi Teja                             }
346*e48c0fc5SRavi Teja                         }
347*e48c0fc5SRavi Teja                         else if (property.first == "Origin")
348*e48c0fc5SRavi Teja                         {
349*e48c0fc5SRavi Teja                             const std::string *origin =
350*e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
351*e48c0fc5SRavi Teja                             if (origin != nullptr)
352*e48c0fc5SRavi Teja                             {
353*e48c0fc5SRavi Teja                                 ipv6_address.origin =
354*e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
355*e48c0fc5SRavi Teja                                                                         false);
356*e48c0fc5SRavi Teja                             }
357*e48c0fc5SRavi Teja                         }
358*e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
359*e48c0fc5SRavi Teja                         {
360*e48c0fc5SRavi Teja                             const uint8_t *prefix =
361*e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
362*e48c0fc5SRavi Teja                             if (prefix != nullptr)
363*e48c0fc5SRavi Teja                             {
364*e48c0fc5SRavi Teja                                 ipv6_address.prefixLength = *prefix;
365*e48c0fc5SRavi Teja                             }
366*e48c0fc5SRavi Teja                         }
367*e48c0fc5SRavi Teja                         else
368*e48c0fc5SRavi Teja                         {
369*e48c0fc5SRavi Teja                             BMCWEB_LOG_ERROR
370*e48c0fc5SRavi Teja                                 << "Got extra property: " << property.first
371*e48c0fc5SRavi Teja                                 << " on the " << objpath.first.str << " object";
372*e48c0fc5SRavi Teja                         }
373*e48c0fc5SRavi Teja                     }
374*e48c0fc5SRavi Teja                     if (ipv6_address.origin == "Static")
375*e48c0fc5SRavi Teja                     {
376*e48c0fc5SRavi Teja                         std::pair<boost::container::flat_set<
377*e48c0fc5SRavi Teja                                       IPv6AddressData>::iterator,
378*e48c0fc5SRavi Teja                                   bool>
379*e48c0fc5SRavi Teja                             iter = ipv6_static_config.insert(
380*e48c0fc5SRavi Teja                                 {objpath.first.str.substr(
381*e48c0fc5SRavi Teja                                     ipv6PathStart.size())});
382*e48c0fc5SRavi Teja                         IPv6AddressData &ipv6_static_address = *iter.first;
383*e48c0fc5SRavi Teja 
384*e48c0fc5SRavi Teja                         ipv6_static_address.address = ipv6_address.address;
385*e48c0fc5SRavi Teja                         ipv6_static_address.prefixLength =
386*e48c0fc5SRavi Teja                             ipv6_address.prefixLength;
387*e48c0fc5SRavi Teja                     }
388*e48c0fc5SRavi Teja                 }
389*e48c0fc5SRavi Teja             }
390*e48c0fc5SRavi Teja         }
391*e48c0fc5SRavi Teja     }
392*e48c0fc5SRavi Teja }
393*e48c0fc5SRavi Teja 
3944a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
3954a0cb85cSEd Tanous inline void
3964a0cb85cSEd Tanous     extractIPData(const std::string &ethiface_id,
3974a0cb85cSEd Tanous                   const GetManagedObjects &dbus_data,
3984a0cb85cSEd Tanous                   boost::container::flat_set<IPv4AddressData> &ipv4_config)
3994a0cb85cSEd Tanous {
4004a0cb85cSEd Tanous     const std::string ipv4PathStart =
4014a0cb85cSEd Tanous         "/xyz/openbmc_project/network/" + ethiface_id + "/ipv4/";
4024a0cb85cSEd Tanous 
4034a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
4044a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
4054a0cb85cSEd Tanous     for (const auto &objpath : dbus_data)
4064a0cb85cSEd Tanous     {
4074a0cb85cSEd Tanous         // Check if proper pattern for object path appears
4084a0cb85cSEd Tanous         if (boost::starts_with(objpath.first.str, ipv4PathStart))
4094a0cb85cSEd Tanous         {
4104a0cb85cSEd Tanous             for (auto &interface : objpath.second)
4114a0cb85cSEd Tanous             {
4124a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
4134a0cb85cSEd Tanous                 {
4144a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
4154a0cb85cSEd Tanous                     // appropriate
4164a0cb85cSEd Tanous                     std::pair<
4174a0cb85cSEd Tanous                         boost::container::flat_set<IPv4AddressData>::iterator,
4184a0cb85cSEd Tanous                         bool>
4194a0cb85cSEd Tanous                         it = ipv4_config.insert(
420b01bf299SEd Tanous                             {objpath.first.str.substr(ipv4PathStart.size())});
4214a0cb85cSEd Tanous                     IPv4AddressData &ipv4_address = *it.first;
4224a0cb85cSEd Tanous                     for (auto &property : interface.second)
4234a0cb85cSEd Tanous                     {
4244a0cb85cSEd Tanous                         if (property.first == "Address")
4254a0cb85cSEd Tanous                         {
4264a0cb85cSEd Tanous                             const std::string *address =
427abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
4284a0cb85cSEd Tanous                             if (address != nullptr)
4294a0cb85cSEd Tanous                             {
4304a0cb85cSEd Tanous                                 ipv4_address.address = *address;
4314a0cb85cSEd Tanous                             }
4324a0cb85cSEd Tanous                         }
4334a0cb85cSEd Tanous                         else if (property.first == "Gateway")
4344a0cb85cSEd Tanous                         {
4354a0cb85cSEd Tanous                             const std::string *gateway =
436abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
4374a0cb85cSEd Tanous                             if (gateway != nullptr)
4384a0cb85cSEd Tanous                             {
4394a0cb85cSEd Tanous                                 ipv4_address.gateway = *gateway;
4404a0cb85cSEd Tanous                             }
4414a0cb85cSEd Tanous                         }
4424a0cb85cSEd Tanous                         else if (property.first == "Origin")
4434a0cb85cSEd Tanous                         {
4444a0cb85cSEd Tanous                             const std::string *origin =
445abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
4464a0cb85cSEd Tanous                             if (origin != nullptr)
4474a0cb85cSEd Tanous                             {
4484a0cb85cSEd Tanous                                 ipv4_address.origin =
4494a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
4504a0cb85cSEd Tanous                                                                         true);
4514a0cb85cSEd Tanous                             }
4524a0cb85cSEd Tanous                         }
4534a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
4544a0cb85cSEd Tanous                         {
4554a0cb85cSEd Tanous                             const uint8_t *mask =
456abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
4574a0cb85cSEd Tanous                             if (mask != nullptr)
4584a0cb85cSEd Tanous                             {
4594a0cb85cSEd Tanous                                 // convert it to the string
4604a0cb85cSEd Tanous                                 ipv4_address.netmask = getNetmask(*mask);
4614a0cb85cSEd Tanous                             }
4624a0cb85cSEd Tanous                         }
4634a0cb85cSEd Tanous                         else
4644a0cb85cSEd Tanous                         {
4654a0cb85cSEd Tanous                             BMCWEB_LOG_ERROR
4664a0cb85cSEd Tanous                                 << "Got extra property: " << property.first
4674a0cb85cSEd Tanous                                 << " on the " << objpath.first.str << " object";
4684a0cb85cSEd Tanous                         }
4694a0cb85cSEd Tanous                     }
4704a0cb85cSEd Tanous                     // Check if given address is local, or global
4714a0cb85cSEd Tanous                     ipv4_address.linktype =
4724a0cb85cSEd Tanous                         boost::starts_with(ipv4_address.address, "169.254.")
4734a0cb85cSEd Tanous                             ? LinkType::Global
4744a0cb85cSEd Tanous                             : LinkType::Local;
4754a0cb85cSEd Tanous                 }
4764a0cb85cSEd Tanous             }
4774a0cb85cSEd Tanous         }
4784a0cb85cSEd Tanous     }
4794a0cb85cSEd Tanous }
480588c3f0dSKowalski, Kamil 
481588c3f0dSKowalski, Kamil /**
482588c3f0dSKowalski, Kamil  * @brief Sets given Id on the given VLAN interface through D-Bus
483588c3f0dSKowalski, Kamil  *
484588c3f0dSKowalski, Kamil  * @param[in] ifaceId       Id of VLAN interface that should be modified
485588c3f0dSKowalski, Kamil  * @param[in] inputVlanId   New ID of the VLAN
486588c3f0dSKowalski, Kamil  * @param[in] callback      Function that will be called after the operation
487588c3f0dSKowalski, Kamil  *
488588c3f0dSKowalski, Kamil  * @return None.
489588c3f0dSKowalski, Kamil  */
490588c3f0dSKowalski, Kamil template <typename CallbackFunc>
4914a0cb85cSEd Tanous void changeVlanId(const std::string &ifaceId, const uint32_t &inputVlanId,
4921abe55efSEd Tanous                   CallbackFunc &&callback)
4931abe55efSEd Tanous {
49455c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
495588c3f0dSKowalski, Kamil         callback, "xyz.openbmc_project.Network",
496588c3f0dSKowalski, Kamil         std::string("/xyz/openbmc_project/network/") + ifaceId,
497588c3f0dSKowalski, Kamil         "org.freedesktop.DBus.Properties", "Set",
498588c3f0dSKowalski, Kamil         "xyz.openbmc_project.Network.VLAN", "Id",
499abf2add6SEd Tanous         std::variant<uint32_t>(inputVlanId));
5004a0cb85cSEd Tanous }
501588c3f0dSKowalski, Kamil 
502588c3f0dSKowalski, Kamil /**
503179db1d7SKowalski, Kamil  * @brief Helper function that verifies IP address to check if it is in
504179db1d7SKowalski, Kamil  *        proper format. If bits pointer is provided, also calculates active
505179db1d7SKowalski, Kamil  *        bit count for Subnet Mask.
506179db1d7SKowalski, Kamil  *
507179db1d7SKowalski, Kamil  * @param[in]  ip     IP that will be verified
508179db1d7SKowalski, Kamil  * @param[out] bits   Calculated mask in bits notation
509179db1d7SKowalski, Kamil  *
510179db1d7SKowalski, Kamil  * @return true in case of success, false otherwise
511179db1d7SKowalski, Kamil  */
5124a0cb85cSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string &ip,
5131abe55efSEd Tanous                                        uint8_t *bits = nullptr)
5141abe55efSEd Tanous {
515179db1d7SKowalski, Kamil     std::vector<std::string> bytesInMask;
516179db1d7SKowalski, Kamil 
517179db1d7SKowalski, Kamil     boost::split(bytesInMask, ip, boost::is_any_of("."));
518179db1d7SKowalski, Kamil 
5194a0cb85cSEd Tanous     static const constexpr int ipV4AddressSectionsCount = 4;
5201abe55efSEd Tanous     if (bytesInMask.size() != ipV4AddressSectionsCount)
5211abe55efSEd Tanous     {
522179db1d7SKowalski, Kamil         return false;
523179db1d7SKowalski, Kamil     }
524179db1d7SKowalski, Kamil 
5251abe55efSEd Tanous     if (bits != nullptr)
5261abe55efSEd Tanous     {
527179db1d7SKowalski, Kamil         *bits = 0;
528179db1d7SKowalski, Kamil     }
529179db1d7SKowalski, Kamil 
530179db1d7SKowalski, Kamil     char *endPtr;
531179db1d7SKowalski, Kamil     long previousValue = 255;
532179db1d7SKowalski, Kamil     bool firstZeroInByteHit;
5331abe55efSEd Tanous     for (const std::string &byte : bytesInMask)
5341abe55efSEd Tanous     {
5351abe55efSEd Tanous         if (byte.empty())
5361abe55efSEd Tanous         {
5371db9ca37SKowalski, Kamil             return false;
5381db9ca37SKowalski, Kamil         }
5391db9ca37SKowalski, Kamil 
540179db1d7SKowalski, Kamil         // Use strtol instead of stroi to avoid exceptions
5411db9ca37SKowalski, Kamil         long value = std::strtol(byte.c_str(), &endPtr, 10);
542179db1d7SKowalski, Kamil 
5434a0cb85cSEd Tanous         // endPtr should point to the end of the string, otherwise given string
5444a0cb85cSEd Tanous         // is not 100% number
5451abe55efSEd Tanous         if (*endPtr != '\0')
5461abe55efSEd Tanous         {
547179db1d7SKowalski, Kamil             return false;
548179db1d7SKowalski, Kamil         }
549179db1d7SKowalski, Kamil 
550179db1d7SKowalski, Kamil         // Value should be contained in byte
5511abe55efSEd Tanous         if (value < 0 || value > 255)
5521abe55efSEd Tanous         {
553179db1d7SKowalski, Kamil             return false;
554179db1d7SKowalski, Kamil         }
555179db1d7SKowalski, Kamil 
5561abe55efSEd Tanous         if (bits != nullptr)
5571abe55efSEd Tanous         {
558179db1d7SKowalski, Kamil             // Mask has to be continuous between bytes
5591abe55efSEd Tanous             if (previousValue != 255 && value != 0)
5601abe55efSEd Tanous             {
561179db1d7SKowalski, Kamil                 return false;
562179db1d7SKowalski, Kamil             }
563179db1d7SKowalski, Kamil 
564179db1d7SKowalski, Kamil             // Mask has to be continuous inside bytes
565179db1d7SKowalski, Kamil             firstZeroInByteHit = false;
566179db1d7SKowalski, Kamil 
567179db1d7SKowalski, Kamil             // Count bits
5681abe55efSEd Tanous             for (int bitIdx = 7; bitIdx >= 0; bitIdx--)
5691abe55efSEd Tanous             {
5701abe55efSEd Tanous                 if (value & (1 << bitIdx))
5711abe55efSEd Tanous                 {
5721abe55efSEd Tanous                     if (firstZeroInByteHit)
5731abe55efSEd Tanous                     {
574179db1d7SKowalski, Kamil                         // Continuity not preserved
575179db1d7SKowalski, Kamil                         return false;
5761abe55efSEd Tanous                     }
5771abe55efSEd Tanous                     else
5781abe55efSEd Tanous                     {
579179db1d7SKowalski, Kamil                         (*bits)++;
580179db1d7SKowalski, Kamil                     }
5811abe55efSEd Tanous                 }
5821abe55efSEd Tanous                 else
5831abe55efSEd Tanous                 {
584179db1d7SKowalski, Kamil                     firstZeroInByteHit = true;
585179db1d7SKowalski, Kamil                 }
586179db1d7SKowalski, Kamil             }
587179db1d7SKowalski, Kamil         }
588179db1d7SKowalski, Kamil 
589179db1d7SKowalski, Kamil         previousValue = value;
590179db1d7SKowalski, Kamil     }
591179db1d7SKowalski, Kamil 
592179db1d7SKowalski, Kamil     return true;
593179db1d7SKowalski, Kamil }
594179db1d7SKowalski, Kamil 
595179db1d7SKowalski, Kamil /**
596b01bf299SEd Tanous  * @brief Changes IPv4 address type property (Address, Gateway)
597b01bf299SEd Tanous  *
598b01bf299SEd Tanous  * @param[in] ifaceId     Id of interface whose IP should be modified
599b01bf299SEd Tanous  * @param[in] ipIdx       Index of IP in input array that should be modified
600b01bf299SEd Tanous  * @param[in] ipHash      DBus Hash id of modified IP
601b01bf299SEd Tanous  * @param[in] name        Name of field in JSON representation
602b01bf299SEd Tanous  * @param[in] newValue    New value that should be written
603b01bf299SEd Tanous  * @param[io] asyncResp   Response object that will be returned to client
604b01bf299SEd Tanous  *
605b01bf299SEd Tanous  * @return true if give IP is valid and has been sent do D-Bus, false
606b01bf299SEd Tanous  * otherwise
607b01bf299SEd Tanous  */
608b01bf299SEd Tanous inline void changeIPv4AddressProperty(
609b01bf299SEd Tanous     const std::string &ifaceId, int ipIdx, const std::string &ipHash,
610b01bf299SEd Tanous     const std::string &name, const std::string &newValue,
611b01bf299SEd Tanous     const std::shared_ptr<AsyncResp> asyncResp)
612b01bf299SEd Tanous {
613b01bf299SEd Tanous     auto callback = [asyncResp, ipIdx, name{std::string(name)},
614b01bf299SEd Tanous                      newValue{std::move(newValue)}](
615b01bf299SEd Tanous                         const boost::system::error_code ec) {
616b01bf299SEd Tanous         if (ec)
617b01bf299SEd Tanous         {
618b01bf299SEd Tanous             messages::internalError(asyncResp->res);
619b01bf299SEd Tanous         }
620b01bf299SEd Tanous         else
621b01bf299SEd Tanous         {
622b01bf299SEd Tanous             asyncResp->res.jsonValue["IPv4Addresses"][ipIdx][name] = newValue;
623b01bf299SEd Tanous         }
624b01bf299SEd Tanous     };
625b01bf299SEd Tanous 
626b01bf299SEd Tanous     crow::connections::systemBus->async_method_call(
627b01bf299SEd Tanous         std::move(callback), "xyz.openbmc_project.Network",
628b01bf299SEd Tanous         "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
629b01bf299SEd Tanous         "org.freedesktop.DBus.Properties", "Set",
630b01bf299SEd Tanous         "xyz.openbmc_project.Network.IP", name,
631b01bf299SEd Tanous         std::variant<std::string>(newValue));
632b01bf299SEd Tanous }
633b01bf299SEd Tanous 
634b01bf299SEd Tanous /**
635179db1d7SKowalski, Kamil  * @brief Changes IPv4 address origin property
636179db1d7SKowalski, Kamil  *
637179db1d7SKowalski, Kamil  * @param[in] ifaceId       Id of interface whose IP should be modified
6384a0cb85cSEd Tanous  * @param[in] ipIdx         Index of IP in input array that should be
6391abe55efSEd Tanous  * modified
640179db1d7SKowalski, Kamil  * @param[in] ipHash        DBus Hash id of modified IP
641179db1d7SKowalski, Kamil  * @param[in] newValue      New value in Redfish format
642179db1d7SKowalski, Kamil  * @param[in] newValueDbus  New value in D-Bus format
643179db1d7SKowalski, Kamil  * @param[io] asyncResp     Response object that will be returned to client
644179db1d7SKowalski, Kamil  *
645179db1d7SKowalski, Kamil  * @return true if give IP is valid and has been sent do D-Bus, false
646179db1d7SKowalski, Kamil  * otherwise
647179db1d7SKowalski, Kamil  */
648b01bf299SEd Tanous inline void changeIPv4Origin(const std::string &ifaceId, int ipIdx,
6491abe55efSEd Tanous                              const std::string &ipHash,
6501abe55efSEd Tanous                              const std::string &newValue,
651179db1d7SKowalski, Kamil                              const std::string &newValueDbus,
6524a0cb85cSEd Tanous                              const std::shared_ptr<AsyncResp> asyncResp)
6531abe55efSEd Tanous {
6544a0cb85cSEd Tanous     auto callback = [asyncResp, ipIdx, newValue{std::move(newValue)}](
6551abe55efSEd Tanous                         const boost::system::error_code ec) {
6561abe55efSEd Tanous         if (ec)
6571abe55efSEd Tanous         {
658a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
6591abe55efSEd Tanous         }
6601abe55efSEd Tanous         else
6611abe55efSEd Tanous         {
6624a0cb85cSEd Tanous             asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["AddressOrigin"] =
663179db1d7SKowalski, Kamil                 newValue;
664179db1d7SKowalski, Kamil         }
665179db1d7SKowalski, Kamil     };
666179db1d7SKowalski, Kamil 
66755c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
668179db1d7SKowalski, Kamil         std::move(callback), "xyz.openbmc_project.Network",
669179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
670179db1d7SKowalski, Kamil         "org.freedesktop.DBus.Properties", "Set",
671179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP", "Origin",
672abf2add6SEd Tanous         std::variant<std::string>(newValueDbus));
6734a0cb85cSEd Tanous }
674179db1d7SKowalski, Kamil 
675179db1d7SKowalski, Kamil /**
676179db1d7SKowalski, Kamil  * @brief Modifies SubnetMask for given IP
677179db1d7SKowalski, Kamil  *
678179db1d7SKowalski, Kamil  * @param[in] ifaceId      Id of interface whose IP should be modified
6794a0cb85cSEd Tanous  * @param[in] ipIdx        Index of IP in input array that should be
6801abe55efSEd Tanous  * modified
681179db1d7SKowalski, Kamil  * @param[in] ipHash       DBus Hash id of modified IP
682179db1d7SKowalski, Kamil  * @param[in] newValueStr  Mask in dot notation as string
683179db1d7SKowalski, Kamil  * @param[in] newValue     Mask as PrefixLength in bitcount
684179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
685179db1d7SKowalski, Kamil  *
686179db1d7SKowalski, Kamil  * @return None
687179db1d7SKowalski, Kamil  */
688b01bf299SEd Tanous inline void changeIPv4SubnetMaskProperty(const std::string &ifaceId, int ipIdx,
6894a0cb85cSEd Tanous                                          const std::string &ipHash,
6904a0cb85cSEd Tanous                                          const std::string &newValueStr,
6914a0cb85cSEd Tanous                                          uint8_t &newValue,
6924a0cb85cSEd Tanous                                          std::shared_ptr<AsyncResp> asyncResp)
6931abe55efSEd Tanous {
6944a0cb85cSEd Tanous     auto callback = [asyncResp, ipIdx, newValueStr{std::move(newValueStr)}](
6951abe55efSEd Tanous                         const boost::system::error_code ec) {
6961abe55efSEd Tanous         if (ec)
6971abe55efSEd Tanous         {
698a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
6991abe55efSEd Tanous         }
7001abe55efSEd Tanous         else
7011abe55efSEd Tanous         {
70255c7b7a2SEd Tanous             asyncResp->res.jsonValue["IPv4Addresses"][ipIdx]["SubnetMask"] =
703179db1d7SKowalski, Kamil                 newValueStr;
704179db1d7SKowalski, Kamil         }
705179db1d7SKowalski, Kamil     };
706179db1d7SKowalski, Kamil 
70755c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
708179db1d7SKowalski, Kamil         std::move(callback), "xyz.openbmc_project.Network",
709179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
710179db1d7SKowalski, Kamil         "org.freedesktop.DBus.Properties", "Set",
711179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP", "PrefixLength",
712abf2add6SEd Tanous         std::variant<uint8_t>(newValue));
7134a0cb85cSEd Tanous }
714588c3f0dSKowalski, Kamil 
715588c3f0dSKowalski, Kamil /**
716179db1d7SKowalski, Kamil  * @brief Deletes given IPv4
717179db1d7SKowalski, Kamil  *
718179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
7194a0cb85cSEd Tanous  * @param[in] ipIdx       Index of IP in input array that should be deleted
720179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
721179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
722179db1d7SKowalski, Kamil  *
723179db1d7SKowalski, Kamil  * @return None
724179db1d7SKowalski, Kamil  */
7254a0cb85cSEd Tanous inline void deleteIPv4(const std::string &ifaceId, const std::string &ipHash,
726179db1d7SKowalski, Kamil                        unsigned int ipIdx,
7274a0cb85cSEd Tanous                        const std::shared_ptr<AsyncResp> asyncResp)
7281abe55efSEd Tanous {
72955c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7304a0cb85cSEd Tanous         [ipIdx, asyncResp](const boost::system::error_code ec) {
7311abe55efSEd Tanous             if (ec)
7321abe55efSEd Tanous             {
733a08b46ccSJason M. Bills                 messages::internalError(asyncResp->res);
7341abe55efSEd Tanous             }
7351abe55efSEd Tanous             else
7361abe55efSEd Tanous             {
73755c7b7a2SEd Tanous                 asyncResp->res.jsonValue["IPv4Addresses"][ipIdx] = nullptr;
738179db1d7SKowalski, Kamil             }
739179db1d7SKowalski, Kamil         },
740179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
741179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" + ipHash,
742179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
743179db1d7SKowalski, Kamil }
744179db1d7SKowalski, Kamil 
745179db1d7SKowalski, Kamil /**
746179db1d7SKowalski, Kamil  * @brief Creates IPv4 with given data
747179db1d7SKowalski, Kamil  *
748179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
7494a0cb85cSEd Tanous  * @param[in] ipIdx       Index of IP in input array that should be deleted
750179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
751179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
752179db1d7SKowalski, Kamil  *
753179db1d7SKowalski, Kamil  * @return None
754179db1d7SKowalski, Kamil  */
755b01bf299SEd Tanous inline void createIPv4(const std::string &ifaceId, unsigned int ipIdx,
756b01bf299SEd Tanous                        uint8_t subnetMask, const std::string &gateway,
757b01bf299SEd Tanous                        const std::string &address,
7584a0cb85cSEd Tanous                        std::shared_ptr<AsyncResp> asyncResp)
7591abe55efSEd Tanous {
76043b761d0SEd Tanous     auto createIpHandler = [asyncResp](const boost::system::error_code ec) {
7611abe55efSEd Tanous         if (ec)
7621abe55efSEd Tanous         {
763a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
764179db1d7SKowalski, Kamil         }
765179db1d7SKowalski, Kamil     };
766179db1d7SKowalski, Kamil 
76755c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
768179db1d7SKowalski, Kamil         std::move(createIpHandler), "xyz.openbmc_project.Network",
769179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
770179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
771179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, subnetMask,
772179db1d7SKowalski, Kamil         gateway);
773179db1d7SKowalski, Kamil }
774*e48c0fc5SRavi Teja 
775*e48c0fc5SRavi Teja /**
776*e48c0fc5SRavi Teja  * @brief Deletes given IPv6
777*e48c0fc5SRavi Teja  *
778*e48c0fc5SRavi Teja  * @param[in] ifaceId     Id of interface whose IP should be deleted
779*e48c0fc5SRavi Teja  * @param[in] ipHash      DBus Hash id of IP that should be deleted
780*e48c0fc5SRavi Teja  * @param[in] ipIdx       Index of IP in input array that should be deleted
781*e48c0fc5SRavi Teja  * @param[io] asyncResp   Response object that will be returned to client
782*e48c0fc5SRavi Teja  *
783*e48c0fc5SRavi Teja  * @return None
784*e48c0fc5SRavi Teja  */
785*e48c0fc5SRavi Teja inline void deleteIPv6(const std::string &ifaceId, const std::string &ipHash,
786*e48c0fc5SRavi Teja                        unsigned int ipIdx,
787*e48c0fc5SRavi Teja                        const std::shared_ptr<AsyncResp> asyncResp)
788*e48c0fc5SRavi Teja {
789*e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
790*e48c0fc5SRavi Teja         [ipIdx, asyncResp](const boost::system::error_code ec) {
791*e48c0fc5SRavi Teja             if (ec)
792*e48c0fc5SRavi Teja             {
793*e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
794*e48c0fc5SRavi Teja             }
795*e48c0fc5SRavi Teja             else
796*e48c0fc5SRavi Teja             {
797*e48c0fc5SRavi Teja                 asyncResp->res.jsonValue["IPv6StaticAddresses"][ipIdx] =
798*e48c0fc5SRavi Teja                     nullptr;
799*e48c0fc5SRavi Teja             }
800*e48c0fc5SRavi Teja         },
801*e48c0fc5SRavi Teja         "xyz.openbmc_project.Network",
802*e48c0fc5SRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" + ipHash,
803*e48c0fc5SRavi Teja         "xyz.openbmc_project.Object.Delete", "Delete");
804*e48c0fc5SRavi Teja }
805*e48c0fc5SRavi Teja 
806*e48c0fc5SRavi Teja /**
807*e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
808*e48c0fc5SRavi Teja  *
809*e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
810*e48c0fc5SRavi Teja  * @param[in] ipIdx        Index of IP in input array that should be added
811*e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
812*e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
813*e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
814*e48c0fc5SRavi Teja  *
815*e48c0fc5SRavi Teja  * @return None
816*e48c0fc5SRavi Teja  */
817*e48c0fc5SRavi Teja inline void createIPv6(const std::string &ifaceId, unsigned int ipIdx,
818*e48c0fc5SRavi Teja                        uint8_t prefixLength, const std::string &address,
819*e48c0fc5SRavi Teja                        std::shared_ptr<AsyncResp> asyncResp)
820*e48c0fc5SRavi Teja {
821*e48c0fc5SRavi Teja     auto createIpHandler = [asyncResp](const boost::system::error_code ec) {
822*e48c0fc5SRavi Teja         if (ec)
823*e48c0fc5SRavi Teja         {
824*e48c0fc5SRavi Teja             messages::internalError(asyncResp->res);
825*e48c0fc5SRavi Teja         }
826*e48c0fc5SRavi Teja     };
827*e48c0fc5SRavi Teja     // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
828*e48c0fc5SRavi Teja     // does not have assosiated gateway property
829*e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
830*e48c0fc5SRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
831*e48c0fc5SRavi Teja         "/xyz/openbmc_project/network/" + ifaceId,
832*e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
833*e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
834*e48c0fc5SRavi Teja         "");
835*e48c0fc5SRavi Teja }
836*e48c0fc5SRavi Teja 
8372a133282Smanojkiraneda using GetAllPropertiesType =
8382a133282Smanojkiraneda     boost::container::flat_map<std::string, sdbusplus::message::variant<bool>>;
8392a133282Smanojkiraneda 
8402a133282Smanojkiraneda inline void getDHCPConfigData(const std::shared_ptr<AsyncResp> asyncResp)
8412a133282Smanojkiraneda {
8422a133282Smanojkiraneda     auto getConfig = [asyncResp](const boost::system::error_code error_code,
8432a133282Smanojkiraneda                                  const GetAllPropertiesType &dbus_data) {
8442a133282Smanojkiraneda         if (error_code)
8452a133282Smanojkiraneda         {
8462a133282Smanojkiraneda             BMCWEB_LOG_ERROR << "D-Bus response error: " << error_code;
8472a133282Smanojkiraneda             messages::internalError(asyncResp->res);
8482a133282Smanojkiraneda             return;
8492a133282Smanojkiraneda         }
850fda13ad2SSunitha Harish         nlohmann::json &DHCPConfigTypeJson = asyncResp->res.jsonValue["DHCPv4"];
8512a133282Smanojkiraneda         for (const auto &property : dbus_data)
8522a133282Smanojkiraneda         {
8532a133282Smanojkiraneda             auto value =
8542a133282Smanojkiraneda                 sdbusplus::message::variant_ns::get_if<bool>(&property.second);
8552a133282Smanojkiraneda 
8562a133282Smanojkiraneda             if (value == nullptr)
8572a133282Smanojkiraneda             {
8582a133282Smanojkiraneda                 continue;
8592a133282Smanojkiraneda             }
8602a133282Smanojkiraneda             if (property.first == "DNSEnabled")
8612a133282Smanojkiraneda             {
8622a133282Smanojkiraneda                 DHCPConfigTypeJson["UseDNSServers"] = *value;
8632a133282Smanojkiraneda             }
8642a133282Smanojkiraneda             else if (property.first == "HostNameEnabled")
8652a133282Smanojkiraneda             {
8662a133282Smanojkiraneda                 DHCPConfigTypeJson["UseDomainName"] = *value;
8672a133282Smanojkiraneda             }
8682a133282Smanojkiraneda             else if (property.first == "NTPEnabled")
8692a133282Smanojkiraneda             {
8702a133282Smanojkiraneda                 DHCPConfigTypeJson["UseNTPServers"] = *value;
8712a133282Smanojkiraneda             }
8722a133282Smanojkiraneda         }
8732a133282Smanojkiraneda     };
8742a133282Smanojkiraneda     crow::connections::systemBus->async_method_call(
8752a133282Smanojkiraneda         std::move(getConfig), "xyz.openbmc_project.Network",
8762a133282Smanojkiraneda         "/xyz/openbmc_project/network/config/dhcp",
8772a133282Smanojkiraneda         "org.freedesktop.DBus.Properties", "GetAll",
8782a133282Smanojkiraneda         "xyz.openbmc_project.Network.DHCPConfiguration");
8792a133282Smanojkiraneda }
880179db1d7SKowalski, Kamil 
881179db1d7SKowalski, Kamil /**
882179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
883179db1d7SKowalski, Kamil  * Object
884179db1d7SKowalski, Kamil  * from EntityManager Network Manager
8854a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
886179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
887179db1d7SKowalski, Kamil  * into JSON
888179db1d7SKowalski, Kamil  */
889179db1d7SKowalski, Kamil template <typename CallbackFunc>
8904a0cb85cSEd Tanous void getEthernetIfaceData(const std::string &ethiface_id,
8911abe55efSEd Tanous                           CallbackFunc &&callback)
8921abe55efSEd Tanous {
89355c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
8944a0cb85cSEd Tanous         [ethiface_id{std::string{ethiface_id}}, callback{std::move(callback)}](
8951abe55efSEd Tanous             const boost::system::error_code error_code,
8964a0cb85cSEd Tanous             const GetManagedObjects &resp) {
89755c7b7a2SEd Tanous             EthernetInterfaceData ethData{};
8984a0cb85cSEd Tanous             boost::container::flat_set<IPv4AddressData> ipv4Data;
899*e48c0fc5SRavi Teja             boost::container::flat_set<IPv6AddressData> ipv6Data;
900*e48c0fc5SRavi Teja             boost::container::flat_set<IPv6AddressData> ipv6StaticData;
901179db1d7SKowalski, Kamil 
9021abe55efSEd Tanous             if (error_code)
9031abe55efSEd Tanous             {
904*e48c0fc5SRavi Teja                 callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData);
905179db1d7SKowalski, Kamil                 return;
906179db1d7SKowalski, Kamil             }
907179db1d7SKowalski, Kamil 
9084c9afe43SEd Tanous             bool found =
9094a0cb85cSEd Tanous                 extractEthernetInterfaceData(ethiface_id, resp, ethData);
9104c9afe43SEd Tanous             if (!found)
9114c9afe43SEd Tanous             {
912*e48c0fc5SRavi Teja                 callback(false, ethData, ipv4Data, ipv6Data, ipv6StaticData);
9134c9afe43SEd Tanous                 return;
9144c9afe43SEd Tanous             }
9154c9afe43SEd Tanous 
9164a0cb85cSEd Tanous             extractIPData(ethiface_id, resp, ipv4Data);
917179db1d7SKowalski, Kamil             // Fix global GW
9181abe55efSEd Tanous             for (IPv4AddressData &ipv4 : ipv4Data)
9191abe55efSEd Tanous             {
9204a0cb85cSEd Tanous                 if ((ipv4.linktype == LinkType::Global) &&
9214a0cb85cSEd Tanous                     (ipv4.gateway == "0.0.0.0"))
9221abe55efSEd Tanous                 {
9234a0cb85cSEd Tanous                     ipv4.gateway = ethData.default_gateway;
924179db1d7SKowalski, Kamil                 }
925179db1d7SKowalski, Kamil             }
926179db1d7SKowalski, Kamil 
927*e48c0fc5SRavi Teja             extractIPV6Data(ethiface_id, resp, ipv6Data, ipv6StaticData);
9284a0cb85cSEd Tanous             // Finally make a callback with usefull data
929*e48c0fc5SRavi Teja             callback(true, ethData, ipv4Data, ipv6Data, ipv6StaticData);
930179db1d7SKowalski, Kamil         },
931179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
932179db1d7SKowalski, Kamil         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
933179db1d7SKowalski, Kamil };
934179db1d7SKowalski, Kamil 
935179db1d7SKowalski, Kamil /**
9369391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
9379391bb9cSRapkiewicz, Pawel  * Manager
9381abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
9391abe55efSEd Tanous  * into JSON.
9409391bb9cSRapkiewicz, Pawel  */
9419391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
9421abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc &&callback)
9431abe55efSEd Tanous {
94455c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
9454a0cb85cSEd Tanous         [callback{std::move(callback)}](
9469391bb9cSRapkiewicz, Pawel             const boost::system::error_code error_code,
9474a0cb85cSEd Tanous             GetManagedObjects &resp) {
9481abe55efSEd Tanous             // Callback requires vector<string> to retrieve all available
9491abe55efSEd Tanous             // ethernet interfaces
9504c9afe43SEd Tanous             boost::container::flat_set<std::string> iface_list;
9514a0cb85cSEd Tanous             iface_list.reserve(resp.size());
9521abe55efSEd Tanous             if (error_code)
9531abe55efSEd Tanous             {
9544a0cb85cSEd Tanous                 callback(false, iface_list);
9559391bb9cSRapkiewicz, Pawel                 return;
9569391bb9cSRapkiewicz, Pawel             }
9579391bb9cSRapkiewicz, Pawel 
9589391bb9cSRapkiewicz, Pawel             // Iterate over all retrieved ObjectPaths.
9594a0cb85cSEd Tanous             for (const auto &objpath : resp)
9601abe55efSEd Tanous             {
9619391bb9cSRapkiewicz, Pawel                 // And all interfaces available for certain ObjectPath.
9624a0cb85cSEd Tanous                 for (const auto &interface : objpath.second)
9631abe55efSEd Tanous                 {
9641abe55efSEd Tanous                     // If interface is
9654a0cb85cSEd Tanous                     // xyz.openbmc_project.Network.EthernetInterface, this is
9664a0cb85cSEd Tanous                     // what we're looking for.
9679391bb9cSRapkiewicz, Pawel                     if (interface.first ==
9681abe55efSEd Tanous                         "xyz.openbmc_project.Network.EthernetInterface")
9691abe55efSEd Tanous                     {
9704a0cb85cSEd Tanous                         // Cut out everyting until last "/", ...
9714a0cb85cSEd Tanous                         const std::string &iface_id = objpath.first.str;
9724a0cb85cSEd Tanous                         std::size_t last_pos = iface_id.rfind("/");
9734a0cb85cSEd Tanous                         if (last_pos != std::string::npos)
9741abe55efSEd Tanous                         {
9759391bb9cSRapkiewicz, Pawel                             // and put it into output vector.
9764c9afe43SEd Tanous                             iface_list.emplace(iface_id.substr(last_pos + 1));
9779391bb9cSRapkiewicz, Pawel                         }
9789391bb9cSRapkiewicz, Pawel                     }
9799391bb9cSRapkiewicz, Pawel                 }
9809391bb9cSRapkiewicz, Pawel             }
981a434f2bdSEd Tanous             // Finally make a callback with useful data
9824a0cb85cSEd Tanous             callback(true, iface_list);
9839391bb9cSRapkiewicz, Pawel         },
984aa2e59c1SEd Tanous         "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
985aa2e59c1SEd Tanous         "org.freedesktop.DBus.ObjectManager", "GetManagedObjects");
9869391bb9cSRapkiewicz, Pawel };
9879391bb9cSRapkiewicz, Pawel 
9889391bb9cSRapkiewicz, Pawel /**
9899391bb9cSRapkiewicz, Pawel  * EthernetCollection derived class for delivering Ethernet Collection Schema
9909391bb9cSRapkiewicz, Pawel  */
9911abe55efSEd Tanous class EthernetCollection : public Node
9921abe55efSEd Tanous {
9939391bb9cSRapkiewicz, Pawel   public:
9944a0cb85cSEd Tanous     template <typename CrowApp>
9951abe55efSEd Tanous     EthernetCollection(CrowApp &app) :
9964a0cb85cSEd Tanous         Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
9971abe55efSEd Tanous     {
998588c3f0dSKowalski, Kamil         entityPrivileges = {
999588c3f0dSKowalski, Kamil             {boost::beast::http::verb::get, {{"Login"}}},
1000e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
1001e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1002e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1003e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1004e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
10059391bb9cSRapkiewicz, Pawel     }
10069391bb9cSRapkiewicz, Pawel 
10079391bb9cSRapkiewicz, Pawel   private:
10089391bb9cSRapkiewicz, Pawel     /**
10099391bb9cSRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
10109391bb9cSRapkiewicz, Pawel      */
101155c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
10121abe55efSEd Tanous                const std::vector<std::string> &params) override
10131abe55efSEd Tanous     {
10140f74e643SEd Tanous         res.jsonValue["@odata.type"] =
10150f74e643SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
10160f74e643SEd Tanous         res.jsonValue["@odata.context"] =
10170f74e643SEd Tanous             "/redfish/v1/"
10180f74e643SEd Tanous             "$metadata#EthernetInterfaceCollection.EthernetInterfaceCollection";
10190f74e643SEd Tanous         res.jsonValue["@odata.id"] =
10200f74e643SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
10210f74e643SEd Tanous         res.jsonValue["Name"] = "Ethernet Network Interface Collection";
10220f74e643SEd Tanous         res.jsonValue["Description"] =
10230f74e643SEd Tanous             "Collection of EthernetInterfaces for this Manager";
10244c9afe43SEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
10254a0cb85cSEd Tanous         // Get eth interface list, and call the below callback for JSON
10261abe55efSEd Tanous         // preparation
1027f12894f8SJason M. Bills         getEthernetIfaceList(
10284c9afe43SEd Tanous             [asyncResp](
10294c9afe43SEd Tanous                 const bool &success,
10304c9afe43SEd Tanous                 const boost::container::flat_set<std::string> &iface_list) {
10314a0cb85cSEd Tanous                 if (!success)
10321abe55efSEd Tanous                 {
10334c9afe43SEd Tanous                     messages::internalError(asyncResp->res);
10344a0cb85cSEd Tanous                     return;
10354a0cb85cSEd Tanous                 }
10364a0cb85cSEd Tanous 
10374c9afe43SEd Tanous                 nlohmann::json &iface_array =
10384c9afe43SEd Tanous                     asyncResp->res.jsonValue["Members"];
10394a0cb85cSEd Tanous                 iface_array = nlohmann::json::array();
1040fda13ad2SSunitha Harish                 std::string tag = "_";
10414a0cb85cSEd Tanous                 for (const std::string &iface_item : iface_list)
10421abe55efSEd Tanous                 {
1043fda13ad2SSunitha Harish                     std::size_t found = iface_item.find(tag);
1044fda13ad2SSunitha Harish                     if (found == std::string::npos)
1045fda13ad2SSunitha Harish                     {
10464a0cb85cSEd Tanous                         iface_array.push_back(
10474a0cb85cSEd Tanous                             {{"@odata.id",
10484a0cb85cSEd Tanous                               "/redfish/v1/Managers/bmc/EthernetInterfaces/" +
10494a0cb85cSEd Tanous                                   iface_item}});
10509391bb9cSRapkiewicz, Pawel                     }
1051fda13ad2SSunitha Harish                 }
10524a0cb85cSEd Tanous 
10534c9afe43SEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] =
10544c9afe43SEd Tanous                     iface_array.size();
10554c9afe43SEd Tanous                 asyncResp->res.jsonValue["@odata.id"] =
10564a0cb85cSEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces";
10579391bb9cSRapkiewicz, Pawel             });
10589391bb9cSRapkiewicz, Pawel     }
10599391bb9cSRapkiewicz, Pawel };
10609391bb9cSRapkiewicz, Pawel 
10619391bb9cSRapkiewicz, Pawel /**
10629391bb9cSRapkiewicz, Pawel  * EthernetInterface derived class for delivering Ethernet Schema
10639391bb9cSRapkiewicz, Pawel  */
10641abe55efSEd Tanous class EthernetInterface : public Node
10651abe55efSEd Tanous {
10669391bb9cSRapkiewicz, Pawel   public:
10679391bb9cSRapkiewicz, Pawel     /*
10689391bb9cSRapkiewicz, Pawel      * Default Constructor
10699391bb9cSRapkiewicz, Pawel      */
10704a0cb85cSEd Tanous     template <typename CrowApp>
10711abe55efSEd Tanous     EthernetInterface(CrowApp &app) :
10724a0cb85cSEd Tanous         Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/",
10731abe55efSEd Tanous              std::string())
10741abe55efSEd Tanous     {
1075588c3f0dSKowalski, Kamil         entityPrivileges = {
1076588c3f0dSKowalski, Kamil             {boost::beast::http::verb::get, {{"Login"}}},
1077e0d918bcSEd Tanous             {boost::beast::http::verb::head, {{"Login"}}},
1078e0d918bcSEd Tanous             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1079e0d918bcSEd Tanous             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1080e0d918bcSEd Tanous             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1081e0d918bcSEd Tanous             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
10829391bb9cSRapkiewicz, Pawel     }
10839391bb9cSRapkiewicz, Pawel 
1084e439f0f8SKowalski, Kamil   private:
1085bc0bd6e0SEd Tanous     void handleHostnamePatch(const std::string &hostname,
10864a0cb85cSEd Tanous                              const std::shared_ptr<AsyncResp> asyncResp)
10871abe55efSEd Tanous     {
1088bc0bd6e0SEd Tanous         asyncResp->res.jsonValue["HostName"] = hostname;
1089bc0bd6e0SEd Tanous         crow::connections::systemBus->async_method_call(
1090bc0bd6e0SEd Tanous             [asyncResp](const boost::system::error_code ec) {
10914a0cb85cSEd Tanous                 if (ec)
10924a0cb85cSEd Tanous                 {
1093a08b46ccSJason M. Bills                     messages::internalError(asyncResp->res);
10941abe55efSEd Tanous                 }
1095bc0bd6e0SEd Tanous             },
1096bc0bd6e0SEd Tanous             "xyz.openbmc_project.Network",
1097bc0bd6e0SEd Tanous             "/xyz/openbmc_project/network/config",
1098bc0bd6e0SEd Tanous             "org.freedesktop.DBus.Properties", "Set",
1099bc0bd6e0SEd Tanous             "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
1100abf2add6SEd Tanous             std::variant<std::string>(hostname));
1101588c3f0dSKowalski, Kamil     }
1102588c3f0dSKowalski, Kamil 
1103d577665bSRatan Gupta     void handleMACAddressPatch(const std::string &ifaceId,
1104d577665bSRatan Gupta                                const std::string &macAddress,
1105d577665bSRatan Gupta                                const std::shared_ptr<AsyncResp> &asyncResp)
1106d577665bSRatan Gupta     {
1107d577665bSRatan Gupta         crow::connections::systemBus->async_method_call(
1108d577665bSRatan Gupta             [asyncResp, macAddress](const boost::system::error_code ec) {
1109d577665bSRatan Gupta                 if (ec)
1110d577665bSRatan Gupta                 {
1111d577665bSRatan Gupta                     messages::internalError(asyncResp->res);
1112d577665bSRatan Gupta                     return;
1113d577665bSRatan Gupta                 }
1114d577665bSRatan Gupta                 asyncResp->res.jsonValue["MACAddress"] = std::move(macAddress);
1115d577665bSRatan Gupta             },
1116d577665bSRatan Gupta             "xyz.openbmc_project.Network",
1117d577665bSRatan Gupta             "/xyz/openbmc_project/network/" + ifaceId,
1118d577665bSRatan Gupta             "org.freedesktop.DBus.Properties", "Set",
1119d577665bSRatan Gupta             "xyz.openbmc_project.Network.MACAddress", "MACAddress",
1120d577665bSRatan Gupta             std::variant<std::string>(macAddress));
1121d577665bSRatan Gupta     }
1122da131a9aSJennifer Lee     void setDHCPEnabled(const std::string &ifaceId,
1123da131a9aSJennifer Lee                         const std::string &propertyName, const bool &value,
1124da131a9aSJennifer Lee                         const std::shared_ptr<AsyncResp> asyncResp)
1125da131a9aSJennifer Lee     {
1126da131a9aSJennifer Lee         crow::connections::systemBus->async_method_call(
1127da131a9aSJennifer Lee             [asyncResp](const boost::system::error_code ec) {
1128da131a9aSJennifer Lee                 if (ec)
1129da131a9aSJennifer Lee                 {
1130da131a9aSJennifer Lee                     BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1131da131a9aSJennifer Lee                     messages::internalError(asyncResp->res);
1132da131a9aSJennifer Lee                     return;
1133da131a9aSJennifer Lee                 }
1134da131a9aSJennifer Lee             },
1135da131a9aSJennifer Lee             "xyz.openbmc_project.Network",
1136da131a9aSJennifer Lee             "/xyz/openbmc_project/network/" + ifaceId,
1137da131a9aSJennifer Lee             "org.freedesktop.DBus.Properties", "Set",
1138da131a9aSJennifer Lee             "xyz.openbmc_project.Network.EthernetInterface", propertyName,
1139da131a9aSJennifer Lee             std::variant<bool>{value});
1140da131a9aSJennifer Lee     }
1141da131a9aSJennifer Lee     void setDHCPv4Config(const std::string &propertyName, const bool &value,
1142da131a9aSJennifer Lee                          const std::shared_ptr<AsyncResp> asyncResp)
1143da131a9aSJennifer Lee     {
1144da131a9aSJennifer Lee         BMCWEB_LOG_DEBUG << propertyName << " = " << value;
1145da131a9aSJennifer Lee         crow::connections::systemBus->async_method_call(
1146da131a9aSJennifer Lee             [asyncResp](const boost::system::error_code ec) {
1147da131a9aSJennifer Lee                 if (ec)
1148da131a9aSJennifer Lee                 {
1149da131a9aSJennifer Lee                     BMCWEB_LOG_ERROR << "D-Bus responses error: " << ec;
1150da131a9aSJennifer Lee                     messages::internalError(asyncResp->res);
1151da131a9aSJennifer Lee                     return;
1152da131a9aSJennifer Lee                 }
1153da131a9aSJennifer Lee             },
1154da131a9aSJennifer Lee             "xyz.openbmc_project.Network",
1155da131a9aSJennifer Lee             "/xyz/openbmc_project/network/config/dhcp",
1156da131a9aSJennifer Lee             "org.freedesktop.DBus.Properties", "Set",
1157da131a9aSJennifer Lee             "xyz.openbmc_project.Network.DHCPConfiguration", propertyName,
1158da131a9aSJennifer Lee             std::variant<bool>{value});
1159da131a9aSJennifer Lee     }
1160d577665bSRatan Gupta 
1161da131a9aSJennifer Lee     void handleDHCPv4Patch(const std::string &ifaceId, nlohmann::json &input,
1162da131a9aSJennifer Lee                            const std::shared_ptr<AsyncResp> asyncResp)
1163da131a9aSJennifer Lee     {
1164da131a9aSJennifer Lee         std::optional<bool> dhcpEnabled;
1165da131a9aSJennifer Lee         std::optional<bool> useDNSServers;
1166da131a9aSJennifer Lee         std::optional<bool> useDomainName;
1167da131a9aSJennifer Lee         std::optional<bool> useNTPServers;
1168da131a9aSJennifer Lee 
1169da131a9aSJennifer Lee         if (!json_util::readJson(input, asyncResp->res, "DHCPEnabled",
1170da131a9aSJennifer Lee                                  dhcpEnabled, "UseDNSServers", useDNSServers,
1171da131a9aSJennifer Lee                                  "UseDomainName", useDomainName,
1172da131a9aSJennifer Lee                                  "UseNTPServers", useNTPServers))
1173da131a9aSJennifer Lee         {
1174da131a9aSJennifer Lee             return;
1175da131a9aSJennifer Lee         }
1176da131a9aSJennifer Lee 
1177da131a9aSJennifer Lee         if (dhcpEnabled)
1178da131a9aSJennifer Lee         {
1179da131a9aSJennifer Lee             BMCWEB_LOG_DEBUG << "set DHCPEnabled...";
1180da131a9aSJennifer Lee             setDHCPEnabled(ifaceId, "DHCPEnabled", *dhcpEnabled, asyncResp);
1181da131a9aSJennifer Lee         }
1182da131a9aSJennifer Lee 
1183da131a9aSJennifer Lee         if (useDNSServers)
1184da131a9aSJennifer Lee         {
1185da131a9aSJennifer Lee             BMCWEB_LOG_DEBUG << "set DNSEnabled...";
1186da131a9aSJennifer Lee             setDHCPv4Config("DNSEnabled", *useDNSServers, asyncResp);
1187da131a9aSJennifer Lee         }
1188da131a9aSJennifer Lee 
1189da131a9aSJennifer Lee         if (useDomainName)
1190da131a9aSJennifer Lee         {
1191da131a9aSJennifer Lee             BMCWEB_LOG_DEBUG << "set HostNameEnabled...";
1192da131a9aSJennifer Lee             setDHCPv4Config("HostNameEnabled", *useDomainName, asyncResp);
1193da131a9aSJennifer Lee         }
1194da131a9aSJennifer Lee 
1195da131a9aSJennifer Lee         if (useNTPServers)
1196da131a9aSJennifer Lee         {
1197da131a9aSJennifer Lee             BMCWEB_LOG_DEBUG << "set NTPEnabled...";
1198da131a9aSJennifer Lee             setDHCPv4Config("NTPEnabled", *useNTPServers, asyncResp);
1199da131a9aSJennifer Lee         }
1200da131a9aSJennifer Lee     }
12014a0cb85cSEd Tanous     void handleIPv4Patch(
1202f476acbfSRatan Gupta         const std::string &ifaceId, nlohmann::json &input,
12034a0cb85cSEd Tanous         const boost::container::flat_set<IPv4AddressData> &ipv4Data,
12044a0cb85cSEd Tanous         const std::shared_ptr<AsyncResp> asyncResp)
12051abe55efSEd Tanous     {
1206f476acbfSRatan Gupta         if (!input.is_array())
1207f476acbfSRatan Gupta         {
1208f476acbfSRatan Gupta             messages::propertyValueTypeError(asyncResp->res, input.dump(),
1209f476acbfSRatan Gupta                                              "IPv4Addresses");
1210f476acbfSRatan Gupta             return;
1211f476acbfSRatan Gupta         }
1212f476acbfSRatan Gupta 
12134a0cb85cSEd Tanous         int entryIdx = 0;
12144a0cb85cSEd Tanous         boost::container::flat_set<IPv4AddressData>::const_iterator thisData =
12154a0cb85cSEd Tanous             ipv4Data.begin();
1216537174c4SEd Tanous         for (nlohmann::json &thisJson : input)
12171abe55efSEd Tanous         {
12184a0cb85cSEd Tanous             std::string pathString =
1219a08b46ccSJason M. Bills                 "IPv4Addresses/" + std::to_string(entryIdx);
1220179db1d7SKowalski, Kamil 
1221f476acbfSRatan Gupta             if (thisJson.is_null())
1222f476acbfSRatan Gupta             {
1223f476acbfSRatan Gupta                 if (thisData != ipv4Data.end())
1224f476acbfSRatan Gupta                 {
1225f476acbfSRatan Gupta                     deleteIPv4(ifaceId, thisData->id, entryIdx, asyncResp);
1226f476acbfSRatan Gupta                     thisData++;
1227f476acbfSRatan Gupta                 }
1228f476acbfSRatan Gupta                 else
1229f476acbfSRatan Gupta                 {
1230f476acbfSRatan Gupta                     messages::propertyValueFormatError(
1231f476acbfSRatan Gupta                         asyncResp->res, input.dump(), pathString);
1232f476acbfSRatan Gupta                     return;
1233f476acbfSRatan Gupta                     // TODO(ratagupt) Not sure about the property where value is
1234f476acbfSRatan Gupta                     // list and if unable to update one of the
1235f476acbfSRatan Gupta                     // list value then should we proceed further or
1236f476acbfSRatan Gupta                     // break there, would ask in the redfish forum
1237f476acbfSRatan Gupta                     // till then we stop processing the next list item.
1238f476acbfSRatan Gupta                 }
1239f476acbfSRatan Gupta                 entryIdx++;
1240f476acbfSRatan Gupta                 continue; // not an error as per the redfish spec.
1241f476acbfSRatan Gupta             }
1242f476acbfSRatan Gupta 
12439474b378SRatan Gupta             if (thisJson.empty())
12449474b378SRatan Gupta             {
12459474b378SRatan Gupta                 if (thisData != ipv4Data.end())
12469474b378SRatan Gupta                 {
12479474b378SRatan Gupta                     thisData++;
12489474b378SRatan Gupta                 }
12499474b378SRatan Gupta                 else
12509474b378SRatan Gupta                 {
12519474b378SRatan Gupta                     messages::propertyMissing(asyncResp->res,
12529474b378SRatan Gupta                                               pathString + "/Address");
12539474b378SRatan Gupta                     return;
1254f476acbfSRatan Gupta                     // TODO(ratagupt) Not sure about the property where value is
12559474b378SRatan Gupta                     // list and if unable to update one of the
12569474b378SRatan Gupta                     // list value then should we proceed further or
12579474b378SRatan Gupta                     // break there, would ask in the redfish forum
12589474b378SRatan Gupta                     // till then we stop processing the next list item.
12599474b378SRatan Gupta                 }
12609474b378SRatan Gupta                 entryIdx++;
12619474b378SRatan Gupta                 continue; // not an error as per the redfish spec.
12629474b378SRatan Gupta             }
12639474b378SRatan Gupta 
1264537174c4SEd Tanous             std::optional<std::string> address;
1265537174c4SEd Tanous             std::optional<std::string> addressOrigin;
1266537174c4SEd Tanous             std::optional<std::string> subnetMask;
1267537174c4SEd Tanous             std::optional<std::string> gateway;
1268537174c4SEd Tanous 
1269537174c4SEd Tanous             if (!json_util::readJson(thisJson, asyncResp->res, "Address",
1270537174c4SEd Tanous                                      address, "AddressOrigin", addressOrigin,
1271537174c4SEd Tanous                                      "SubnetMask", subnetMask, "Gateway",
1272537174c4SEd Tanous                                      gateway))
1273537174c4SEd Tanous             {
1274537174c4SEd Tanous                 return;
1275179db1d7SKowalski, Kamil             }
1276179db1d7SKowalski, Kamil 
1277537174c4SEd Tanous             if (address)
12781abe55efSEd Tanous             {
1279537174c4SEd Tanous                 if (!ipv4VerifyIpAndGetBitcount(*address))
12801abe55efSEd Tanous                 {
1281537174c4SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
12824a0cb85cSEd Tanous                                                        pathString + "/Address");
1283537174c4SEd Tanous                     return;
12844a0cb85cSEd Tanous                 }
12854a0cb85cSEd Tanous             }
12864a0cb85cSEd Tanous 
1287537174c4SEd Tanous             uint8_t prefixLength = 0;
1288537174c4SEd Tanous             if (subnetMask)
12894a0cb85cSEd Tanous             {
1290537174c4SEd Tanous                 if (!ipv4VerifyIpAndGetBitcount(*subnetMask, &prefixLength))
12914a0cb85cSEd Tanous                 {
1292f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1293537174c4SEd Tanous                         asyncResp->res, *subnetMask,
12944a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1295537174c4SEd Tanous                     return;
12964a0cb85cSEd Tanous                 }
12974a0cb85cSEd Tanous             }
12984a0cb85cSEd Tanous             std::string addressOriginInDBusFormat;
1299537174c4SEd Tanous             if (addressOrigin)
13004a0cb85cSEd Tanous             {
13014a0cb85cSEd Tanous                 // Get Address origin in proper format
13024a0cb85cSEd Tanous                 addressOriginInDBusFormat =
1303537174c4SEd Tanous                     translateAddressOriginRedfishToDbus(*addressOrigin);
13044a0cb85cSEd Tanous                 if (addressOriginInDBusFormat.empty())
13054a0cb85cSEd Tanous                 {
13064a0cb85cSEd Tanous                     messages::propertyValueNotInList(
1307537174c4SEd Tanous                         asyncResp->res, *addressOrigin,
1308a08b46ccSJason M. Bills                         pathString + "/AddressOrigin");
1309537174c4SEd Tanous                     return;
13104a0cb85cSEd Tanous                 }
13114a0cb85cSEd Tanous             }
13124a0cb85cSEd Tanous 
1313537174c4SEd Tanous             if (gateway)
13144a0cb85cSEd Tanous             {
1315537174c4SEd Tanous                 if (!ipv4VerifyIpAndGetBitcount(*gateway))
13164a0cb85cSEd Tanous                 {
1317537174c4SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1318537174c4SEd Tanous                                                        pathString + "/Gateway");
1319537174c4SEd Tanous                     return;
13204a0cb85cSEd Tanous                 }
13214a0cb85cSEd Tanous             }
13224a0cb85cSEd Tanous 
1323f476acbfSRatan Gupta             // if IP address exist then  modify it.
13244a0cb85cSEd Tanous             if (thisData != ipv4Data.end())
13254a0cb85cSEd Tanous             {
1326179db1d7SKowalski, Kamil                 // Apply changes
1327537174c4SEd Tanous                 if (address)
13281abe55efSEd Tanous                 {
1329f476acbfSRatan Gupta                     auto callback = [asyncResp, entryIdx,
1330f476acbfSRatan Gupta                                      address{std::string(*address)}](
13314a0cb85cSEd Tanous                                         const boost::system::error_code ec) {
13324a0cb85cSEd Tanous                         if (ec)
13331abe55efSEd Tanous                         {
1334a08b46ccSJason M. Bills                             messages::internalError(asyncResp->res);
13354a0cb85cSEd Tanous                             return;
13364a0cb85cSEd Tanous                         }
1337f476acbfSRatan Gupta                         asyncResp->res
1338f476acbfSRatan Gupta                             .jsonValue["IPv4Addresses"][entryIdx]["Address"] =
1339f476acbfSRatan Gupta                             std::move(address);
13404a0cb85cSEd Tanous                     };
13414a0cb85cSEd Tanous 
13424a0cb85cSEd Tanous                     crow::connections::systemBus->async_method_call(
13434a0cb85cSEd Tanous                         std::move(callback), "xyz.openbmc_project.Network",
1344f476acbfSRatan Gupta                         "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" +
1345f476acbfSRatan Gupta                             thisData->id,
13464a0cb85cSEd Tanous                         "org.freedesktop.DBus.Properties", "Set",
13474a0cb85cSEd Tanous                         "xyz.openbmc_project.Network.IP", "Address",
1348537174c4SEd Tanous                         std::variant<std::string>(*address));
1349179db1d7SKowalski, Kamil                 }
1350179db1d7SKowalski, Kamil 
1351537174c4SEd Tanous                 if (subnetMask)
13521abe55efSEd Tanous                 {
13534a0cb85cSEd Tanous                     changeIPv4SubnetMaskProperty(ifaceId, entryIdx,
1354537174c4SEd Tanous                                                  thisData->id, *subnetMask,
1355537174c4SEd Tanous                                                  prefixLength, asyncResp);
1356179db1d7SKowalski, Kamil                 }
1357179db1d7SKowalski, Kamil 
1358537174c4SEd Tanous                 if (addressOrigin)
13591abe55efSEd Tanous                 {
13604a0cb85cSEd Tanous                     changeIPv4Origin(ifaceId, entryIdx, thisData->id,
1361f476acbfSRatan Gupta                                      *addressOrigin, addressOriginInDBusFormat,
1362f476acbfSRatan Gupta                                      asyncResp);
1363179db1d7SKowalski, Kamil                 }
1364179db1d7SKowalski, Kamil 
1365537174c4SEd Tanous                 if (gateway)
13661abe55efSEd Tanous                 {
1367f476acbfSRatan Gupta                     auto callback = [asyncResp, entryIdx,
1368537174c4SEd Tanous                                      gateway{std::string(*gateway)}](
13694a0cb85cSEd Tanous                                         const boost::system::error_code ec) {
13704a0cb85cSEd Tanous                         if (ec)
13711abe55efSEd Tanous                         {
1372a08b46ccSJason M. Bills                             messages::internalError(asyncResp->res);
13734a0cb85cSEd Tanous                             return;
13744a0cb85cSEd Tanous                         }
1375f476acbfSRatan Gupta                         asyncResp->res
1376f476acbfSRatan Gupta                             .jsonValue["IPv4Addresses"][entryIdx]["Gateway"] =
1377537174c4SEd Tanous                             std::move(gateway);
13784a0cb85cSEd Tanous                     };
13794a0cb85cSEd Tanous 
13804a0cb85cSEd Tanous                     crow::connections::systemBus->async_method_call(
13814a0cb85cSEd Tanous                         std::move(callback), "xyz.openbmc_project.Network",
1382f476acbfSRatan Gupta                         "/xyz/openbmc_project/network/" + ifaceId + "/ipv4/" +
1383f476acbfSRatan Gupta                             thisData->id,
13844a0cb85cSEd Tanous                         "org.freedesktop.DBus.Properties", "Set",
13854a0cb85cSEd Tanous                         "xyz.openbmc_project.Network.IP", "Gateway",
1386537174c4SEd Tanous                         std::variant<std::string>(*gateway));
13874a0cb85cSEd Tanous                 }
1388f476acbfSRatan Gupta 
13894a0cb85cSEd Tanous                 thisData++;
13901abe55efSEd Tanous             }
13911abe55efSEd Tanous             else
13921abe55efSEd Tanous             {
13934a0cb85cSEd Tanous                 // Create IPv4 with provided data
1394537174c4SEd Tanous                 if (!gateway)
13951abe55efSEd Tanous                 {
1396a08b46ccSJason M. Bills                     messages::propertyMissing(asyncResp->res,
13974a0cb85cSEd Tanous                                               pathString + "/Gateway");
13984a0cb85cSEd Tanous                     continue;
13994a0cb85cSEd Tanous                 }
14004a0cb85cSEd Tanous 
1401537174c4SEd Tanous                 if (!address)
14021abe55efSEd Tanous                 {
1403a08b46ccSJason M. Bills                     messages::propertyMissing(asyncResp->res,
14044a0cb85cSEd Tanous                                               pathString + "/Address");
14054a0cb85cSEd Tanous                     continue;
14064a0cb85cSEd Tanous                 }
14074a0cb85cSEd Tanous 
1408537174c4SEd Tanous                 if (!subnetMask)
14091abe55efSEd Tanous                 {
1410a08b46ccSJason M. Bills                     messages::propertyMissing(asyncResp->res,
14114a0cb85cSEd Tanous                                               pathString + "/SubnetMask");
14124a0cb85cSEd Tanous                     continue;
1413588c3f0dSKowalski, Kamil                 }
1414588c3f0dSKowalski, Kamil 
1415b01bf299SEd Tanous                 createIPv4(ifaceId, entryIdx, prefixLength, *gateway, *address,
1416b01bf299SEd Tanous                            asyncResp);
141795897b20SRatan Gupta 
141895897b20SRatan Gupta                 nlohmann::json &ipv4AddressJson =
141995897b20SRatan Gupta                     asyncResp->res.jsonValue["IPv4Addresses"][entryIdx];
142095897b20SRatan Gupta                 ipv4AddressJson["Address"] = *address;
142195897b20SRatan Gupta                 ipv4AddressJson["SubnetMask"] = *subnetMask;
142295897b20SRatan Gupta                 ipv4AddressJson["Gateway"] = *gateway;
14234a0cb85cSEd Tanous             }
14244a0cb85cSEd Tanous             entryIdx++;
14254a0cb85cSEd Tanous         }
14264a0cb85cSEd Tanous     }
14274a0cb85cSEd Tanous 
1428f85837bfSRAJESWARAN THILLAIGOVINDAN     void handleStaticNameServersPatch(
1429f85837bfSRAJESWARAN THILLAIGOVINDAN         const std::string &ifaceId,
1430f85837bfSRAJESWARAN THILLAIGOVINDAN         const std::vector<std::string> &updatedStaticNameServers,
1431f85837bfSRAJESWARAN THILLAIGOVINDAN         const std::shared_ptr<AsyncResp> &asyncResp)
1432f85837bfSRAJESWARAN THILLAIGOVINDAN     {
1433f85837bfSRAJESWARAN THILLAIGOVINDAN         crow::connections::systemBus->async_method_call(
1434f85837bfSRAJESWARAN THILLAIGOVINDAN             [asyncResp,
1435f85837bfSRAJESWARAN THILLAIGOVINDAN              updatedStaticNameServers](const boost::system::error_code ec) {
1436f85837bfSRAJESWARAN THILLAIGOVINDAN                 if (ec)
1437f85837bfSRAJESWARAN THILLAIGOVINDAN                 {
1438f85837bfSRAJESWARAN THILLAIGOVINDAN                     messages::internalError(asyncResp->res);
1439f85837bfSRAJESWARAN THILLAIGOVINDAN                     return;
1440f85837bfSRAJESWARAN THILLAIGOVINDAN                 }
1441f85837bfSRAJESWARAN THILLAIGOVINDAN                 asyncResp->res.jsonValue["NameServers"] =
1442f85837bfSRAJESWARAN THILLAIGOVINDAN                     updatedStaticNameServers;
1443f85837bfSRAJESWARAN THILLAIGOVINDAN                 asyncResp->res.jsonValue["StaticNameServers"] =
1444f85837bfSRAJESWARAN THILLAIGOVINDAN                     updatedStaticNameServers;
1445f85837bfSRAJESWARAN THILLAIGOVINDAN             },
1446f85837bfSRAJESWARAN THILLAIGOVINDAN             "xyz.openbmc_project.Network",
1447f85837bfSRAJESWARAN THILLAIGOVINDAN             "/xyz/openbmc_project/network/" + ifaceId,
1448f85837bfSRAJESWARAN THILLAIGOVINDAN             "org.freedesktop.DBus.Properties", "Set",
1449f85837bfSRAJESWARAN THILLAIGOVINDAN             "xyz.openbmc_project.Network.EthernetInterface", "Nameservers",
1450f85837bfSRAJESWARAN THILLAIGOVINDAN             std::variant<std::vector<std::string>>{updatedStaticNameServers});
1451f85837bfSRAJESWARAN THILLAIGOVINDAN     }
1452f85837bfSRAJESWARAN THILLAIGOVINDAN 
1453*e48c0fc5SRavi Teja     void handleIPv6StaticAddressesPatch(
1454*e48c0fc5SRavi Teja         const std::string &ifaceId, nlohmann::json &input,
1455*e48c0fc5SRavi Teja         const boost::container::flat_set<IPv6AddressData> &ipv6StaticData,
1456*e48c0fc5SRavi Teja         const std::shared_ptr<AsyncResp> asyncResp)
1457*e48c0fc5SRavi Teja     {
1458*e48c0fc5SRavi Teja         if (!input.is_array())
1459*e48c0fc5SRavi Teja         {
1460*e48c0fc5SRavi Teja             messages::propertyValueTypeError(asyncResp->res, input.dump(),
1461*e48c0fc5SRavi Teja                                              "IPv6StaticAddresses");
1462*e48c0fc5SRavi Teja             return;
1463*e48c0fc5SRavi Teja         }
1464*e48c0fc5SRavi Teja 
1465*e48c0fc5SRavi Teja         int entryIdx = 0;
1466*e48c0fc5SRavi Teja         boost::container::flat_set<IPv6AddressData>::const_iterator thisData =
1467*e48c0fc5SRavi Teja             ipv6StaticData.begin();
1468*e48c0fc5SRavi Teja         for (nlohmann::json &thisJson : input)
1469*e48c0fc5SRavi Teja         {
1470*e48c0fc5SRavi Teja             std::string pathString =
1471*e48c0fc5SRavi Teja                 "IPv6StaticAddresses/" + std::to_string(entryIdx);
1472*e48c0fc5SRavi Teja 
1473*e48c0fc5SRavi Teja             if (thisJson.is_null())
1474*e48c0fc5SRavi Teja             {
1475*e48c0fc5SRavi Teja                 if (thisData != ipv6StaticData.end())
1476*e48c0fc5SRavi Teja                 {
1477*e48c0fc5SRavi Teja                     deleteIPv6(ifaceId, thisData->id, entryIdx, asyncResp);
1478*e48c0fc5SRavi Teja                     thisData++;
1479*e48c0fc5SRavi Teja                 }
1480*e48c0fc5SRavi Teja                 else
1481*e48c0fc5SRavi Teja                 {
1482*e48c0fc5SRavi Teja                     messages::propertyValueFormatError(
1483*e48c0fc5SRavi Teja                         asyncResp->res, input.dump(), pathString);
1484*e48c0fc5SRavi Teja                     return;
1485*e48c0fc5SRavi Teja                 }
1486*e48c0fc5SRavi Teja                 entryIdx++;
1487*e48c0fc5SRavi Teja                 continue;
1488*e48c0fc5SRavi Teja             }
1489*e48c0fc5SRavi Teja 
1490*e48c0fc5SRavi Teja             if (thisJson.empty())
1491*e48c0fc5SRavi Teja             {
1492*e48c0fc5SRavi Teja                 if (thisData != ipv6StaticData.end())
1493*e48c0fc5SRavi Teja                 {
1494*e48c0fc5SRavi Teja                     thisData++;
1495*e48c0fc5SRavi Teja                 }
1496*e48c0fc5SRavi Teja                 else
1497*e48c0fc5SRavi Teja                 {
1498*e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1499*e48c0fc5SRavi Teja                                               pathString + "/Address");
1500*e48c0fc5SRavi Teja                     return;
1501*e48c0fc5SRavi Teja                 }
1502*e48c0fc5SRavi Teja                 entryIdx++;
1503*e48c0fc5SRavi Teja                 continue;
1504*e48c0fc5SRavi Teja             }
1505*e48c0fc5SRavi Teja 
1506*e48c0fc5SRavi Teja             std::optional<std::string> address;
1507*e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
1508*e48c0fc5SRavi Teja 
1509*e48c0fc5SRavi Teja             if (!json_util::readJson(thisJson, asyncResp->res, "Address",
1510*e48c0fc5SRavi Teja                                      address, "PrefixLength", prefixLength))
1511*e48c0fc5SRavi Teja             {
1512*e48c0fc5SRavi Teja                 return;
1513*e48c0fc5SRavi Teja             }
1514*e48c0fc5SRavi Teja 
1515*e48c0fc5SRavi Teja             // if IP address exist then  modify it.
1516*e48c0fc5SRavi Teja             if (thisData != ipv6StaticData.end())
1517*e48c0fc5SRavi Teja             {
1518*e48c0fc5SRavi Teja                 // Apply changes
1519*e48c0fc5SRavi Teja                 if (address)
1520*e48c0fc5SRavi Teja                 {
1521*e48c0fc5SRavi Teja                     auto callback = [asyncResp, entryIdx,
1522*e48c0fc5SRavi Teja                                      address{std::string(*address)}](
1523*e48c0fc5SRavi Teja                                         const boost::system::error_code ec) {
1524*e48c0fc5SRavi Teja                         if (ec)
1525*e48c0fc5SRavi Teja                         {
1526*e48c0fc5SRavi Teja                             messages::internalError(asyncResp->res);
1527*e48c0fc5SRavi Teja                             return;
1528*e48c0fc5SRavi Teja                         }
1529*e48c0fc5SRavi Teja                         asyncResp->res.jsonValue["IPv6StaticAddresses"]
1530*e48c0fc5SRavi Teja                                                 [entryIdx]["Address"] =
1531*e48c0fc5SRavi Teja                             std::move(address);
1532*e48c0fc5SRavi Teja                     };
1533*e48c0fc5SRavi Teja 
1534*e48c0fc5SRavi Teja                     crow::connections::systemBus->async_method_call(
1535*e48c0fc5SRavi Teja                         std::move(callback), "xyz.openbmc_project.Network",
1536*e48c0fc5SRavi Teja                         "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" +
1537*e48c0fc5SRavi Teja                             thisData->id,
1538*e48c0fc5SRavi Teja                         "org.freedesktop.DBus.Properties", "Set",
1539*e48c0fc5SRavi Teja                         "xyz.openbmc_project.Network.IP", "Address",
1540*e48c0fc5SRavi Teja                         std::variant<std::string>(*address));
1541*e48c0fc5SRavi Teja                 }
1542*e48c0fc5SRavi Teja 
1543*e48c0fc5SRavi Teja                 if (prefixLength)
1544*e48c0fc5SRavi Teja                 {
1545*e48c0fc5SRavi Teja                     auto callback = [asyncResp, entryIdx,
1546*e48c0fc5SRavi Teja                                      prefixLength{uint8_t(*prefixLength)}](
1547*e48c0fc5SRavi Teja                                         const boost::system::error_code ec) {
1548*e48c0fc5SRavi Teja                         if (ec)
1549*e48c0fc5SRavi Teja                         {
1550*e48c0fc5SRavi Teja                             messages::internalError(asyncResp->res);
1551*e48c0fc5SRavi Teja                             return;
1552*e48c0fc5SRavi Teja                         }
1553*e48c0fc5SRavi Teja                         asyncResp->res.jsonValue["IPv6StaticAddresses"]
1554*e48c0fc5SRavi Teja                                                 [entryIdx]["PrefixLength"] =
1555*e48c0fc5SRavi Teja                             std::move(prefixLength);
1556*e48c0fc5SRavi Teja                     };
1557*e48c0fc5SRavi Teja 
1558*e48c0fc5SRavi Teja                     crow::connections::systemBus->async_method_call(
1559*e48c0fc5SRavi Teja                         std::move(callback), "xyz.openbmc_project.Network",
1560*e48c0fc5SRavi Teja                         "/xyz/openbmc_project/network/" + ifaceId + "/ipv6/" +
1561*e48c0fc5SRavi Teja                             thisData->id,
1562*e48c0fc5SRavi Teja                         "org.freedesktop.DBus.Properties", "Set",
1563*e48c0fc5SRavi Teja                         "xyz.openbmc_project.Network.IP", "PrefixLength",
1564*e48c0fc5SRavi Teja                         std::variant<uint8_t>(*prefixLength));
1565*e48c0fc5SRavi Teja                 }
1566*e48c0fc5SRavi Teja 
1567*e48c0fc5SRavi Teja                 thisData++;
1568*e48c0fc5SRavi Teja             }
1569*e48c0fc5SRavi Teja             else
1570*e48c0fc5SRavi Teja             {
1571*e48c0fc5SRavi Teja                 // Create IPv6 with provided data
1572*e48c0fc5SRavi Teja 
1573*e48c0fc5SRavi Teja                 if (!prefixLength)
1574*e48c0fc5SRavi Teja                 {
1575*e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1576*e48c0fc5SRavi Teja                                               pathString + "/PrefixLength");
1577*e48c0fc5SRavi Teja                     continue;
1578*e48c0fc5SRavi Teja                 }
1579*e48c0fc5SRavi Teja 
1580*e48c0fc5SRavi Teja                 if (!address)
1581*e48c0fc5SRavi Teja                 {
1582*e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1583*e48c0fc5SRavi Teja                                               pathString + "/Address");
1584*e48c0fc5SRavi Teja                     continue;
1585*e48c0fc5SRavi Teja                 }
1586*e48c0fc5SRavi Teja 
1587*e48c0fc5SRavi Teja                 createIPv6(ifaceId, entryIdx, *prefixLength, *address,
1588*e48c0fc5SRavi Teja                            asyncResp);
1589*e48c0fc5SRavi Teja 
1590*e48c0fc5SRavi Teja                 nlohmann::json &ipv6StaticAddressJson =
1591*e48c0fc5SRavi Teja                     asyncResp->res.jsonValue["IPv6StaticAddresses"][entryIdx];
1592*e48c0fc5SRavi Teja                 ipv6StaticAddressJson["Address"] = *address;
1593*e48c0fc5SRavi Teja                 ipv6StaticAddressJson["PrefixLength"] = *prefixLength;
1594*e48c0fc5SRavi Teja             }
1595*e48c0fc5SRavi Teja             entryIdx++;
1596*e48c0fc5SRavi Teja         }
1597*e48c0fc5SRavi Teja     }
1598*e48c0fc5SRavi Teja 
15990f74e643SEd Tanous     void parseInterfaceData(
16000f74e643SEd Tanous         nlohmann::json &json_response, const std::string &iface_id,
16010f74e643SEd Tanous         const EthernetInterfaceData &ethData,
1602*e48c0fc5SRavi Teja         const boost::container::flat_set<IPv4AddressData> &ipv4Data,
1603*e48c0fc5SRavi Teja         const boost::container::flat_set<IPv6AddressData> &ipv6Data,
1604*e48c0fc5SRavi Teja         const boost::container::flat_set<IPv6AddressData> &ipv6StaticData)
16054a0cb85cSEd Tanous     {
16064a0cb85cSEd Tanous         json_response["Id"] = iface_id;
16074a0cb85cSEd Tanous         json_response["@odata.id"] =
16084a0cb85cSEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces/" + iface_id;
1609029573d4SEd Tanous         json_response["InterfaceEnabled"] = true;
1610029573d4SEd Tanous         if (ethData.speed == 0)
1611029573d4SEd Tanous         {
1612029573d4SEd Tanous             json_response["LinkStatus"] = "NoLink";
1613029573d4SEd Tanous             json_response["Status"] = {
1614029573d4SEd Tanous                 {"Health", "OK"},
1615029573d4SEd Tanous                 {"State", "Disabled"},
1616029573d4SEd Tanous             };
1617029573d4SEd Tanous         }
1618029573d4SEd Tanous         else
1619029573d4SEd Tanous         {
1620029573d4SEd Tanous             json_response["LinkStatus"] = "LinkUp";
1621029573d4SEd Tanous             json_response["Status"] = {
1622029573d4SEd Tanous                 {"Health", "OK"},
1623029573d4SEd Tanous                 {"State", "Enabled"},
1624029573d4SEd Tanous             };
1625029573d4SEd Tanous         }
16264a0cb85cSEd Tanous         json_response["SpeedMbps"] = ethData.speed;
16274a0cb85cSEd Tanous         json_response["MACAddress"] = ethData.mac_address;
1628fda13ad2SSunitha Harish         json_response["DHCPv4"]["DHCPEnabled"] = ethData.DHCPEnabled;
16292a133282Smanojkiraneda 
16304a0cb85cSEd Tanous         if (!ethData.hostname.empty())
16314a0cb85cSEd Tanous         {
16324a0cb85cSEd Tanous             json_response["HostName"] = ethData.hostname;
16334a0cb85cSEd Tanous         }
16344a0cb85cSEd Tanous 
1635fda13ad2SSunitha Harish         json_response["VLANs"] = {
1636fda13ad2SSunitha Harish             {"@odata.id", "/redfish/v1/Managers/bmc/EthernetInterfaces/" +
1637fda13ad2SSunitha Harish                               iface_id + "/VLANs"}};
1638fda13ad2SSunitha Harish 
1639029573d4SEd Tanous         json_response["NameServers"] = ethData.nameservers;
1640f85837bfSRAJESWARAN THILLAIGOVINDAN         json_response["StaticNameServers"] = ethData.nameservers;
16414a0cb85cSEd Tanous 
16424a0cb85cSEd Tanous         if (ipv4Data.size() > 0)
16434a0cb85cSEd Tanous         {
16444a0cb85cSEd Tanous             nlohmann::json &ipv4_array = json_response["IPv4Addresses"];
16454a0cb85cSEd Tanous             ipv4_array = nlohmann::json::array();
16464a0cb85cSEd Tanous             for (auto &ipv4_config : ipv4Data)
16474a0cb85cSEd Tanous             {
1648fa5053a6SGunnar Mills 
1649fa5053a6SGunnar Mills                 std::string gatewayStr = ipv4_config.gateway;
1650fa5053a6SGunnar Mills                 if (gatewayStr.empty())
1651fa5053a6SGunnar Mills                 {
1652fa5053a6SGunnar Mills                     gatewayStr = "0.0.0.0";
1653fa5053a6SGunnar Mills                 }
1654fa5053a6SGunnar Mills 
16554a0cb85cSEd Tanous                 ipv4_array.push_back({{"AddressOrigin", ipv4_config.origin},
16564a0cb85cSEd Tanous                                       {"SubnetMask", ipv4_config.netmask},
1657029573d4SEd Tanous                                       {"Address", ipv4_config.address},
1658fa5053a6SGunnar Mills                                       {"Gateway", gatewayStr}});
16594a0cb85cSEd Tanous             }
16604a0cb85cSEd Tanous         }
16619a6fc6feSRavi Teja         json_response["IPv6DefaultGateway"] = ethData.ipv6_default_gateway;
1662*e48c0fc5SRavi Teja 
1663*e48c0fc5SRavi Teja         nlohmann::json &ipv6_array = json_response["IPv6Addresses"];
1664*e48c0fc5SRavi Teja         ipv6_array = nlohmann::json::array();
1665*e48c0fc5SRavi Teja         for (auto &ipv6_config : ipv6Data)
1666*e48c0fc5SRavi Teja         {
1667*e48c0fc5SRavi Teja             ipv6_array.push_back({{"Address", ipv6_config.address},
1668*e48c0fc5SRavi Teja                                   {"PrefixLength", ipv6_config.prefixLength},
1669*e48c0fc5SRavi Teja                                   {"AddressOrigin", ipv6_config.origin}});
1670*e48c0fc5SRavi Teja         }
1671*e48c0fc5SRavi Teja 
1672*e48c0fc5SRavi Teja         nlohmann::json &ipv6_static_array =
1673*e48c0fc5SRavi Teja             json_response["IPv6StaticAddresses"];
1674*e48c0fc5SRavi Teja         ipv6_static_array = nlohmann::json::array();
1675*e48c0fc5SRavi Teja         for (auto &ipv6_static_config : ipv6StaticData)
1676*e48c0fc5SRavi Teja         {
1677*e48c0fc5SRavi Teja             ipv6_static_array.push_back(
1678*e48c0fc5SRavi Teja                 {{"Address", ipv6_static_config.address},
1679*e48c0fc5SRavi Teja                  {"PrefixLength", ipv6_static_config.prefixLength}});
1680*e48c0fc5SRavi Teja         }
1681588c3f0dSKowalski, Kamil     }
1682588c3f0dSKowalski, Kamil 
16839391bb9cSRapkiewicz, Pawel     /**
16849391bb9cSRapkiewicz, Pawel      * Functions triggers appropriate requests on DBus
16859391bb9cSRapkiewicz, Pawel      */
168655c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
16871abe55efSEd Tanous                const std::vector<std::string> &params) override
16881abe55efSEd Tanous     {
16894a0cb85cSEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
16901abe55efSEd Tanous         if (params.size() != 1)
16911abe55efSEd Tanous         {
1692f12894f8SJason M. Bills             messages::internalError(asyncResp->res);
16939391bb9cSRapkiewicz, Pawel             return;
16949391bb9cSRapkiewicz, Pawel         }
16959391bb9cSRapkiewicz, Pawel 
16964a0cb85cSEd Tanous         getEthernetIfaceData(
16974a0cb85cSEd Tanous             params[0],
16984a0cb85cSEd Tanous             [this, asyncResp, iface_id{std::string(params[0])}](
16994a0cb85cSEd Tanous                 const bool &success, const EthernetInterfaceData &ethData,
1700*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv4AddressData> &ipv4Data,
1701*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData> &ipv6Data,
1702*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData>
1703*e48c0fc5SRavi Teja                     &ipv6StaticData) {
17044a0cb85cSEd Tanous                 if (!success)
17051abe55efSEd Tanous                 {
17061abe55efSEd Tanous                     // TODO(Pawel)consider distinguish between non existing
17071abe55efSEd Tanous                     // object, and other errors
1708f12894f8SJason M. Bills                     messages::resourceNotFound(asyncResp->res,
1709f12894f8SJason M. Bills                                                "EthernetInterface", iface_id);
17104a0cb85cSEd Tanous                     return;
17119391bb9cSRapkiewicz, Pawel                 }
17124c9afe43SEd Tanous 
17134c9afe43SEd Tanous                 // because this has no dependence on the interface at this
17144c9afe43SEd Tanous                 // point, it needs to be done after we know the interface
17154c9afe43SEd Tanous                 // exists, not before.
17164c9afe43SEd Tanous                 getDHCPConfigData(asyncResp);
17174c9afe43SEd Tanous 
17180f74e643SEd Tanous                 asyncResp->res.jsonValue["@odata.type"] =
1719fda13ad2SSunitha Harish                     "#EthernetInterface.v1_4_1.EthernetInterface";
17200f74e643SEd Tanous                 asyncResp->res.jsonValue["@odata.context"] =
17210f74e643SEd Tanous                     "/redfish/v1/$metadata#EthernetInterface.EthernetInterface";
17220f74e643SEd Tanous                 asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
17230f74e643SEd Tanous                 asyncResp->res.jsonValue["Description"] =
17240f74e643SEd Tanous                     "Management Network Interface";
17250f74e643SEd Tanous 
17260f74e643SEd Tanous                 parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData,
1727*e48c0fc5SRavi Teja                                    ipv4Data, ipv6Data, ipv6StaticData);
17289391bb9cSRapkiewicz, Pawel             });
17299391bb9cSRapkiewicz, Pawel     }
17309391bb9cSRapkiewicz, Pawel 
173155c7b7a2SEd Tanous     void doPatch(crow::Response &res, const crow::Request &req,
17321abe55efSEd Tanous                  const std::vector<std::string> &params) override
17331abe55efSEd Tanous     {
17344a0cb85cSEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
17351abe55efSEd Tanous         if (params.size() != 1)
17361abe55efSEd Tanous         {
1737f12894f8SJason M. Bills             messages::internalError(asyncResp->res);
1738588c3f0dSKowalski, Kamil             return;
1739588c3f0dSKowalski, Kamil         }
1740588c3f0dSKowalski, Kamil 
17414a0cb85cSEd Tanous         const std::string &iface_id = params[0];
1742588c3f0dSKowalski, Kamil 
1743bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
1744d577665bSRatan Gupta         std::optional<std::string> macAddress;
17459a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
1746f476acbfSRatan Gupta         std::optional<nlohmann::json> ipv4Addresses;
1747f476acbfSRatan Gupta         std::optional<nlohmann::json> ipv6Addresses;
1748*e48c0fc5SRavi Teja         std::optional<nlohmann::json> ipv6StaticAddresses;
1749f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
17505112e9b4SRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> nameServers;
1751da131a9aSJennifer Lee         std::optional<nlohmann::json> dhcpv4;
17520627a2c7SEd Tanous 
1753fda13ad2SSunitha Harish         if (!json_util::readJson(
1754fda13ad2SSunitha Harish                 req, res, "HostName", hostname, "IPv4Addresses", ipv4Addresses,
1755f85837bfSRAJESWARAN THILLAIGOVINDAN                 "IPv6Addresses", ipv6Addresses, "MACAddress", macAddress,
17569a6fc6feSRavi Teja                 "StaticNameServers", staticNameServers, "IPv6DefaultGateway",
1757*e48c0fc5SRavi Teja                 ipv6DefaultGateway, "IPv6StaticAddresses", ipv6StaticAddresses,
1758*e48c0fc5SRavi Teja                 "NameServers", nameServers, "DHCPv4", dhcpv4))
17591abe55efSEd Tanous         {
1760588c3f0dSKowalski, Kamil             return;
1761588c3f0dSKowalski, Kamil         }
1762f15aad37SRatan Gupta 
1763da131a9aSJennifer Lee         if (dhcpv4)
1764da131a9aSJennifer Lee         {
1765da131a9aSJennifer Lee             handleDHCPv4Patch(iface_id, *dhcpv4, asyncResp);
1766da131a9aSJennifer Lee         }
1767da131a9aSJennifer Lee 
17684a0cb85cSEd Tanous         // Get single eth interface data, and call the below callback for JSON
1769588c3f0dSKowalski, Kamil         // preparation
17704a0cb85cSEd Tanous         getEthernetIfaceData(
17714a0cb85cSEd Tanous             iface_id,
1772fda13ad2SSunitha Harish             [this, asyncResp, iface_id, hostname = std::move(hostname),
1773fda13ad2SSunitha Harish              macAddress = std::move(macAddress),
17740627a2c7SEd Tanous              ipv4Addresses = std::move(ipv4Addresses),
1775f85837bfSRAJESWARAN THILLAIGOVINDAN              ipv6Addresses = std::move(ipv6Addresses),
17769a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
1777*e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
17785112e9b4SRAJESWARAN THILLAIGOVINDAN              staticNameServers = std::move(staticNameServers),
17795112e9b4SRAJESWARAN THILLAIGOVINDAN              nameServers = std::move(nameServers)](
17804a0cb85cSEd Tanous                 const bool &success, const EthernetInterfaceData &ethData,
1781*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv4AddressData> &ipv4Data,
1782*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData> &ipv6Data,
1783*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData>
1784*e48c0fc5SRavi Teja                     &ipv6StaticData) {
17851abe55efSEd Tanous                 if (!success)
17861abe55efSEd Tanous                 {
1787588c3f0dSKowalski, Kamil                     // ... otherwise return error
17881abe55efSEd Tanous                     // TODO(Pawel)consider distinguish between non existing
17891abe55efSEd Tanous                     // object, and other errors
1790fda13ad2SSunitha Harish                     messages::resourceNotFound(asyncResp->res,
1791fda13ad2SSunitha Harish                                                "Ethernet Interface", iface_id);
1792588c3f0dSKowalski, Kamil                     return;
1793588c3f0dSKowalski, Kamil                 }
1794588c3f0dSKowalski, Kamil 
17950f74e643SEd Tanous                 parseInterfaceData(asyncResp->res.jsonValue, iface_id, ethData,
1796*e48c0fc5SRavi Teja                                    ipv4Data, ipv6Data, ipv6StaticData);
1797588c3f0dSKowalski, Kamil 
17980627a2c7SEd Tanous                 if (hostname)
17991abe55efSEd Tanous                 {
18000627a2c7SEd Tanous                     handleHostnamePatch(*hostname, asyncResp);
18011abe55efSEd Tanous                 }
18020627a2c7SEd Tanous 
1803d577665bSRatan Gupta                 if (macAddress)
1804d577665bSRatan Gupta                 {
1805d577665bSRatan Gupta                     handleMACAddressPatch(iface_id, *macAddress, asyncResp);
1806d577665bSRatan Gupta                 }
1807d577665bSRatan Gupta 
18080627a2c7SEd Tanous                 if (ipv4Addresses)
18091abe55efSEd Tanous                 {
1810537174c4SEd Tanous                     // TODO(ed) for some reason the capture of ipv4Addresses
1811537174c4SEd Tanous                     // above is returning a const value, not a non-const value.
1812537174c4SEd Tanous                     // This doesn't really work for us, as we need to be able to
1813537174c4SEd Tanous                     // efficiently move out the intermedia nlohmann::json
1814537174c4SEd Tanous                     // objects. This makes a copy of the structure, and operates
1815537174c4SEd Tanous                     // on that, but could be done more efficiently
1816f476acbfSRatan Gupta                     nlohmann::json ipv4 = std::move(*ipv4Addresses);
1817537174c4SEd Tanous                     handleIPv4Patch(iface_id, ipv4, ipv4Data, asyncResp);
18181abe55efSEd Tanous                 }
18190627a2c7SEd Tanous 
18205112e9b4SRAJESWARAN THILLAIGOVINDAN                 if (nameServers)
18215112e9b4SRAJESWARAN THILLAIGOVINDAN                 {
18225112e9b4SRAJESWARAN THILLAIGOVINDAN                     // Data.Permissions is read-only
18235112e9b4SRAJESWARAN THILLAIGOVINDAN                     messages::propertyNotWritable(asyncResp->res,
18245112e9b4SRAJESWARAN THILLAIGOVINDAN                                                   "NameServers");
18255112e9b4SRAJESWARAN THILLAIGOVINDAN                 }
18265112e9b4SRAJESWARAN THILLAIGOVINDAN 
18270627a2c7SEd Tanous                 if (ipv6Addresses)
18281abe55efSEd Tanous                 {
1829179db1d7SKowalski, Kamil                     // TODO(kkowalsk) IPv6 Not supported on D-Bus yet
1830a08b46ccSJason M. Bills                     messages::propertyNotWritable(asyncResp->res,
18310627a2c7SEd Tanous                                                   "IPv6Addresses");
1832588c3f0dSKowalski, Kamil                 }
1833f85837bfSRAJESWARAN THILLAIGOVINDAN 
1834f85837bfSRAJESWARAN THILLAIGOVINDAN                 if (staticNameServers)
1835f85837bfSRAJESWARAN THILLAIGOVINDAN                 {
1836f85837bfSRAJESWARAN THILLAIGOVINDAN                     handleStaticNameServersPatch(iface_id, *staticNameServers,
1837f85837bfSRAJESWARAN THILLAIGOVINDAN                                                  asyncResp);
1838f85837bfSRAJESWARAN THILLAIGOVINDAN                 }
18399a6fc6feSRavi Teja 
18409a6fc6feSRavi Teja                 if (ipv6DefaultGateway)
18419a6fc6feSRavi Teja                 {
18429a6fc6feSRavi Teja                     messages::propertyNotWritable(asyncResp->res,
18439a6fc6feSRavi Teja                                                   "IPv6DefaultGateway");
18449a6fc6feSRavi Teja                 }
1845*e48c0fc5SRavi Teja 
1846*e48c0fc5SRavi Teja                 if (ipv6StaticAddresses)
1847*e48c0fc5SRavi Teja                 {
1848*e48c0fc5SRavi Teja                     nlohmann::json ipv6Static = std::move(*ipv6StaticAddresses);
1849*e48c0fc5SRavi Teja                     handleIPv6StaticAddressesPatch(iface_id, ipv6Static,
1850*e48c0fc5SRavi Teja                                                    ipv6StaticData, asyncResp);
1851*e48c0fc5SRavi Teja 
1852*e48c0fc5SRavi Teja                     // call getEthernetIfaceData to populate updated static
1853*e48c0fc5SRavi Teja                     // addresses data to "IPv6Addresses" json collection
1854*e48c0fc5SRavi Teja                     getEthernetIfaceData(
1855*e48c0fc5SRavi Teja                         iface_id,
1856*e48c0fc5SRavi Teja                         [this, asyncResp, iface_id](
1857*e48c0fc5SRavi Teja                             const bool &success,
1858*e48c0fc5SRavi Teja                             const EthernetInterfaceData &ethData,
1859*e48c0fc5SRavi Teja                             const boost::container::flat_set<IPv4AddressData>
1860*e48c0fc5SRavi Teja                                 &ipv4Data,
1861*e48c0fc5SRavi Teja                             const boost::container::flat_set<IPv6AddressData>
1862*e48c0fc5SRavi Teja                                 &ipv6Data,
1863*e48c0fc5SRavi Teja                             const boost::container::flat_set<IPv6AddressData>
1864*e48c0fc5SRavi Teja                                 &ipv6StaticData) {
1865*e48c0fc5SRavi Teja                             if (!success)
1866*e48c0fc5SRavi Teja                             {
1867*e48c0fc5SRavi Teja                                 messages::resourceNotFound(asyncResp->res,
1868*e48c0fc5SRavi Teja                                                            "Ethernet Interface",
1869*e48c0fc5SRavi Teja                                                            iface_id);
1870*e48c0fc5SRavi Teja                                 return;
1871*e48c0fc5SRavi Teja                             }
1872*e48c0fc5SRavi Teja 
1873*e48c0fc5SRavi Teja                             parseInterfaceData(asyncResp->res.jsonValue,
1874*e48c0fc5SRavi Teja                                                iface_id, ethData, ipv4Data,
1875*e48c0fc5SRavi Teja                                                ipv6Data, ipv6StaticData);
1876*e48c0fc5SRavi Teja                         });
1877*e48c0fc5SRavi Teja                 }
1878588c3f0dSKowalski, Kamil             });
1879588c3f0dSKowalski, Kamil     }
18809391bb9cSRapkiewicz, Pawel };
18819391bb9cSRapkiewicz, Pawel 
1882e439f0f8SKowalski, Kamil /**
18834a0cb85cSEd Tanous  * VlanNetworkInterface derived class for delivering VLANNetworkInterface
18844a0cb85cSEd Tanous  * Schema
1885e439f0f8SKowalski, Kamil  */
18861abe55efSEd Tanous class VlanNetworkInterface : public Node
18871abe55efSEd Tanous {
1888e439f0f8SKowalski, Kamil   public:
1889e439f0f8SKowalski, Kamil     /*
1890e439f0f8SKowalski, Kamil      * Default Constructor
1891e439f0f8SKowalski, Kamil      */
1892e439f0f8SKowalski, Kamil     template <typename CrowApp>
18931abe55efSEd Tanous     VlanNetworkInterface(CrowApp &app) :
18944a0cb85cSEd Tanous         Node(app,
18950f74e643SEd Tanous              "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/<str>",
18961abe55efSEd Tanous              std::string(), std::string())
18971abe55efSEd Tanous     {
1898e439f0f8SKowalski, Kamil         entityPrivileges = {
1899e439f0f8SKowalski, Kamil             {boost::beast::http::verb::get, {{"Login"}}},
1900e439f0f8SKowalski, Kamil             {boost::beast::http::verb::head, {{"Login"}}},
1901e439f0f8SKowalski, Kamil             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
1902e439f0f8SKowalski, Kamil             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
1903e439f0f8SKowalski, Kamil             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
1904e439f0f8SKowalski, Kamil             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
1905e439f0f8SKowalski, Kamil     }
1906e439f0f8SKowalski, Kamil 
1907e439f0f8SKowalski, Kamil   private:
19080f74e643SEd Tanous     void parseInterfaceData(
19090f74e643SEd Tanous         nlohmann::json &json_response, const std::string &parent_iface_id,
19100f74e643SEd Tanous         const std::string &iface_id, const EthernetInterfaceData &ethData,
1911*e48c0fc5SRavi Teja         const boost::container::flat_set<IPv4AddressData> &ipv4Data,
1912*e48c0fc5SRavi Teja         const boost::container::flat_set<IPv6AddressData> &ipv6Data,
1913*e48c0fc5SRavi Teja         const boost::container::flat_set<IPv6AddressData> &ipv6StaticData)
19141abe55efSEd Tanous     {
1915e439f0f8SKowalski, Kamil         // Fill out obvious data...
19164a0cb85cSEd Tanous         json_response["Id"] = iface_id;
19174a0cb85cSEd Tanous         json_response["@odata.id"] =
19184a0cb85cSEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces/" + parent_iface_id +
19194a0cb85cSEd Tanous             "/VLANs/" + iface_id;
1920e439f0f8SKowalski, Kamil 
19214a0cb85cSEd Tanous         json_response["VLANEnable"] = true;
1922fda13ad2SSunitha Harish         if (!ethData.vlan_id.empty())
19234a0cb85cSEd Tanous         {
1924fda13ad2SSunitha Harish             json_response["VLANId"] = ethData.vlan_id.back();
19254a0cb85cSEd Tanous         }
1926e439f0f8SKowalski, Kamil     }
1927e439f0f8SKowalski, Kamil 
1928fda13ad2SSunitha Harish     bool verifyNames(const std::string &parent, const std::string &iface)
19291abe55efSEd Tanous     {
19301abe55efSEd Tanous         if (!boost::starts_with(iface, parent + "_"))
19311abe55efSEd Tanous         {
1932927a505aSKowalski, Kamil             return false;
19331abe55efSEd Tanous         }
19341abe55efSEd Tanous         else
19351abe55efSEd Tanous         {
1936927a505aSKowalski, Kamil             return true;
1937927a505aSKowalski, Kamil         }
1938927a505aSKowalski, Kamil     }
1939927a505aSKowalski, Kamil 
1940e439f0f8SKowalski, Kamil     /**
1941e439f0f8SKowalski, Kamil      * Functions triggers appropriate requests on DBus
1942e439f0f8SKowalski, Kamil      */
194355c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
19441abe55efSEd Tanous                const std::vector<std::string> &params) override
19451abe55efSEd Tanous     {
19464a0cb85cSEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
19474a0cb85cSEd Tanous         // TODO(Pawel) this shall be parameterized call (two params) to get
1948e439f0f8SKowalski, Kamil         // EthernetInterfaces for any Manager, not only hardcoded 'openbmc'.
1949e439f0f8SKowalski, Kamil         // Check if there is required param, truly entering this shall be
1950e439f0f8SKowalski, Kamil         // impossible.
19511abe55efSEd Tanous         if (params.size() != 2)
19521abe55efSEd Tanous         {
1953f12894f8SJason M. Bills             messages::internalError(res);
1954e439f0f8SKowalski, Kamil             res.end();
1955e439f0f8SKowalski, Kamil             return;
1956e439f0f8SKowalski, Kamil         }
1957e439f0f8SKowalski, Kamil 
19584a0cb85cSEd Tanous         const std::string &parent_iface_id = params[0];
19594a0cb85cSEd Tanous         const std::string &iface_id = params[1];
19600f74e643SEd Tanous         res.jsonValue["@odata.type"] =
19610f74e643SEd Tanous             "#VLanNetworkInterface.v1_1_0.VLanNetworkInterface";
19620f74e643SEd Tanous         res.jsonValue["@odata.context"] =
19630f74e643SEd Tanous             "/redfish/v1/$metadata#VLanNetworkInterface.VLanNetworkInterface";
19640f74e643SEd Tanous         res.jsonValue["Name"] = "VLAN Network Interface";
1965e439f0f8SKowalski, Kamil 
1966fda13ad2SSunitha Harish         if (!verifyNames(parent_iface_id, iface_id))
19671abe55efSEd Tanous         {
1968a434f2bdSEd Tanous             return;
1969a434f2bdSEd Tanous         }
1970a434f2bdSEd Tanous 
1971e439f0f8SKowalski, Kamil         // Get single eth interface data, and call the below callback for JSON
1972e439f0f8SKowalski, Kamil         // preparation
19734a0cb85cSEd Tanous         getEthernetIfaceData(
1974fda13ad2SSunitha Harish             params[1],
1975fda13ad2SSunitha Harish             [this, asyncResp, parent_iface_id{std::string(params[0])},
1976fda13ad2SSunitha Harish              iface_id{std::string(params[1])}](
19774a0cb85cSEd Tanous                 const bool &success, const EthernetInterfaceData &ethData,
1978*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv4AddressData> &ipv4Data,
1979*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData> &ipv6Data,
1980*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData>
1981*e48c0fc5SRavi Teja                     &ipv6StaticData) {
1982fda13ad2SSunitha Harish                 if (success && ethData.vlan_id.size() != 0)
19831abe55efSEd Tanous                 {
19840f74e643SEd Tanous                     parseInterfaceData(asyncResp->res.jsonValue,
19850f74e643SEd Tanous                                        parent_iface_id, iface_id, ethData,
1986*e48c0fc5SRavi Teja                                        ipv4Data, ipv6Data, ipv6StaticData);
19871abe55efSEd Tanous                 }
19881abe55efSEd Tanous                 else
19891abe55efSEd Tanous                 {
1990e439f0f8SKowalski, Kamil                     // ... otherwise return error
19911abe55efSEd Tanous                     // TODO(Pawel)consider distinguish between non existing
19921abe55efSEd Tanous                     // object, and other errors
1993f12894f8SJason M. Bills                     messages::resourceNotFound(
1994f12894f8SJason M. Bills                         asyncResp->res, "VLAN Network Interface", iface_id);
1995e439f0f8SKowalski, Kamil                 }
1996e439f0f8SKowalski, Kamil             });
1997e439f0f8SKowalski, Kamil     }
1998e439f0f8SKowalski, Kamil 
199955c7b7a2SEd Tanous     void doPatch(crow::Response &res, const crow::Request &req,
20001abe55efSEd Tanous                  const std::vector<std::string> &params) override
20011abe55efSEd Tanous     {
20024a0cb85cSEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
20031abe55efSEd Tanous         if (params.size() != 2)
20041abe55efSEd Tanous         {
2005f12894f8SJason M. Bills             messages::internalError(asyncResp->res);
2006e439f0f8SKowalski, Kamil             return;
2007e439f0f8SKowalski, Kamil         }
2008e439f0f8SKowalski, Kamil 
2009d76323e5SEd Tanous         const std::string &parentIfaceId = params[0];
201055c7b7a2SEd Tanous         const std::string &ifaceId = params[1];
2011927a505aSKowalski, Kamil 
2012fda13ad2SSunitha Harish         if (!verifyNames(parentIfaceId, ifaceId))
20131abe55efSEd Tanous         {
2014fda13ad2SSunitha Harish             messages::resourceNotFound(asyncResp->res, "VLAN Network Interface",
2015fda13ad2SSunitha Harish                                        ifaceId);
2016927a505aSKowalski, Kamil             return;
2017927a505aSKowalski, Kamil         }
2018927a505aSKowalski, Kamil 
20190627a2c7SEd Tanous         bool vlanEnable = false;
20200627a2c7SEd Tanous         uint64_t vlanId = 0;
20210627a2c7SEd Tanous 
20220627a2c7SEd Tanous         if (!json_util::readJson(req, res, "VLANEnable", vlanEnable, "VLANId",
20230627a2c7SEd Tanous                                  vlanId))
20241abe55efSEd Tanous         {
2025927a505aSKowalski, Kamil             return;
2026927a505aSKowalski, Kamil         }
2027927a505aSKowalski, Kamil 
2028927a505aSKowalski, Kamil         // Get single eth interface data, and call the below callback for JSON
2029927a505aSKowalski, Kamil         // preparation
2030*e48c0fc5SRavi Teja         getEthernetIfaceData(
2031*e48c0fc5SRavi Teja             params[1],
2032*e48c0fc5SRavi Teja             [this, asyncResp, parentIfaceId{std::string(params[0])},
2033*e48c0fc5SRavi Teja              ifaceId{std::string(params[1])}, &vlanEnable, &vlanId](
2034*e48c0fc5SRavi Teja                 const bool &success, const EthernetInterfaceData &ethData,
2035*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv4AddressData> &ipv4Data,
2036*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData> &ipv6Data,
2037*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData>
2038*e48c0fc5SRavi Teja                     &ipv6StaticData) {
203908244d02SSunitha Harish                 if (success && !ethData.vlan_id.empty())
204008244d02SSunitha Harish                 {
204108244d02SSunitha Harish                     parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId,
2042*e48c0fc5SRavi Teja                                        ifaceId, ethData, ipv4Data, ipv6Data,
2043*e48c0fc5SRavi Teja                                        ipv6StaticData);
204408244d02SSunitha Harish                     auto callback =
204508244d02SSunitha Harish                         [asyncResp](const boost::system::error_code ec) {
204608244d02SSunitha Harish                             if (ec)
204708244d02SSunitha Harish                             {
204808244d02SSunitha Harish                                 messages::internalError(asyncResp->res);
204908244d02SSunitha Harish                             }
205008244d02SSunitha Harish                         };
205108244d02SSunitha Harish 
205208244d02SSunitha Harish                     if (vlanEnable == true)
205308244d02SSunitha Harish                     {
205408244d02SSunitha Harish                         crow::connections::systemBus->async_method_call(
205508244d02SSunitha Harish                             std::move(callback), "xyz.openbmc_project.Network",
205608244d02SSunitha Harish                             "/xyz/openbmc_project/network/" + ifaceId,
205708244d02SSunitha Harish                             "org.freedesktop.DBus.Properties", "Set",
205808244d02SSunitha Harish                             "xyz.openbmc_project.Network.VLAN", "Id",
205908244d02SSunitha Harish                             std::variant<uint32_t>(vlanId));
206008244d02SSunitha Harish                     }
206108244d02SSunitha Harish                     else
206208244d02SSunitha Harish                     {
2063*e48c0fc5SRavi Teja                         BMCWEB_LOG_DEBUG << "vlanEnable is false. Deleting the "
2064*e48c0fc5SRavi Teja                                             "vlan interface";
206508244d02SSunitha Harish                         crow::connections::systemBus->async_method_call(
206608244d02SSunitha Harish                             std::move(callback), "xyz.openbmc_project.Network",
2067*e48c0fc5SRavi Teja                             std::string("/xyz/openbmc_project/network/") +
2068*e48c0fc5SRavi Teja                                 ifaceId,
206908244d02SSunitha Harish                             "xyz.openbmc_project.Object.Delete", "Delete");
207008244d02SSunitha Harish                     }
207108244d02SSunitha Harish                 }
207208244d02SSunitha Harish                 else
20731abe55efSEd Tanous                 {
20741abe55efSEd Tanous                     // TODO(Pawel)consider distinguish between non existing
20751abe55efSEd Tanous                     // object, and other errors
2076*e48c0fc5SRavi Teja                     messages::resourceNotFound(
2077*e48c0fc5SRavi Teja                         asyncResp->res, "VLAN Network Interface", ifaceId);
2078927a505aSKowalski, Kamil                     return;
2079927a505aSKowalski, Kamil                 }
2080927a505aSKowalski, Kamil             });
2081e439f0f8SKowalski, Kamil     }
2082e439f0f8SKowalski, Kamil 
208355c7b7a2SEd Tanous     void doDelete(crow::Response &res, const crow::Request &req,
20841abe55efSEd Tanous                   const std::vector<std::string> &params) override
20851abe55efSEd Tanous     {
20864a0cb85cSEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
20871abe55efSEd Tanous         if (params.size() != 2)
20881abe55efSEd Tanous         {
2089f12894f8SJason M. Bills             messages::internalError(asyncResp->res);
2090e439f0f8SKowalski, Kamil             return;
2091e439f0f8SKowalski, Kamil         }
2092e439f0f8SKowalski, Kamil 
2093d76323e5SEd Tanous         const std::string &parentIfaceId = params[0];
209455c7b7a2SEd Tanous         const std::string &ifaceId = params[1];
2095927a505aSKowalski, Kamil 
2096fda13ad2SSunitha Harish         if (!verifyNames(parentIfaceId, ifaceId))
20971abe55efSEd Tanous         {
2098fda13ad2SSunitha Harish             messages::resourceNotFound(asyncResp->res, "VLAN Network Interface",
2099fda13ad2SSunitha Harish                                        ifaceId);
2100927a505aSKowalski, Kamil             return;
2101927a505aSKowalski, Kamil         }
2102927a505aSKowalski, Kamil 
2103927a505aSKowalski, Kamil         // Get single eth interface data, and call the below callback for JSON
2104927a505aSKowalski, Kamil         // preparation
2105f12894f8SJason M. Bills         getEthernetIfaceData(
2106fda13ad2SSunitha Harish             params[1],
2107fda13ad2SSunitha Harish             [this, asyncResp, parentIfaceId{std::string(params[0])},
2108fda13ad2SSunitha Harish              ifaceId{std::string(params[1])}](
2109f12894f8SJason M. Bills                 const bool &success, const EthernetInterfaceData &ethData,
2110*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv4AddressData> &ipv4Data,
2111*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData> &ipv6Data,
2112*e48c0fc5SRavi Teja                 const boost::container::flat_set<IPv6AddressData>
2113*e48c0fc5SRavi Teja                     &ipv6StaticData) {
2114fda13ad2SSunitha Harish                 if (success && !ethData.vlan_id.empty())
21151abe55efSEd Tanous                 {
21160f74e643SEd Tanous                     parseInterfaceData(asyncResp->res.jsonValue, parentIfaceId,
2117*e48c0fc5SRavi Teja                                        ifaceId, ethData, ipv4Data, ipv6Data,
2118*e48c0fc5SRavi Teja                                        ipv6StaticData);
2119927a505aSKowalski, Kamil 
2120f12894f8SJason M. Bills                     auto callback =
2121f12894f8SJason M. Bills                         [asyncResp](const boost::system::error_code ec) {
21221abe55efSEd Tanous                             if (ec)
21231abe55efSEd Tanous                             {
2124f12894f8SJason M. Bills                                 messages::internalError(asyncResp->res);
2125927a505aSKowalski, Kamil                             }
21264a0cb85cSEd Tanous                         };
21274a0cb85cSEd Tanous                     crow::connections::systemBus->async_method_call(
21284a0cb85cSEd Tanous                         std::move(callback), "xyz.openbmc_project.Network",
21294a0cb85cSEd Tanous                         std::string("/xyz/openbmc_project/network/") + ifaceId,
21304a0cb85cSEd Tanous                         "xyz.openbmc_project.Object.Delete", "Delete");
21311abe55efSEd Tanous                 }
21321abe55efSEd Tanous                 else
21331abe55efSEd Tanous                 {
2134927a505aSKowalski, Kamil                     // ... otherwise return error
2135f12894f8SJason M. Bills                     // TODO(Pawel)consider distinguish between non existing
2136f12894f8SJason M. Bills                     // object, and other errors
2137f12894f8SJason M. Bills                     messages::resourceNotFound(
2138f12894f8SJason M. Bills                         asyncResp->res, "VLAN Network Interface", ifaceId);
2139927a505aSKowalski, Kamil                 }
2140927a505aSKowalski, Kamil             });
2141e439f0f8SKowalski, Kamil     }
2142e439f0f8SKowalski, Kamil };
2143e439f0f8SKowalski, Kamil 
2144e439f0f8SKowalski, Kamil /**
2145e439f0f8SKowalski, Kamil  * VlanNetworkInterfaceCollection derived class for delivering
2146e439f0f8SKowalski, Kamil  * VLANNetworkInterface Collection Schema
2147e439f0f8SKowalski, Kamil  */
21481abe55efSEd Tanous class VlanNetworkInterfaceCollection : public Node
21491abe55efSEd Tanous {
2150e439f0f8SKowalski, Kamil   public:
2151e439f0f8SKowalski, Kamil     template <typename CrowApp>
21521abe55efSEd Tanous     VlanNetworkInterfaceCollection(CrowApp &app) :
21534a0cb85cSEd Tanous         Node(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/VLANs/",
21544a0cb85cSEd Tanous              std::string())
21551abe55efSEd Tanous     {
2156e439f0f8SKowalski, Kamil         entityPrivileges = {
2157e439f0f8SKowalski, Kamil             {boost::beast::http::verb::get, {{"Login"}}},
2158e439f0f8SKowalski, Kamil             {boost::beast::http::verb::head, {{"Login"}}},
2159e439f0f8SKowalski, Kamil             {boost::beast::http::verb::patch, {{"ConfigureComponents"}}},
2160e439f0f8SKowalski, Kamil             {boost::beast::http::verb::put, {{"ConfigureComponents"}}},
2161e439f0f8SKowalski, Kamil             {boost::beast::http::verb::delete_, {{"ConfigureComponents"}}},
2162e439f0f8SKowalski, Kamil             {boost::beast::http::verb::post, {{"ConfigureComponents"}}}};
2163e439f0f8SKowalski, Kamil     }
2164e439f0f8SKowalski, Kamil 
2165e439f0f8SKowalski, Kamil   private:
2166e439f0f8SKowalski, Kamil     /**
2167e439f0f8SKowalski, Kamil      * Functions triggers appropriate requests on DBus
2168e439f0f8SKowalski, Kamil      */
216955c7b7a2SEd Tanous     void doGet(crow::Response &res, const crow::Request &req,
21701abe55efSEd Tanous                const std::vector<std::string> &params) override
21711abe55efSEd Tanous     {
21724a0cb85cSEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
21731abe55efSEd Tanous         if (params.size() != 1)
21741abe55efSEd Tanous         {
2175e439f0f8SKowalski, Kamil             // This means there is a problem with the router
2176f12894f8SJason M. Bills             messages::internalError(asyncResp->res);
2177e439f0f8SKowalski, Kamil             return;
2178e439f0f8SKowalski, Kamil         }
2179e439f0f8SKowalski, Kamil 
21804a0cb85cSEd Tanous         const std::string &rootInterfaceName = params[0];
2181e439f0f8SKowalski, Kamil 
21824a0cb85cSEd Tanous         // Get eth interface list, and call the below callback for JSON
21831abe55efSEd Tanous         // preparation
2184f12894f8SJason M. Bills         getEthernetIfaceList(
218543b761d0SEd Tanous             [asyncResp, rootInterfaceName{std::string(rootInterfaceName)}](
21861abe55efSEd Tanous                 const bool &success,
21874c9afe43SEd Tanous                 const boost::container::flat_set<std::string> &iface_list) {
21884a0cb85cSEd Tanous                 if (!success)
21891abe55efSEd Tanous                 {
2190f12894f8SJason M. Bills                     messages::internalError(asyncResp->res);
21914a0cb85cSEd Tanous                     return;
21921abe55efSEd Tanous                 }
21934c9afe43SEd Tanous 
21944c9afe43SEd Tanous                 if (iface_list.find(rootInterfaceName) == iface_list.end())
21954c9afe43SEd Tanous                 {
21964c9afe43SEd Tanous                     messages::resourceNotFound(asyncResp->res,
21974c9afe43SEd Tanous                                                "VLanNetworkInterfaceCollection",
21984c9afe43SEd Tanous                                                rootInterfaceName);
21994c9afe43SEd Tanous                     return;
22004c9afe43SEd Tanous                 }
22014c9afe43SEd Tanous 
22020f74e643SEd Tanous                 asyncResp->res.jsonValue["@odata.type"] =
22030f74e643SEd Tanous                     "#VLanNetworkInterfaceCollection."
22040f74e643SEd Tanous                     "VLanNetworkInterfaceCollection";
22050f74e643SEd Tanous                 asyncResp->res.jsonValue["@odata.context"] =
22060f74e643SEd Tanous                     "/redfish/v1/$metadata"
22070f74e643SEd Tanous                     "#VLanNetworkInterfaceCollection."
22080f74e643SEd Tanous                     "VLanNetworkInterfaceCollection";
22090f74e643SEd Tanous                 asyncResp->res.jsonValue["Name"] =
22100f74e643SEd Tanous                     "VLAN Network Interface Collection";
22114a0cb85cSEd Tanous 
22124a0cb85cSEd Tanous                 nlohmann::json iface_array = nlohmann::json::array();
22134a0cb85cSEd Tanous 
22144a0cb85cSEd Tanous                 for (const std::string &iface_item : iface_list)
22151abe55efSEd Tanous                 {
22164a0cb85cSEd Tanous                     if (boost::starts_with(iface_item, rootInterfaceName + "_"))
22174a0cb85cSEd Tanous                     {
22184a0cb85cSEd Tanous                         iface_array.push_back(
22194a0cb85cSEd Tanous                             {{"@odata.id",
22204a0cb85cSEd Tanous                               "/redfish/v1/Managers/bmc/EthernetInterfaces/" +
22214a0cb85cSEd Tanous                                   rootInterfaceName + "/VLANs/" + iface_item}});
2222e439f0f8SKowalski, Kamil                     }
2223e439f0f8SKowalski, Kamil                 }
2224e439f0f8SKowalski, Kamil 
22254a0cb85cSEd Tanous                 asyncResp->res.jsonValue["Members@odata.count"] =
22264a0cb85cSEd Tanous                     iface_array.size();
22274a0cb85cSEd Tanous                 asyncResp->res.jsonValue["Members"] = std::move(iface_array);
22284a0cb85cSEd Tanous                 asyncResp->res.jsonValue["@odata.id"] =
22294a0cb85cSEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/" +
22304a0cb85cSEd Tanous                     rootInterfaceName + "/VLANs";
2231e439f0f8SKowalski, Kamil             });
2232e439f0f8SKowalski, Kamil     }
2233e439f0f8SKowalski, Kamil 
223455c7b7a2SEd Tanous     void doPost(crow::Response &res, const crow::Request &req,
22351abe55efSEd Tanous                 const std::vector<std::string> &params) override
22361abe55efSEd Tanous     {
22374a0cb85cSEd Tanous         std::shared_ptr<AsyncResp> asyncResp = std::make_shared<AsyncResp>(res);
22381abe55efSEd Tanous         if (params.size() != 1)
22391abe55efSEd Tanous         {
2240f12894f8SJason M. Bills             messages::internalError(asyncResp->res);
2241e439f0f8SKowalski, Kamil             return;
2242e439f0f8SKowalski, Kamil         }
2243fda13ad2SSunitha Harish         bool vlanEnable = false;
22440627a2c7SEd Tanous         uint32_t vlanId = 0;
2245fda13ad2SSunitha Harish         if (!json_util::readJson(req, res, "VLANId", vlanId, "VLANEnable",
2246fda13ad2SSunitha Harish                                  vlanEnable))
22471abe55efSEd Tanous         {
22484a0cb85cSEd Tanous             return;
2249e439f0f8SKowalski, Kamil         }
2250fda13ad2SSunitha Harish         // Need both vlanId and vlanEnable to service this request
2251fda13ad2SSunitha Harish         if (!vlanId)
2252fda13ad2SSunitha Harish         {
2253fda13ad2SSunitha Harish             messages::propertyMissing(asyncResp->res, "VLANId");
2254fda13ad2SSunitha Harish         }
2255fda13ad2SSunitha Harish         if (!vlanEnable)
2256fda13ad2SSunitha Harish         {
2257fda13ad2SSunitha Harish             messages::propertyMissing(asyncResp->res, "VLANEnable");
2258fda13ad2SSunitha Harish         }
2259fda13ad2SSunitha Harish         if (static_cast<bool>(vlanId) ^ static_cast<bool>(vlanEnable))
2260fda13ad2SSunitha Harish         {
2261fda13ad2SSunitha Harish             return;
2262fda13ad2SSunitha Harish         }
2263fda13ad2SSunitha Harish 
22644a0cb85cSEd Tanous         const std::string &rootInterfaceName = params[0];
22654a0cb85cSEd Tanous         auto callback = [asyncResp](const boost::system::error_code ec) {
22661abe55efSEd Tanous             if (ec)
22671abe55efSEd Tanous             {
22684a0cb85cSEd Tanous                 // TODO(ed) make more consistent error messages based on
22694a0cb85cSEd Tanous                 // phosphor-network responses
2270f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
22714a0cb85cSEd Tanous                 return;
22721abe55efSEd Tanous             }
2273f12894f8SJason M. Bills             messages::created(asyncResp->res);
2274e439f0f8SKowalski, Kamil         };
22754a0cb85cSEd Tanous         crow::connections::systemBus->async_method_call(
22764a0cb85cSEd Tanous             std::move(callback), "xyz.openbmc_project.Network",
22774a0cb85cSEd Tanous             "/xyz/openbmc_project/network",
22784a0cb85cSEd Tanous             "xyz.openbmc_project.Network.VLAN.Create", "VLAN",
22790627a2c7SEd Tanous             rootInterfaceName, vlanId);
22804a0cb85cSEd Tanous     }
22814a0cb85cSEd Tanous };
22829391bb9cSRapkiewicz, Pawel } // namespace redfish
2283