xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision e93abac6d60c4b409ad72086dac153f23d793ac1)
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 
183ccb3adbSEd Tanous #include "app.hpp"
193ccb3adbSEd Tanous #include "dbus_singleton.hpp"
207a1dbc48SGeorge Liu #include "dbus_utility.hpp"
213ccb3adbSEd Tanous #include "error_messages.hpp"
222c5875a2SEd Tanous #include "human_sort.hpp"
233ccb3adbSEd Tanous #include "query.hpp"
243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
25033f1e4dSEd Tanous #include "utils/ip_utils.hpp"
263ccb3adbSEd Tanous #include "utils/json_utils.hpp"
27033f1e4dSEd Tanous 
28ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp>
29ef4c65b7SEd Tanous #include <boost/url/format.hpp>
301214b7e7SGunnar Mills 
317a1dbc48SGeorge Liu #include <array>
323dfed536SEd Tanous #include <cstddef>
33ce73d5c8SSunitha Harish #include <memory>
34a24526dcSEd Tanous #include <optional>
353544d2a7SEd Tanous #include <ranges>
36ab6554f1SJoshi-Mansi #include <regex>
377a1dbc48SGeorge Liu #include <string_view>
383dfed536SEd Tanous #include <variant>
3977179532SEd Tanous #include <vector>
409391bb9cSRapkiewicz, Pawel 
411abe55efSEd Tanous namespace redfish
421abe55efSEd Tanous {
439391bb9cSRapkiewicz, Pawel 
444a0cb85cSEd Tanous enum class LinkType
454a0cb85cSEd Tanous {
464a0cb85cSEd Tanous     Local,
474a0cb85cSEd Tanous     Global
484a0cb85cSEd Tanous };
499391bb9cSRapkiewicz, Pawel 
50743eb1c0SJohnathan Mantey enum class IpVersion
51743eb1c0SJohnathan Mantey {
52743eb1c0SJohnathan Mantey     IpV4,
53743eb1c0SJohnathan Mantey     IpV6
54743eb1c0SJohnathan Mantey };
55743eb1c0SJohnathan Mantey 
569391bb9cSRapkiewicz, Pawel /**
579391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
589391bb9cSRapkiewicz, Pawel  */
591abe55efSEd Tanous struct IPv4AddressData
601abe55efSEd Tanous {
61179db1d7SKowalski, Kamil     std::string id;
624a0cb85cSEd Tanous     std::string address;
634a0cb85cSEd Tanous     std::string domain;
644a0cb85cSEd Tanous     std::string gateway;
659391bb9cSRapkiewicz, Pawel     std::string netmask;
669391bb9cSRapkiewicz, Pawel     std::string origin;
6777179532SEd Tanous     LinkType linktype{};
6877179532SEd Tanous     bool isActive{};
699391bb9cSRapkiewicz, Pawel };
709391bb9cSRapkiewicz, Pawel 
719391bb9cSRapkiewicz, Pawel /**
72e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
73e48c0fc5SRavi Teja  */
74e48c0fc5SRavi Teja struct IPv6AddressData
75e48c0fc5SRavi Teja {
76e48c0fc5SRavi Teja     std::string id;
77e48c0fc5SRavi Teja     std::string address;
78e48c0fc5SRavi Teja     std::string origin;
7977179532SEd Tanous     uint8_t prefixLength = 0;
80e48c0fc5SRavi Teja };
81ce73d5c8SSunitha Harish 
82ce73d5c8SSunitha Harish /**
83ce73d5c8SSunitha Harish  * Structure for keeping static route data required by Redfish
84ce73d5c8SSunitha Harish  */
85ce73d5c8SSunitha Harish struct StaticGatewayData
86ce73d5c8SSunitha Harish {
87ce73d5c8SSunitha Harish     std::string id;
88ce73d5c8SSunitha Harish     std::string gateway;
89ce73d5c8SSunitha Harish     size_t prefixLength = 0;
90ce73d5c8SSunitha Harish     std::string protocol;
91ce73d5c8SSunitha Harish };
92ce73d5c8SSunitha Harish 
93e48c0fc5SRavi Teja /**
949391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
959391bb9cSRapkiewicz, Pawel  * available from DBus
969391bb9cSRapkiewicz, Pawel  */
971abe55efSEd Tanous struct EthernetInterfaceData
981abe55efSEd Tanous {
994a0cb85cSEd Tanous     uint32_t speed;
10035fb5311STejas Patil     size_t mtuSize;
10182695a5bSJiaqing Zhao     bool autoNeg;
102e4588158SJishnu CM     bool dnsv4Enabled;
103e4588158SJishnu CM     bool dnsv6Enabled;
10491c441ecSRavi Teja     bool domainv4Enabled;
10591c441ecSRavi Teja     bool domainv6Enabled;
106e4588158SJishnu CM     bool ntpv4Enabled;
107e4588158SJishnu CM     bool ntpv6Enabled;
108e4588158SJishnu CM     bool hostNamev4Enabled;
109e4588158SJishnu CM     bool hostNamev6Enabled;
110aa05fb27SJohnathan Mantey     bool linkUp;
111eeedda23SJohnathan Mantey     bool nicEnabled;
112b10d8db0SRavi Teja     bool ipv6AcceptRa;
11382695a5bSJiaqing Zhao     std::string dhcpEnabled;
1141f8c7b5dSJohnathan Mantey     std::string operatingMode;
11582695a5bSJiaqing Zhao     std::string hostName;
11682695a5bSJiaqing Zhao     std::string defaultGateway;
11782695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
118ce73d5c8SSunitha Harish     std::string ipv6StaticDefaultGateway;
11982695a5bSJiaqing Zhao     std::string macAddress;
12017e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
1210f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1220f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
123d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1249391bb9cSRapkiewicz, Pawel };
1259391bb9cSRapkiewicz, Pawel 
1261f8c7b5dSJohnathan Mantey struct DHCPParameters
1271f8c7b5dSJohnathan Mantey {
1281f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
12982695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
13082695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
13182695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1321f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1331f8c7b5dSJohnathan Mantey };
1341f8c7b5dSJohnathan Mantey 
1359391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1369391bb9cSRapkiewicz, Pawel // into full dot notation
1371abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1381abe55efSEd Tanous {
1399391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1409391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1419391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1429391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1439391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1449391bb9cSRapkiewicz, Pawel     return netmask;
1459391bb9cSRapkiewicz, Pawel }
1469391bb9cSRapkiewicz, Pawel 
14782695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1481f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1491f8c7b5dSJohnathan Mantey {
1501f8c7b5dSJohnathan Mantey     if (isIPv4)
1511f8c7b5dSJohnathan Mantey     {
1521f8c7b5dSJohnathan Mantey         return (
1531f8c7b5dSJohnathan Mantey             (inputDHCP ==
1541f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1551f8c7b5dSJohnathan Mantey             (inputDHCP ==
1561f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1571f8c7b5dSJohnathan Mantey     }
1581f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1591f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1601f8c7b5dSJohnathan Mantey             (inputDHCP ==
1611f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1621f8c7b5dSJohnathan Mantey }
1631f8c7b5dSJohnathan Mantey 
1642c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1651f8c7b5dSJohnathan Mantey {
1661f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1671f8c7b5dSJohnathan Mantey     {
1681f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1691f8c7b5dSJohnathan Mantey     }
1703174e4dfSEd Tanous     if (isIPv4)
1711f8c7b5dSJohnathan Mantey     {
1721f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1731f8c7b5dSJohnathan Mantey     }
1743174e4dfSEd Tanous     if (isIPv6)
1751f8c7b5dSJohnathan Mantey     {
1761f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1771f8c7b5dSJohnathan Mantey     }
1781f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1791f8c7b5dSJohnathan Mantey }
1801f8c7b5dSJohnathan Mantey 
1814a0cb85cSEd Tanous inline std::string
1824a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1834a0cb85cSEd Tanous                                         bool isIPv4)
1841abe55efSEd Tanous {
1854a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1861abe55efSEd Tanous     {
1874a0cb85cSEd Tanous         return "Static";
1889391bb9cSRapkiewicz, Pawel     }
1894a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1901abe55efSEd Tanous     {
1914a0cb85cSEd Tanous         if (isIPv4)
1921abe55efSEd Tanous         {
1934a0cb85cSEd Tanous             return "IPv4LinkLocal";
1941abe55efSEd Tanous         }
1954a0cb85cSEd Tanous         return "LinkLocal";
1969391bb9cSRapkiewicz, Pawel     }
1974a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1981abe55efSEd Tanous     {
1994a0cb85cSEd Tanous         if (isIPv4)
2004a0cb85cSEd Tanous         {
2014a0cb85cSEd Tanous             return "DHCP";
2024a0cb85cSEd Tanous         }
2034a0cb85cSEd Tanous         return "DHCPv6";
2044a0cb85cSEd Tanous     }
2054a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
2064a0cb85cSEd Tanous     {
2074a0cb85cSEd Tanous         return "SLAAC";
2084a0cb85cSEd Tanous     }
2094a0cb85cSEd Tanous     return "";
2104a0cb85cSEd Tanous }
2114a0cb85cSEd Tanous 
21202cad96eSEd Tanous inline bool extractEthernetInterfaceData(
21302cad96eSEd Tanous     const std::string& ethifaceId,
21402cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
2154a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
2164a0cb85cSEd Tanous {
2174c9afe43SEd Tanous     bool idFound = false;
21802cad96eSEd Tanous     for (const auto& objpath : dbusData)
2194a0cb85cSEd Tanous     {
22002cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
2214a0cb85cSEd Tanous         {
22281ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
223029573d4SEd Tanous             {
2244c9afe43SEd Tanous                 idFound = true;
2254a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2264a0cb85cSEd Tanous                 {
2274a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2284a0cb85cSEd Tanous                     {
2294a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2304a0cb85cSEd Tanous                         {
2314a0cb85cSEd Tanous                             const std::string* mac =
232abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2334a0cb85cSEd Tanous                             if (mac != nullptr)
2344a0cb85cSEd Tanous                             {
23582695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2364a0cb85cSEd Tanous                             }
2374a0cb85cSEd Tanous                         }
2384a0cb85cSEd Tanous                     }
2394a0cb85cSEd Tanous                 }
2404a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2414a0cb85cSEd Tanous                 {
2424a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2434a0cb85cSEd Tanous                     {
2444a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2454a0cb85cSEd Tanous                         {
2461b6b96c5SEd Tanous                             const uint32_t* id =
247abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2484a0cb85cSEd Tanous                             if (id != nullptr)
2494a0cb85cSEd Tanous                             {
25017e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2514a0cb85cSEd Tanous                             }
2524a0cb85cSEd Tanous                         }
2534a0cb85cSEd Tanous                     }
2544a0cb85cSEd Tanous                 }
2554a0cb85cSEd Tanous                 else if (ifacePair.first ==
2564a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2574a0cb85cSEd Tanous                 {
2584a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2594a0cb85cSEd Tanous                     {
2604a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2614a0cb85cSEd Tanous                         {
2622c70f800SEd Tanous                             const bool* autoNeg =
263abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2642c70f800SEd Tanous                             if (autoNeg != nullptr)
2654a0cb85cSEd Tanous                             {
26682695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2674a0cb85cSEd Tanous                             }
2684a0cb85cSEd Tanous                         }
2694a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2704a0cb85cSEd Tanous                         {
2714a0cb85cSEd Tanous                             const uint32_t* speed =
272abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2734a0cb85cSEd Tanous                             if (speed != nullptr)
2744a0cb85cSEd Tanous                             {
2754a0cb85cSEd Tanous                                 ethData.speed = *speed;
2764a0cb85cSEd Tanous                             }
2774a0cb85cSEd Tanous                         }
27835fb5311STejas Patil                         else if (propertyPair.first == "MTU")
27935fb5311STejas Patil                         {
2803e7a8da6SAnthony                             const size_t* mtuSize =
2813e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
28235fb5311STejas Patil                             if (mtuSize != nullptr)
28335fb5311STejas Patil                             {
28435fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
28535fb5311STejas Patil                             }
28635fb5311STejas Patil                         }
287aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
288aa05fb27SJohnathan Mantey                         {
289aa05fb27SJohnathan Mantey                             const bool* linkUp =
290aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
291aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
292aa05fb27SJohnathan Mantey                             {
293aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
294aa05fb27SJohnathan Mantey                             }
295aa05fb27SJohnathan Mantey                         }
296eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
297eeedda23SJohnathan Mantey                         {
298eeedda23SJohnathan Mantey                             const bool* nicEnabled =
299eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
300eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
301eeedda23SJohnathan Mantey                             {
302eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
303eeedda23SJohnathan Mantey                             }
304eeedda23SJohnathan Mantey                         }
305b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
306b10d8db0SRavi Teja                         {
307b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
308b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
309b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
310b10d8db0SRavi Teja                             {
311b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
312b10d8db0SRavi Teja                             }
313b10d8db0SRavi Teja                         }
314f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
315029573d4SEd Tanous                         {
316029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
3178d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
318029573d4SEd Tanous                                     &propertyPair.second);
319029573d4SEd Tanous                             if (nameservers != nullptr)
320029573d4SEd Tanous                             {
321f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3220f6efdc1Smanojkiran.eda@gmail.com                             }
3230f6efdc1Smanojkiran.eda@gmail.com                         }
3240f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3250f6efdc1Smanojkiran.eda@gmail.com                         {
3260f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3278d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3280f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3290f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3300f6efdc1Smanojkiran.eda@gmail.com                             {
331f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3324a0cb85cSEd Tanous                             }
3334a0cb85cSEd Tanous                         }
3342a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3352a133282Smanojkiraneda                         {
3362c70f800SEd Tanous                             const std::string* dhcpEnabled =
3371f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3382c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3392a133282Smanojkiraneda                             {
34082695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3412a133282Smanojkiraneda                             }
3422a133282Smanojkiraneda                         }
343d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
344d24bfc7aSJennifer Lee                         {
345d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3468d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
347d24bfc7aSJennifer Lee                                     &propertyPair.second);
348d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
349d24bfc7aSJennifer Lee                             {
350f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
351d24bfc7aSJennifer Lee                             }
352d24bfc7aSJennifer Lee                         }
3539010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3549010ec2eSRavi Teja                         {
3559010ec2eSRavi Teja                             const std::string* defaultGateway =
3569010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3579010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3589010ec2eSRavi Teja                             {
3599010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3609010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3619010ec2eSRavi Teja                                 {
36282695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3639010ec2eSRavi Teja                                 }
3649010ec2eSRavi Teja                                 else
3659010ec2eSRavi Teja                                 {
36682695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3679010ec2eSRavi Teja                                 }
3689010ec2eSRavi Teja                             }
3699010ec2eSRavi Teja                         }
3709010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3719010ec2eSRavi Teja                         {
3729010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3739010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3749010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3759010ec2eSRavi Teja                             {
3769010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3779010ec2eSRavi Teja                                     *defaultGateway6;
3789010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3799010ec2eSRavi Teja                                 {
38082695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3819010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3829010ec2eSRavi Teja                                 }
3839010ec2eSRavi Teja                                 else
3849010ec2eSRavi Teja                                 {
38582695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3869010ec2eSRavi Teja                                         defaultGateway6Str;
3879010ec2eSRavi Teja                                 }
3889010ec2eSRavi Teja                             }
3899010ec2eSRavi Teja                         }
390029573d4SEd Tanous                     }
391029573d4SEd Tanous                 }
392029573d4SEd Tanous             }
3931f8c7b5dSJohnathan Mantey 
394e4588158SJishnu CM             sdbusplus::message::object_path path(
395e4588158SJishnu CM                 "/xyz/openbmc_project/network");
396e4588158SJishnu CM             sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
397e4588158SJishnu CM                                                         "dhcp4";
398e4588158SJishnu CM 
399e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
4001f8c7b5dSJohnathan Mantey             {
4011f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
4021f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
4031f8c7b5dSJohnathan Mantey                 {
4041f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
4051f8c7b5dSJohnathan Mantey                     {
4061f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
4071f8c7b5dSJohnathan Mantey                         {
4082c70f800SEd Tanous                             const bool* dnsEnabled =
4091f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4102c70f800SEd Tanous                             if (dnsEnabled != nullptr)
4111f8c7b5dSJohnathan Mantey                             {
412e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
4131f8c7b5dSJohnathan Mantey                             }
4141f8c7b5dSJohnathan Mantey                         }
41591c441ecSRavi Teja                         else if (propertyPair.first == "DomainEnabled")
41691c441ecSRavi Teja                         {
41791c441ecSRavi Teja                             const bool* domainEnabled =
41891c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
41991c441ecSRavi Teja                             if (domainEnabled != nullptr)
42091c441ecSRavi Teja                             {
42191c441ecSRavi Teja                                 ethData.domainv4Enabled = *domainEnabled;
42291c441ecSRavi Teja                             }
42391c441ecSRavi Teja                         }
4241f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
4251f8c7b5dSJohnathan Mantey                         {
4262c70f800SEd Tanous                             const bool* ntpEnabled =
4271f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4282c70f800SEd Tanous                             if (ntpEnabled != nullptr)
4291f8c7b5dSJohnathan Mantey                             {
430e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4311f8c7b5dSJohnathan Mantey                             }
4321f8c7b5dSJohnathan Mantey                         }
4331f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4341f8c7b5dSJohnathan Mantey                         {
4352c70f800SEd Tanous                             const bool* hostNameEnabled =
4361f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4372c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4381f8c7b5dSJohnathan Mantey                             {
439e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
440e4588158SJishnu CM                             }
441e4588158SJishnu CM                         }
442e4588158SJishnu CM                     }
443e4588158SJishnu CM                 }
444e4588158SJishnu CM             }
445e4588158SJishnu CM 
446e4588158SJishnu CM             sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
447e4588158SJishnu CM                                                         "dhcp6";
448e4588158SJishnu CM 
449e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
450e4588158SJishnu CM             {
451e4588158SJishnu CM                 if (ifacePair.first ==
452e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
453e4588158SJishnu CM                 {
454e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
455e4588158SJishnu CM                     {
456e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
457e4588158SJishnu CM                         {
458e4588158SJishnu CM                             const bool* dnsEnabled =
459e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
460e4588158SJishnu CM                             if (dnsEnabled != nullptr)
461e4588158SJishnu CM                             {
462e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
463e4588158SJishnu CM                             }
464e4588158SJishnu CM                         }
46591c441ecSRavi Teja                         if (propertyPair.first == "DomainEnabled")
46691c441ecSRavi Teja                         {
46791c441ecSRavi Teja                             const bool* domainEnabled =
46891c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
46991c441ecSRavi Teja                             if (domainEnabled != nullptr)
47091c441ecSRavi Teja                             {
47191c441ecSRavi Teja                                 ethData.domainv6Enabled = *domainEnabled;
47291c441ecSRavi Teja                             }
47391c441ecSRavi Teja                         }
474e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
475e4588158SJishnu CM                         {
476e4588158SJishnu CM                             const bool* ntpEnabled =
477e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
478e4588158SJishnu CM                             if (ntpEnabled != nullptr)
479e4588158SJishnu CM                             {
480e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
481e4588158SJishnu CM                             }
482e4588158SJishnu CM                         }
483e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
484e4588158SJishnu CM                         {
485e4588158SJishnu CM                             const bool* hostNameEnabled =
486e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
487e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
488e4588158SJishnu CM                             {
489e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
4901f8c7b5dSJohnathan Mantey                             }
4911f8c7b5dSJohnathan Mantey                         }
4921f8c7b5dSJohnathan Mantey                     }
4931f8c7b5dSJohnathan Mantey                 }
4941f8c7b5dSJohnathan Mantey             }
495029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
496029573d4SEd Tanous             // to check eth number
497029573d4SEd Tanous             if (ifacePair.first ==
4984a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4994a0cb85cSEd Tanous             {
5004a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
5014a0cb85cSEd Tanous                 {
5024a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
5034a0cb85cSEd Tanous                     {
5044a0cb85cSEd Tanous                         const std::string* hostname =
5058d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
5064a0cb85cSEd Tanous                         if (hostname != nullptr)
5074a0cb85cSEd Tanous                         {
50882695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
5094a0cb85cSEd Tanous                         }
5104a0cb85cSEd Tanous                     }
5114a0cb85cSEd Tanous                 }
5124a0cb85cSEd Tanous             }
5134a0cb85cSEd Tanous         }
5144a0cb85cSEd Tanous     }
5154c9afe43SEd Tanous     return idFound;
5164a0cb85cSEd Tanous }
5174a0cb85cSEd Tanous 
518e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
51977179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
520711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
52177179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
522e48c0fc5SRavi Teja {
52389492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
52489492a15SPatrick Williams                                     ethifaceId;
525e48c0fc5SRavi Teja 
526e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
527e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
52881ce609eSEd Tanous     for (const auto& objpath : dbusData)
529e48c0fc5SRavi Teja     {
530e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
531353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
532e48c0fc5SRavi Teja         {
5339eb808c1SEd Tanous             for (const auto& interface : objpath.second)
534e48c0fc5SRavi Teja             {
535e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
536e48c0fc5SRavi Teja                 {
5373544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
538353163e9STony Lee                                                      [](const auto& property) {
539353163e9STony Lee                         return property.first == "Type";
540353163e9STony Lee                     });
541353163e9STony Lee                     if (type == interface.second.end())
542353163e9STony Lee                     {
543353163e9STony Lee                         continue;
544353163e9STony Lee                     }
545353163e9STony Lee 
546353163e9STony Lee                     const std::string* typeStr =
547353163e9STony Lee                         std::get_if<std::string>(&type->second);
548353163e9STony Lee 
549353163e9STony Lee                     if (typeStr == nullptr ||
550353163e9STony Lee                         (*typeStr !=
551353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
552353163e9STony Lee                     {
553353163e9STony Lee                         continue;
554353163e9STony Lee                     }
555353163e9STony Lee 
556e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
557e48c0fc5SRavi Teja                     // appropriate
55877179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5592c70f800SEd Tanous                     ipv6Address.id =
560353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5619eb808c1SEd Tanous                     for (const auto& property : interface.second)
562e48c0fc5SRavi Teja                     {
563e48c0fc5SRavi Teja                         if (property.first == "Address")
564e48c0fc5SRavi Teja                         {
565e48c0fc5SRavi Teja                             const std::string* address =
566e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
567e48c0fc5SRavi Teja                             if (address != nullptr)
568e48c0fc5SRavi Teja                             {
5692c70f800SEd Tanous                                 ipv6Address.address = *address;
570e48c0fc5SRavi Teja                             }
571e48c0fc5SRavi Teja                         }
572e48c0fc5SRavi Teja                         else if (property.first == "Origin")
573e48c0fc5SRavi Teja                         {
574e48c0fc5SRavi Teja                             const std::string* origin =
575e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
576e48c0fc5SRavi Teja                             if (origin != nullptr)
577e48c0fc5SRavi Teja                             {
5782c70f800SEd Tanous                                 ipv6Address.origin =
579e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
580e48c0fc5SRavi Teja                                                                         false);
581e48c0fc5SRavi Teja                             }
582e48c0fc5SRavi Teja                         }
583e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
584e48c0fc5SRavi Teja                         {
585e48c0fc5SRavi Teja                             const uint8_t* prefix =
586e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
587e48c0fc5SRavi Teja                             if (prefix != nullptr)
588e48c0fc5SRavi Teja                             {
5892c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
590e48c0fc5SRavi Teja                             }
591e48c0fc5SRavi Teja                         }
592889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
593889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
594889ff694SAsmitha Karunanithi                         {
595889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
596889ff694SAsmitha Karunanithi                         }
597e48c0fc5SRavi Teja                         else
598e48c0fc5SRavi Teja                         {
59962598e31SEd Tanous                             BMCWEB_LOG_ERROR(
60062598e31SEd Tanous                                 "Got extra property: {} on the {} object",
60162598e31SEd Tanous                                 property.first, objpath.first.str);
602e48c0fc5SRavi Teja                         }
603e48c0fc5SRavi Teja                     }
604e48c0fc5SRavi Teja                 }
605e48c0fc5SRavi Teja             }
606e48c0fc5SRavi Teja         }
607e48c0fc5SRavi Teja     }
608e48c0fc5SRavi Teja }
609e48c0fc5SRavi Teja 
6104a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
61177179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
612711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
61377179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
6144a0cb85cSEd Tanous {
61589492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
61689492a15SPatrick Williams                                     ethifaceId;
6174a0cb85cSEd Tanous 
6184a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
6194a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
62081ce609eSEd Tanous     for (const auto& objpath : dbusData)
6214a0cb85cSEd Tanous     {
6224a0cb85cSEd Tanous         // Check if proper pattern for object path appears
623353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
6244a0cb85cSEd Tanous         {
6259eb808c1SEd Tanous             for (const auto& interface : objpath.second)
6264a0cb85cSEd Tanous             {
6274a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
6284a0cb85cSEd Tanous                 {
6293544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
630353163e9STony Lee                                                      [](const auto& property) {
631353163e9STony Lee                         return property.first == "Type";
632353163e9STony Lee                     });
633353163e9STony Lee                     if (type == interface.second.end())
634353163e9STony Lee                     {
635353163e9STony Lee                         continue;
636353163e9STony Lee                     }
637353163e9STony Lee 
638353163e9STony Lee                     const std::string* typeStr =
639353163e9STony Lee                         std::get_if<std::string>(&type->second);
640353163e9STony Lee 
641353163e9STony Lee                     if (typeStr == nullptr ||
642353163e9STony Lee                         (*typeStr !=
643353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
644353163e9STony Lee                     {
645353163e9STony Lee                         continue;
646353163e9STony Lee                     }
647353163e9STony Lee 
6484a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6494a0cb85cSEd Tanous                     // appropriate
65077179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6512c70f800SEd Tanous                     ipv4Address.id =
652353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6539eb808c1SEd Tanous                     for (const auto& property : interface.second)
6544a0cb85cSEd Tanous                     {
6554a0cb85cSEd Tanous                         if (property.first == "Address")
6564a0cb85cSEd Tanous                         {
6574a0cb85cSEd Tanous                             const std::string* address =
658abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6594a0cb85cSEd Tanous                             if (address != nullptr)
6604a0cb85cSEd Tanous                             {
6612c70f800SEd Tanous                                 ipv4Address.address = *address;
6624a0cb85cSEd Tanous                             }
6634a0cb85cSEd Tanous                         }
6644a0cb85cSEd Tanous                         else if (property.first == "Origin")
6654a0cb85cSEd Tanous                         {
6664a0cb85cSEd Tanous                             const std::string* origin =
667abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6684a0cb85cSEd Tanous                             if (origin != nullptr)
6694a0cb85cSEd Tanous                             {
6702c70f800SEd Tanous                                 ipv4Address.origin =
6714a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6724a0cb85cSEd Tanous                                                                         true);
6734a0cb85cSEd Tanous                             }
6744a0cb85cSEd Tanous                         }
6754a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6764a0cb85cSEd Tanous                         {
6774a0cb85cSEd Tanous                             const uint8_t* mask =
678abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6794a0cb85cSEd Tanous                             if (mask != nullptr)
6804a0cb85cSEd Tanous                             {
6814a0cb85cSEd Tanous                                 // convert it to the string
6822c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6834a0cb85cSEd Tanous                             }
6844a0cb85cSEd Tanous                         }
685889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
686889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
687889ff694SAsmitha Karunanithi                         {
688889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
689889ff694SAsmitha Karunanithi                         }
6904a0cb85cSEd Tanous                         else
6914a0cb85cSEd Tanous                         {
69262598e31SEd Tanous                             BMCWEB_LOG_ERROR(
69362598e31SEd Tanous                                 "Got extra property: {} on the {} object",
69462598e31SEd Tanous                                 property.first, objpath.first.str);
6954a0cb85cSEd Tanous                         }
6964a0cb85cSEd Tanous                     }
6974a0cb85cSEd Tanous                     // Check if given address is local, or global
6982c70f800SEd Tanous                     ipv4Address.linktype =
69911ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
70018659d10SJohnathan Mantey                             ? LinkType::Local
70118659d10SJohnathan Mantey                             : LinkType::Global;
7024a0cb85cSEd Tanous                 }
7034a0cb85cSEd Tanous             }
7044a0cb85cSEd Tanous         }
7054a0cb85cSEd Tanous     }
7064a0cb85cSEd Tanous }
707588c3f0dSKowalski, Kamil 
708588c3f0dSKowalski, Kamil /**
709743eb1c0SJohnathan Mantey  * @brief Modifies the default gateway assigned to the NIC
710743eb1c0SJohnathan Mantey  *
711743eb1c0SJohnathan Mantey  * @param[in] ifaceId     Id of network interface whose default gateway is to be
712743eb1c0SJohnathan Mantey  *                        changed
713743eb1c0SJohnathan Mantey  * @param[in] gateway     The new gateway value. Assigning an empty string
714743eb1c0SJohnathan Mantey  *                        causes the gateway to be deleted
715743eb1c0SJohnathan Mantey  * @param[io] asyncResp   Response object that will be returned to client
716743eb1c0SJohnathan Mantey  *
717743eb1c0SJohnathan Mantey  * @return None
718743eb1c0SJohnathan Mantey  */
719743eb1c0SJohnathan Mantey inline void updateIPv4DefaultGateway(
720743eb1c0SJohnathan Mantey     const std::string& ifaceId, const std::string& gateway,
721743eb1c0SJohnathan Mantey     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
722743eb1c0SJohnathan Mantey {
723743eb1c0SJohnathan Mantey     setDbusProperty(
724*e93abac6SGinu George         asyncResp, "Gateway", "xyz.openbmc_project.Network",
725743eb1c0SJohnathan Mantey         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
726743eb1c0SJohnathan Mantey             ifaceId,
727743eb1c0SJohnathan Mantey         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
728*e93abac6SGinu George         gateway);
729743eb1c0SJohnathan Mantey }
730743eb1c0SJohnathan Mantey 
731743eb1c0SJohnathan Mantey /**
732743eb1c0SJohnathan Mantey  * @brief Deletes given static IP address for the interface
733179db1d7SKowalski, Kamil  *
734179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
735179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
736179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
737179db1d7SKowalski, Kamil  *
738179db1d7SKowalski, Kamil  * @return None
739179db1d7SKowalski, Kamil  */
7409c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
7419c5e585cSRavi Teja                             const std::string& ipHash,
7428d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7431abe55efSEd Tanous {
74455c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7455e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
7461abe55efSEd Tanous         if (ec)
7471abe55efSEd Tanous         {
748a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7491abe55efSEd Tanous         }
750179db1d7SKowalski, Kamil     },
751179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
7529c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
753179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
754179db1d7SKowalski, Kamil }
755179db1d7SKowalski, Kamil 
756179db1d7SKowalski, Kamil /**
75701784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
758179db1d7SKowalski, Kamil  *
75901784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
76001784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
76101784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
76201784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
763179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
764179db1d7SKowalski, Kamil  *
765179db1d7SKowalski, Kamil  * @return None
766179db1d7SKowalski, Kamil  */
767cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
768cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7698d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7701abe55efSEd Tanous {
7715a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
7725a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
7731abe55efSEd Tanous         if (ec)
7741abe55efSEd Tanous         {
775a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7769010ec2eSRavi Teja             return;
777179db1d7SKowalski, Kamil         }
7789010ec2eSRavi Teja     };
7799010ec2eSRavi Teja 
7809010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7819010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
782179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
783179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
78401784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
785179db1d7SKowalski, Kamil         gateway);
786179db1d7SKowalski, Kamil }
787e48c0fc5SRavi Teja 
788e48c0fc5SRavi Teja /**
789743eb1c0SJohnathan Mantey  * @brief Deletes the IP entry for this interface and creates a replacement
790743eb1c0SJohnathan Mantey  * static entry
79101784826SJohnathan Mantey  *
79201784826SJohnathan Mantey  * @param[in] ifaceId        Id of interface upon which to create the IPv6 entry
79301784826SJohnathan Mantey  * @param[in] id             The unique hash entry identifying the DBus entry
794743eb1c0SJohnathan Mantey  * @param[in] prefixLength   Prefix syntax for the subnet mask
795743eb1c0SJohnathan Mantey  * @param[in] address        Address to assign to this interface
796743eb1c0SJohnathan Mantey  * @param[in] numStaticAddrs Count of IPv4 static addresses
79701784826SJohnathan Mantey  * @param[io] asyncResp      Response object that will be returned to client
79801784826SJohnathan Mantey  *
79901784826SJohnathan Mantey  * @return None
80001784826SJohnathan Mantey  */
8019c5e585cSRavi Teja 
8029c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
8039c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
8048d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
8059c5e585cSRavi Teja     const std::string& gateway,
8068d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
80701784826SJohnathan Mantey {
80801784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
8099c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
8109c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
81101784826SJohnathan Mantey         if (ec)
81201784826SJohnathan Mantey         {
81301784826SJohnathan Mantey             messages::internalError(asyncResp->res);
81401784826SJohnathan Mantey         }
8159c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
8169c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
81701784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
8185e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
81923a21a1cSEd Tanous             if (ec2)
82001784826SJohnathan Mantey             {
82101784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
82201784826SJohnathan Mantey             }
82301784826SJohnathan Mantey         },
82401784826SJohnathan Mantey             "xyz.openbmc_project.Network",
82501784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
8269c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
8279c5e585cSRavi Teja             prefixLength, gateway);
82801784826SJohnathan Mantey     },
82901784826SJohnathan Mantey         "xyz.openbmc_project.Network",
8309c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
83101784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
83201784826SJohnathan Mantey }
83301784826SJohnathan Mantey 
834ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData(
835ce73d5c8SSunitha Harish     const std::string& ethifaceId,
836ce73d5c8SSunitha Harish     const dbus::utility::ManagedObjectType& dbusData,
837ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>& staticGatewayConfig)
838ce73d5c8SSunitha Harish {
839ce73d5c8SSunitha Harish     std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
840ce73d5c8SSunitha Harish     staticGatewayPathStart += ethifaceId;
841ce73d5c8SSunitha Harish 
842ce73d5c8SSunitha Harish     for (const auto& objpath : dbusData)
843ce73d5c8SSunitha Harish     {
844ce73d5c8SSunitha Harish         if (!std::string_view(objpath.first.str)
845ce73d5c8SSunitha Harish                  .starts_with(staticGatewayPathStart))
846ce73d5c8SSunitha Harish         {
847ce73d5c8SSunitha Harish             continue;
848ce73d5c8SSunitha Harish         }
849ce73d5c8SSunitha Harish         for (const auto& interface : objpath.second)
850ce73d5c8SSunitha Harish         {
851ce73d5c8SSunitha Harish             if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
852ce73d5c8SSunitha Harish             {
853ce73d5c8SSunitha Harish                 continue;
854ce73d5c8SSunitha Harish             }
855ce73d5c8SSunitha Harish             StaticGatewayData& staticGateway =
856ce73d5c8SSunitha Harish                 staticGatewayConfig.emplace_back();
857ce73d5c8SSunitha Harish             staticGateway.id = objpath.first.filename();
858ce73d5c8SSunitha Harish 
859ce73d5c8SSunitha Harish             bool success = sdbusplus::unpackPropertiesNoThrow(
860ce73d5c8SSunitha Harish                 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
861ce73d5c8SSunitha Harish                 "Gateway", staticGateway.gateway, "PrefixLength",
862ce73d5c8SSunitha Harish                 staticGateway.prefixLength, "ProtocolType",
863ce73d5c8SSunitha Harish                 staticGateway.protocol);
864ce73d5c8SSunitha Harish             if (!success)
865ce73d5c8SSunitha Harish             {
866ce73d5c8SSunitha Harish                 return false;
867ce73d5c8SSunitha Harish             }
868ce73d5c8SSunitha Harish         }
869ce73d5c8SSunitha Harish     }
870ce73d5c8SSunitha Harish     return true;
871ce73d5c8SSunitha Harish }
872ce73d5c8SSunitha Harish 
87301784826SJohnathan Mantey /**
874e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
875e48c0fc5SRavi Teja  *
876e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
877e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
878e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
879e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
880e48c0fc5SRavi Teja  *
881e48c0fc5SRavi Teja  * @return None
882e48c0fc5SRavi Teja  */
88301784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
88401784826SJohnathan Mantey                        const std::string& address,
8858d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
886e48c0fc5SRavi Teja {
887ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
888ce73d5c8SSunitha Harish     path /= ifaceId;
889ce73d5c8SSunitha Harish 
8905a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
8915a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
892e48c0fc5SRavi Teja         if (ec)
893e48c0fc5SRavi Teja         {
894fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
895fc23ef8aSNitin Kumar Kotania             {
896fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
897fc23ef8aSNitin Kumar Kotania                                                    "Address");
898fc23ef8aSNitin Kumar Kotania             }
899fc23ef8aSNitin Kumar Kotania             else
900fc23ef8aSNitin Kumar Kotania             {
901e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
902e48c0fc5SRavi Teja             }
903fc23ef8aSNitin Kumar Kotania         }
904e48c0fc5SRavi Teja     };
905ce73d5c8SSunitha Harish     // Passing null for gateway, as per redfish spec IPv6StaticAddresses
906ce73d5c8SSunitha Harish     // object does not have associated gateway property
907e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
908ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
909e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
910e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
911e48c0fc5SRavi Teja         "");
912e48c0fc5SRavi Teja }
913e48c0fc5SRavi Teja 
914179db1d7SKowalski, Kamil /**
915ce73d5c8SSunitha Harish  * @brief Deletes given IPv6 Static Gateway
916ce73d5c8SSunitha Harish  *
917ce73d5c8SSunitha Harish  * @param[in] ifaceId     Id of interface whose IP should be deleted
918ce73d5c8SSunitha Harish  * @param[in] ipHash      DBus Hash id of IP that should be deleted
919ce73d5c8SSunitha Harish  * @param[io] asyncResp   Response object that will be returned to client
920ce73d5c8SSunitha Harish  *
921ce73d5c8SSunitha Harish  * @return None
922ce73d5c8SSunitha Harish  */
923ce73d5c8SSunitha Harish inline void
924ce73d5c8SSunitha Harish     deleteIPv6Gateway(std::string_view gatewayId,
925ce73d5c8SSunitha Harish                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
926ce73d5c8SSunitha Harish {
927ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
928ce73d5c8SSunitha Harish     path /= gatewayId;
929ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
930ce73d5c8SSunitha Harish         [asyncResp](const boost::system::error_code& ec) {
931ce73d5c8SSunitha Harish         if (ec)
932ce73d5c8SSunitha Harish         {
933ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
934ce73d5c8SSunitha Harish         }
935ce73d5c8SSunitha Harish     },
936ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
937ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
938ce73d5c8SSunitha Harish }
939ce73d5c8SSunitha Harish 
940ce73d5c8SSunitha Harish /**
941ce73d5c8SSunitha Harish  * @brief Creates IPv6 static default gateway with given data
942ce73d5c8SSunitha Harish  *
943ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose IP should be added
944ce73d5c8SSunitha Harish  * @param[in] prefixLength Prefix length that needs to be added
945ce73d5c8SSunitha Harish  * @param[in] gateway      Gateway address that needs to be added
946ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
947ce73d5c8SSunitha Harish  *
948ce73d5c8SSunitha Harish  * @return None
949ce73d5c8SSunitha Harish  */
950ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway(
951ce73d5c8SSunitha Harish     std::string_view ifaceId, size_t prefixLength, std::string_view gateway,
952ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
953ce73d5c8SSunitha Harish {
954ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
955ce73d5c8SSunitha Harish     path /= ifaceId;
956ce73d5c8SSunitha Harish     auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
957ce73d5c8SSunitha Harish         if (ec)
958ce73d5c8SSunitha Harish         {
959ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
960ce73d5c8SSunitha Harish         }
961ce73d5c8SSunitha Harish     };
962ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
963ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
964ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
965ce73d5c8SSunitha Harish         gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
966ce73d5c8SSunitha Harish }
967ce73d5c8SSunitha Harish 
968ce73d5c8SSunitha Harish /**
969ce73d5c8SSunitha Harish  * @brief Deletes the IPv6 default gateway entry for this interface and
970ce73d5c8SSunitha Harish  * creates a replacement IPv6 default gateway entry
971ce73d5c8SSunitha Harish  *
972ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface upon which to create the IPv6
973ce73d5c8SSunitha Harish  * entry
974ce73d5c8SSunitha Harish  * @param[in] gateway      IPv6 gateway to assign to this interface
975ce73d5c8SSunitha Harish  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
976ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
977ce73d5c8SSunitha Harish  *
978ce73d5c8SSunitha Harish  * @return None
979ce73d5c8SSunitha Harish  */
980ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway(
981ce73d5c8SSunitha Harish     std::string_view ifaceId, std::string_view gatewayId,
982ce73d5c8SSunitha Harish     std::string_view gateway, size_t prefixLength,
983ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
984ce73d5c8SSunitha Harish {
985ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
986ce73d5c8SSunitha Harish     path /= gatewayId;
987ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
988ce73d5c8SSunitha Harish         [asyncResp, ifaceId, gateway,
989ce73d5c8SSunitha Harish          prefixLength](const boost::system::error_code& ec) {
990ce73d5c8SSunitha Harish         if (ec)
991ce73d5c8SSunitha Harish         {
992ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
993ce73d5c8SSunitha Harish             return;
994ce73d5c8SSunitha Harish         }
995ce73d5c8SSunitha Harish         createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp);
996ce73d5c8SSunitha Harish     },
997ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
998ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
999ce73d5c8SSunitha Harish }
1000ce73d5c8SSunitha Harish 
1001ce73d5c8SSunitha Harish /**
1002ce73d5c8SSunitha Harish  * @brief Sets IPv6 default gateway with given data
1003ce73d5c8SSunitha Harish  *
1004ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose gateway should be added
1005ce73d5c8SSunitha Harish  * @param[in] input        Contains address that needs to be added
1006ce73d5c8SSunitha Harish  * @param[in] staticGatewayData  Current static gateways in the system
1007ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
1008ce73d5c8SSunitha Harish  *
1009ce73d5c8SSunitha Harish  * @return None
1010ce73d5c8SSunitha Harish  */
1011ce73d5c8SSunitha Harish 
1012ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway(
10133dfed536SEd Tanous     const std::string& ifaceId,
10143dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1015ce73d5c8SSunitha Harish     const std::vector<StaticGatewayData>& staticGatewayData,
1016ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1017ce73d5c8SSunitha Harish {
1018ce73d5c8SSunitha Harish     size_t entryIdx = 1;
1019ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>::const_iterator staticGatewayEntry =
1020ce73d5c8SSunitha Harish         staticGatewayData.begin();
1021ce73d5c8SSunitha Harish 
10223dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
10233dfed536SEd Tanous          input)
1024ce73d5c8SSunitha Harish     {
1025ce73d5c8SSunitha Harish         // find the next gateway entry
1026ce73d5c8SSunitha Harish         while (staticGatewayEntry != staticGatewayData.end())
1027ce73d5c8SSunitha Harish         {
1028ce73d5c8SSunitha Harish             if (staticGatewayEntry->protocol ==
1029ce73d5c8SSunitha Harish                 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1030ce73d5c8SSunitha Harish             {
1031ce73d5c8SSunitha Harish                 break;
1032ce73d5c8SSunitha Harish             }
1033ce73d5c8SSunitha Harish             staticGatewayEntry++;
1034ce73d5c8SSunitha Harish         }
1035ce73d5c8SSunitha Harish         std::string pathString = "IPv6StaticDefaultGateways/" +
1036ce73d5c8SSunitha Harish                                  std::to_string(entryIdx);
10373dfed536SEd Tanous         nlohmann::json::object_t* obj =
10383dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
10393dfed536SEd Tanous         if (obj == nullptr)
1040ce73d5c8SSunitha Harish         {
1041ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1042ce73d5c8SSunitha Harish             {
1043ce73d5c8SSunitha Harish                 messages::resourceCannotBeDeleted(asyncResp->res);
1044ce73d5c8SSunitha Harish                 return;
1045ce73d5c8SSunitha Harish             }
1046ce73d5c8SSunitha Harish             deleteIPv6Gateway(staticGatewayEntry->id, asyncResp);
1047ce73d5c8SSunitha Harish             return;
1048ce73d5c8SSunitha Harish         }
10493dfed536SEd Tanous         if (obj->empty())
1050ce73d5c8SSunitha Harish         {
1051ce73d5c8SSunitha Harish             // Do nothing, but make sure the entry exists.
1052ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1053ce73d5c8SSunitha Harish             {
10543dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
1055ce73d5c8SSunitha Harish                                                    pathString);
1056ce73d5c8SSunitha Harish                 return;
1057ce73d5c8SSunitha Harish             }
1058ce73d5c8SSunitha Harish         }
1059ce73d5c8SSunitha Harish         std::optional<std::string> address;
1060ce73d5c8SSunitha Harish         std::optional<size_t> prefixLength;
1061ce73d5c8SSunitha Harish 
10623dfed536SEd Tanous         if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address,
10633dfed536SEd Tanous                                        "PrefixLength", prefixLength))
1064ce73d5c8SSunitha Harish         {
1065ce73d5c8SSunitha Harish             return;
1066ce73d5c8SSunitha Harish         }
1067ce73d5c8SSunitha Harish         const std::string* addr = nullptr;
1068ce73d5c8SSunitha Harish         size_t prefix = 0;
1069ce73d5c8SSunitha Harish         if (address)
1070ce73d5c8SSunitha Harish         {
1071ce73d5c8SSunitha Harish             addr = &(*address);
1072ce73d5c8SSunitha Harish         }
1073ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1074ce73d5c8SSunitha Harish         {
1075ce73d5c8SSunitha Harish             addr = &(staticGatewayEntry->gateway);
1076ce73d5c8SSunitha Harish         }
1077ce73d5c8SSunitha Harish         else
1078ce73d5c8SSunitha Harish         {
1079ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res, pathString + "/Address");
1080ce73d5c8SSunitha Harish             return;
1081ce73d5c8SSunitha Harish         }
1082ce73d5c8SSunitha Harish         if (prefixLength)
1083ce73d5c8SSunitha Harish         {
1084ce73d5c8SSunitha Harish             prefix = *prefixLength;
1085ce73d5c8SSunitha Harish         }
1086ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1087ce73d5c8SSunitha Harish         {
1088ce73d5c8SSunitha Harish             prefix = staticGatewayEntry->prefixLength;
1089ce73d5c8SSunitha Harish         }
1090ce73d5c8SSunitha Harish         else
1091ce73d5c8SSunitha Harish         {
1092ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res,
1093ce73d5c8SSunitha Harish                                       pathString + "/PrefixLength");
1094ce73d5c8SSunitha Harish             return;
1095ce73d5c8SSunitha Harish         }
1096ce73d5c8SSunitha Harish         if (staticGatewayEntry != staticGatewayData.end())
1097ce73d5c8SSunitha Harish         {
1098ce73d5c8SSunitha Harish             deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
1099ce73d5c8SSunitha Harish                                               *addr, prefix, asyncResp);
1100ce73d5c8SSunitha Harish             staticGatewayEntry++;
1101ce73d5c8SSunitha Harish         }
1102ce73d5c8SSunitha Harish         else
1103ce73d5c8SSunitha Harish         {
1104ce73d5c8SSunitha Harish             createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp);
1105ce73d5c8SSunitha Harish         }
1106ce73d5c8SSunitha Harish         entryIdx++;
1107ce73d5c8SSunitha Harish     }
1108ce73d5c8SSunitha Harish }
1109ce73d5c8SSunitha Harish 
1110ce73d5c8SSunitha Harish /**
1111179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
1112179db1d7SKowalski, Kamil  * Object
1113179db1d7SKowalski, Kamil  * from EntityManager Network Manager
11144a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
1115179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
1116179db1d7SKowalski, Kamil  * into JSON
1117179db1d7SKowalski, Kamil  */
1118179db1d7SKowalski, Kamil template <typename CallbackFunc>
111981ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
11201abe55efSEd Tanous                           CallbackFunc&& callback)
11211abe55efSEd Tanous {
1122f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1123f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1124f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1125f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
11268cb2c024SEd Tanous          callback = std::forward<CallbackFunc>(callback)](
11278b24275dSEd Tanous             const boost::system::error_code& ec,
11283dfed536SEd Tanous             const dbus::utility::ManagedObjectType& resp) mutable {
112955c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
113077179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
113177179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
1132ce73d5c8SSunitha Harish         std::vector<StaticGatewayData> ipv6GatewayData;
1133179db1d7SKowalski, Kamil 
11348b24275dSEd Tanous         if (ec)
11351abe55efSEd Tanous         {
1136ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1137179db1d7SKowalski, Kamil             return;
1138179db1d7SKowalski, Kamil         }
1139179db1d7SKowalski, Kamil 
1140002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
11414c9afe43SEd Tanous         if (!found)
11424c9afe43SEd Tanous         {
1143ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
11444c9afe43SEd Tanous             return;
11454c9afe43SEd Tanous         }
11464c9afe43SEd Tanous 
11472c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
1148179db1d7SKowalski, Kamil         // Fix global GW
11491abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
11501abe55efSEd Tanous         {
1151c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
1152c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
11539010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
11541abe55efSEd Tanous             {
115582695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
1156179db1d7SKowalski, Kamil             }
1157179db1d7SKowalski, Kamil         }
1158179db1d7SKowalski, Kamil 
11592c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
1160ce73d5c8SSunitha Harish         if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData))
1161ce73d5c8SSunitha Harish         {
1162ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1163ce73d5c8SSunitha Harish         }
11644e0453b1SGunnar Mills         // Finally make a callback with useful data
1165ce73d5c8SSunitha Harish         callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1166f5892d0dSGeorge Liu     });
1167271584abSEd Tanous }
1168179db1d7SKowalski, Kamil 
1169179db1d7SKowalski, Kamil /**
11709391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
11719391bb9cSRapkiewicz, Pawel  * Manager
11721abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
11731abe55efSEd Tanous  * into JSON.
11749391bb9cSRapkiewicz, Pawel  */
11759391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
11761abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
11771abe55efSEd Tanous {
1178f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1179f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1180f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
11818cb2c024SEd Tanous         [callback = std::forward<CallbackFunc>(callback)](
11828b24275dSEd Tanous             const boost::system::error_code& ec,
1183f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
11841abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
11851abe55efSEd Tanous         // ethernet interfaces
118677179532SEd Tanous         std::vector<std::string> ifaceList;
11872c70f800SEd Tanous         ifaceList.reserve(resp.size());
11888b24275dSEd Tanous         if (ec)
11891abe55efSEd Tanous         {
11902c70f800SEd Tanous             callback(false, ifaceList);
11919391bb9cSRapkiewicz, Pawel             return;
11929391bb9cSRapkiewicz, Pawel         }
11939391bb9cSRapkiewicz, Pawel 
11949391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
11954a0cb85cSEd Tanous         for (const auto& objpath : resp)
11961abe55efSEd Tanous         {
11979391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
11984a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
11991abe55efSEd Tanous             {
12001abe55efSEd Tanous                 // If interface is
12014a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
12024a0cb85cSEd Tanous                 // what we're looking for.
12039391bb9cSRapkiewicz, Pawel                 if (interface.first ==
12041abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
12051abe55efSEd Tanous                 {
12062dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
12072dfd18efSEd Tanous                     if (ifaceId.empty())
12081abe55efSEd Tanous                     {
12092dfd18efSEd Tanous                         continue;
12109391bb9cSRapkiewicz, Pawel                     }
12112dfd18efSEd Tanous                     // and put it into output vector.
121277179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
12139391bb9cSRapkiewicz, Pawel                 }
12149391bb9cSRapkiewicz, Pawel             }
12159391bb9cSRapkiewicz, Pawel         }
12162c5875a2SEd Tanous 
12173544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
12182c5875a2SEd Tanous 
1219a434f2bdSEd Tanous         // Finally make a callback with useful data
12202c70f800SEd Tanous         callback(true, ifaceList);
1221f5892d0dSGeorge Liu     });
1222271584abSEd Tanous }
12239391bb9cSRapkiewicz, Pawel 
12244f48d5f6SEd Tanous inline void
12254f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
12268d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12271abe55efSEd Tanous {
1228ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
1229ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
1230ab6554f1SJoshi-Mansi     {
1231ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
1232ab6554f1SJoshi-Mansi                                            "HostName");
1233ab6554f1SJoshi-Mansi         return;
1234ab6554f1SJoshi-Mansi     }
1235d02aad39SEd Tanous     setDbusProperty(
1236*e93abac6SGinu George         asyncResp, "HostName", "xyz.openbmc_project.Network",
1237d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network/config"),
1238d02aad39SEd Tanous         "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
1239*e93abac6SGinu George         hostname);
1240588c3f0dSKowalski, Kamil }
1241588c3f0dSKowalski, Kamil 
12424f48d5f6SEd Tanous inline void
124335fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
124435fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
124535fb5311STejas Patil {
1246d02aad39SEd Tanous     sdbusplus::message::object_path objPath("/xyz/openbmc_project/network");
1247d02aad39SEd Tanous     objPath /= ifaceId;
1248*e93abac6SGinu George     setDbusProperty(asyncResp, "MTUSize", "xyz.openbmc_project.Network",
1249*e93abac6SGinu George                     objPath, "xyz.openbmc_project.Network.EthernetInterface",
1250*e93abac6SGinu George                     "MTU", mtuSize);
125135fb5311STejas Patil }
125235fb5311STejas Patil 
125335fb5311STejas Patil inline void
12544f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
1255bf648f77SEd Tanous                           const std::string& domainname,
12568d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1257ab6554f1SJoshi-Mansi {
1258ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
1259d02aad39SEd Tanous     setDbusProperty(
1260*e93abac6SGinu George         asyncResp, "FQDN", "xyz.openbmc_project.Network",
1261d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1262d02aad39SEd Tanous             ifaceId,
1263*e93abac6SGinu George         "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
1264d02aad39SEd Tanous         vectorDomainname);
1265ab6554f1SJoshi-Mansi }
1266ab6554f1SJoshi-Mansi 
12674f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1268bf648f77SEd Tanous {
1269bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
12703544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1271bf648f77SEd Tanous     {
1272bf648f77SEd Tanous         return false;
1273bf648f77SEd Tanous     }
1274bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1275bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1276bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1277bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
12784b242749SEd Tanous     const static std::regex pattern(
1279bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1280bf648f77SEd Tanous 
1281bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1282bf648f77SEd Tanous }
1283bf648f77SEd Tanous 
12844f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1285bf648f77SEd Tanous {
1286bf648f77SEd Tanous     // Can have multiple subdomains
1287bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
12884b242749SEd Tanous     const static std::regex pattern(
12890fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1290bf648f77SEd Tanous 
1291bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1292bf648f77SEd Tanous }
1293bf648f77SEd Tanous 
12944f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
12958d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1296ab6554f1SJoshi-Mansi {
1297ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1298ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1299ab6554f1SJoshi-Mansi     {
1300ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1301ab6554f1SJoshi-Mansi         return;
1302ab6554f1SJoshi-Mansi     }
1303ab6554f1SJoshi-Mansi 
1304ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1305ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1306ab6554f1SJoshi-Mansi     {
1307ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1308ab6554f1SJoshi-Mansi         return;
1309ab6554f1SJoshi-Mansi     }
1310ab6554f1SJoshi-Mansi 
1311ab6554f1SJoshi-Mansi     std::string hostname;
1312ab6554f1SJoshi-Mansi     std::string domainname;
1313ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1314ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1315ab6554f1SJoshi-Mansi 
1316ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1317ab6554f1SJoshi-Mansi     {
1318ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1319ab6554f1SJoshi-Mansi         return;
1320ab6554f1SJoshi-Mansi     }
1321ab6554f1SJoshi-Mansi 
1322ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1323ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1324ab6554f1SJoshi-Mansi }
1325ab6554f1SJoshi-Mansi 
13264f48d5f6SEd Tanous inline void
13274f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1328bf648f77SEd Tanous                           const std::string& macAddress,
13298d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1330d577665bSRatan Gupta {
1331d02aad39SEd Tanous     setDbusProperty(
1332*e93abac6SGinu George         asyncResp, "MACAddress", "xyz.openbmc_project.Network",
1333d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1334d02aad39SEd Tanous             ifaceId,
1335*e93abac6SGinu George         "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress);
1336d577665bSRatan Gupta }
1337286b9118SJohnathan Mantey 
13384f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
13394f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
13404f48d5f6SEd Tanous                            const bool v6Value,
13418d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1342da131a9aSJennifer Lee {
13432c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
1344d02aad39SEd Tanous     setDbusProperty(
1345*e93abac6SGinu George         asyncResp, "DHCPv4", "xyz.openbmc_project.Network",
1346d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1347d02aad39SEd Tanous             ifaceId,
1348*e93abac6SGinu George         "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp);
1349eeedda23SJohnathan Mantey }
1350eeedda23SJohnathan Mantey 
1351e4588158SJishnu CM enum class NetworkType
1352e4588158SJishnu CM {
1353e4588158SJishnu CM     dhcp4,
1354e4588158SJishnu CM     dhcp6
1355e4588158SJishnu CM };
1356e4588158SJishnu CM 
1357e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1358e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1359e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1360da131a9aSJennifer Lee {
136162598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
13621847f2a0SAsmitha Karunanithi     std::string redfishPropertyName;
1363e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1364e4588158SJishnu CM     path /= ethifaceId;
1365e4588158SJishnu CM 
1366e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1367e4588158SJishnu CM     {
1368e4588158SJishnu CM         path /= "dhcp4";
13691847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv4";
1370e4588158SJishnu CM     }
1371e4588158SJishnu CM     else
1372e4588158SJishnu CM     {
1373e4588158SJishnu CM         path /= "dhcp6";
13741847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv6";
1375e4588158SJishnu CM     }
1376e4588158SJishnu CM 
1377*e93abac6SGinu George     setDbusProperty(
1378*e93abac6SGinu George         asyncResp, redfishPropertyName, "xyz.openbmc_project.Network", path,
1379*e93abac6SGinu George         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value);
1380da131a9aSJennifer Lee }
1381d577665bSRatan Gupta 
1382b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1383b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1384b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1385b10d8db0SRavi Teja {
1386b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1387b10d8db0SRavi Teja     path /= ifaceId;
1388*e93abac6SGinu George     setDbusProperty(asyncResp,
13891847f2a0SAsmitha Karunanithi                     "StatelessAddressAutoConfig/IPv6AutoConfigEnabled",
1390*e93abac6SGinu George                     "xyz.openbmc_project.Network", path,
1391*e93abac6SGinu George                     "xyz.openbmc_project.Network.EthernetInterface",
1392*e93abac6SGinu George                     "IPv6AcceptRA", ipv6AutoConfigEnabled);
1393b10d8db0SRavi Teja }
1394b10d8db0SRavi Teja 
13954f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
13961f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1397f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1398f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
13998d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1400da131a9aSJennifer Lee {
140182695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
140282695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1403da131a9aSJennifer Lee 
1404743eb1c0SJohnathan Mantey     if (ipv4Active)
1405743eb1c0SJohnathan Mantey     {
1406743eb1c0SJohnathan Mantey         updateIPv4DefaultGateway(ifaceId, "", asyncResp);
1407743eb1c0SJohnathan Mantey     }
14081f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
14091f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
14101f8c7b5dSJohnathan Mantey 
14111f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
14121f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1413da131a9aSJennifer Lee     {
1414b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
14151f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
14161f8c7b5dSJohnathan Mantey         {
1417bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1418bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
14191f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1420da131a9aSJennifer Lee             return;
1421da131a9aSJennifer Lee         }
1422b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
14231f8c7b5dSJohnathan Mantey     }
14241f8c7b5dSJohnathan Mantey     else
1425da131a9aSJennifer Lee     {
14261f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
14271f8c7b5dSJohnathan Mantey     }
14281f8c7b5dSJohnathan Mantey 
1429e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1430e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1431e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
14321f8c7b5dSJohnathan Mantey     {
1433e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
14341f8c7b5dSJohnathan Mantey     }
1435e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
14361f8c7b5dSJohnathan Mantey     {
1437e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
14381f8c7b5dSJohnathan Mantey     }
14391f8c7b5dSJohnathan Mantey 
1440e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1441e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1442e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
14431f8c7b5dSJohnathan Mantey     {
1444e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
14451f8c7b5dSJohnathan Mantey     }
1446e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
14471f8c7b5dSJohnathan Mantey     {
1448e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
14491f8c7b5dSJohnathan Mantey     }
14501f8c7b5dSJohnathan Mantey 
145191c441ecSRavi Teja     bool nextUsev4Domain = ethData.domainv4Enabled;
145291c441ecSRavi Teja     bool nextUsev6Domain = ethData.domainv6Enabled;
1453e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
14541f8c7b5dSJohnathan Mantey     {
1455e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
14561f8c7b5dSJohnathan Mantey     }
1457e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
14581f8c7b5dSJohnathan Mantey     {
1459e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
14601f8c7b5dSJohnathan Mantey     }
14611f8c7b5dSJohnathan Mantey 
146262598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
14631f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
14641f8c7b5dSJohnathan Mantey                    asyncResp);
146562598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1466e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1467e4588158SJishnu CM                   NetworkType::dhcp4);
146862598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1469e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1470e4588158SJishnu CM                   NetworkType::dhcp4);
147191c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled...");
147291c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
1473e4588158SJishnu CM                   NetworkType::dhcp4);
1474e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1475e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1476e4588158SJishnu CM                   NetworkType::dhcp6);
1477e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1478e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1479e4588158SJishnu CM                   NetworkType::dhcp6);
148091c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
148191c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
1482e4588158SJishnu CM                   NetworkType::dhcp6);
1483da131a9aSJennifer Lee }
148401784826SJohnathan Mantey 
148577179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
148677179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
148777179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
148801784826SJohnathan Mantey {
148917a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
149017a897dfSManojkiran Eda         return value.origin == "Static";
149117a897dfSManojkiran Eda     });
149201784826SJohnathan Mantey }
149301784826SJohnathan Mantey 
149477179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
149577179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
149677179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
149701784826SJohnathan Mantey {
149817a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
149917a897dfSManojkiran Eda         return value.origin == "Static";
150017a897dfSManojkiran Eda     });
150101784826SJohnathan Mantey }
150201784826SJohnathan Mantey 
15033dfed536SEd Tanous inline void handleIPv4StaticPatch(
15043dfed536SEd Tanous     const std::string& ifaceId,
15053dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1506743eb1c0SJohnathan Mantey     const EthernetInterfaceData& ethData,
150777179532SEd Tanous     const std::vector<IPv4AddressData>& ipv4Data,
15088d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
15091abe55efSEd Tanous {
1510271584abSEd Tanous     unsigned entryIdx = 1;
151101784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
151201784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
151301784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
151401784826SJohnathan Mantey     // into the NIC.
151577179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
15162c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
151701784826SJohnathan Mantey 
1518743eb1c0SJohnathan Mantey     bool gatewayValueAssigned{};
15194a8f5d43SJohnathan Mantey     bool preserveGateway{};
1520743eb1c0SJohnathan Mantey     std::string activePath{};
1521743eb1c0SJohnathan Mantey     std::string activeGateway{};
1522743eb1c0SJohnathan Mantey     if (!ethData.defaultGateway.empty() && ethData.defaultGateway != "0.0.0.0")
1523743eb1c0SJohnathan Mantey     {
1524743eb1c0SJohnathan Mantey         // The NIC is already configured with a default gateway. Use this if
1525743eb1c0SJohnathan Mantey         // the leading entry in the PATCH is '{}', which is preserving an active
1526743eb1c0SJohnathan Mantey         // static address.
1527743eb1c0SJohnathan Mantey         activeGateway = ethData.defaultGateway;
1528743eb1c0SJohnathan Mantey         activePath = "IPv4StaticAddresses/1";
1529743eb1c0SJohnathan Mantey         gatewayValueAssigned = true;
1530743eb1c0SJohnathan Mantey     }
1531743eb1c0SJohnathan Mantey 
15323dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
15333dfed536SEd Tanous          input)
15341abe55efSEd Tanous     {
153589492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
153689492a15SPatrick Williams                                  std::to_string(entryIdx);
15373dfed536SEd Tanous         nlohmann::json::object_t* obj =
15383dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
1539743eb1c0SJohnathan Mantey         if (obj == nullptr)
1540743eb1c0SJohnathan Mantey         {
1541743eb1c0SJohnathan Mantey             if (nicIpEntry != ipv4Data.cend())
1542743eb1c0SJohnathan Mantey             {
1543743eb1c0SJohnathan Mantey                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
1544743eb1c0SJohnathan Mantey                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1545743eb1c0SJohnathan Mantey                                                   ipv4Data.cend());
15464a8f5d43SJohnathan Mantey                 if (!preserveGateway && (nicIpEntry == ipv4Data.cend()))
1547743eb1c0SJohnathan Mantey                 {
1548743eb1c0SJohnathan Mantey                     // All entries have been processed, and this last has
1549743eb1c0SJohnathan Mantey                     // requested the IP address be deleted. No prior entry
1550743eb1c0SJohnathan Mantey                     // performed an action that created or modified a
1551743eb1c0SJohnathan Mantey                     // gateway. Deleting this IP address means the default
1552743eb1c0SJohnathan Mantey                     // gateway entry has to be removed as well.
1553743eb1c0SJohnathan Mantey                     updateIPv4DefaultGateway(ifaceId, "", asyncResp);
1554743eb1c0SJohnathan Mantey                 }
1555743eb1c0SJohnathan Mantey                 entryIdx++;
1556743eb1c0SJohnathan Mantey                 continue;
1557743eb1c0SJohnathan Mantey             }
1558743eb1c0SJohnathan Mantey             // Received a DELETE action on an entry not assigned to the NIC
1559743eb1c0SJohnathan Mantey             messages::resourceCannotBeDeleted(asyncResp->res);
1560743eb1c0SJohnathan Mantey             return;
1561743eb1c0SJohnathan Mantey         }
1562743eb1c0SJohnathan Mantey 
1563743eb1c0SJohnathan Mantey         // An Add/Modify action is requested
1564743eb1c0SJohnathan Mantey         if (!obj->empty())
1565f476acbfSRatan Gupta         {
1566537174c4SEd Tanous             std::optional<std::string> address;
1567537174c4SEd Tanous             std::optional<std::string> subnetMask;
1568537174c4SEd Tanous             std::optional<std::string> gateway;
1569537174c4SEd Tanous 
15703dfed536SEd Tanous             if (!json_util::readJsonObject(*obj, asyncResp->res, "Address",
15717e27d832SJohnathan Mantey                                            address, "SubnetMask", subnetMask,
15727e27d832SJohnathan Mantey                                            "Gateway", gateway))
1573537174c4SEd Tanous             {
15743dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
157571f52d96SEd Tanous                                                    pathString);
1576537174c4SEd Tanous                 return;
1577179db1d7SKowalski, Kamil             }
1578179db1d7SKowalski, Kamil 
157901784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
158001784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
158101784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
158201784826SJohnathan Mantey             // current request.
1583537174c4SEd Tanous             if (address)
15841abe55efSEd Tanous             {
1585e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
158601784826SJohnathan Mantey                 {
1587bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1588bf648f77SEd Tanous                                                        pathString + "/Address");
1589e01d0c36SEd Tanous                     return;
159001784826SJohnathan Mantey                 }
159101784826SJohnathan Mantey             }
159285ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
159301784826SJohnathan Mantey             {
1594e01d0c36SEd Tanous                 address = (nicIpEntry->address);
159501784826SJohnathan Mantey             }
159601784826SJohnathan Mantey             else
159701784826SJohnathan Mantey             {
159801784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
159901784826SJohnathan Mantey                                           pathString + "/Address");
1600e01d0c36SEd Tanous                 return;
16014a0cb85cSEd Tanous             }
16024a0cb85cSEd Tanous 
1603e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1604537174c4SEd Tanous             if (subnetMask)
16054a0cb85cSEd Tanous             {
1606033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1607033f1e4dSEd Tanous                                                          &prefixLength))
16084a0cb85cSEd Tanous                 {
1609f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1610537174c4SEd Tanous                         asyncResp->res, *subnetMask,
16114a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1612e01d0c36SEd Tanous                     return;
16134a0cb85cSEd Tanous                 }
16144a0cb85cSEd Tanous             }
161585ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
16164a0cb85cSEd Tanous             {
1617033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
161801784826SJohnathan Mantey                                                          &prefixLength))
16194a0cb85cSEd Tanous                 {
162001784826SJohnathan Mantey                     messages::propertyValueFormatError(
162185ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
162201784826SJohnathan Mantey                         pathString + "/SubnetMask");
1623e01d0c36SEd Tanous                     return;
16244a0cb85cSEd Tanous                 }
16254a0cb85cSEd Tanous             }
16261abe55efSEd Tanous             else
16271abe55efSEd Tanous             {
162801784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
162901784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1630e01d0c36SEd Tanous                 return;
163101784826SJohnathan Mantey             }
163201784826SJohnathan Mantey 
163301784826SJohnathan Mantey             if (gateway)
163401784826SJohnathan Mantey             {
1635e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
163601784826SJohnathan Mantey                 {
1637bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1638bf648f77SEd Tanous                                                        pathString + "/Gateway");
1639e01d0c36SEd Tanous                     return;
164001784826SJohnathan Mantey                 }
164101784826SJohnathan Mantey             }
164285ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
164301784826SJohnathan Mantey             {
1644e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
164501784826SJohnathan Mantey             }
164601784826SJohnathan Mantey             else
16471abe55efSEd Tanous             {
1648a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
16494a0cb85cSEd Tanous                                           pathString + "/Gateway");
165001784826SJohnathan Mantey                 return;
16514a0cb85cSEd Tanous             }
16524a0cb85cSEd Tanous 
1653743eb1c0SJohnathan Mantey             if (gatewayValueAssigned)
1654743eb1c0SJohnathan Mantey             {
1655743eb1c0SJohnathan Mantey                 if (activeGateway != gateway)
1656743eb1c0SJohnathan Mantey                 {
1657743eb1c0SJohnathan Mantey                     // A NIC can only have a single active gateway value.
1658743eb1c0SJohnathan Mantey                     // If any gateway in the array of static addresses
1659743eb1c0SJohnathan Mantey                     // mismatch the PATCH is in error.
1660743eb1c0SJohnathan Mantey                     std::string arg1 = pathString + "/Gateway";
1661743eb1c0SJohnathan Mantey                     std::string arg2 = activePath + "/Gateway";
1662743eb1c0SJohnathan Mantey                     messages::propertyValueConflict(asyncResp->res, arg1, arg2);
1663743eb1c0SJohnathan Mantey                     return;
1664743eb1c0SJohnathan Mantey                 }
1665743eb1c0SJohnathan Mantey             }
1666743eb1c0SJohnathan Mantey             else
1667743eb1c0SJohnathan Mantey             {
1668743eb1c0SJohnathan Mantey                 // Capture the very first gateway value from the incoming
1669743eb1c0SJohnathan Mantey                 // JSON record and use it at the default gateway.
1670743eb1c0SJohnathan Mantey                 updateIPv4DefaultGateway(ifaceId, *gateway, asyncResp);
1671743eb1c0SJohnathan Mantey                 activeGateway = *gateway;
1672743eb1c0SJohnathan Mantey                 activePath = pathString;
1673743eb1c0SJohnathan Mantey                 gatewayValueAssigned = true;
1674743eb1c0SJohnathan Mantey             }
1675743eb1c0SJohnathan Mantey 
167685ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
16771abe55efSEd Tanous             {
16789c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
167977eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
168077eb0153SEd Tanous                                          *gateway, asyncResp);
168189492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
168289492a15SPatrick Williams                                                   ipv4Data.cend());
16834a8f5d43SJohnathan Mantey                 preserveGateway = true;
1684588c3f0dSKowalski, Kamil             }
168501784826SJohnathan Mantey             else
168601784826SJohnathan Mantey             {
1687cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1688cb13a392SEd Tanous                            asyncResp);
16894a8f5d43SJohnathan Mantey                 preserveGateway = true;
16904a0cb85cSEd Tanous             }
16914a0cb85cSEd Tanous             entryIdx++;
16924a0cb85cSEd Tanous         }
169301784826SJohnathan Mantey         else
169401784826SJohnathan Mantey         {
1695743eb1c0SJohnathan Mantey             // Received {}, do not modify this address
169685ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
169701784826SJohnathan Mantey             {
169889492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
169989492a15SPatrick Williams                                                   ipv4Data.cend());
17004a8f5d43SJohnathan Mantey                 preserveGateway = true;
170101784826SJohnathan Mantey                 entryIdx++;
170201784826SJohnathan Mantey             }
1703743eb1c0SJohnathan Mantey             else
1704743eb1c0SJohnathan Mantey             {
1705743eb1c0SJohnathan Mantey                 // Requested a DO NOT MODIFY action on an entry not assigned
1706743eb1c0SJohnathan Mantey                 // to the NIC
1707743eb1c0SJohnathan Mantey                 messages::propertyValueFormatError(asyncResp->res, *obj,
1708743eb1c0SJohnathan Mantey                                                    pathString);
1709743eb1c0SJohnathan Mantey                 return;
1710743eb1c0SJohnathan Mantey             }
1711743eb1c0SJohnathan Mantey         }
171201784826SJohnathan Mantey     }
17134a0cb85cSEd Tanous }
17144a0cb85cSEd Tanous 
17154f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1716f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1717f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
17188d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1719f85837bfSRAJESWARAN THILLAIGOVINDAN {
17201847f2a0SAsmitha Karunanithi     setDbusProperty(
1721*e93abac6SGinu George         asyncResp, "StaticNameServers", "xyz.openbmc_project.Network",
17221847f2a0SAsmitha Karunanithi         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
17231847f2a0SAsmitha Karunanithi             ifaceId,
17249ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1725*e93abac6SGinu George         updatedStaticNameServers);
1726f85837bfSRAJESWARAN THILLAIGOVINDAN }
1727f85837bfSRAJESWARAN THILLAIGOVINDAN 
17284f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
17293dfed536SEd Tanous     const std::string& ifaceId,
17303dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
173177179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
17328d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1733e48c0fc5SRavi Teja {
1734271584abSEd Tanous     size_t entryIdx = 1;
173577179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
17362c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
17373dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
17383dfed536SEd Tanous          input)
1739e48c0fc5SRavi Teja     {
174089492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
174189492a15SPatrick Williams                                  std::to_string(entryIdx);
17423dfed536SEd Tanous         nlohmann::json::object_t* obj =
17433dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
17443dfed536SEd Tanous         if (obj != nullptr && !obj->empty())
1745e48c0fc5SRavi Teja         {
1746e48c0fc5SRavi Teja             std::optional<std::string> address;
1747e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
17483dfed536SEd Tanous             nlohmann::json::object_t thisJsonCopy = *obj;
17493dfed536SEd Tanous             if (!json_util::readJsonObject(thisJsonCopy, asyncResp->res,
17503dfed536SEd Tanous                                            "Address", address, "PrefixLength",
17513dfed536SEd Tanous                                            prefixLength))
1752e48c0fc5SRavi Teja             {
17533dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJsonCopy,
175471f52d96SEd Tanous                                                    pathString);
1755e48c0fc5SRavi Teja                 return;
1756e48c0fc5SRavi Teja             }
1757e48c0fc5SRavi Teja 
175801784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
175901784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
176001784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
176101784826SJohnathan Mantey             // current request.
1762d547d8d2SEd Tanous             if (!address)
1763e48c0fc5SRavi Teja             {
1764d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
176501784826SJohnathan Mantey                 {
176601784826SJohnathan Mantey                     messages::propertyMissing(asyncResp->res,
176701784826SJohnathan Mantey                                               pathString + "/Address");
176801784826SJohnathan Mantey                     return;
1769e48c0fc5SRavi Teja                 }
1770d547d8d2SEd Tanous                 address = nicIpEntry->address;
1771d547d8d2SEd Tanous             }
1772e48c0fc5SRavi Teja 
1773d547d8d2SEd Tanous             if (!prefixLength)
1774e48c0fc5SRavi Teja             {
1775d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
1776e48c0fc5SRavi Teja                 {
1777e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1778e48c0fc5SRavi Teja                                               pathString + "/PrefixLength");
177901784826SJohnathan Mantey                     return;
1780e48c0fc5SRavi Teja                 }
1781d547d8d2SEd Tanous                 prefixLength = nicIpEntry->prefixLength;
1782d547d8d2SEd Tanous             }
1783e48c0fc5SRavi Teja 
178485ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1785e48c0fc5SRavi Teja             {
17869c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1787d547d8d2SEd Tanous                                          nicIpEntry->id, *prefixLength,
1788d547d8d2SEd Tanous                                          *address, "", asyncResp);
178989492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
179089492a15SPatrick Williams                                                   ipv6Data.cend());
179101784826SJohnathan Mantey             }
179201784826SJohnathan Mantey             else
179301784826SJohnathan Mantey             {
1794d547d8d2SEd Tanous                 createIPv6(ifaceId, *prefixLength, *address, asyncResp);
1795e48c0fc5SRavi Teja             }
1796e48c0fc5SRavi Teja             entryIdx++;
1797e48c0fc5SRavi Teja         }
179801784826SJohnathan Mantey         else
179901784826SJohnathan Mantey         {
180085ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
180101784826SJohnathan Mantey             {
180201784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
180301784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
180401784826SJohnathan Mantey                 // in error, so bail out.
18053dfed536SEd Tanous                 if (obj == nullptr)
180601784826SJohnathan Mantey                 {
180701784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
180801784826SJohnathan Mantey                     return;
180901784826SJohnathan Mantey                 }
18103dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
181171f52d96SEd Tanous                                                    pathString);
181201784826SJohnathan Mantey                 return;
181301784826SJohnathan Mantey             }
181401784826SJohnathan Mantey 
18153dfed536SEd Tanous             if (obj == nullptr)
181601784826SJohnathan Mantey             {
18179c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
181801784826SJohnathan Mantey             }
181985ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
182001784826SJohnathan Mantey             {
182189492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
182289492a15SPatrick Williams                                                   ipv6Data.cend());
182301784826SJohnathan Mantey             }
182401784826SJohnathan Mantey             entryIdx++;
182501784826SJohnathan Mantey         }
182601784826SJohnathan Mantey     }
1827e48c0fc5SRavi Teja }
1828e48c0fc5SRavi Teja 
18297857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
18307857cb8dSJiaqing Zhao {
18317857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
18327857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
18337857cb8dSJiaqing Zhao }
18347857cb8dSJiaqing Zhao 
183577179532SEd Tanous inline void
183677179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
183777179532SEd Tanous                        const std::string& ifaceId,
183877179532SEd Tanous                        const EthernetInterfaceData& ethData,
183977179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
1840ce73d5c8SSunitha Harish                        const std::vector<IPv6AddressData>& ipv6Data,
1841ce73d5c8SSunitha Harish                        const std::vector<StaticGatewayData>& ipv6GatewayData)
18424a0cb85cSEd Tanous {
18432c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
184481ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1845253f11b8SEd Tanous     jsonResponse["@odata.id"] =
1846253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}",
1847253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId);
18482c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1849eeedda23SJohnathan Mantey 
1850eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1851eeedda23SJohnathan Mantey     {
18520ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
18532c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1854029573d4SEd Tanous     }
1855029573d4SEd Tanous     else
1856029573d4SEd Tanous     {
18572c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
18582c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1859029573d4SEd Tanous     }
1860aa05fb27SJohnathan Mantey 
18612c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
186235fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
186382695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
18642c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
186582695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1866e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1867e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1868de9ad764SRavi Teja     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled;
18692c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1870b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
18711f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1872e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1873e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1874de9ad764SRavi Teja     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled;
1875b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1876b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
18772a133282Smanojkiraneda 
187882695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
18794a0cb85cSEd Tanous     {
188082695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1881ab6554f1SJoshi-Mansi 
1882ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1883ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1884ab6554f1SJoshi-Mansi         // FQDN
188582695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1886d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1887d24bfc7aSJennifer Lee         {
18882c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1889d24bfc7aSJennifer Lee         }
18902c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
18914a0cb85cSEd Tanous     }
18924a0cb85cSEd Tanous 
18937857cb8dSJiaqing Zhao     if (ethData.vlanId)
18947857cb8dSJiaqing Zhao     {
18957857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
18967857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
18977857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
18987857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
18997857cb8dSJiaqing Zhao 
19007857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
19017857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
19027857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
1903253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
1904253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME,
19057857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
19067857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
19077857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
19087857cb8dSJiaqing Zhao     }
19097857cb8dSJiaqing Zhao     else
19107857cb8dSJiaqing Zhao     {
19117857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
19127857cb8dSJiaqing Zhao     }
19137857cb8dSJiaqing Zhao 
19142c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
19152c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
19164a0cb85cSEd Tanous 
19172c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
19182c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
19192c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
19202c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
19219eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
19224a0cb85cSEd Tanous     {
19232c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1924fa5053a6SGunnar Mills         if (gatewayStr.empty())
1925fa5053a6SGunnar Mills         {
1926fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1927fa5053a6SGunnar Mills         }
19281476687dSEd Tanous         nlohmann::json::object_t ipv4;
19291476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
19301476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
19311476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
19321476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1933fa5053a6SGunnar Mills 
19342c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1935d1d50814SRavi Teja         {
19361476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1937d1d50814SRavi Teja         }
19381476687dSEd Tanous 
1939b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
194001784826SJohnathan Mantey     }
1941d1d50814SRavi Teja 
194282695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
19437ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
19447ea79e5eSRavi Teja     {
19457ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
19467ea79e5eSRavi Teja     }
19477ea79e5eSRavi Teja 
19487ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1949e48c0fc5SRavi Teja 
1950ce73d5c8SSunitha Harish     nlohmann::json::array_t ipv6StaticGatewayArray;
1951ce73d5c8SSunitha Harish     for (const auto& ipv6GatewayConfig : ipv6GatewayData)
1952ce73d5c8SSunitha Harish     {
1953ce73d5c8SSunitha Harish         nlohmann::json::object_t ipv6Gateway;
1954ce73d5c8SSunitha Harish         ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
1955ce73d5c8SSunitha Harish         ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength;
1956ce73d5c8SSunitha Harish         ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
1957ce73d5c8SSunitha Harish     }
1958ce73d5c8SSunitha Harish     jsonResponse["IPv6StaticDefaultGateways"] =
1959ce73d5c8SSunitha Harish         std::move(ipv6StaticGatewayArray);
1960ce73d5c8SSunitha Harish 
19612c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
19622c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
19632c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
19642c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
19657f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
19662c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
19677f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
19689eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1969e48c0fc5SRavi Teja     {
19701476687dSEd Tanous         nlohmann::json::object_t ipv6;
19711476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
19721476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
19731476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1974f8361275SSunitha Harish 
1975b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
19762c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1977e48c0fc5SRavi Teja         {
19781476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
19791476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
19801476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1981b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
198201784826SJohnathan Mantey         }
1983e48c0fc5SRavi Teja     }
1984588c3f0dSKowalski, Kamil }
1985588c3f0dSKowalski, Kamil 
1986e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1987e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1988e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1989e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1990e7caf250SJiaqing Zhao {
1991e7caf250SJiaqing Zhao     if (!ec)
1992e7caf250SJiaqing Zhao     {
1993e7caf250SJiaqing Zhao         return;
1994e7caf250SJiaqing Zhao     }
1995e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
1996e7caf250SJiaqing Zhao     if (dbusError == nullptr)
1997e7caf250SJiaqing Zhao     {
1998e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
1999e7caf250SJiaqing Zhao         return;
2000e7caf250SJiaqing Zhao     }
200162598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2002e7caf250SJiaqing Zhao 
2003e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
2004e7caf250SJiaqing Zhao         dbusError->name)
2005e7caf250SJiaqing Zhao     {
2006e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2007e7caf250SJiaqing Zhao                                    ifaceId);
2008e7caf250SJiaqing Zhao         return;
2009e7caf250SJiaqing Zhao     }
2010e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
2011e7caf250SJiaqing Zhao         dbusError->name)
2012e7caf250SJiaqing Zhao     {
2013e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
2014e7caf250SJiaqing Zhao         return;
2015e7caf250SJiaqing Zhao     }
2016e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
2017e7caf250SJiaqing Zhao }
2018e7caf250SJiaqing Zhao 
2019b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2020b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
2021b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
2022b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
2023b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
2024b5ca3fdcSJiaqing Zhao 
2025b5ca3fdcSJiaqing Zhao )
2026b5ca3fdcSJiaqing Zhao {
2027b5ca3fdcSJiaqing Zhao     if (ec)
2028b5ca3fdcSJiaqing Zhao     {
2029b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
2030b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
2031b5ca3fdcSJiaqing Zhao         {
2032b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
2033b5ca3fdcSJiaqing Zhao             return;
2034b5ca3fdcSJiaqing Zhao         }
203562598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2036b5ca3fdcSJiaqing Zhao 
2037b5ca3fdcSJiaqing Zhao         if (std::string_view(
2038b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
2039b5ca3fdcSJiaqing Zhao             dbusError->name)
2040b5ca3fdcSJiaqing Zhao         {
2041b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2042b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2043b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2044b5ca3fdcSJiaqing Zhao             return;
2045b5ca3fdcSJiaqing Zhao         }
2046b5ca3fdcSJiaqing Zhao         if (std::string_view(
2047b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
2048b5ca3fdcSJiaqing Zhao             dbusError->name)
2049b5ca3fdcSJiaqing Zhao         {
2050b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
2051b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
2052b5ca3fdcSJiaqing Zhao             return;
2053b5ca3fdcSJiaqing Zhao         }
2054b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
2055b5ca3fdcSJiaqing Zhao         return;
2056b5ca3fdcSJiaqing Zhao     }
2057b5ca3fdcSJiaqing Zhao 
2058253f11b8SEd Tanous     const boost::urls::url vlanInterfaceUri =
2059253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}",
2060253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface);
2061b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
2062b5ca3fdcSJiaqing Zhao }
2063b5ca3fdcSJiaqing Zhao 
2064bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
2065bf648f77SEd Tanous {
2066253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
2067ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
20681476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
20691476687dSEd Tanous             [&app](const crow::Request& req,
2070253f11b8SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2071253f11b8SEd Tanous                    const std::string& managerId) {
20723ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
207345ca1b86SEd Tanous         {
207445ca1b86SEd Tanous             return;
207545ca1b86SEd Tanous         }
207645ca1b86SEd Tanous 
2077253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2078253f11b8SEd Tanous         {
2079253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2080253f11b8SEd Tanous             return;
2081253f11b8SEd Tanous         }
2082253f11b8SEd Tanous 
2083bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2084bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2085bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2086253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
2087253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2088bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
2089bf648f77SEd Tanous             "Ethernet Network Interface Collection";
2090bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
2091bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
2092bf648f77SEd Tanous 
2093bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
2094bf648f77SEd Tanous         // preparation
2095002d39b4SEd Tanous         getEthernetIfaceList(
209677179532SEd Tanous             [asyncResp](const bool& success,
209777179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
2098bf648f77SEd Tanous             if (!success)
20991abe55efSEd Tanous             {
2100f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
21019391bb9cSRapkiewicz, Pawel                 return;
21029391bb9cSRapkiewicz, Pawel             }
21039391bb9cSRapkiewicz, Pawel 
2104002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2105bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
2106bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
2107bf648f77SEd Tanous             {
21081476687dSEd Tanous                 nlohmann::json::object_t iface;
2109ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
2110253f11b8SEd Tanous                     "/redfish/v1/Managers/{}/EthernetInterfaces/{}",
2111253f11b8SEd Tanous                     BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem);
21127857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
2113bf648f77SEd Tanous             }
2114bf648f77SEd Tanous 
2115002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
2116253f11b8SEd Tanous             asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2117253f11b8SEd Tanous                 "/redfish/v1/Managers/{}/EthernetInterfaces",
2118253f11b8SEd Tanous                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2119bf648f77SEd Tanous         });
2120bf648f77SEd Tanous     });
2121bf648f77SEd Tanous 
2122253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
2123b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
2124b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
2125b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
2126253f11b8SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2127253f11b8SEd Tanous                    const std::string& managerId) {
2128b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2129b5ca3fdcSJiaqing Zhao         {
2130b5ca3fdcSJiaqing Zhao             return;
2131b5ca3fdcSJiaqing Zhao         }
2132b5ca3fdcSJiaqing Zhao 
2133253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2134253f11b8SEd Tanous         {
2135253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2136253f11b8SEd Tanous             return;
2137253f11b8SEd Tanous         }
2138253f11b8SEd Tanous 
2139b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
2140b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
21413dfed536SEd Tanous         std::vector<nlohmann::json::object_t> relatedInterfaces;
2142b5ca3fdcSJiaqing Zhao 
2143b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
2144b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
2145b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
2146b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
2147b5ca3fdcSJiaqing Zhao         {
2148b5ca3fdcSJiaqing Zhao             return;
2149b5ca3fdcSJiaqing Zhao         }
2150b5ca3fdcSJiaqing Zhao 
2151b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
2152b5ca3fdcSJiaqing Zhao         {
2153b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
2154b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
2155b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
2156b5ca3fdcSJiaqing Zhao             return;
2157b5ca3fdcSJiaqing Zhao         }
2158b5ca3fdcSJiaqing Zhao 
2159b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
21603dfed536SEd Tanous         if (!json_util::readJsonObject(relatedInterfaces[0], asyncResp->res,
2161b5ca3fdcSJiaqing Zhao                                        "@odata.id", parentInterfaceUri))
2162b5ca3fdcSJiaqing Zhao         {
2163b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
2164b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
2165b5ca3fdcSJiaqing Zhao             return;
2166b5ca3fdcSJiaqing Zhao         }
216762598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
2168b5ca3fdcSJiaqing Zhao 
21696fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
2170b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
2171b5ca3fdcSJiaqing Zhao         if (!parsedUri)
2172b5ca3fdcSJiaqing Zhao         {
2173b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
2174b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2175b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2176b5ca3fdcSJiaqing Zhao             return;
2177b5ca3fdcSJiaqing Zhao         }
2178b5ca3fdcSJiaqing Zhao 
2179b5ca3fdcSJiaqing Zhao         std::string parentInterface;
2180b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
2181b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
2182b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
2183b5ca3fdcSJiaqing Zhao         {
2184b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2185b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2186b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2187b5ca3fdcSJiaqing Zhao             return;
2188b5ca3fdcSJiaqing Zhao         }
2189b5ca3fdcSJiaqing Zhao 
2190b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
2191b5ca3fdcSJiaqing Zhao         {
2192b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
2193b5ca3fdcSJiaqing Zhao             // create
2194b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
2195b5ca3fdcSJiaqing Zhao                                              "false");
2196b5ca3fdcSJiaqing Zhao             return;
2197b5ca3fdcSJiaqing Zhao         }
2198b5ca3fdcSJiaqing Zhao 
2199b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
2200b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
2201b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
2202b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
2203b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
2204b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
2205b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
2206b5ca3fdcSJiaqing Zhao                             m);
2207b5ca3fdcSJiaqing Zhao         },
2208b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
2209b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
2210b5ca3fdcSJiaqing Zhao             vlanId);
2211b5ca3fdcSJiaqing Zhao     });
2212b5ca3fdcSJiaqing Zhao 
2213253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2214ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
2215bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
221645ca1b86SEd Tanous             [&app](const crow::Request& req,
2217bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2218253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
22193ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
222045ca1b86SEd Tanous         {
222145ca1b86SEd Tanous             return;
222245ca1b86SEd Tanous         }
2223253f11b8SEd Tanous 
2224253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2225253f11b8SEd Tanous         {
2226253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2227253f11b8SEd Tanous             return;
2228253f11b8SEd Tanous         }
2229253f11b8SEd Tanous 
22304a0cb85cSEd Tanous         getEthernetIfaceData(
2231bf648f77SEd Tanous             ifaceId,
2232ce73d5c8SSunitha Harish             [asyncResp,
2233ce73d5c8SSunitha Harish              ifaceId](const bool& success, const EthernetInterfaceData& ethData,
223477179532SEd Tanous                       const std::vector<IPv4AddressData>& ipv4Data,
2235ce73d5c8SSunitha Harish                       const std::vector<IPv6AddressData>& ipv6Data,
2236ce73d5c8SSunitha Harish                       const std::vector<StaticGatewayData>& ipv6GatewayData) {
22374a0cb85cSEd Tanous             if (!success)
22381abe55efSEd Tanous             {
2239bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2240bf648f77SEd Tanous                 // existing object, and other errors
2241002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2242002d39b4SEd Tanous                                            ifaceId);
22434a0cb85cSEd Tanous                 return;
22449391bb9cSRapkiewicz, Pawel             }
22454c9afe43SEd Tanous 
22460f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
224793bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
2248002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
22490f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
22500f74e643SEd Tanous                 "Management Network Interface";
22510f74e643SEd Tanous 
2252ce73d5c8SSunitha Harish             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data,
2253ce73d5c8SSunitha Harish                                ipv6GatewayData);
22549391bb9cSRapkiewicz, Pawel         });
2255bf648f77SEd Tanous     });
22569391bb9cSRapkiewicz, Pawel 
2257253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2258ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2259bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
226045ca1b86SEd Tanous             [&app](const crow::Request& req,
2261bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2262253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
22633ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
226445ca1b86SEd Tanous         {
226545ca1b86SEd Tanous             return;
226645ca1b86SEd Tanous         }
2267253f11b8SEd Tanous 
2268253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2269253f11b8SEd Tanous         {
2270253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2271253f11b8SEd Tanous             return;
2272253f11b8SEd Tanous         }
2273253f11b8SEd Tanous 
2274bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2275ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2276d577665bSRatan Gupta         std::optional<std::string> macAddress;
22779a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
22783dfed536SEd Tanous         std::optional<
22793dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
22803dfed536SEd Tanous             ipv4StaticAddresses;
22813dfed536SEd Tanous         std::optional<
22823dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
22833dfed536SEd Tanous             ipv6StaticAddresses;
22843dfed536SEd Tanous         std::optional<
22853dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
22863dfed536SEd Tanous             ipv6StaticDefaultGateways;
2287f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2288b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2289eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
229035fb5311STejas Patil         std::optional<size_t> mtuSize;
22911f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
22921f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2293b10d8db0SRavi Teja         // clang-format off
22943dfed536SEd Tanous         if (!json_util::readJsonPatch(req, asyncResp->res,
22953dfed536SEd Tanous                 "DHCPv4/DHCPEnabled",   v4dhcpParms.dhcpv4Enabled,
22963dfed536SEd Tanous                 "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers,
22973dfed536SEd Tanous                 "DHCPv4/UseDomainName", v4dhcpParms.useDomainName,
22983dfed536SEd Tanous                 "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers,
22993dfed536SEd Tanous                 "DHCPv6/OperatingMode", v6dhcpParms.dhcpv6OperatingMode,
23003dfed536SEd Tanous                 "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers,
23013dfed536SEd Tanous                 "DHCPv6/UseDomainName", v6dhcpParms.useDomainName,
23023dfed536SEd Tanous                 "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers,
2303b10d8db0SRavi Teja                 "FQDN", fqdn,
2304b10d8db0SRavi Teja                 "HostName", hostname,
2305b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2306b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2307b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2308ce73d5c8SSunitha Harish                 "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways,
2309b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2310b10d8db0SRavi Teja                 "MACAddress", macAddress,
2311b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2312b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2313b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2314b10d8db0SRavi Teja                 )
2315b10d8db0SRavi Teja             )
23161abe55efSEd Tanous         {
2317588c3f0dSKowalski, Kamil             return;
2318588c3f0dSKowalski, Kamil         }
2319b10d8db0SRavi Teja         // clang-format on
2320da131a9aSJennifer Lee 
2321bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2322bf648f77SEd Tanous         // for JSON preparation
23234a0cb85cSEd Tanous         getEthernetIfaceData(
23242c70f800SEd Tanous             ifaceId,
2325bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2326ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2327d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
23289a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2329e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2330ce73d5c8SSunitha Harish              ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways),
23313dfed536SEd Tanous              staticNameServers = std::move(staticNameServers), mtuSize,
2332b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2333f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
23343dfed536SEd Tanous                 const bool success, const EthernetInterfaceData& ethData,
233577179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
2336ce73d5c8SSunitha Harish                 const std::vector<IPv6AddressData>& ipv6Data,
23373dfed536SEd Tanous                 const std::vector<StaticGatewayData>& ipv6GatewayData) mutable {
23381abe55efSEd Tanous             if (!success)
23391abe55efSEd Tanous             {
2340588c3f0dSKowalski, Kamil                 // ... otherwise return error
2341bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2342bf648f77SEd Tanous                 // existing object, and other errors
2343002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2344002d39b4SEd Tanous                                            ifaceId);
2345588c3f0dSKowalski, Kamil                 return;
2346588c3f0dSKowalski, Kamil             }
2347588c3f0dSKowalski, Kamil 
2348002d39b4SEd Tanous             handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2349002d39b4SEd Tanous                             asyncResp);
23501f8c7b5dSJohnathan Mantey 
23510627a2c7SEd Tanous             if (hostname)
23521abe55efSEd Tanous             {
23530627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
23541abe55efSEd Tanous             }
23550627a2c7SEd Tanous 
2356b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2357b10d8db0SRavi Teja             {
2358b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2359b10d8db0SRavi Teja                                            asyncResp);
2360b10d8db0SRavi Teja             }
2361b10d8db0SRavi Teja 
2362ab6554f1SJoshi-Mansi             if (fqdn)
2363ab6554f1SJoshi-Mansi             {
23642c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2365ab6554f1SJoshi-Mansi             }
2366ab6554f1SJoshi-Mansi 
2367d577665bSRatan Gupta             if (macAddress)
2368d577665bSRatan Gupta             {
2369002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2370d577665bSRatan Gupta             }
2371d577665bSRatan Gupta 
2372d1d50814SRavi Teja             if (ipv4StaticAddresses)
2373d1d50814SRavi Teja             {
2374743eb1c0SJohnathan Mantey                 handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ethData,
2375743eb1c0SJohnathan Mantey                                       ipv4Data, asyncResp);
23761abe55efSEd Tanous             }
23770627a2c7SEd Tanous 
2378f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2379f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2380002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2381002d39b4SEd Tanous                                              asyncResp);
2382f85837bfSRAJESWARAN THILLAIGOVINDAN             }
23839a6fc6feSRavi Teja 
23849a6fc6feSRavi Teja             if (ipv6DefaultGateway)
23859a6fc6feSRavi Teja             {
23869a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
23879a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
23889a6fc6feSRavi Teja             }
2389e48c0fc5SRavi Teja 
2390e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2391e48c0fc5SRavi Teja             {
2392ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2393ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2394e48c0fc5SRavi Teja             }
2395eeedda23SJohnathan Mantey 
2396ce73d5c8SSunitha Harish             if (ipv6StaticDefaultGateway)
2397ce73d5c8SSunitha Harish             {
2398ce73d5c8SSunitha Harish                 handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway,
2399ce73d5c8SSunitha Harish                                          ipv6GatewayData, asyncResp);
2400ce73d5c8SSunitha Harish             }
2401ce73d5c8SSunitha Harish 
2402eeedda23SJohnathan Mantey             if (interfaceEnabled)
2403eeedda23SJohnathan Mantey             {
2404*e93abac6SGinu George                 setDbusProperty(asyncResp, "InterfaceEnabled",
2405*e93abac6SGinu George                                 "xyz.openbmc_project.Network",
2406d02aad39SEd Tanous                                 sdbusplus::message::object_path(
2407d02aad39SEd Tanous                                     "/xyz/openbmc_project/network") /
2408d02aad39SEd Tanous                                     ifaceId,
2409d02aad39SEd Tanous                                 "xyz.openbmc_project.Network.EthernetInterface",
2410*e93abac6SGinu George                                 "NICEnabled", *interfaceEnabled);
2411eeedda23SJohnathan Mantey             }
241235fb5311STejas Patil 
241335fb5311STejas Patil             if (mtuSize)
241435fb5311STejas Patil             {
241535fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
241635fb5311STejas Patil             }
2417588c3f0dSKowalski, Kamil         });
2418bf648f77SEd Tanous     });
2419e7caf250SJiaqing Zhao 
2420253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2421e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2422e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2423e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2424e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2425253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
2426e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2427e7caf250SJiaqing Zhao         {
2428e7caf250SJiaqing Zhao             return;
2429e7caf250SJiaqing Zhao         }
2430e7caf250SJiaqing Zhao 
2431253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2432253f11b8SEd Tanous         {
2433253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2434253f11b8SEd Tanous             return;
2435253f11b8SEd Tanous         }
2436253f11b8SEd Tanous 
2437e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2438e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2439e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2440e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2441e7caf250SJiaqing Zhao         },
2442e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2443e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2444e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2445e7caf250SJiaqing Zhao     });
24464a0cb85cSEd Tanous }
2447bf648f77SEd Tanous 
24489391bb9cSRapkiewicz, Pawel } // namespace redfish
2449