xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision 539d8c6bc399e516d39bcaa18262cf206f4c1035)
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"
22*539d8c6bSEd Tanous #include "generated/enums/ethernet_interface.hpp"
23*539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
242c5875a2SEd Tanous #include "human_sort.hpp"
253ccb3adbSEd Tanous #include "query.hpp"
263ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
27033f1e4dSEd Tanous #include "utils/ip_utils.hpp"
283ccb3adbSEd Tanous #include "utils/json_utils.hpp"
29033f1e4dSEd Tanous 
30ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp>
31ef4c65b7SEd Tanous #include <boost/url/format.hpp>
321214b7e7SGunnar Mills 
337a1dbc48SGeorge Liu #include <array>
343dfed536SEd Tanous #include <cstddef>
35ce73d5c8SSunitha Harish #include <memory>
36a24526dcSEd Tanous #include <optional>
373544d2a7SEd Tanous #include <ranges>
38ab6554f1SJoshi-Mansi #include <regex>
397a1dbc48SGeorge Liu #include <string_view>
403dfed536SEd Tanous #include <variant>
4177179532SEd Tanous #include <vector>
429391bb9cSRapkiewicz, Pawel 
431abe55efSEd Tanous namespace redfish
441abe55efSEd Tanous {
459391bb9cSRapkiewicz, Pawel 
464a0cb85cSEd Tanous enum class LinkType
474a0cb85cSEd Tanous {
484a0cb85cSEd Tanous     Local,
494a0cb85cSEd Tanous     Global
504a0cb85cSEd Tanous };
519391bb9cSRapkiewicz, Pawel 
52743eb1c0SJohnathan Mantey enum class IpVersion
53743eb1c0SJohnathan Mantey {
54743eb1c0SJohnathan Mantey     IpV4,
55743eb1c0SJohnathan Mantey     IpV6
56743eb1c0SJohnathan Mantey };
57743eb1c0SJohnathan Mantey 
589391bb9cSRapkiewicz, Pawel /**
599391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
609391bb9cSRapkiewicz, Pawel  */
611abe55efSEd Tanous struct IPv4AddressData
621abe55efSEd Tanous {
63179db1d7SKowalski, Kamil     std::string id;
644a0cb85cSEd Tanous     std::string address;
654a0cb85cSEd Tanous     std::string domain;
664a0cb85cSEd Tanous     std::string gateway;
679391bb9cSRapkiewicz, Pawel     std::string netmask;
689391bb9cSRapkiewicz, Pawel     std::string origin;
6977179532SEd Tanous     LinkType linktype{};
7077179532SEd Tanous     bool isActive{};
719391bb9cSRapkiewicz, Pawel };
729391bb9cSRapkiewicz, Pawel 
739391bb9cSRapkiewicz, Pawel /**
74e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
75e48c0fc5SRavi Teja  */
76e48c0fc5SRavi Teja struct IPv6AddressData
77e48c0fc5SRavi Teja {
78e48c0fc5SRavi Teja     std::string id;
79e48c0fc5SRavi Teja     std::string address;
80e48c0fc5SRavi Teja     std::string origin;
8177179532SEd Tanous     uint8_t prefixLength = 0;
82e48c0fc5SRavi Teja };
83ce73d5c8SSunitha Harish 
84ce73d5c8SSunitha Harish /**
85ce73d5c8SSunitha Harish  * Structure for keeping static route data required by Redfish
86ce73d5c8SSunitha Harish  */
87ce73d5c8SSunitha Harish struct StaticGatewayData
88ce73d5c8SSunitha Harish {
89ce73d5c8SSunitha Harish     std::string id;
90ce73d5c8SSunitha Harish     std::string gateway;
91ce73d5c8SSunitha Harish     size_t prefixLength = 0;
92ce73d5c8SSunitha Harish     std::string protocol;
93ce73d5c8SSunitha Harish };
94ce73d5c8SSunitha Harish 
95e48c0fc5SRavi Teja /**
969391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
979391bb9cSRapkiewicz, Pawel  * available from DBus
989391bb9cSRapkiewicz, Pawel  */
991abe55efSEd Tanous struct EthernetInterfaceData
1001abe55efSEd Tanous {
1014a0cb85cSEd Tanous     uint32_t speed;
10235fb5311STejas Patil     size_t mtuSize;
10382695a5bSJiaqing Zhao     bool autoNeg;
104e4588158SJishnu CM     bool dnsv4Enabled;
105e4588158SJishnu CM     bool dnsv6Enabled;
10691c441ecSRavi Teja     bool domainv4Enabled;
10791c441ecSRavi Teja     bool domainv6Enabled;
108e4588158SJishnu CM     bool ntpv4Enabled;
109e4588158SJishnu CM     bool ntpv6Enabled;
110e4588158SJishnu CM     bool hostNamev4Enabled;
111e4588158SJishnu CM     bool hostNamev6Enabled;
112aa05fb27SJohnathan Mantey     bool linkUp;
113eeedda23SJohnathan Mantey     bool nicEnabled;
114b10d8db0SRavi Teja     bool ipv6AcceptRa;
11582695a5bSJiaqing Zhao     std::string dhcpEnabled;
1161f8c7b5dSJohnathan Mantey     std::string operatingMode;
11782695a5bSJiaqing Zhao     std::string hostName;
11882695a5bSJiaqing Zhao     std::string defaultGateway;
11982695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
120ce73d5c8SSunitha Harish     std::string ipv6StaticDefaultGateway;
12182695a5bSJiaqing Zhao     std::string macAddress;
12217e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
1230f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1240f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
125d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1269391bb9cSRapkiewicz, Pawel };
1279391bb9cSRapkiewicz, Pawel 
1281f8c7b5dSJohnathan Mantey struct DHCPParameters
1291f8c7b5dSJohnathan Mantey {
1301f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
13182695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
13282695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
13382695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1341f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1351f8c7b5dSJohnathan Mantey };
1361f8c7b5dSJohnathan Mantey 
1379391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1389391bb9cSRapkiewicz, Pawel // into full dot notation
1391abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1401abe55efSEd Tanous {
1419391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1429391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1439391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1449391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1459391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1469391bb9cSRapkiewicz, Pawel     return netmask;
1479391bb9cSRapkiewicz, Pawel }
1489391bb9cSRapkiewicz, Pawel 
14982695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1501f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1511f8c7b5dSJohnathan Mantey {
1521f8c7b5dSJohnathan Mantey     if (isIPv4)
1531f8c7b5dSJohnathan Mantey     {
1541f8c7b5dSJohnathan Mantey         return (
1551f8c7b5dSJohnathan Mantey             (inputDHCP ==
1561f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1571f8c7b5dSJohnathan Mantey             (inputDHCP ==
1581f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1591f8c7b5dSJohnathan Mantey     }
1601f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1611f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1621f8c7b5dSJohnathan Mantey             (inputDHCP ==
1631f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1641f8c7b5dSJohnathan Mantey }
1651f8c7b5dSJohnathan Mantey 
1662c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1671f8c7b5dSJohnathan Mantey {
1681f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1691f8c7b5dSJohnathan Mantey     {
1701f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1711f8c7b5dSJohnathan Mantey     }
1723174e4dfSEd Tanous     if (isIPv4)
1731f8c7b5dSJohnathan Mantey     {
1741f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1751f8c7b5dSJohnathan Mantey     }
1763174e4dfSEd Tanous     if (isIPv6)
1771f8c7b5dSJohnathan Mantey     {
1781f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1791f8c7b5dSJohnathan Mantey     }
1801f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1811f8c7b5dSJohnathan Mantey }
1821f8c7b5dSJohnathan Mantey 
1834a0cb85cSEd Tanous inline std::string
1844a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1854a0cb85cSEd Tanous                                         bool isIPv4)
1861abe55efSEd Tanous {
1874a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1881abe55efSEd Tanous     {
1894a0cb85cSEd Tanous         return "Static";
1909391bb9cSRapkiewicz, Pawel     }
1914a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1921abe55efSEd Tanous     {
1934a0cb85cSEd Tanous         if (isIPv4)
1941abe55efSEd Tanous         {
1954a0cb85cSEd Tanous             return "IPv4LinkLocal";
1961abe55efSEd Tanous         }
1974a0cb85cSEd Tanous         return "LinkLocal";
1989391bb9cSRapkiewicz, Pawel     }
1994a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
2001abe55efSEd Tanous     {
2014a0cb85cSEd Tanous         if (isIPv4)
2024a0cb85cSEd Tanous         {
2034a0cb85cSEd Tanous             return "DHCP";
2044a0cb85cSEd Tanous         }
2054a0cb85cSEd Tanous         return "DHCPv6";
2064a0cb85cSEd Tanous     }
2074a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
2084a0cb85cSEd Tanous     {
2094a0cb85cSEd Tanous         return "SLAAC";
2104a0cb85cSEd Tanous     }
2114a0cb85cSEd Tanous     return "";
2124a0cb85cSEd Tanous }
2134a0cb85cSEd Tanous 
21402cad96eSEd Tanous inline bool extractEthernetInterfaceData(
21502cad96eSEd Tanous     const std::string& ethifaceId,
21602cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
2174a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
2184a0cb85cSEd Tanous {
2194c9afe43SEd Tanous     bool idFound = false;
22002cad96eSEd Tanous     for (const auto& objpath : dbusData)
2214a0cb85cSEd Tanous     {
22202cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
2234a0cb85cSEd Tanous         {
22481ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
225029573d4SEd Tanous             {
2264c9afe43SEd Tanous                 idFound = true;
2274a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2284a0cb85cSEd Tanous                 {
2294a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2304a0cb85cSEd Tanous                     {
2314a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2324a0cb85cSEd Tanous                         {
2334a0cb85cSEd Tanous                             const std::string* mac =
234abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2354a0cb85cSEd Tanous                             if (mac != nullptr)
2364a0cb85cSEd Tanous                             {
23782695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2384a0cb85cSEd Tanous                             }
2394a0cb85cSEd Tanous                         }
2404a0cb85cSEd Tanous                     }
2414a0cb85cSEd Tanous                 }
2424a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2434a0cb85cSEd Tanous                 {
2444a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2454a0cb85cSEd Tanous                     {
2464a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2474a0cb85cSEd Tanous                         {
2481b6b96c5SEd Tanous                             const uint32_t* id =
249abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2504a0cb85cSEd Tanous                             if (id != nullptr)
2514a0cb85cSEd Tanous                             {
25217e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2534a0cb85cSEd Tanous                             }
2544a0cb85cSEd Tanous                         }
2554a0cb85cSEd Tanous                     }
2564a0cb85cSEd Tanous                 }
2574a0cb85cSEd Tanous                 else if (ifacePair.first ==
2584a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2594a0cb85cSEd Tanous                 {
2604a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2614a0cb85cSEd Tanous                     {
2624a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2634a0cb85cSEd Tanous                         {
2642c70f800SEd Tanous                             const bool* autoNeg =
265abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2662c70f800SEd Tanous                             if (autoNeg != nullptr)
2674a0cb85cSEd Tanous                             {
26882695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2694a0cb85cSEd Tanous                             }
2704a0cb85cSEd Tanous                         }
2714a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2724a0cb85cSEd Tanous                         {
2734a0cb85cSEd Tanous                             const uint32_t* speed =
274abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2754a0cb85cSEd Tanous                             if (speed != nullptr)
2764a0cb85cSEd Tanous                             {
2774a0cb85cSEd Tanous                                 ethData.speed = *speed;
2784a0cb85cSEd Tanous                             }
2794a0cb85cSEd Tanous                         }
28035fb5311STejas Patil                         else if (propertyPair.first == "MTU")
28135fb5311STejas Patil                         {
2823e7a8da6SAnthony                             const size_t* mtuSize =
2833e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
28435fb5311STejas Patil                             if (mtuSize != nullptr)
28535fb5311STejas Patil                             {
28635fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
28735fb5311STejas Patil                             }
28835fb5311STejas Patil                         }
289aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
290aa05fb27SJohnathan Mantey                         {
291aa05fb27SJohnathan Mantey                             const bool* linkUp =
292aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
293aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
294aa05fb27SJohnathan Mantey                             {
295aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
296aa05fb27SJohnathan Mantey                             }
297aa05fb27SJohnathan Mantey                         }
298eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
299eeedda23SJohnathan Mantey                         {
300eeedda23SJohnathan Mantey                             const bool* nicEnabled =
301eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
302eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
303eeedda23SJohnathan Mantey                             {
304eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
305eeedda23SJohnathan Mantey                             }
306eeedda23SJohnathan Mantey                         }
307b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
308b10d8db0SRavi Teja                         {
309b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
310b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
311b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
312b10d8db0SRavi Teja                             {
313b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
314b10d8db0SRavi Teja                             }
315b10d8db0SRavi Teja                         }
316f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
317029573d4SEd Tanous                         {
318029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
3198d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
320029573d4SEd Tanous                                     &propertyPair.second);
321029573d4SEd Tanous                             if (nameservers != nullptr)
322029573d4SEd Tanous                             {
323f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3240f6efdc1Smanojkiran.eda@gmail.com                             }
3250f6efdc1Smanojkiran.eda@gmail.com                         }
3260f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3270f6efdc1Smanojkiran.eda@gmail.com                         {
3280f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3298d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3300f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3310f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3320f6efdc1Smanojkiran.eda@gmail.com                             {
333f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3344a0cb85cSEd Tanous                             }
3354a0cb85cSEd Tanous                         }
3362a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3372a133282Smanojkiraneda                         {
3382c70f800SEd Tanous                             const std::string* dhcpEnabled =
3391f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3402c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3412a133282Smanojkiraneda                             {
34282695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3432a133282Smanojkiraneda                             }
3442a133282Smanojkiraneda                         }
345d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
346d24bfc7aSJennifer Lee                         {
347d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3488d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
349d24bfc7aSJennifer Lee                                     &propertyPair.second);
350d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
351d24bfc7aSJennifer Lee                             {
352f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
353d24bfc7aSJennifer Lee                             }
354d24bfc7aSJennifer Lee                         }
3559010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3569010ec2eSRavi Teja                         {
3579010ec2eSRavi Teja                             const std::string* defaultGateway =
3589010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3599010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3609010ec2eSRavi Teja                             {
3619010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3629010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3639010ec2eSRavi Teja                                 {
36482695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3659010ec2eSRavi Teja                                 }
3669010ec2eSRavi Teja                                 else
3679010ec2eSRavi Teja                                 {
36882695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3699010ec2eSRavi Teja                                 }
3709010ec2eSRavi Teja                             }
3719010ec2eSRavi Teja                         }
3729010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3739010ec2eSRavi Teja                         {
3749010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3759010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3769010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3779010ec2eSRavi Teja                             {
3789010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3799010ec2eSRavi Teja                                     *defaultGateway6;
3809010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3819010ec2eSRavi Teja                                 {
38282695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3839010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3849010ec2eSRavi Teja                                 }
3859010ec2eSRavi Teja                                 else
3869010ec2eSRavi Teja                                 {
38782695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3889010ec2eSRavi Teja                                         defaultGateway6Str;
3899010ec2eSRavi Teja                                 }
3909010ec2eSRavi Teja                             }
3919010ec2eSRavi Teja                         }
392029573d4SEd Tanous                     }
393029573d4SEd Tanous                 }
394029573d4SEd Tanous             }
3951f8c7b5dSJohnathan Mantey 
396e4588158SJishnu CM             sdbusplus::message::object_path path(
397e4588158SJishnu CM                 "/xyz/openbmc_project/network");
398e4588158SJishnu CM             sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
399e4588158SJishnu CM                                                         "dhcp4";
400e4588158SJishnu CM 
401e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
4021f8c7b5dSJohnathan Mantey             {
4031f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
4041f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
4051f8c7b5dSJohnathan Mantey                 {
4061f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
4071f8c7b5dSJohnathan Mantey                     {
4081f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
4091f8c7b5dSJohnathan Mantey                         {
4102c70f800SEd Tanous                             const bool* dnsEnabled =
4111f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4122c70f800SEd Tanous                             if (dnsEnabled != nullptr)
4131f8c7b5dSJohnathan Mantey                             {
414e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
4151f8c7b5dSJohnathan Mantey                             }
4161f8c7b5dSJohnathan Mantey                         }
41791c441ecSRavi Teja                         else if (propertyPair.first == "DomainEnabled")
41891c441ecSRavi Teja                         {
41991c441ecSRavi Teja                             const bool* domainEnabled =
42091c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
42191c441ecSRavi Teja                             if (domainEnabled != nullptr)
42291c441ecSRavi Teja                             {
42391c441ecSRavi Teja                                 ethData.domainv4Enabled = *domainEnabled;
42491c441ecSRavi Teja                             }
42591c441ecSRavi Teja                         }
4261f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
4271f8c7b5dSJohnathan Mantey                         {
4282c70f800SEd Tanous                             const bool* ntpEnabled =
4291f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4302c70f800SEd Tanous                             if (ntpEnabled != nullptr)
4311f8c7b5dSJohnathan Mantey                             {
432e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4331f8c7b5dSJohnathan Mantey                             }
4341f8c7b5dSJohnathan Mantey                         }
4351f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4361f8c7b5dSJohnathan Mantey                         {
4372c70f800SEd Tanous                             const bool* hostNameEnabled =
4381f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4392c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4401f8c7b5dSJohnathan Mantey                             {
441e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
442e4588158SJishnu CM                             }
443e4588158SJishnu CM                         }
444e4588158SJishnu CM                     }
445e4588158SJishnu CM                 }
446e4588158SJishnu CM             }
447e4588158SJishnu CM 
448e4588158SJishnu CM             sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
449e4588158SJishnu CM                                                         "dhcp6";
450e4588158SJishnu CM 
451e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
452e4588158SJishnu CM             {
453e4588158SJishnu CM                 if (ifacePair.first ==
454e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
455e4588158SJishnu CM                 {
456e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
457e4588158SJishnu CM                     {
458e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
459e4588158SJishnu CM                         {
460e4588158SJishnu CM                             const bool* dnsEnabled =
461e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
462e4588158SJishnu CM                             if (dnsEnabled != nullptr)
463e4588158SJishnu CM                             {
464e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
465e4588158SJishnu CM                             }
466e4588158SJishnu CM                         }
46791c441ecSRavi Teja                         if (propertyPair.first == "DomainEnabled")
46891c441ecSRavi Teja                         {
46991c441ecSRavi Teja                             const bool* domainEnabled =
47091c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
47191c441ecSRavi Teja                             if (domainEnabled != nullptr)
47291c441ecSRavi Teja                             {
47391c441ecSRavi Teja                                 ethData.domainv6Enabled = *domainEnabled;
47491c441ecSRavi Teja                             }
47591c441ecSRavi Teja                         }
476e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
477e4588158SJishnu CM                         {
478e4588158SJishnu CM                             const bool* ntpEnabled =
479e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
480e4588158SJishnu CM                             if (ntpEnabled != nullptr)
481e4588158SJishnu CM                             {
482e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
483e4588158SJishnu CM                             }
484e4588158SJishnu CM                         }
485e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
486e4588158SJishnu CM                         {
487e4588158SJishnu CM                             const bool* hostNameEnabled =
488e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
489e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
490e4588158SJishnu CM                             {
491e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
4921f8c7b5dSJohnathan Mantey                             }
4931f8c7b5dSJohnathan Mantey                         }
4941f8c7b5dSJohnathan Mantey                     }
4951f8c7b5dSJohnathan Mantey                 }
4961f8c7b5dSJohnathan Mantey             }
497029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
498029573d4SEd Tanous             // to check eth number
499029573d4SEd Tanous             if (ifacePair.first ==
5004a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
5014a0cb85cSEd Tanous             {
5024a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
5034a0cb85cSEd Tanous                 {
5044a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
5054a0cb85cSEd Tanous                     {
5064a0cb85cSEd Tanous                         const std::string* hostname =
5078d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
5084a0cb85cSEd Tanous                         if (hostname != nullptr)
5094a0cb85cSEd Tanous                         {
51082695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
5114a0cb85cSEd Tanous                         }
5124a0cb85cSEd Tanous                     }
5134a0cb85cSEd Tanous                 }
5144a0cb85cSEd Tanous             }
5154a0cb85cSEd Tanous         }
5164a0cb85cSEd Tanous     }
5174c9afe43SEd Tanous     return idFound;
5184a0cb85cSEd Tanous }
5194a0cb85cSEd Tanous 
520e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
52177179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
522711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
52377179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
524e48c0fc5SRavi Teja {
52589492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
52689492a15SPatrick Williams                                     ethifaceId;
527e48c0fc5SRavi Teja 
528e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
529e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
53081ce609eSEd Tanous     for (const auto& objpath : dbusData)
531e48c0fc5SRavi Teja     {
532e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
533353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
534e48c0fc5SRavi Teja         {
5359eb808c1SEd Tanous             for (const auto& interface : objpath.second)
536e48c0fc5SRavi Teja             {
537e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
538e48c0fc5SRavi Teja                 {
5393544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
540353163e9STony Lee                                                      [](const auto& property) {
541353163e9STony Lee                         return property.first == "Type";
542353163e9STony Lee                     });
543353163e9STony Lee                     if (type == interface.second.end())
544353163e9STony Lee                     {
545353163e9STony Lee                         continue;
546353163e9STony Lee                     }
547353163e9STony Lee 
548353163e9STony Lee                     const std::string* typeStr =
549353163e9STony Lee                         std::get_if<std::string>(&type->second);
550353163e9STony Lee 
551353163e9STony Lee                     if (typeStr == nullptr ||
552353163e9STony Lee                         (*typeStr !=
553353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
554353163e9STony Lee                     {
555353163e9STony Lee                         continue;
556353163e9STony Lee                     }
557353163e9STony Lee 
558e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
559e48c0fc5SRavi Teja                     // appropriate
56077179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5612c70f800SEd Tanous                     ipv6Address.id =
562353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5639eb808c1SEd Tanous                     for (const auto& property : interface.second)
564e48c0fc5SRavi Teja                     {
565e48c0fc5SRavi Teja                         if (property.first == "Address")
566e48c0fc5SRavi Teja                         {
567e48c0fc5SRavi Teja                             const std::string* address =
568e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
569e48c0fc5SRavi Teja                             if (address != nullptr)
570e48c0fc5SRavi Teja                             {
5712c70f800SEd Tanous                                 ipv6Address.address = *address;
572e48c0fc5SRavi Teja                             }
573e48c0fc5SRavi Teja                         }
574e48c0fc5SRavi Teja                         else if (property.first == "Origin")
575e48c0fc5SRavi Teja                         {
576e48c0fc5SRavi Teja                             const std::string* origin =
577e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
578e48c0fc5SRavi Teja                             if (origin != nullptr)
579e48c0fc5SRavi Teja                             {
5802c70f800SEd Tanous                                 ipv6Address.origin =
581e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
582e48c0fc5SRavi Teja                                                                         false);
583e48c0fc5SRavi Teja                             }
584e48c0fc5SRavi Teja                         }
585e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
586e48c0fc5SRavi Teja                         {
587e48c0fc5SRavi Teja                             const uint8_t* prefix =
588e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
589e48c0fc5SRavi Teja                             if (prefix != nullptr)
590e48c0fc5SRavi Teja                             {
5912c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
592e48c0fc5SRavi Teja                             }
593e48c0fc5SRavi Teja                         }
594889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
595889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
596889ff694SAsmitha Karunanithi                         {
597889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
598889ff694SAsmitha Karunanithi                         }
599e48c0fc5SRavi Teja                         else
600e48c0fc5SRavi Teja                         {
60162598e31SEd Tanous                             BMCWEB_LOG_ERROR(
60262598e31SEd Tanous                                 "Got extra property: {} on the {} object",
60362598e31SEd Tanous                                 property.first, objpath.first.str);
604e48c0fc5SRavi Teja                         }
605e48c0fc5SRavi Teja                     }
606e48c0fc5SRavi Teja                 }
607e48c0fc5SRavi Teja             }
608e48c0fc5SRavi Teja         }
609e48c0fc5SRavi Teja     }
610e48c0fc5SRavi Teja }
611e48c0fc5SRavi Teja 
6124a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
61377179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
614711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
61577179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
6164a0cb85cSEd Tanous {
61789492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
61889492a15SPatrick Williams                                     ethifaceId;
6194a0cb85cSEd Tanous 
6204a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
6214a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
62281ce609eSEd Tanous     for (const auto& objpath : dbusData)
6234a0cb85cSEd Tanous     {
6244a0cb85cSEd Tanous         // Check if proper pattern for object path appears
625353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
6264a0cb85cSEd Tanous         {
6279eb808c1SEd Tanous             for (const auto& interface : objpath.second)
6284a0cb85cSEd Tanous             {
6294a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
6304a0cb85cSEd Tanous                 {
6313544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
632353163e9STony Lee                                                      [](const auto& property) {
633353163e9STony Lee                         return property.first == "Type";
634353163e9STony Lee                     });
635353163e9STony Lee                     if (type == interface.second.end())
636353163e9STony Lee                     {
637353163e9STony Lee                         continue;
638353163e9STony Lee                     }
639353163e9STony Lee 
640353163e9STony Lee                     const std::string* typeStr =
641353163e9STony Lee                         std::get_if<std::string>(&type->second);
642353163e9STony Lee 
643353163e9STony Lee                     if (typeStr == nullptr ||
644353163e9STony Lee                         (*typeStr !=
645353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
646353163e9STony Lee                     {
647353163e9STony Lee                         continue;
648353163e9STony Lee                     }
649353163e9STony Lee 
6504a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6514a0cb85cSEd Tanous                     // appropriate
65277179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6532c70f800SEd Tanous                     ipv4Address.id =
654353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6559eb808c1SEd Tanous                     for (const auto& property : interface.second)
6564a0cb85cSEd Tanous                     {
6574a0cb85cSEd Tanous                         if (property.first == "Address")
6584a0cb85cSEd Tanous                         {
6594a0cb85cSEd Tanous                             const std::string* address =
660abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6614a0cb85cSEd Tanous                             if (address != nullptr)
6624a0cb85cSEd Tanous                             {
6632c70f800SEd Tanous                                 ipv4Address.address = *address;
6644a0cb85cSEd Tanous                             }
6654a0cb85cSEd Tanous                         }
6664a0cb85cSEd Tanous                         else if (property.first == "Origin")
6674a0cb85cSEd Tanous                         {
6684a0cb85cSEd Tanous                             const std::string* origin =
669abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6704a0cb85cSEd Tanous                             if (origin != nullptr)
6714a0cb85cSEd Tanous                             {
6722c70f800SEd Tanous                                 ipv4Address.origin =
6734a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6744a0cb85cSEd Tanous                                                                         true);
6754a0cb85cSEd Tanous                             }
6764a0cb85cSEd Tanous                         }
6774a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6784a0cb85cSEd Tanous                         {
6794a0cb85cSEd Tanous                             const uint8_t* mask =
680abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6814a0cb85cSEd Tanous                             if (mask != nullptr)
6824a0cb85cSEd Tanous                             {
6834a0cb85cSEd Tanous                                 // convert it to the string
6842c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6854a0cb85cSEd Tanous                             }
6864a0cb85cSEd Tanous                         }
687889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
688889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
689889ff694SAsmitha Karunanithi                         {
690889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
691889ff694SAsmitha Karunanithi                         }
6924a0cb85cSEd Tanous                         else
6934a0cb85cSEd Tanous                         {
69462598e31SEd Tanous                             BMCWEB_LOG_ERROR(
69562598e31SEd Tanous                                 "Got extra property: {} on the {} object",
69662598e31SEd Tanous                                 property.first, objpath.first.str);
6974a0cb85cSEd Tanous                         }
6984a0cb85cSEd Tanous                     }
6994a0cb85cSEd Tanous                     // Check if given address is local, or global
7002c70f800SEd Tanous                     ipv4Address.linktype =
70111ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
70218659d10SJohnathan Mantey                             ? LinkType::Local
70318659d10SJohnathan Mantey                             : LinkType::Global;
7044a0cb85cSEd Tanous                 }
7054a0cb85cSEd Tanous             }
7064a0cb85cSEd Tanous         }
7074a0cb85cSEd Tanous     }
7084a0cb85cSEd Tanous }
709588c3f0dSKowalski, Kamil 
710588c3f0dSKowalski, Kamil /**
711743eb1c0SJohnathan Mantey  * @brief Modifies the default gateway assigned to the NIC
712743eb1c0SJohnathan Mantey  *
713743eb1c0SJohnathan Mantey  * @param[in] ifaceId     Id of network interface whose default gateway is to be
714743eb1c0SJohnathan Mantey  *                        changed
715743eb1c0SJohnathan Mantey  * @param[in] gateway     The new gateway value. Assigning an empty string
716743eb1c0SJohnathan Mantey  *                        causes the gateway to be deleted
717743eb1c0SJohnathan Mantey  * @param[io] asyncResp   Response object that will be returned to client
718743eb1c0SJohnathan Mantey  *
719743eb1c0SJohnathan Mantey  * @return None
720743eb1c0SJohnathan Mantey  */
721743eb1c0SJohnathan Mantey inline void updateIPv4DefaultGateway(
722743eb1c0SJohnathan Mantey     const std::string& ifaceId, const std::string& gateway,
723743eb1c0SJohnathan Mantey     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
724743eb1c0SJohnathan Mantey {
725743eb1c0SJohnathan Mantey     setDbusProperty(
726e93abac6SGinu George         asyncResp, "Gateway", "xyz.openbmc_project.Network",
727743eb1c0SJohnathan Mantey         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
728743eb1c0SJohnathan Mantey             ifaceId,
729743eb1c0SJohnathan Mantey         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
730e93abac6SGinu George         gateway);
731743eb1c0SJohnathan Mantey }
732743eb1c0SJohnathan Mantey 
733743eb1c0SJohnathan Mantey /**
734743eb1c0SJohnathan Mantey  * @brief Deletes given static IP address for the interface
735179db1d7SKowalski, Kamil  *
736179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
737179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
738179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
739179db1d7SKowalski, Kamil  *
740179db1d7SKowalski, Kamil  * @return None
741179db1d7SKowalski, Kamil  */
7429c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
7439c5e585cSRavi Teja                             const std::string& ipHash,
7448d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7451abe55efSEd Tanous {
74655c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7475e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
7481abe55efSEd Tanous         if (ec)
7491abe55efSEd Tanous         {
750a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7511abe55efSEd Tanous         }
752179db1d7SKowalski, Kamil     },
753179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
7549c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
755179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
756179db1d7SKowalski, Kamil }
757179db1d7SKowalski, Kamil 
758179db1d7SKowalski, Kamil /**
75901784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
760179db1d7SKowalski, Kamil  *
76101784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
76201784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
76301784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
76401784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
765179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
766179db1d7SKowalski, Kamil  *
767179db1d7SKowalski, Kamil  * @return None
768179db1d7SKowalski, Kamil  */
769cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
770cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7718d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7721abe55efSEd Tanous {
7735a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
7745a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
7751abe55efSEd Tanous         if (ec)
7761abe55efSEd Tanous         {
777a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7789010ec2eSRavi Teja             return;
779179db1d7SKowalski, Kamil         }
7809010ec2eSRavi Teja     };
7819010ec2eSRavi Teja 
7829010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7839010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
784179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
785179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
78601784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
787179db1d7SKowalski, Kamil         gateway);
788179db1d7SKowalski, Kamil }
789e48c0fc5SRavi Teja 
790e48c0fc5SRavi Teja /**
791743eb1c0SJohnathan Mantey  * @brief Deletes the IP entry for this interface and creates a replacement
792743eb1c0SJohnathan Mantey  * static entry
79301784826SJohnathan Mantey  *
79401784826SJohnathan Mantey  * @param[in] ifaceId        Id of interface upon which to create the IPv6 entry
79501784826SJohnathan Mantey  * @param[in] id             The unique hash entry identifying the DBus entry
796743eb1c0SJohnathan Mantey  * @param[in] prefixLength   Prefix syntax for the subnet mask
797743eb1c0SJohnathan Mantey  * @param[in] address        Address to assign to this interface
798743eb1c0SJohnathan Mantey  * @param[in] numStaticAddrs Count of IPv4 static addresses
79901784826SJohnathan Mantey  * @param[io] asyncResp      Response object that will be returned to client
80001784826SJohnathan Mantey  *
80101784826SJohnathan Mantey  * @return None
80201784826SJohnathan Mantey  */
8039c5e585cSRavi Teja 
8049c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
8059c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
8068d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
8079c5e585cSRavi Teja     const std::string& gateway,
8088d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
80901784826SJohnathan Mantey {
81001784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
8119c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
8129c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
81301784826SJohnathan Mantey         if (ec)
81401784826SJohnathan Mantey         {
81501784826SJohnathan Mantey             messages::internalError(asyncResp->res);
81601784826SJohnathan Mantey         }
8179c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
8189c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
81901784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
8205e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
82123a21a1cSEd Tanous             if (ec2)
82201784826SJohnathan Mantey             {
82301784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
82401784826SJohnathan Mantey             }
82501784826SJohnathan Mantey         },
82601784826SJohnathan Mantey             "xyz.openbmc_project.Network",
82701784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
8289c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
8299c5e585cSRavi Teja             prefixLength, gateway);
83001784826SJohnathan Mantey     },
83101784826SJohnathan Mantey         "xyz.openbmc_project.Network",
8329c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
83301784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
83401784826SJohnathan Mantey }
83501784826SJohnathan Mantey 
836ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData(
837ce73d5c8SSunitha Harish     const std::string& ethifaceId,
838ce73d5c8SSunitha Harish     const dbus::utility::ManagedObjectType& dbusData,
839ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>& staticGatewayConfig)
840ce73d5c8SSunitha Harish {
841ce73d5c8SSunitha Harish     std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
842ce73d5c8SSunitha Harish     staticGatewayPathStart += ethifaceId;
843ce73d5c8SSunitha Harish 
844ce73d5c8SSunitha Harish     for (const auto& objpath : dbusData)
845ce73d5c8SSunitha Harish     {
846ce73d5c8SSunitha Harish         if (!std::string_view(objpath.first.str)
847ce73d5c8SSunitha Harish                  .starts_with(staticGatewayPathStart))
848ce73d5c8SSunitha Harish         {
849ce73d5c8SSunitha Harish             continue;
850ce73d5c8SSunitha Harish         }
851ce73d5c8SSunitha Harish         for (const auto& interface : objpath.second)
852ce73d5c8SSunitha Harish         {
853ce73d5c8SSunitha Harish             if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
854ce73d5c8SSunitha Harish             {
855ce73d5c8SSunitha Harish                 continue;
856ce73d5c8SSunitha Harish             }
857ce73d5c8SSunitha Harish             StaticGatewayData& staticGateway =
858ce73d5c8SSunitha Harish                 staticGatewayConfig.emplace_back();
859ce73d5c8SSunitha Harish             staticGateway.id = objpath.first.filename();
860ce73d5c8SSunitha Harish 
861ce73d5c8SSunitha Harish             bool success = sdbusplus::unpackPropertiesNoThrow(
862ce73d5c8SSunitha Harish                 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
863ce73d5c8SSunitha Harish                 "Gateway", staticGateway.gateway, "PrefixLength",
864ce73d5c8SSunitha Harish                 staticGateway.prefixLength, "ProtocolType",
865ce73d5c8SSunitha Harish                 staticGateway.protocol);
866ce73d5c8SSunitha Harish             if (!success)
867ce73d5c8SSunitha Harish             {
868ce73d5c8SSunitha Harish                 return false;
869ce73d5c8SSunitha Harish             }
870ce73d5c8SSunitha Harish         }
871ce73d5c8SSunitha Harish     }
872ce73d5c8SSunitha Harish     return true;
873ce73d5c8SSunitha Harish }
874ce73d5c8SSunitha Harish 
87501784826SJohnathan Mantey /**
876e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
877e48c0fc5SRavi Teja  *
878e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
879e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
880e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
881e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
882e48c0fc5SRavi Teja  *
883e48c0fc5SRavi Teja  * @return None
884e48c0fc5SRavi Teja  */
88501784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
88601784826SJohnathan Mantey                        const std::string& address,
8878d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
888e48c0fc5SRavi Teja {
889ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
890ce73d5c8SSunitha Harish     path /= ifaceId;
891ce73d5c8SSunitha Harish 
8925a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
8935a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
894e48c0fc5SRavi Teja         if (ec)
895e48c0fc5SRavi Teja         {
896fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
897fc23ef8aSNitin Kumar Kotania             {
898fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
899fc23ef8aSNitin Kumar Kotania                                                    "Address");
900fc23ef8aSNitin Kumar Kotania             }
901fc23ef8aSNitin Kumar Kotania             else
902fc23ef8aSNitin Kumar Kotania             {
903e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
904e48c0fc5SRavi Teja             }
905fc23ef8aSNitin Kumar Kotania         }
906e48c0fc5SRavi Teja     };
907ce73d5c8SSunitha Harish     // Passing null for gateway, as per redfish spec IPv6StaticAddresses
908ce73d5c8SSunitha Harish     // object does not have associated gateway property
909e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
910ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
911e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
912e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
913e48c0fc5SRavi Teja         "");
914e48c0fc5SRavi Teja }
915e48c0fc5SRavi Teja 
916179db1d7SKowalski, Kamil /**
917ce73d5c8SSunitha Harish  * @brief Deletes given IPv6 Static Gateway
918ce73d5c8SSunitha Harish  *
919ce73d5c8SSunitha Harish  * @param[in] ifaceId     Id of interface whose IP should be deleted
920ce73d5c8SSunitha Harish  * @param[in] ipHash      DBus Hash id of IP that should be deleted
921ce73d5c8SSunitha Harish  * @param[io] asyncResp   Response object that will be returned to client
922ce73d5c8SSunitha Harish  *
923ce73d5c8SSunitha Harish  * @return None
924ce73d5c8SSunitha Harish  */
925ce73d5c8SSunitha Harish inline void
926ce73d5c8SSunitha Harish     deleteIPv6Gateway(std::string_view gatewayId,
927ce73d5c8SSunitha Harish                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
928ce73d5c8SSunitha Harish {
929ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
930ce73d5c8SSunitha Harish     path /= gatewayId;
931ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
932ce73d5c8SSunitha Harish         [asyncResp](const boost::system::error_code& ec) {
933ce73d5c8SSunitha Harish         if (ec)
934ce73d5c8SSunitha Harish         {
935ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
936ce73d5c8SSunitha Harish         }
937ce73d5c8SSunitha Harish     },
938ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
939ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
940ce73d5c8SSunitha Harish }
941ce73d5c8SSunitha Harish 
942ce73d5c8SSunitha Harish /**
943ce73d5c8SSunitha Harish  * @brief Creates IPv6 static default gateway with given data
944ce73d5c8SSunitha Harish  *
945ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose IP should be added
946ce73d5c8SSunitha Harish  * @param[in] prefixLength Prefix length that needs to be added
947ce73d5c8SSunitha Harish  * @param[in] gateway      Gateway address that needs to be added
948ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
949ce73d5c8SSunitha Harish  *
950ce73d5c8SSunitha Harish  * @return None
951ce73d5c8SSunitha Harish  */
952ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway(
953ce73d5c8SSunitha Harish     std::string_view ifaceId, size_t prefixLength, std::string_view gateway,
954ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
955ce73d5c8SSunitha Harish {
956ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
957ce73d5c8SSunitha Harish     path /= ifaceId;
958ce73d5c8SSunitha Harish     auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
959ce73d5c8SSunitha Harish         if (ec)
960ce73d5c8SSunitha Harish         {
961ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
962ce73d5c8SSunitha Harish         }
963ce73d5c8SSunitha Harish     };
964ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
965ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
966ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
967ce73d5c8SSunitha Harish         gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
968ce73d5c8SSunitha Harish }
969ce73d5c8SSunitha Harish 
970ce73d5c8SSunitha Harish /**
971ce73d5c8SSunitha Harish  * @brief Deletes the IPv6 default gateway entry for this interface and
972ce73d5c8SSunitha Harish  * creates a replacement IPv6 default gateway entry
973ce73d5c8SSunitha Harish  *
974ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface upon which to create the IPv6
975ce73d5c8SSunitha Harish  * entry
976ce73d5c8SSunitha Harish  * @param[in] gateway      IPv6 gateway to assign to this interface
977ce73d5c8SSunitha Harish  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
978ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
979ce73d5c8SSunitha Harish  *
980ce73d5c8SSunitha Harish  * @return None
981ce73d5c8SSunitha Harish  */
982ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway(
983ce73d5c8SSunitha Harish     std::string_view ifaceId, std::string_view gatewayId,
984ce73d5c8SSunitha Harish     std::string_view gateway, size_t prefixLength,
985ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
986ce73d5c8SSunitha Harish {
987ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
988ce73d5c8SSunitha Harish     path /= gatewayId;
989ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
990ce73d5c8SSunitha Harish         [asyncResp, ifaceId, gateway,
991ce73d5c8SSunitha Harish          prefixLength](const boost::system::error_code& ec) {
992ce73d5c8SSunitha Harish         if (ec)
993ce73d5c8SSunitha Harish         {
994ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
995ce73d5c8SSunitha Harish             return;
996ce73d5c8SSunitha Harish         }
997ce73d5c8SSunitha Harish         createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp);
998ce73d5c8SSunitha Harish     },
999ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
1000ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
1001ce73d5c8SSunitha Harish }
1002ce73d5c8SSunitha Harish 
1003ce73d5c8SSunitha Harish /**
1004ce73d5c8SSunitha Harish  * @brief Sets IPv6 default gateway with given data
1005ce73d5c8SSunitha Harish  *
1006ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose gateway should be added
1007ce73d5c8SSunitha Harish  * @param[in] input        Contains address that needs to be added
1008ce73d5c8SSunitha Harish  * @param[in] staticGatewayData  Current static gateways in the system
1009ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
1010ce73d5c8SSunitha Harish  *
1011ce73d5c8SSunitha Harish  * @return None
1012ce73d5c8SSunitha Harish  */
1013ce73d5c8SSunitha Harish 
1014ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway(
10153dfed536SEd Tanous     const std::string& ifaceId,
10163dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1017ce73d5c8SSunitha Harish     const std::vector<StaticGatewayData>& staticGatewayData,
1018ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1019ce73d5c8SSunitha Harish {
1020ce73d5c8SSunitha Harish     size_t entryIdx = 1;
1021ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>::const_iterator staticGatewayEntry =
1022ce73d5c8SSunitha Harish         staticGatewayData.begin();
1023ce73d5c8SSunitha Harish 
10243dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
10253dfed536SEd Tanous          input)
1026ce73d5c8SSunitha Harish     {
1027ce73d5c8SSunitha Harish         // find the next gateway entry
1028ce73d5c8SSunitha Harish         while (staticGatewayEntry != staticGatewayData.end())
1029ce73d5c8SSunitha Harish         {
1030ce73d5c8SSunitha Harish             if (staticGatewayEntry->protocol ==
1031ce73d5c8SSunitha Harish                 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1032ce73d5c8SSunitha Harish             {
1033ce73d5c8SSunitha Harish                 break;
1034ce73d5c8SSunitha Harish             }
1035ce73d5c8SSunitha Harish             staticGatewayEntry++;
1036ce73d5c8SSunitha Harish         }
1037ce73d5c8SSunitha Harish         std::string pathString = "IPv6StaticDefaultGateways/" +
1038ce73d5c8SSunitha Harish                                  std::to_string(entryIdx);
10393dfed536SEd Tanous         nlohmann::json::object_t* obj =
10403dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
10413dfed536SEd Tanous         if (obj == nullptr)
1042ce73d5c8SSunitha Harish         {
1043ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1044ce73d5c8SSunitha Harish             {
1045ce73d5c8SSunitha Harish                 messages::resourceCannotBeDeleted(asyncResp->res);
1046ce73d5c8SSunitha Harish                 return;
1047ce73d5c8SSunitha Harish             }
1048ce73d5c8SSunitha Harish             deleteIPv6Gateway(staticGatewayEntry->id, asyncResp);
1049ce73d5c8SSunitha Harish             return;
1050ce73d5c8SSunitha Harish         }
10513dfed536SEd Tanous         if (obj->empty())
1052ce73d5c8SSunitha Harish         {
1053ce73d5c8SSunitha Harish             // Do nothing, but make sure the entry exists.
1054ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1055ce73d5c8SSunitha Harish             {
10563dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
1057ce73d5c8SSunitha Harish                                                    pathString);
1058ce73d5c8SSunitha Harish                 return;
1059ce73d5c8SSunitha Harish             }
1060ce73d5c8SSunitha Harish         }
1061ce73d5c8SSunitha Harish         std::optional<std::string> address;
1062ce73d5c8SSunitha Harish         std::optional<size_t> prefixLength;
1063ce73d5c8SSunitha Harish 
10643dfed536SEd Tanous         if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address,
10653dfed536SEd Tanous                                        "PrefixLength", prefixLength))
1066ce73d5c8SSunitha Harish         {
1067ce73d5c8SSunitha Harish             return;
1068ce73d5c8SSunitha Harish         }
1069ce73d5c8SSunitha Harish         const std::string* addr = nullptr;
1070ce73d5c8SSunitha Harish         size_t prefix = 0;
1071ce73d5c8SSunitha Harish         if (address)
1072ce73d5c8SSunitha Harish         {
1073ce73d5c8SSunitha Harish             addr = &(*address);
1074ce73d5c8SSunitha Harish         }
1075ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1076ce73d5c8SSunitha Harish         {
1077ce73d5c8SSunitha Harish             addr = &(staticGatewayEntry->gateway);
1078ce73d5c8SSunitha Harish         }
1079ce73d5c8SSunitha Harish         else
1080ce73d5c8SSunitha Harish         {
1081ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res, pathString + "/Address");
1082ce73d5c8SSunitha Harish             return;
1083ce73d5c8SSunitha Harish         }
1084ce73d5c8SSunitha Harish         if (prefixLength)
1085ce73d5c8SSunitha Harish         {
1086ce73d5c8SSunitha Harish             prefix = *prefixLength;
1087ce73d5c8SSunitha Harish         }
1088ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1089ce73d5c8SSunitha Harish         {
1090ce73d5c8SSunitha Harish             prefix = staticGatewayEntry->prefixLength;
1091ce73d5c8SSunitha Harish         }
1092ce73d5c8SSunitha Harish         else
1093ce73d5c8SSunitha Harish         {
1094ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res,
1095ce73d5c8SSunitha Harish                                       pathString + "/PrefixLength");
1096ce73d5c8SSunitha Harish             return;
1097ce73d5c8SSunitha Harish         }
1098ce73d5c8SSunitha Harish         if (staticGatewayEntry != staticGatewayData.end())
1099ce73d5c8SSunitha Harish         {
1100ce73d5c8SSunitha Harish             deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
1101ce73d5c8SSunitha Harish                                               *addr, prefix, asyncResp);
1102ce73d5c8SSunitha Harish             staticGatewayEntry++;
1103ce73d5c8SSunitha Harish         }
1104ce73d5c8SSunitha Harish         else
1105ce73d5c8SSunitha Harish         {
1106ce73d5c8SSunitha Harish             createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp);
1107ce73d5c8SSunitha Harish         }
1108ce73d5c8SSunitha Harish         entryIdx++;
1109ce73d5c8SSunitha Harish     }
1110ce73d5c8SSunitha Harish }
1111ce73d5c8SSunitha Harish 
1112ce73d5c8SSunitha Harish /**
1113179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
1114179db1d7SKowalski, Kamil  * Object
1115179db1d7SKowalski, Kamil  * from EntityManager Network Manager
11164a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
1117179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
1118179db1d7SKowalski, Kamil  * into JSON
1119179db1d7SKowalski, Kamil  */
1120179db1d7SKowalski, Kamil template <typename CallbackFunc>
112181ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
11221abe55efSEd Tanous                           CallbackFunc&& callback)
11231abe55efSEd Tanous {
1124f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1125f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1126f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1127f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
11288cb2c024SEd Tanous          callback = std::forward<CallbackFunc>(callback)](
11298b24275dSEd Tanous             const boost::system::error_code& ec,
11303dfed536SEd Tanous             const dbus::utility::ManagedObjectType& resp) mutable {
113155c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
113277179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
113377179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
1134ce73d5c8SSunitha Harish         std::vector<StaticGatewayData> ipv6GatewayData;
1135179db1d7SKowalski, Kamil 
11368b24275dSEd Tanous         if (ec)
11371abe55efSEd Tanous         {
1138ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1139179db1d7SKowalski, Kamil             return;
1140179db1d7SKowalski, Kamil         }
1141179db1d7SKowalski, Kamil 
1142002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
11434c9afe43SEd Tanous         if (!found)
11444c9afe43SEd Tanous         {
1145ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
11464c9afe43SEd Tanous             return;
11474c9afe43SEd Tanous         }
11484c9afe43SEd Tanous 
11492c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
1150179db1d7SKowalski, Kamil         // Fix global GW
11511abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
11521abe55efSEd Tanous         {
1153c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
1154c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
11559010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
11561abe55efSEd Tanous             {
115782695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
1158179db1d7SKowalski, Kamil             }
1159179db1d7SKowalski, Kamil         }
1160179db1d7SKowalski, Kamil 
11612c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
1162ce73d5c8SSunitha Harish         if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData))
1163ce73d5c8SSunitha Harish         {
1164ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1165ce73d5c8SSunitha Harish         }
11664e0453b1SGunnar Mills         // Finally make a callback with useful data
1167ce73d5c8SSunitha Harish         callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1168f5892d0dSGeorge Liu     });
1169271584abSEd Tanous }
1170179db1d7SKowalski, Kamil 
1171179db1d7SKowalski, Kamil /**
11729391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
11739391bb9cSRapkiewicz, Pawel  * Manager
11741abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
11751abe55efSEd Tanous  * into JSON.
11769391bb9cSRapkiewicz, Pawel  */
11779391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
11781abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
11791abe55efSEd Tanous {
1180f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1181f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1182f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
11838cb2c024SEd Tanous         [callback = std::forward<CallbackFunc>(callback)](
11848b24275dSEd Tanous             const boost::system::error_code& ec,
1185f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
11861abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
11871abe55efSEd Tanous         // ethernet interfaces
118877179532SEd Tanous         std::vector<std::string> ifaceList;
11892c70f800SEd Tanous         ifaceList.reserve(resp.size());
11908b24275dSEd Tanous         if (ec)
11911abe55efSEd Tanous         {
11922c70f800SEd Tanous             callback(false, ifaceList);
11939391bb9cSRapkiewicz, Pawel             return;
11949391bb9cSRapkiewicz, Pawel         }
11959391bb9cSRapkiewicz, Pawel 
11969391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
11974a0cb85cSEd Tanous         for (const auto& objpath : resp)
11981abe55efSEd Tanous         {
11999391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
12004a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
12011abe55efSEd Tanous             {
12021abe55efSEd Tanous                 // If interface is
12034a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
12044a0cb85cSEd Tanous                 // what we're looking for.
12059391bb9cSRapkiewicz, Pawel                 if (interface.first ==
12061abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
12071abe55efSEd Tanous                 {
12082dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
12092dfd18efSEd Tanous                     if (ifaceId.empty())
12101abe55efSEd Tanous                     {
12112dfd18efSEd Tanous                         continue;
12129391bb9cSRapkiewicz, Pawel                     }
12132dfd18efSEd Tanous                     // and put it into output vector.
121477179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
12159391bb9cSRapkiewicz, Pawel                 }
12169391bb9cSRapkiewicz, Pawel             }
12179391bb9cSRapkiewicz, Pawel         }
12182c5875a2SEd Tanous 
12193544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
12202c5875a2SEd Tanous 
1221a434f2bdSEd Tanous         // Finally make a callback with useful data
12222c70f800SEd Tanous         callback(true, ifaceList);
1223f5892d0dSGeorge Liu     });
1224271584abSEd Tanous }
12259391bb9cSRapkiewicz, Pawel 
12264f48d5f6SEd Tanous inline void
12274f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
12288d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12291abe55efSEd Tanous {
1230ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
1231ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
1232ab6554f1SJoshi-Mansi     {
1233ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
1234ab6554f1SJoshi-Mansi                                            "HostName");
1235ab6554f1SJoshi-Mansi         return;
1236ab6554f1SJoshi-Mansi     }
1237d02aad39SEd Tanous     setDbusProperty(
1238e93abac6SGinu George         asyncResp, "HostName", "xyz.openbmc_project.Network",
1239d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network/config"),
1240d02aad39SEd Tanous         "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
1241e93abac6SGinu George         hostname);
1242588c3f0dSKowalski, Kamil }
1243588c3f0dSKowalski, Kamil 
12444f48d5f6SEd Tanous inline void
124535fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
124635fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
124735fb5311STejas Patil {
1248d02aad39SEd Tanous     sdbusplus::message::object_path objPath("/xyz/openbmc_project/network");
1249d02aad39SEd Tanous     objPath /= ifaceId;
1250e93abac6SGinu George     setDbusProperty(asyncResp, "MTUSize", "xyz.openbmc_project.Network",
1251e93abac6SGinu George                     objPath, "xyz.openbmc_project.Network.EthernetInterface",
1252e93abac6SGinu George                     "MTU", mtuSize);
125335fb5311STejas Patil }
125435fb5311STejas Patil 
125535fb5311STejas Patil inline void
12564f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
1257bf648f77SEd Tanous                           const std::string& domainname,
12588d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1259ab6554f1SJoshi-Mansi {
1260ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
1261d02aad39SEd Tanous     setDbusProperty(
1262e93abac6SGinu George         asyncResp, "FQDN", "xyz.openbmc_project.Network",
1263d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1264d02aad39SEd Tanous             ifaceId,
1265e93abac6SGinu George         "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
1266d02aad39SEd Tanous         vectorDomainname);
1267ab6554f1SJoshi-Mansi }
1268ab6554f1SJoshi-Mansi 
12694f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1270bf648f77SEd Tanous {
1271bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
12723544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1273bf648f77SEd Tanous     {
1274bf648f77SEd Tanous         return false;
1275bf648f77SEd Tanous     }
1276bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1277bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1278bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1279bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
12804b242749SEd Tanous     const static std::regex pattern(
1281bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1282bf648f77SEd Tanous 
1283bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1284bf648f77SEd Tanous }
1285bf648f77SEd Tanous 
12864f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1287bf648f77SEd Tanous {
1288bf648f77SEd Tanous     // Can have multiple subdomains
1289bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
12904b242749SEd Tanous     const static std::regex pattern(
12910fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1292bf648f77SEd Tanous 
1293bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1294bf648f77SEd Tanous }
1295bf648f77SEd Tanous 
12964f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
12978d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1298ab6554f1SJoshi-Mansi {
1299ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1300ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1301ab6554f1SJoshi-Mansi     {
1302ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1303ab6554f1SJoshi-Mansi         return;
1304ab6554f1SJoshi-Mansi     }
1305ab6554f1SJoshi-Mansi 
1306ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1307ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1308ab6554f1SJoshi-Mansi     {
1309ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1310ab6554f1SJoshi-Mansi         return;
1311ab6554f1SJoshi-Mansi     }
1312ab6554f1SJoshi-Mansi 
1313ab6554f1SJoshi-Mansi     std::string hostname;
1314ab6554f1SJoshi-Mansi     std::string domainname;
1315ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1316ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1317ab6554f1SJoshi-Mansi 
1318ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1319ab6554f1SJoshi-Mansi     {
1320ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1321ab6554f1SJoshi-Mansi         return;
1322ab6554f1SJoshi-Mansi     }
1323ab6554f1SJoshi-Mansi 
1324ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1325ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1326ab6554f1SJoshi-Mansi }
1327ab6554f1SJoshi-Mansi 
13284f48d5f6SEd Tanous inline void
13294f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1330bf648f77SEd Tanous                           const std::string& macAddress,
13318d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1332d577665bSRatan Gupta {
1333d02aad39SEd Tanous     setDbusProperty(
1334e93abac6SGinu George         asyncResp, "MACAddress", "xyz.openbmc_project.Network",
1335d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1336d02aad39SEd Tanous             ifaceId,
1337e93abac6SGinu George         "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress);
1338d577665bSRatan Gupta }
1339286b9118SJohnathan Mantey 
13404f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
13414f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
13424f48d5f6SEd Tanous                            const bool v6Value,
13438d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1344da131a9aSJennifer Lee {
13452c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
1346d02aad39SEd Tanous     setDbusProperty(
1347e93abac6SGinu George         asyncResp, "DHCPv4", "xyz.openbmc_project.Network",
1348d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1349d02aad39SEd Tanous             ifaceId,
1350e93abac6SGinu George         "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp);
1351eeedda23SJohnathan Mantey }
1352eeedda23SJohnathan Mantey 
1353e4588158SJishnu CM enum class NetworkType
1354e4588158SJishnu CM {
1355e4588158SJishnu CM     dhcp4,
1356e4588158SJishnu CM     dhcp6
1357e4588158SJishnu CM };
1358e4588158SJishnu CM 
1359e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1360e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1361e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1362da131a9aSJennifer Lee {
136362598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
13641847f2a0SAsmitha Karunanithi     std::string redfishPropertyName;
1365e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1366e4588158SJishnu CM     path /= ethifaceId;
1367e4588158SJishnu CM 
1368e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1369e4588158SJishnu CM     {
1370e4588158SJishnu CM         path /= "dhcp4";
13711847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv4";
1372e4588158SJishnu CM     }
1373e4588158SJishnu CM     else
1374e4588158SJishnu CM     {
1375e4588158SJishnu CM         path /= "dhcp6";
13761847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv6";
1377e4588158SJishnu CM     }
1378e4588158SJishnu CM 
1379e93abac6SGinu George     setDbusProperty(
1380e93abac6SGinu George         asyncResp, redfishPropertyName, "xyz.openbmc_project.Network", path,
1381e93abac6SGinu George         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value);
1382da131a9aSJennifer Lee }
1383d577665bSRatan Gupta 
1384b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1385b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1386b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1387b10d8db0SRavi Teja {
1388b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1389b10d8db0SRavi Teja     path /= ifaceId;
1390e93abac6SGinu George     setDbusProperty(asyncResp,
13911847f2a0SAsmitha Karunanithi                     "StatelessAddressAutoConfig/IPv6AutoConfigEnabled",
1392e93abac6SGinu George                     "xyz.openbmc_project.Network", path,
1393e93abac6SGinu George                     "xyz.openbmc_project.Network.EthernetInterface",
1394e93abac6SGinu George                     "IPv6AcceptRA", ipv6AutoConfigEnabled);
1395b10d8db0SRavi Teja }
1396b10d8db0SRavi Teja 
13974f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
13981f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1399f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1400f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
14018d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1402da131a9aSJennifer Lee {
140382695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
140482695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1405da131a9aSJennifer Lee 
1406743eb1c0SJohnathan Mantey     if (ipv4Active)
1407743eb1c0SJohnathan Mantey     {
1408743eb1c0SJohnathan Mantey         updateIPv4DefaultGateway(ifaceId, "", asyncResp);
1409743eb1c0SJohnathan Mantey     }
14101f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
14111f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
14121f8c7b5dSJohnathan Mantey 
14131f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
14141f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1415da131a9aSJennifer Lee     {
1416b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
14171f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
14181f8c7b5dSJohnathan Mantey         {
1419bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1420bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
14211f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1422da131a9aSJennifer Lee             return;
1423da131a9aSJennifer Lee         }
1424b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
14251f8c7b5dSJohnathan Mantey     }
14261f8c7b5dSJohnathan Mantey     else
1427da131a9aSJennifer Lee     {
14281f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
14291f8c7b5dSJohnathan Mantey     }
14301f8c7b5dSJohnathan Mantey 
1431e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1432e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1433e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
14341f8c7b5dSJohnathan Mantey     {
1435e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
14361f8c7b5dSJohnathan Mantey     }
1437e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
14381f8c7b5dSJohnathan Mantey     {
1439e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
14401f8c7b5dSJohnathan Mantey     }
14411f8c7b5dSJohnathan Mantey 
1442e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1443e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1444e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
14451f8c7b5dSJohnathan Mantey     {
1446e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
14471f8c7b5dSJohnathan Mantey     }
1448e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
14491f8c7b5dSJohnathan Mantey     {
1450e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
14511f8c7b5dSJohnathan Mantey     }
14521f8c7b5dSJohnathan Mantey 
145391c441ecSRavi Teja     bool nextUsev4Domain = ethData.domainv4Enabled;
145491c441ecSRavi Teja     bool nextUsev6Domain = ethData.domainv6Enabled;
1455e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
14561f8c7b5dSJohnathan Mantey     {
1457e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
14581f8c7b5dSJohnathan Mantey     }
1459e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
14601f8c7b5dSJohnathan Mantey     {
1461e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
14621f8c7b5dSJohnathan Mantey     }
14631f8c7b5dSJohnathan Mantey 
146462598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
14651f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
14661f8c7b5dSJohnathan Mantey                    asyncResp);
146762598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1468e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1469e4588158SJishnu CM                   NetworkType::dhcp4);
147062598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1471e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1472e4588158SJishnu CM                   NetworkType::dhcp4);
147391c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled...");
147491c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
1475e4588158SJishnu CM                   NetworkType::dhcp4);
1476e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1477e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1478e4588158SJishnu CM                   NetworkType::dhcp6);
1479e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1480e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1481e4588158SJishnu CM                   NetworkType::dhcp6);
148291c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
148391c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
1484e4588158SJishnu CM                   NetworkType::dhcp6);
1485da131a9aSJennifer Lee }
148601784826SJohnathan Mantey 
148777179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
148877179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
148977179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
149001784826SJohnathan Mantey {
149117a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
149217a897dfSManojkiran Eda         return value.origin == "Static";
149317a897dfSManojkiran Eda     });
149401784826SJohnathan Mantey }
149501784826SJohnathan Mantey 
149677179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
149777179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
149877179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
149901784826SJohnathan Mantey {
150017a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
150117a897dfSManojkiran Eda         return value.origin == "Static";
150217a897dfSManojkiran Eda     });
150301784826SJohnathan Mantey }
150401784826SJohnathan Mantey 
15053dfed536SEd Tanous inline void handleIPv4StaticPatch(
15063dfed536SEd Tanous     const std::string& ifaceId,
15073dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1508743eb1c0SJohnathan Mantey     const EthernetInterfaceData& ethData,
150977179532SEd Tanous     const std::vector<IPv4AddressData>& ipv4Data,
15108d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
15111abe55efSEd Tanous {
1512271584abSEd Tanous     unsigned entryIdx = 1;
151301784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
151401784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
151501784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
151601784826SJohnathan Mantey     // into the NIC.
151777179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
15182c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
151901784826SJohnathan Mantey 
1520743eb1c0SJohnathan Mantey     bool gatewayValueAssigned{};
15214a8f5d43SJohnathan Mantey     bool preserveGateway{};
1522743eb1c0SJohnathan Mantey     std::string activePath{};
1523743eb1c0SJohnathan Mantey     std::string activeGateway{};
1524743eb1c0SJohnathan Mantey     if (!ethData.defaultGateway.empty() && ethData.defaultGateway != "0.0.0.0")
1525743eb1c0SJohnathan Mantey     {
1526743eb1c0SJohnathan Mantey         // The NIC is already configured with a default gateway. Use this if
1527743eb1c0SJohnathan Mantey         // the leading entry in the PATCH is '{}', which is preserving an active
1528743eb1c0SJohnathan Mantey         // static address.
1529743eb1c0SJohnathan Mantey         activeGateway = ethData.defaultGateway;
1530743eb1c0SJohnathan Mantey         activePath = "IPv4StaticAddresses/1";
1531743eb1c0SJohnathan Mantey         gatewayValueAssigned = true;
1532743eb1c0SJohnathan Mantey     }
1533743eb1c0SJohnathan Mantey 
15343dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
15353dfed536SEd Tanous          input)
15361abe55efSEd Tanous     {
153789492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
153889492a15SPatrick Williams                                  std::to_string(entryIdx);
15393dfed536SEd Tanous         nlohmann::json::object_t* obj =
15403dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
1541743eb1c0SJohnathan Mantey         if (obj == nullptr)
1542743eb1c0SJohnathan Mantey         {
1543743eb1c0SJohnathan Mantey             if (nicIpEntry != ipv4Data.cend())
1544743eb1c0SJohnathan Mantey             {
1545743eb1c0SJohnathan Mantey                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
1546743eb1c0SJohnathan Mantey                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
1547743eb1c0SJohnathan Mantey                                                   ipv4Data.cend());
15484a8f5d43SJohnathan Mantey                 if (!preserveGateway && (nicIpEntry == ipv4Data.cend()))
1549743eb1c0SJohnathan Mantey                 {
1550743eb1c0SJohnathan Mantey                     // All entries have been processed, and this last has
1551743eb1c0SJohnathan Mantey                     // requested the IP address be deleted. No prior entry
1552743eb1c0SJohnathan Mantey                     // performed an action that created or modified a
1553743eb1c0SJohnathan Mantey                     // gateway. Deleting this IP address means the default
1554743eb1c0SJohnathan Mantey                     // gateway entry has to be removed as well.
1555743eb1c0SJohnathan Mantey                     updateIPv4DefaultGateway(ifaceId, "", asyncResp);
1556743eb1c0SJohnathan Mantey                 }
1557743eb1c0SJohnathan Mantey                 entryIdx++;
1558743eb1c0SJohnathan Mantey                 continue;
1559743eb1c0SJohnathan Mantey             }
1560743eb1c0SJohnathan Mantey             // Received a DELETE action on an entry not assigned to the NIC
1561743eb1c0SJohnathan Mantey             messages::resourceCannotBeDeleted(asyncResp->res);
1562743eb1c0SJohnathan Mantey             return;
1563743eb1c0SJohnathan Mantey         }
1564743eb1c0SJohnathan Mantey 
1565743eb1c0SJohnathan Mantey         // An Add/Modify action is requested
1566743eb1c0SJohnathan Mantey         if (!obj->empty())
1567f476acbfSRatan Gupta         {
1568537174c4SEd Tanous             std::optional<std::string> address;
1569537174c4SEd Tanous             std::optional<std::string> subnetMask;
1570537174c4SEd Tanous             std::optional<std::string> gateway;
1571537174c4SEd Tanous 
15723dfed536SEd Tanous             if (!json_util::readJsonObject(*obj, asyncResp->res, "Address",
15737e27d832SJohnathan Mantey                                            address, "SubnetMask", subnetMask,
15747e27d832SJohnathan Mantey                                            "Gateway", gateway))
1575537174c4SEd Tanous             {
15763dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
157771f52d96SEd Tanous                                                    pathString);
1578537174c4SEd Tanous                 return;
1579179db1d7SKowalski, Kamil             }
1580179db1d7SKowalski, Kamil 
158101784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
158201784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
158301784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
158401784826SJohnathan Mantey             // current request.
1585537174c4SEd Tanous             if (address)
15861abe55efSEd Tanous             {
1587e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
158801784826SJohnathan Mantey                 {
1589bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1590bf648f77SEd Tanous                                                        pathString + "/Address");
1591e01d0c36SEd Tanous                     return;
159201784826SJohnathan Mantey                 }
159301784826SJohnathan Mantey             }
159485ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
159501784826SJohnathan Mantey             {
1596e01d0c36SEd Tanous                 address = (nicIpEntry->address);
159701784826SJohnathan Mantey             }
159801784826SJohnathan Mantey             else
159901784826SJohnathan Mantey             {
160001784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
160101784826SJohnathan Mantey                                           pathString + "/Address");
1602e01d0c36SEd Tanous                 return;
16034a0cb85cSEd Tanous             }
16044a0cb85cSEd Tanous 
1605e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1606537174c4SEd Tanous             if (subnetMask)
16074a0cb85cSEd Tanous             {
1608033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1609033f1e4dSEd Tanous                                                          &prefixLength))
16104a0cb85cSEd Tanous                 {
1611f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1612537174c4SEd Tanous                         asyncResp->res, *subnetMask,
16134a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1614e01d0c36SEd Tanous                     return;
16154a0cb85cSEd Tanous                 }
16164a0cb85cSEd Tanous             }
161785ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
16184a0cb85cSEd Tanous             {
1619033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
162001784826SJohnathan Mantey                                                          &prefixLength))
16214a0cb85cSEd Tanous                 {
162201784826SJohnathan Mantey                     messages::propertyValueFormatError(
162385ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
162401784826SJohnathan Mantey                         pathString + "/SubnetMask");
1625e01d0c36SEd Tanous                     return;
16264a0cb85cSEd Tanous                 }
16274a0cb85cSEd Tanous             }
16281abe55efSEd Tanous             else
16291abe55efSEd Tanous             {
163001784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
163101784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1632e01d0c36SEd Tanous                 return;
163301784826SJohnathan Mantey             }
163401784826SJohnathan Mantey 
163501784826SJohnathan Mantey             if (gateway)
163601784826SJohnathan Mantey             {
1637e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
163801784826SJohnathan Mantey                 {
1639bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1640bf648f77SEd Tanous                                                        pathString + "/Gateway");
1641e01d0c36SEd Tanous                     return;
164201784826SJohnathan Mantey                 }
164301784826SJohnathan Mantey             }
164485ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
164501784826SJohnathan Mantey             {
1646e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
164701784826SJohnathan Mantey             }
164801784826SJohnathan Mantey             else
16491abe55efSEd Tanous             {
1650a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
16514a0cb85cSEd Tanous                                           pathString + "/Gateway");
165201784826SJohnathan Mantey                 return;
16534a0cb85cSEd Tanous             }
16544a0cb85cSEd Tanous 
1655743eb1c0SJohnathan Mantey             if (gatewayValueAssigned)
1656743eb1c0SJohnathan Mantey             {
1657743eb1c0SJohnathan Mantey                 if (activeGateway != gateway)
1658743eb1c0SJohnathan Mantey                 {
1659743eb1c0SJohnathan Mantey                     // A NIC can only have a single active gateway value.
1660743eb1c0SJohnathan Mantey                     // If any gateway in the array of static addresses
1661743eb1c0SJohnathan Mantey                     // mismatch the PATCH is in error.
1662743eb1c0SJohnathan Mantey                     std::string arg1 = pathString + "/Gateway";
1663743eb1c0SJohnathan Mantey                     std::string arg2 = activePath + "/Gateway";
1664743eb1c0SJohnathan Mantey                     messages::propertyValueConflict(asyncResp->res, arg1, arg2);
1665743eb1c0SJohnathan Mantey                     return;
1666743eb1c0SJohnathan Mantey                 }
1667743eb1c0SJohnathan Mantey             }
1668743eb1c0SJohnathan Mantey             else
1669743eb1c0SJohnathan Mantey             {
1670743eb1c0SJohnathan Mantey                 // Capture the very first gateway value from the incoming
1671743eb1c0SJohnathan Mantey                 // JSON record and use it at the default gateway.
1672743eb1c0SJohnathan Mantey                 updateIPv4DefaultGateway(ifaceId, *gateway, asyncResp);
1673743eb1c0SJohnathan Mantey                 activeGateway = *gateway;
1674743eb1c0SJohnathan Mantey                 activePath = pathString;
1675743eb1c0SJohnathan Mantey                 gatewayValueAssigned = true;
1676743eb1c0SJohnathan Mantey             }
1677743eb1c0SJohnathan Mantey 
167885ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
16791abe55efSEd Tanous             {
16809c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
168177eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
168277eb0153SEd Tanous                                          *gateway, asyncResp);
168389492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
168489492a15SPatrick Williams                                                   ipv4Data.cend());
16854a8f5d43SJohnathan Mantey                 preserveGateway = true;
1686588c3f0dSKowalski, Kamil             }
168701784826SJohnathan Mantey             else
168801784826SJohnathan Mantey             {
1689cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1690cb13a392SEd Tanous                            asyncResp);
16914a8f5d43SJohnathan Mantey                 preserveGateway = true;
16924a0cb85cSEd Tanous             }
16934a0cb85cSEd Tanous             entryIdx++;
16944a0cb85cSEd Tanous         }
169501784826SJohnathan Mantey         else
169601784826SJohnathan Mantey         {
1697743eb1c0SJohnathan Mantey             // Received {}, do not modify this address
169885ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
169901784826SJohnathan Mantey             {
170089492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
170189492a15SPatrick Williams                                                   ipv4Data.cend());
17024a8f5d43SJohnathan Mantey                 preserveGateway = true;
170301784826SJohnathan Mantey                 entryIdx++;
170401784826SJohnathan Mantey             }
1705743eb1c0SJohnathan Mantey             else
1706743eb1c0SJohnathan Mantey             {
1707743eb1c0SJohnathan Mantey                 // Requested a DO NOT MODIFY action on an entry not assigned
1708743eb1c0SJohnathan Mantey                 // to the NIC
1709743eb1c0SJohnathan Mantey                 messages::propertyValueFormatError(asyncResp->res, *obj,
1710743eb1c0SJohnathan Mantey                                                    pathString);
1711743eb1c0SJohnathan Mantey                 return;
1712743eb1c0SJohnathan Mantey             }
1713743eb1c0SJohnathan Mantey         }
171401784826SJohnathan Mantey     }
17154a0cb85cSEd Tanous }
17164a0cb85cSEd Tanous 
17174f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1718f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1719f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
17208d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1721f85837bfSRAJESWARAN THILLAIGOVINDAN {
17221847f2a0SAsmitha Karunanithi     setDbusProperty(
1723e93abac6SGinu George         asyncResp, "StaticNameServers", "xyz.openbmc_project.Network",
17241847f2a0SAsmitha Karunanithi         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
17251847f2a0SAsmitha Karunanithi             ifaceId,
17269ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1727e93abac6SGinu George         updatedStaticNameServers);
1728f85837bfSRAJESWARAN THILLAIGOVINDAN }
1729f85837bfSRAJESWARAN THILLAIGOVINDAN 
17304f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
17313dfed536SEd Tanous     const std::string& ifaceId,
17323dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
173377179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
17348d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1735e48c0fc5SRavi Teja {
1736271584abSEd Tanous     size_t entryIdx = 1;
173777179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
17382c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
17393dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
17403dfed536SEd Tanous          input)
1741e48c0fc5SRavi Teja     {
174289492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
174389492a15SPatrick Williams                                  std::to_string(entryIdx);
17443dfed536SEd Tanous         nlohmann::json::object_t* obj =
17453dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
17463dfed536SEd Tanous         if (obj != nullptr && !obj->empty())
1747e48c0fc5SRavi Teja         {
1748e48c0fc5SRavi Teja             std::optional<std::string> address;
1749e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
17503dfed536SEd Tanous             nlohmann::json::object_t thisJsonCopy = *obj;
17513dfed536SEd Tanous             if (!json_util::readJsonObject(thisJsonCopy, asyncResp->res,
17523dfed536SEd Tanous                                            "Address", address, "PrefixLength",
17533dfed536SEd Tanous                                            prefixLength))
1754e48c0fc5SRavi Teja             {
17553dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJsonCopy,
175671f52d96SEd Tanous                                                    pathString);
1757e48c0fc5SRavi Teja                 return;
1758e48c0fc5SRavi Teja             }
1759e48c0fc5SRavi Teja 
176001784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
176101784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
176201784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
176301784826SJohnathan Mantey             // current request.
1764d547d8d2SEd Tanous             if (!address)
1765e48c0fc5SRavi Teja             {
1766d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
176701784826SJohnathan Mantey                 {
176801784826SJohnathan Mantey                     messages::propertyMissing(asyncResp->res,
176901784826SJohnathan Mantey                                               pathString + "/Address");
177001784826SJohnathan Mantey                     return;
1771e48c0fc5SRavi Teja                 }
1772d547d8d2SEd Tanous                 address = nicIpEntry->address;
1773d547d8d2SEd Tanous             }
1774e48c0fc5SRavi Teja 
1775d547d8d2SEd Tanous             if (!prefixLength)
1776e48c0fc5SRavi Teja             {
1777d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
1778e48c0fc5SRavi Teja                 {
1779e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1780e48c0fc5SRavi Teja                                               pathString + "/PrefixLength");
178101784826SJohnathan Mantey                     return;
1782e48c0fc5SRavi Teja                 }
1783d547d8d2SEd Tanous                 prefixLength = nicIpEntry->prefixLength;
1784d547d8d2SEd Tanous             }
1785e48c0fc5SRavi Teja 
178685ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1787e48c0fc5SRavi Teja             {
17889c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1789d547d8d2SEd Tanous                                          nicIpEntry->id, *prefixLength,
1790d547d8d2SEd Tanous                                          *address, "", asyncResp);
179189492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
179289492a15SPatrick Williams                                                   ipv6Data.cend());
179301784826SJohnathan Mantey             }
179401784826SJohnathan Mantey             else
179501784826SJohnathan Mantey             {
1796d547d8d2SEd Tanous                 createIPv6(ifaceId, *prefixLength, *address, asyncResp);
1797e48c0fc5SRavi Teja             }
1798e48c0fc5SRavi Teja             entryIdx++;
1799e48c0fc5SRavi Teja         }
180001784826SJohnathan Mantey         else
180101784826SJohnathan Mantey         {
180285ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
180301784826SJohnathan Mantey             {
180401784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
180501784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
180601784826SJohnathan Mantey                 // in error, so bail out.
18073dfed536SEd Tanous                 if (obj == nullptr)
180801784826SJohnathan Mantey                 {
180901784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
181001784826SJohnathan Mantey                     return;
181101784826SJohnathan Mantey                 }
18123dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
181371f52d96SEd Tanous                                                    pathString);
181401784826SJohnathan Mantey                 return;
181501784826SJohnathan Mantey             }
181601784826SJohnathan Mantey 
18173dfed536SEd Tanous             if (obj == nullptr)
181801784826SJohnathan Mantey             {
18199c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
182001784826SJohnathan Mantey             }
182185ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
182201784826SJohnathan Mantey             {
182389492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
182489492a15SPatrick Williams                                                   ipv6Data.cend());
182501784826SJohnathan Mantey             }
182601784826SJohnathan Mantey             entryIdx++;
182701784826SJohnathan Mantey         }
182801784826SJohnathan Mantey     }
1829e48c0fc5SRavi Teja }
1830e48c0fc5SRavi Teja 
18317857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
18327857cb8dSJiaqing Zhao {
18337857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
18347857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
18357857cb8dSJiaqing Zhao }
18367857cb8dSJiaqing Zhao 
183777179532SEd Tanous inline void
183877179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
183977179532SEd Tanous                        const std::string& ifaceId,
184077179532SEd Tanous                        const EthernetInterfaceData& ethData,
184177179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
1842ce73d5c8SSunitha Harish                        const std::vector<IPv6AddressData>& ipv6Data,
1843ce73d5c8SSunitha Harish                        const std::vector<StaticGatewayData>& ipv6GatewayData)
18444a0cb85cSEd Tanous {
18452c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
184681ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1847253f11b8SEd Tanous     jsonResponse["@odata.id"] =
1848253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}",
1849253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId);
18502c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1851eeedda23SJohnathan Mantey 
1852eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1853eeedda23SJohnathan Mantey     {
1854*539d8c6bSEd Tanous         jsonResponse["LinkStatus"] =
1855*539d8c6bSEd Tanous             ethData.linkUp ? ethernet_interface::LinkStatus::LinkUp
1856*539d8c6bSEd Tanous                            : ethernet_interface::LinkStatus::LinkDown;
1857*539d8c6bSEd Tanous         jsonResponse["Status"]["State"] = resource::State::Enabled;
1858029573d4SEd Tanous     }
1859029573d4SEd Tanous     else
1860029573d4SEd Tanous     {
1861*539d8c6bSEd Tanous         jsonResponse["LinkStatus"] = ethernet_interface::LinkStatus::NoLink;
1862*539d8c6bSEd Tanous         jsonResponse["Status"]["State"] = resource::State::Disabled;
1863029573d4SEd Tanous     }
1864aa05fb27SJohnathan Mantey 
18652c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
186635fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
186782695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
18682c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
186982695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1870e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1871e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1872de9ad764SRavi Teja     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled;
18732c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1874b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
18751f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1876e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1877e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1878de9ad764SRavi Teja     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled;
1879b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1880b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
18812a133282Smanojkiraneda 
188282695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
18834a0cb85cSEd Tanous     {
188482695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1885ab6554f1SJoshi-Mansi 
1886ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1887ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1888ab6554f1SJoshi-Mansi         // FQDN
188982695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1890d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1891d24bfc7aSJennifer Lee         {
18922c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1893d24bfc7aSJennifer Lee         }
18942c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
18954a0cb85cSEd Tanous     }
18964a0cb85cSEd Tanous 
18977857cb8dSJiaqing Zhao     if (ethData.vlanId)
18987857cb8dSJiaqing Zhao     {
1899*539d8c6bSEd Tanous         jsonResponse["EthernetInterfaceType"] =
1900*539d8c6bSEd Tanous             ethernet_interface::EthernetDeviceType::Virtual;
19017857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
19027857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
19037857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
19047857cb8dSJiaqing Zhao 
19057857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
19067857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
19077857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
1908253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
1909253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME,
19107857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
19117857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
19127857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
19137857cb8dSJiaqing Zhao     }
19147857cb8dSJiaqing Zhao     else
19157857cb8dSJiaqing Zhao     {
1916*539d8c6bSEd Tanous         jsonResponse["EthernetInterfaceType"] =
1917*539d8c6bSEd Tanous             ethernet_interface::EthernetDeviceType::Physical;
19187857cb8dSJiaqing Zhao     }
19197857cb8dSJiaqing Zhao 
19202c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
19212c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
19224a0cb85cSEd Tanous 
19232c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
19242c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
19252c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
19262c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
19279eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
19284a0cb85cSEd Tanous     {
19292c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1930fa5053a6SGunnar Mills         if (gatewayStr.empty())
1931fa5053a6SGunnar Mills         {
1932fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1933fa5053a6SGunnar Mills         }
19341476687dSEd Tanous         nlohmann::json::object_t ipv4;
19351476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
19361476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
19371476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
19381476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1939fa5053a6SGunnar Mills 
19402c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1941d1d50814SRavi Teja         {
19421476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1943d1d50814SRavi Teja         }
19441476687dSEd Tanous 
1945b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
194601784826SJohnathan Mantey     }
1947d1d50814SRavi Teja 
194882695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
19497ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
19507ea79e5eSRavi Teja     {
19517ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
19527ea79e5eSRavi Teja     }
19537ea79e5eSRavi Teja 
19547ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1955e48c0fc5SRavi Teja 
1956ce73d5c8SSunitha Harish     nlohmann::json::array_t ipv6StaticGatewayArray;
1957ce73d5c8SSunitha Harish     for (const auto& ipv6GatewayConfig : ipv6GatewayData)
1958ce73d5c8SSunitha Harish     {
1959ce73d5c8SSunitha Harish         nlohmann::json::object_t ipv6Gateway;
1960ce73d5c8SSunitha Harish         ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
1961ce73d5c8SSunitha Harish         ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength;
1962ce73d5c8SSunitha Harish         ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
1963ce73d5c8SSunitha Harish     }
1964ce73d5c8SSunitha Harish     jsonResponse["IPv6StaticDefaultGateways"] =
1965ce73d5c8SSunitha Harish         std::move(ipv6StaticGatewayArray);
1966ce73d5c8SSunitha Harish 
19672c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
19682c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
19692c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
19702c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
19717f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
19722c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
19737f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
19749eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1975e48c0fc5SRavi Teja     {
19761476687dSEd Tanous         nlohmann::json::object_t ipv6;
19771476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
19781476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
19791476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1980f8361275SSunitha Harish 
1981b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
19822c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1983e48c0fc5SRavi Teja         {
19841476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
19851476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
19861476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1987b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
198801784826SJohnathan Mantey         }
1989e48c0fc5SRavi Teja     }
1990588c3f0dSKowalski, Kamil }
1991588c3f0dSKowalski, Kamil 
1992e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1993e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1994e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1995e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1996e7caf250SJiaqing Zhao {
1997e7caf250SJiaqing Zhao     if (!ec)
1998e7caf250SJiaqing Zhao     {
1999e7caf250SJiaqing Zhao         return;
2000e7caf250SJiaqing Zhao     }
2001e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
2002e7caf250SJiaqing Zhao     if (dbusError == nullptr)
2003e7caf250SJiaqing Zhao     {
2004e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
2005e7caf250SJiaqing Zhao         return;
2006e7caf250SJiaqing Zhao     }
200762598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2008e7caf250SJiaqing Zhao 
2009e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
2010e7caf250SJiaqing Zhao         dbusError->name)
2011e7caf250SJiaqing Zhao     {
2012e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2013e7caf250SJiaqing Zhao                                    ifaceId);
2014e7caf250SJiaqing Zhao         return;
2015e7caf250SJiaqing Zhao     }
2016e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
2017e7caf250SJiaqing Zhao         dbusError->name)
2018e7caf250SJiaqing Zhao     {
2019e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
2020e7caf250SJiaqing Zhao         return;
2021e7caf250SJiaqing Zhao     }
2022e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
2023e7caf250SJiaqing Zhao }
2024e7caf250SJiaqing Zhao 
2025b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2026b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
2027b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
2028b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
2029b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
2030b5ca3fdcSJiaqing Zhao 
2031b5ca3fdcSJiaqing Zhao )
2032b5ca3fdcSJiaqing Zhao {
2033b5ca3fdcSJiaqing Zhao     if (ec)
2034b5ca3fdcSJiaqing Zhao     {
2035b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
2036b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
2037b5ca3fdcSJiaqing Zhao         {
2038b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
2039b5ca3fdcSJiaqing Zhao             return;
2040b5ca3fdcSJiaqing Zhao         }
204162598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2042b5ca3fdcSJiaqing Zhao 
2043b5ca3fdcSJiaqing Zhao         if (std::string_view(
2044b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
2045b5ca3fdcSJiaqing Zhao             dbusError->name)
2046b5ca3fdcSJiaqing Zhao         {
2047b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2048b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2049b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2050b5ca3fdcSJiaqing Zhao             return;
2051b5ca3fdcSJiaqing Zhao         }
2052b5ca3fdcSJiaqing Zhao         if (std::string_view(
2053b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
2054b5ca3fdcSJiaqing Zhao             dbusError->name)
2055b5ca3fdcSJiaqing Zhao         {
2056b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
2057b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
2058b5ca3fdcSJiaqing Zhao             return;
2059b5ca3fdcSJiaqing Zhao         }
2060b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
2061b5ca3fdcSJiaqing Zhao         return;
2062b5ca3fdcSJiaqing Zhao     }
2063b5ca3fdcSJiaqing Zhao 
2064253f11b8SEd Tanous     const boost::urls::url vlanInterfaceUri =
2065253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}",
2066253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface);
2067b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
2068b5ca3fdcSJiaqing Zhao }
2069b5ca3fdcSJiaqing Zhao 
2070bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
2071bf648f77SEd Tanous {
2072253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
2073ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
20741476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
20751476687dSEd Tanous             [&app](const crow::Request& req,
2076253f11b8SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2077253f11b8SEd Tanous                    const std::string& managerId) {
20783ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
207945ca1b86SEd Tanous         {
208045ca1b86SEd Tanous             return;
208145ca1b86SEd Tanous         }
208245ca1b86SEd Tanous 
2083253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2084253f11b8SEd Tanous         {
2085253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2086253f11b8SEd Tanous             return;
2087253f11b8SEd Tanous         }
2088253f11b8SEd Tanous 
2089bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2090bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2091bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2092253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
2093253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2094bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
2095bf648f77SEd Tanous             "Ethernet Network Interface Collection";
2096bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
2097bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
2098bf648f77SEd Tanous 
2099bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
2100bf648f77SEd Tanous         // preparation
2101002d39b4SEd Tanous         getEthernetIfaceList(
210277179532SEd Tanous             [asyncResp](const bool& success,
210377179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
2104bf648f77SEd Tanous             if (!success)
21051abe55efSEd Tanous             {
2106f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
21079391bb9cSRapkiewicz, Pawel                 return;
21089391bb9cSRapkiewicz, Pawel             }
21099391bb9cSRapkiewicz, Pawel 
2110002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2111bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
2112bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
2113bf648f77SEd Tanous             {
21141476687dSEd Tanous                 nlohmann::json::object_t iface;
2115ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
2116253f11b8SEd Tanous                     "/redfish/v1/Managers/{}/EthernetInterfaces/{}",
2117253f11b8SEd Tanous                     BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem);
21187857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
2119bf648f77SEd Tanous             }
2120bf648f77SEd Tanous 
2121002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
2122253f11b8SEd Tanous             asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2123253f11b8SEd Tanous                 "/redfish/v1/Managers/{}/EthernetInterfaces",
2124253f11b8SEd Tanous                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2125bf648f77SEd Tanous         });
2126bf648f77SEd Tanous     });
2127bf648f77SEd Tanous 
2128253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
2129b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
2130b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
2131b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
2132253f11b8SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2133253f11b8SEd Tanous                    const std::string& managerId) {
2134b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2135b5ca3fdcSJiaqing Zhao         {
2136b5ca3fdcSJiaqing Zhao             return;
2137b5ca3fdcSJiaqing Zhao         }
2138b5ca3fdcSJiaqing Zhao 
2139253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2140253f11b8SEd Tanous         {
2141253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2142253f11b8SEd Tanous             return;
2143253f11b8SEd Tanous         }
2144253f11b8SEd Tanous 
2145b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
2146b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
21473dfed536SEd Tanous         std::vector<nlohmann::json::object_t> relatedInterfaces;
2148b5ca3fdcSJiaqing Zhao 
2149b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
2150b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
2151b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
2152b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
2153b5ca3fdcSJiaqing Zhao         {
2154b5ca3fdcSJiaqing Zhao             return;
2155b5ca3fdcSJiaqing Zhao         }
2156b5ca3fdcSJiaqing Zhao 
2157b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
2158b5ca3fdcSJiaqing Zhao         {
2159b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
2160b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
2161b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
2162b5ca3fdcSJiaqing Zhao             return;
2163b5ca3fdcSJiaqing Zhao         }
2164b5ca3fdcSJiaqing Zhao 
2165b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
21663dfed536SEd Tanous         if (!json_util::readJsonObject(relatedInterfaces[0], asyncResp->res,
2167b5ca3fdcSJiaqing Zhao                                        "@odata.id", parentInterfaceUri))
2168b5ca3fdcSJiaqing Zhao         {
2169b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
2170b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
2171b5ca3fdcSJiaqing Zhao             return;
2172b5ca3fdcSJiaqing Zhao         }
217362598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
2174b5ca3fdcSJiaqing Zhao 
21756fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
2176b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
2177b5ca3fdcSJiaqing Zhao         if (!parsedUri)
2178b5ca3fdcSJiaqing Zhao         {
2179b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
2180b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2181b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2182b5ca3fdcSJiaqing Zhao             return;
2183b5ca3fdcSJiaqing Zhao         }
2184b5ca3fdcSJiaqing Zhao 
2185b5ca3fdcSJiaqing Zhao         std::string parentInterface;
2186b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
2187b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
2188b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
2189b5ca3fdcSJiaqing Zhao         {
2190b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2191b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2192b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2193b5ca3fdcSJiaqing Zhao             return;
2194b5ca3fdcSJiaqing Zhao         }
2195b5ca3fdcSJiaqing Zhao 
2196b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
2197b5ca3fdcSJiaqing Zhao         {
2198b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
2199b5ca3fdcSJiaqing Zhao             // create
2200b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
2201b5ca3fdcSJiaqing Zhao                                              "false");
2202b5ca3fdcSJiaqing Zhao             return;
2203b5ca3fdcSJiaqing Zhao         }
2204b5ca3fdcSJiaqing Zhao 
2205b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
2206b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
2207b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
2208b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
2209b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
2210b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
2211b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
2212b5ca3fdcSJiaqing Zhao                             m);
2213b5ca3fdcSJiaqing Zhao         },
2214b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
2215b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
2216b5ca3fdcSJiaqing Zhao             vlanId);
2217b5ca3fdcSJiaqing Zhao     });
2218b5ca3fdcSJiaqing Zhao 
2219253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2220ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
2221bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
222245ca1b86SEd Tanous             [&app](const crow::Request& req,
2223bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2224253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
22253ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
222645ca1b86SEd Tanous         {
222745ca1b86SEd Tanous             return;
222845ca1b86SEd Tanous         }
2229253f11b8SEd Tanous 
2230253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2231253f11b8SEd Tanous         {
2232253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2233253f11b8SEd Tanous             return;
2234253f11b8SEd Tanous         }
2235253f11b8SEd Tanous 
22364a0cb85cSEd Tanous         getEthernetIfaceData(
2237bf648f77SEd Tanous             ifaceId,
2238ce73d5c8SSunitha Harish             [asyncResp,
2239ce73d5c8SSunitha Harish              ifaceId](const bool& success, const EthernetInterfaceData& ethData,
224077179532SEd Tanous                       const std::vector<IPv4AddressData>& ipv4Data,
2241ce73d5c8SSunitha Harish                       const std::vector<IPv6AddressData>& ipv6Data,
2242ce73d5c8SSunitha Harish                       const std::vector<StaticGatewayData>& ipv6GatewayData) {
22434a0cb85cSEd Tanous             if (!success)
22441abe55efSEd Tanous             {
2245bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2246bf648f77SEd Tanous                 // existing object, and other errors
2247002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2248002d39b4SEd Tanous                                            ifaceId);
22494a0cb85cSEd Tanous                 return;
22509391bb9cSRapkiewicz, Pawel             }
22514c9afe43SEd Tanous 
22520f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
225393bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
2254002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
22550f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
22560f74e643SEd Tanous                 "Management Network Interface";
22570f74e643SEd Tanous 
2258ce73d5c8SSunitha Harish             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data,
2259ce73d5c8SSunitha Harish                                ipv6GatewayData);
22609391bb9cSRapkiewicz, Pawel         });
2261bf648f77SEd Tanous     });
22629391bb9cSRapkiewicz, Pawel 
2263253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2264ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2265bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
226645ca1b86SEd Tanous             [&app](const crow::Request& req,
2267bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2268253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
22693ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
227045ca1b86SEd Tanous         {
227145ca1b86SEd Tanous             return;
227245ca1b86SEd Tanous         }
2273253f11b8SEd Tanous 
2274253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2275253f11b8SEd Tanous         {
2276253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2277253f11b8SEd Tanous             return;
2278253f11b8SEd Tanous         }
2279253f11b8SEd Tanous 
2280bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2281ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2282d577665bSRatan Gupta         std::optional<std::string> macAddress;
22839a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
22843dfed536SEd Tanous         std::optional<
22853dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
22863dfed536SEd Tanous             ipv4StaticAddresses;
22873dfed536SEd Tanous         std::optional<
22883dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
22893dfed536SEd Tanous             ipv6StaticAddresses;
22903dfed536SEd Tanous         std::optional<
22913dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
22923dfed536SEd Tanous             ipv6StaticDefaultGateways;
2293f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2294b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2295eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
229635fb5311STejas Patil         std::optional<size_t> mtuSize;
22971f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
22981f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2299b10d8db0SRavi Teja         // clang-format off
23003dfed536SEd Tanous         if (!json_util::readJsonPatch(req, asyncResp->res,
23013dfed536SEd Tanous                 "DHCPv4/DHCPEnabled",   v4dhcpParms.dhcpv4Enabled,
23023dfed536SEd Tanous                 "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers,
23033dfed536SEd Tanous                 "DHCPv4/UseDomainName", v4dhcpParms.useDomainName,
23043dfed536SEd Tanous                 "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers,
23053dfed536SEd Tanous                 "DHCPv6/OperatingMode", v6dhcpParms.dhcpv6OperatingMode,
23063dfed536SEd Tanous                 "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers,
23073dfed536SEd Tanous                 "DHCPv6/UseDomainName", v6dhcpParms.useDomainName,
23083dfed536SEd Tanous                 "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers,
2309b10d8db0SRavi Teja                 "FQDN", fqdn,
2310b10d8db0SRavi Teja                 "HostName", hostname,
2311b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2312b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2313b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2314ce73d5c8SSunitha Harish                 "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways,
2315b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2316b10d8db0SRavi Teja                 "MACAddress", macAddress,
2317b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2318b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2319b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2320b10d8db0SRavi Teja                 )
2321b10d8db0SRavi Teja             )
23221abe55efSEd Tanous         {
2323588c3f0dSKowalski, Kamil             return;
2324588c3f0dSKowalski, Kamil         }
2325b10d8db0SRavi Teja         // clang-format on
2326da131a9aSJennifer Lee 
2327bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2328bf648f77SEd Tanous         // for JSON preparation
23294a0cb85cSEd Tanous         getEthernetIfaceData(
23302c70f800SEd Tanous             ifaceId,
2331bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2332ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2333d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
23349a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2335e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2336ce73d5c8SSunitha Harish              ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways),
23373dfed536SEd Tanous              staticNameServers = std::move(staticNameServers), mtuSize,
2338b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2339f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
23403dfed536SEd Tanous                 const bool success, const EthernetInterfaceData& ethData,
234177179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
2342ce73d5c8SSunitha Harish                 const std::vector<IPv6AddressData>& ipv6Data,
23433dfed536SEd Tanous                 const std::vector<StaticGatewayData>& ipv6GatewayData) mutable {
23441abe55efSEd Tanous             if (!success)
23451abe55efSEd Tanous             {
2346588c3f0dSKowalski, Kamil                 // ... otherwise return error
2347bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2348bf648f77SEd Tanous                 // existing object, and other errors
2349002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2350002d39b4SEd Tanous                                            ifaceId);
2351588c3f0dSKowalski, Kamil                 return;
2352588c3f0dSKowalski, Kamil             }
2353588c3f0dSKowalski, Kamil 
2354002d39b4SEd Tanous             handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2355002d39b4SEd Tanous                             asyncResp);
23561f8c7b5dSJohnathan Mantey 
23570627a2c7SEd Tanous             if (hostname)
23581abe55efSEd Tanous             {
23590627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
23601abe55efSEd Tanous             }
23610627a2c7SEd Tanous 
2362b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2363b10d8db0SRavi Teja             {
2364b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2365b10d8db0SRavi Teja                                            asyncResp);
2366b10d8db0SRavi Teja             }
2367b10d8db0SRavi Teja 
2368ab6554f1SJoshi-Mansi             if (fqdn)
2369ab6554f1SJoshi-Mansi             {
23702c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2371ab6554f1SJoshi-Mansi             }
2372ab6554f1SJoshi-Mansi 
2373d577665bSRatan Gupta             if (macAddress)
2374d577665bSRatan Gupta             {
2375002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2376d577665bSRatan Gupta             }
2377d577665bSRatan Gupta 
2378d1d50814SRavi Teja             if (ipv4StaticAddresses)
2379d1d50814SRavi Teja             {
2380743eb1c0SJohnathan Mantey                 handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ethData,
2381743eb1c0SJohnathan Mantey                                       ipv4Data, asyncResp);
23821abe55efSEd Tanous             }
23830627a2c7SEd Tanous 
2384f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2385f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2386002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2387002d39b4SEd Tanous                                              asyncResp);
2388f85837bfSRAJESWARAN THILLAIGOVINDAN             }
23899a6fc6feSRavi Teja 
23909a6fc6feSRavi Teja             if (ipv6DefaultGateway)
23919a6fc6feSRavi Teja             {
23929a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
23939a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
23949a6fc6feSRavi Teja             }
2395e48c0fc5SRavi Teja 
2396e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2397e48c0fc5SRavi Teja             {
2398ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2399ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2400e48c0fc5SRavi Teja             }
2401eeedda23SJohnathan Mantey 
2402ce73d5c8SSunitha Harish             if (ipv6StaticDefaultGateway)
2403ce73d5c8SSunitha Harish             {
2404ce73d5c8SSunitha Harish                 handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway,
2405ce73d5c8SSunitha Harish                                          ipv6GatewayData, asyncResp);
2406ce73d5c8SSunitha Harish             }
2407ce73d5c8SSunitha Harish 
2408eeedda23SJohnathan Mantey             if (interfaceEnabled)
2409eeedda23SJohnathan Mantey             {
2410e93abac6SGinu George                 setDbusProperty(asyncResp, "InterfaceEnabled",
2411e93abac6SGinu George                                 "xyz.openbmc_project.Network",
2412d02aad39SEd Tanous                                 sdbusplus::message::object_path(
2413d02aad39SEd Tanous                                     "/xyz/openbmc_project/network") /
2414d02aad39SEd Tanous                                     ifaceId,
2415d02aad39SEd Tanous                                 "xyz.openbmc_project.Network.EthernetInterface",
2416e93abac6SGinu George                                 "NICEnabled", *interfaceEnabled);
2417eeedda23SJohnathan Mantey             }
241835fb5311STejas Patil 
241935fb5311STejas Patil             if (mtuSize)
242035fb5311STejas Patil             {
242135fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
242235fb5311STejas Patil             }
2423588c3f0dSKowalski, Kamil         });
2424bf648f77SEd Tanous     });
2425e7caf250SJiaqing Zhao 
2426253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2427e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2428e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2429e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2430e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2431253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
2432e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2433e7caf250SJiaqing Zhao         {
2434e7caf250SJiaqing Zhao             return;
2435e7caf250SJiaqing Zhao         }
2436e7caf250SJiaqing Zhao 
2437253f11b8SEd Tanous         if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2438253f11b8SEd Tanous         {
2439253f11b8SEd Tanous             messages::resourceNotFound(asyncResp->res, "Manager", managerId);
2440253f11b8SEd Tanous             return;
2441253f11b8SEd Tanous         }
2442253f11b8SEd Tanous 
2443e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2444e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2445e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2446e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2447e7caf250SJiaqing Zhao         },
2448e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2449e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2450e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2451e7caf250SJiaqing Zhao     });
24524a0cb85cSEd Tanous }
2453bf648f77SEd Tanous 
24549391bb9cSRapkiewicz, Pawel } // namespace redfish
2455