xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision d547d8d2c30a7d00852855da8ecc15c0cc424b0e)
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 
1813451e39SWilly Tu #include "bmcweb_config.h"
1913451e39SWilly Tu 
203ccb3adbSEd Tanous #include "app.hpp"
213ccb3adbSEd Tanous #include "dbus_singleton.hpp"
227a1dbc48SGeorge Liu #include "dbus_utility.hpp"
233ccb3adbSEd Tanous #include "error_messages.hpp"
243ccb3adbSEd Tanous #include "health.hpp"
252c5875a2SEd Tanous #include "human_sort.hpp"
263ccb3adbSEd Tanous #include "query.hpp"
273ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
28033f1e4dSEd Tanous #include "utils/ip_utils.hpp"
293ccb3adbSEd Tanous #include "utils/json_utils.hpp"
30033f1e4dSEd Tanous 
31ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp>
32ef4c65b7SEd Tanous #include <boost/url/format.hpp>
331214b7e7SGunnar Mills 
347a1dbc48SGeorge Liu #include <array>
35ce73d5c8SSunitha Harish #include <memory>
36a24526dcSEd Tanous #include <optional>
373544d2a7SEd Tanous #include <ranges>
38ab6554f1SJoshi-Mansi #include <regex>
397a1dbc48SGeorge Liu #include <string_view>
4077179532SEd Tanous #include <vector>
419391bb9cSRapkiewicz, Pawel 
421abe55efSEd Tanous namespace redfish
431abe55efSEd Tanous {
449391bb9cSRapkiewicz, Pawel 
454a0cb85cSEd Tanous enum class LinkType
464a0cb85cSEd Tanous {
474a0cb85cSEd Tanous     Local,
484a0cb85cSEd Tanous     Global
494a0cb85cSEd Tanous };
509391bb9cSRapkiewicz, Pawel 
519391bb9cSRapkiewicz, Pawel /**
529391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
539391bb9cSRapkiewicz, Pawel  */
541abe55efSEd Tanous struct IPv4AddressData
551abe55efSEd Tanous {
56179db1d7SKowalski, Kamil     std::string id;
574a0cb85cSEd Tanous     std::string address;
584a0cb85cSEd Tanous     std::string domain;
594a0cb85cSEd Tanous     std::string gateway;
609391bb9cSRapkiewicz, Pawel     std::string netmask;
619391bb9cSRapkiewicz, Pawel     std::string origin;
6277179532SEd Tanous     LinkType linktype{};
6377179532SEd Tanous     bool isActive{};
649391bb9cSRapkiewicz, Pawel };
659391bb9cSRapkiewicz, Pawel 
669391bb9cSRapkiewicz, Pawel /**
67e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
68e48c0fc5SRavi Teja  */
69e48c0fc5SRavi Teja struct IPv6AddressData
70e48c0fc5SRavi Teja {
71e48c0fc5SRavi Teja     std::string id;
72e48c0fc5SRavi Teja     std::string address;
73e48c0fc5SRavi Teja     std::string origin;
7477179532SEd Tanous     uint8_t prefixLength = 0;
75e48c0fc5SRavi Teja };
76ce73d5c8SSunitha Harish 
77ce73d5c8SSunitha Harish /**
78ce73d5c8SSunitha Harish  * Structure for keeping static route data required by Redfish
79ce73d5c8SSunitha Harish  */
80ce73d5c8SSunitha Harish struct StaticGatewayData
81ce73d5c8SSunitha Harish {
82ce73d5c8SSunitha Harish     std::string id;
83ce73d5c8SSunitha Harish     std::string gateway;
84ce73d5c8SSunitha Harish     size_t prefixLength = 0;
85ce73d5c8SSunitha Harish     std::string protocol;
86ce73d5c8SSunitha Harish };
87ce73d5c8SSunitha Harish 
88e48c0fc5SRavi Teja /**
899391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
909391bb9cSRapkiewicz, Pawel  * available from DBus
919391bb9cSRapkiewicz, Pawel  */
921abe55efSEd Tanous struct EthernetInterfaceData
931abe55efSEd Tanous {
944a0cb85cSEd Tanous     uint32_t speed;
9535fb5311STejas Patil     size_t mtuSize;
9682695a5bSJiaqing Zhao     bool autoNeg;
97e4588158SJishnu CM     bool dnsv4Enabled;
98e4588158SJishnu CM     bool dnsv6Enabled;
9991c441ecSRavi Teja     bool domainv4Enabled;
10091c441ecSRavi Teja     bool domainv6Enabled;
101e4588158SJishnu CM     bool ntpv4Enabled;
102e4588158SJishnu CM     bool ntpv6Enabled;
103e4588158SJishnu CM     bool hostNamev4Enabled;
104e4588158SJishnu CM     bool hostNamev6Enabled;
105aa05fb27SJohnathan Mantey     bool linkUp;
106eeedda23SJohnathan Mantey     bool nicEnabled;
107b10d8db0SRavi Teja     bool ipv6AcceptRa;
10882695a5bSJiaqing Zhao     std::string dhcpEnabled;
1091f8c7b5dSJohnathan Mantey     std::string operatingMode;
11082695a5bSJiaqing Zhao     std::string hostName;
11182695a5bSJiaqing Zhao     std::string defaultGateway;
11282695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
113ce73d5c8SSunitha Harish     std::string ipv6StaticDefaultGateway;
11482695a5bSJiaqing Zhao     std::string macAddress;
11517e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
1160f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1170f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
118d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1199391bb9cSRapkiewicz, Pawel };
1209391bb9cSRapkiewicz, Pawel 
1211f8c7b5dSJohnathan Mantey struct DHCPParameters
1221f8c7b5dSJohnathan Mantey {
1231f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
12482695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
12582695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
12682695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1271f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1281f8c7b5dSJohnathan Mantey };
1291f8c7b5dSJohnathan Mantey 
1309391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1319391bb9cSRapkiewicz, Pawel // into full dot notation
1321abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1331abe55efSEd Tanous {
1349391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1359391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1369391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1379391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1389391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1399391bb9cSRapkiewicz, Pawel     return netmask;
1409391bb9cSRapkiewicz, Pawel }
1419391bb9cSRapkiewicz, Pawel 
14282695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1431f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1441f8c7b5dSJohnathan Mantey {
1451f8c7b5dSJohnathan Mantey     if (isIPv4)
1461f8c7b5dSJohnathan Mantey     {
1471f8c7b5dSJohnathan Mantey         return (
1481f8c7b5dSJohnathan Mantey             (inputDHCP ==
1491f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1501f8c7b5dSJohnathan Mantey             (inputDHCP ==
1511f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1521f8c7b5dSJohnathan Mantey     }
1531f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1541f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1551f8c7b5dSJohnathan Mantey             (inputDHCP ==
1561f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1571f8c7b5dSJohnathan Mantey }
1581f8c7b5dSJohnathan Mantey 
1592c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1601f8c7b5dSJohnathan Mantey {
1611f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1621f8c7b5dSJohnathan Mantey     {
1631f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1641f8c7b5dSJohnathan Mantey     }
1653174e4dfSEd Tanous     if (isIPv4)
1661f8c7b5dSJohnathan Mantey     {
1671f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1681f8c7b5dSJohnathan Mantey     }
1693174e4dfSEd Tanous     if (isIPv6)
1701f8c7b5dSJohnathan Mantey     {
1711f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1721f8c7b5dSJohnathan Mantey     }
1731f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1741f8c7b5dSJohnathan Mantey }
1751f8c7b5dSJohnathan Mantey 
1764a0cb85cSEd Tanous inline std::string
1774a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1784a0cb85cSEd Tanous                                         bool isIPv4)
1791abe55efSEd Tanous {
1804a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1811abe55efSEd Tanous     {
1824a0cb85cSEd Tanous         return "Static";
1839391bb9cSRapkiewicz, Pawel     }
1844a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1851abe55efSEd Tanous     {
1864a0cb85cSEd Tanous         if (isIPv4)
1871abe55efSEd Tanous         {
1884a0cb85cSEd Tanous             return "IPv4LinkLocal";
1891abe55efSEd Tanous         }
1904a0cb85cSEd Tanous         return "LinkLocal";
1919391bb9cSRapkiewicz, Pawel     }
1924a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1931abe55efSEd Tanous     {
1944a0cb85cSEd Tanous         if (isIPv4)
1954a0cb85cSEd Tanous         {
1964a0cb85cSEd Tanous             return "DHCP";
1974a0cb85cSEd Tanous         }
1984a0cb85cSEd Tanous         return "DHCPv6";
1994a0cb85cSEd Tanous     }
2004a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
2014a0cb85cSEd Tanous     {
2024a0cb85cSEd Tanous         return "SLAAC";
2034a0cb85cSEd Tanous     }
2044a0cb85cSEd Tanous     return "";
2054a0cb85cSEd Tanous }
2064a0cb85cSEd Tanous 
20702cad96eSEd Tanous inline bool extractEthernetInterfaceData(
20802cad96eSEd Tanous     const std::string& ethifaceId,
20902cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
2104a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
2114a0cb85cSEd Tanous {
2124c9afe43SEd Tanous     bool idFound = false;
21302cad96eSEd Tanous     for (const auto& objpath : dbusData)
2144a0cb85cSEd Tanous     {
21502cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
2164a0cb85cSEd Tanous         {
21781ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
218029573d4SEd Tanous             {
2194c9afe43SEd Tanous                 idFound = true;
2204a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2214a0cb85cSEd Tanous                 {
2224a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2234a0cb85cSEd Tanous                     {
2244a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2254a0cb85cSEd Tanous                         {
2264a0cb85cSEd Tanous                             const std::string* mac =
227abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2284a0cb85cSEd Tanous                             if (mac != nullptr)
2294a0cb85cSEd Tanous                             {
23082695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2314a0cb85cSEd Tanous                             }
2324a0cb85cSEd Tanous                         }
2334a0cb85cSEd Tanous                     }
2344a0cb85cSEd Tanous                 }
2354a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2364a0cb85cSEd Tanous                 {
2374a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2384a0cb85cSEd Tanous                     {
2394a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2404a0cb85cSEd Tanous                         {
2411b6b96c5SEd Tanous                             const uint32_t* id =
242abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2434a0cb85cSEd Tanous                             if (id != nullptr)
2444a0cb85cSEd Tanous                             {
24517e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2464a0cb85cSEd Tanous                             }
2474a0cb85cSEd Tanous                         }
2484a0cb85cSEd Tanous                     }
2494a0cb85cSEd Tanous                 }
2504a0cb85cSEd Tanous                 else if (ifacePair.first ==
2514a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2524a0cb85cSEd Tanous                 {
2534a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2544a0cb85cSEd Tanous                     {
2554a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2564a0cb85cSEd Tanous                         {
2572c70f800SEd Tanous                             const bool* autoNeg =
258abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2592c70f800SEd Tanous                             if (autoNeg != nullptr)
2604a0cb85cSEd Tanous                             {
26182695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2624a0cb85cSEd Tanous                             }
2634a0cb85cSEd Tanous                         }
2644a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2654a0cb85cSEd Tanous                         {
2664a0cb85cSEd Tanous                             const uint32_t* speed =
267abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2684a0cb85cSEd Tanous                             if (speed != nullptr)
2694a0cb85cSEd Tanous                             {
2704a0cb85cSEd Tanous                                 ethData.speed = *speed;
2714a0cb85cSEd Tanous                             }
2724a0cb85cSEd Tanous                         }
27335fb5311STejas Patil                         else if (propertyPair.first == "MTU")
27435fb5311STejas Patil                         {
2753e7a8da6SAnthony                             const size_t* mtuSize =
2763e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
27735fb5311STejas Patil                             if (mtuSize != nullptr)
27835fb5311STejas Patil                             {
27935fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
28035fb5311STejas Patil                             }
28135fb5311STejas Patil                         }
282aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
283aa05fb27SJohnathan Mantey                         {
284aa05fb27SJohnathan Mantey                             const bool* linkUp =
285aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
286aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
287aa05fb27SJohnathan Mantey                             {
288aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
289aa05fb27SJohnathan Mantey                             }
290aa05fb27SJohnathan Mantey                         }
291eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
292eeedda23SJohnathan Mantey                         {
293eeedda23SJohnathan Mantey                             const bool* nicEnabled =
294eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
295eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
296eeedda23SJohnathan Mantey                             {
297eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
298eeedda23SJohnathan Mantey                             }
299eeedda23SJohnathan Mantey                         }
300b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
301b10d8db0SRavi Teja                         {
302b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
303b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
304b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
305b10d8db0SRavi Teja                             {
306b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
307b10d8db0SRavi Teja                             }
308b10d8db0SRavi Teja                         }
309f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
310029573d4SEd Tanous                         {
311029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
3128d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
313029573d4SEd Tanous                                     &propertyPair.second);
314029573d4SEd Tanous                             if (nameservers != nullptr)
315029573d4SEd Tanous                             {
316f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3170f6efdc1Smanojkiran.eda@gmail.com                             }
3180f6efdc1Smanojkiran.eda@gmail.com                         }
3190f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3200f6efdc1Smanojkiran.eda@gmail.com                         {
3210f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3228d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3230f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3240f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3250f6efdc1Smanojkiran.eda@gmail.com                             {
326f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3274a0cb85cSEd Tanous                             }
3284a0cb85cSEd Tanous                         }
3292a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3302a133282Smanojkiraneda                         {
3312c70f800SEd Tanous                             const std::string* dhcpEnabled =
3321f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3332c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3342a133282Smanojkiraneda                             {
33582695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3362a133282Smanojkiraneda                             }
3372a133282Smanojkiraneda                         }
338d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
339d24bfc7aSJennifer Lee                         {
340d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3418d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
342d24bfc7aSJennifer Lee                                     &propertyPair.second);
343d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
344d24bfc7aSJennifer Lee                             {
345f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
346d24bfc7aSJennifer Lee                             }
347d24bfc7aSJennifer Lee                         }
3489010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3499010ec2eSRavi Teja                         {
3509010ec2eSRavi Teja                             const std::string* defaultGateway =
3519010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3529010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3539010ec2eSRavi Teja                             {
3549010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3559010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3569010ec2eSRavi Teja                                 {
35782695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3589010ec2eSRavi Teja                                 }
3599010ec2eSRavi Teja                                 else
3609010ec2eSRavi Teja                                 {
36182695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3629010ec2eSRavi Teja                                 }
3639010ec2eSRavi Teja                             }
3649010ec2eSRavi Teja                         }
3659010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3669010ec2eSRavi Teja                         {
3679010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3689010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3699010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3709010ec2eSRavi Teja                             {
3719010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3729010ec2eSRavi Teja                                     *defaultGateway6;
3739010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3749010ec2eSRavi Teja                                 {
37582695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3769010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3779010ec2eSRavi Teja                                 }
3789010ec2eSRavi Teja                                 else
3799010ec2eSRavi Teja                                 {
38082695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3819010ec2eSRavi Teja                                         defaultGateway6Str;
3829010ec2eSRavi Teja                                 }
3839010ec2eSRavi Teja                             }
3849010ec2eSRavi Teja                         }
385029573d4SEd Tanous                     }
386029573d4SEd Tanous                 }
387029573d4SEd Tanous             }
3881f8c7b5dSJohnathan Mantey 
389e4588158SJishnu CM             sdbusplus::message::object_path path(
390e4588158SJishnu CM                 "/xyz/openbmc_project/network");
391e4588158SJishnu CM             sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
392e4588158SJishnu CM                                                         "dhcp4";
393e4588158SJishnu CM 
394e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
3951f8c7b5dSJohnathan Mantey             {
3961f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
3971f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
3981f8c7b5dSJohnathan Mantey                 {
3991f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
4001f8c7b5dSJohnathan Mantey                     {
4011f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
4021f8c7b5dSJohnathan Mantey                         {
4032c70f800SEd Tanous                             const bool* dnsEnabled =
4041f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4052c70f800SEd Tanous                             if (dnsEnabled != nullptr)
4061f8c7b5dSJohnathan Mantey                             {
407e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
4081f8c7b5dSJohnathan Mantey                             }
4091f8c7b5dSJohnathan Mantey                         }
41091c441ecSRavi Teja                         else if (propertyPair.first == "DomainEnabled")
41191c441ecSRavi Teja                         {
41291c441ecSRavi Teja                             const bool* domainEnabled =
41391c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
41491c441ecSRavi Teja                             if (domainEnabled != nullptr)
41591c441ecSRavi Teja                             {
41691c441ecSRavi Teja                                 ethData.domainv4Enabled = *domainEnabled;
41791c441ecSRavi Teja                             }
41891c441ecSRavi Teja                         }
4191f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
4201f8c7b5dSJohnathan Mantey                         {
4212c70f800SEd Tanous                             const bool* ntpEnabled =
4221f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4232c70f800SEd Tanous                             if (ntpEnabled != nullptr)
4241f8c7b5dSJohnathan Mantey                             {
425e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4261f8c7b5dSJohnathan Mantey                             }
4271f8c7b5dSJohnathan Mantey                         }
4281f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4291f8c7b5dSJohnathan Mantey                         {
4302c70f800SEd Tanous                             const bool* hostNameEnabled =
4311f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4322c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4331f8c7b5dSJohnathan Mantey                             {
434e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
435e4588158SJishnu CM                             }
436e4588158SJishnu CM                         }
437e4588158SJishnu CM                     }
438e4588158SJishnu CM                 }
439e4588158SJishnu CM             }
440e4588158SJishnu CM 
441e4588158SJishnu CM             sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
442e4588158SJishnu CM                                                         "dhcp6";
443e4588158SJishnu CM 
444e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
445e4588158SJishnu CM             {
446e4588158SJishnu CM                 if (ifacePair.first ==
447e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
448e4588158SJishnu CM                 {
449e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
450e4588158SJishnu CM                     {
451e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
452e4588158SJishnu CM                         {
453e4588158SJishnu CM                             const bool* dnsEnabled =
454e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
455e4588158SJishnu CM                             if (dnsEnabled != nullptr)
456e4588158SJishnu CM                             {
457e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
458e4588158SJishnu CM                             }
459e4588158SJishnu CM                         }
46091c441ecSRavi Teja                         if (propertyPair.first == "DomainEnabled")
46191c441ecSRavi Teja                         {
46291c441ecSRavi Teja                             const bool* domainEnabled =
46391c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
46491c441ecSRavi Teja                             if (domainEnabled != nullptr)
46591c441ecSRavi Teja                             {
46691c441ecSRavi Teja                                 ethData.domainv6Enabled = *domainEnabled;
46791c441ecSRavi Teja                             }
46891c441ecSRavi Teja                         }
469e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
470e4588158SJishnu CM                         {
471e4588158SJishnu CM                             const bool* ntpEnabled =
472e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
473e4588158SJishnu CM                             if (ntpEnabled != nullptr)
474e4588158SJishnu CM                             {
475e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
476e4588158SJishnu CM                             }
477e4588158SJishnu CM                         }
478e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
479e4588158SJishnu CM                         {
480e4588158SJishnu CM                             const bool* hostNameEnabled =
481e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
482e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
483e4588158SJishnu CM                             {
484e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
4851f8c7b5dSJohnathan Mantey                             }
4861f8c7b5dSJohnathan Mantey                         }
4871f8c7b5dSJohnathan Mantey                     }
4881f8c7b5dSJohnathan Mantey                 }
4891f8c7b5dSJohnathan Mantey             }
490029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
491029573d4SEd Tanous             // to check eth number
492029573d4SEd Tanous             if (ifacePair.first ==
4934a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4944a0cb85cSEd Tanous             {
4954a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
4964a0cb85cSEd Tanous                 {
4974a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
4984a0cb85cSEd Tanous                     {
4994a0cb85cSEd Tanous                         const std::string* hostname =
5008d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
5014a0cb85cSEd Tanous                         if (hostname != nullptr)
5024a0cb85cSEd Tanous                         {
50382695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
5044a0cb85cSEd Tanous                         }
5054a0cb85cSEd Tanous                     }
5064a0cb85cSEd Tanous                 }
5074a0cb85cSEd Tanous             }
5084a0cb85cSEd Tanous         }
5094a0cb85cSEd Tanous     }
5104c9afe43SEd Tanous     return idFound;
5114a0cb85cSEd Tanous }
5124a0cb85cSEd Tanous 
513e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
51477179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
515711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
51677179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
517e48c0fc5SRavi Teja {
51889492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
51989492a15SPatrick Williams                                     ethifaceId;
520e48c0fc5SRavi Teja 
521e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
522e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
52381ce609eSEd Tanous     for (const auto& objpath : dbusData)
524e48c0fc5SRavi Teja     {
525e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
526353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
527e48c0fc5SRavi Teja         {
5289eb808c1SEd Tanous             for (const auto& interface : objpath.second)
529e48c0fc5SRavi Teja             {
530e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
531e48c0fc5SRavi Teja                 {
5323544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
533353163e9STony Lee                                                      [](const auto& property) {
534353163e9STony Lee                         return property.first == "Type";
535353163e9STony Lee                     });
536353163e9STony Lee                     if (type == interface.second.end())
537353163e9STony Lee                     {
538353163e9STony Lee                         continue;
539353163e9STony Lee                     }
540353163e9STony Lee 
541353163e9STony Lee                     const std::string* typeStr =
542353163e9STony Lee                         std::get_if<std::string>(&type->second);
543353163e9STony Lee 
544353163e9STony Lee                     if (typeStr == nullptr ||
545353163e9STony Lee                         (*typeStr !=
546353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
547353163e9STony Lee                     {
548353163e9STony Lee                         continue;
549353163e9STony Lee                     }
550353163e9STony Lee 
551e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
552e48c0fc5SRavi Teja                     // appropriate
55377179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5542c70f800SEd Tanous                     ipv6Address.id =
555353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5569eb808c1SEd Tanous                     for (const auto& property : interface.second)
557e48c0fc5SRavi Teja                     {
558e48c0fc5SRavi Teja                         if (property.first == "Address")
559e48c0fc5SRavi Teja                         {
560e48c0fc5SRavi Teja                             const std::string* address =
561e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
562e48c0fc5SRavi Teja                             if (address != nullptr)
563e48c0fc5SRavi Teja                             {
5642c70f800SEd Tanous                                 ipv6Address.address = *address;
565e48c0fc5SRavi Teja                             }
566e48c0fc5SRavi Teja                         }
567e48c0fc5SRavi Teja                         else if (property.first == "Origin")
568e48c0fc5SRavi Teja                         {
569e48c0fc5SRavi Teja                             const std::string* origin =
570e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
571e48c0fc5SRavi Teja                             if (origin != nullptr)
572e48c0fc5SRavi Teja                             {
5732c70f800SEd Tanous                                 ipv6Address.origin =
574e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
575e48c0fc5SRavi Teja                                                                         false);
576e48c0fc5SRavi Teja                             }
577e48c0fc5SRavi Teja                         }
578e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
579e48c0fc5SRavi Teja                         {
580e48c0fc5SRavi Teja                             const uint8_t* prefix =
581e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
582e48c0fc5SRavi Teja                             if (prefix != nullptr)
583e48c0fc5SRavi Teja                             {
5842c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
585e48c0fc5SRavi Teja                             }
586e48c0fc5SRavi Teja                         }
587889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
588889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
589889ff694SAsmitha Karunanithi                         {
590889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
591889ff694SAsmitha Karunanithi                         }
592e48c0fc5SRavi Teja                         else
593e48c0fc5SRavi Teja                         {
59462598e31SEd Tanous                             BMCWEB_LOG_ERROR(
59562598e31SEd Tanous                                 "Got extra property: {} on the {} object",
59662598e31SEd Tanous                                 property.first, objpath.first.str);
597e48c0fc5SRavi Teja                         }
598e48c0fc5SRavi Teja                     }
599e48c0fc5SRavi Teja                 }
600e48c0fc5SRavi Teja             }
601e48c0fc5SRavi Teja         }
602e48c0fc5SRavi Teja     }
603e48c0fc5SRavi Teja }
604e48c0fc5SRavi Teja 
6054a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
60677179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
607711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
60877179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
6094a0cb85cSEd Tanous {
61089492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
61189492a15SPatrick Williams                                     ethifaceId;
6124a0cb85cSEd Tanous 
6134a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
6144a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
61581ce609eSEd Tanous     for (const auto& objpath : dbusData)
6164a0cb85cSEd Tanous     {
6174a0cb85cSEd Tanous         // Check if proper pattern for object path appears
618353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
6194a0cb85cSEd Tanous         {
6209eb808c1SEd Tanous             for (const auto& interface : objpath.second)
6214a0cb85cSEd Tanous             {
6224a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
6234a0cb85cSEd Tanous                 {
6243544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
625353163e9STony Lee                                                      [](const auto& property) {
626353163e9STony Lee                         return property.first == "Type";
627353163e9STony Lee                     });
628353163e9STony Lee                     if (type == interface.second.end())
629353163e9STony Lee                     {
630353163e9STony Lee                         continue;
631353163e9STony Lee                     }
632353163e9STony Lee 
633353163e9STony Lee                     const std::string* typeStr =
634353163e9STony Lee                         std::get_if<std::string>(&type->second);
635353163e9STony Lee 
636353163e9STony Lee                     if (typeStr == nullptr ||
637353163e9STony Lee                         (*typeStr !=
638353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
639353163e9STony Lee                     {
640353163e9STony Lee                         continue;
641353163e9STony Lee                     }
642353163e9STony Lee 
6434a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6444a0cb85cSEd Tanous                     // appropriate
64577179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6462c70f800SEd Tanous                     ipv4Address.id =
647353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6489eb808c1SEd Tanous                     for (const auto& property : interface.second)
6494a0cb85cSEd Tanous                     {
6504a0cb85cSEd Tanous                         if (property.first == "Address")
6514a0cb85cSEd Tanous                         {
6524a0cb85cSEd Tanous                             const std::string* address =
653abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6544a0cb85cSEd Tanous                             if (address != nullptr)
6554a0cb85cSEd Tanous                             {
6562c70f800SEd Tanous                                 ipv4Address.address = *address;
6574a0cb85cSEd Tanous                             }
6584a0cb85cSEd Tanous                         }
6594a0cb85cSEd Tanous                         else if (property.first == "Origin")
6604a0cb85cSEd Tanous                         {
6614a0cb85cSEd Tanous                             const std::string* origin =
662abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6634a0cb85cSEd Tanous                             if (origin != nullptr)
6644a0cb85cSEd Tanous                             {
6652c70f800SEd Tanous                                 ipv4Address.origin =
6664a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6674a0cb85cSEd Tanous                                                                         true);
6684a0cb85cSEd Tanous                             }
6694a0cb85cSEd Tanous                         }
6704a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6714a0cb85cSEd Tanous                         {
6724a0cb85cSEd Tanous                             const uint8_t* mask =
673abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6744a0cb85cSEd Tanous                             if (mask != nullptr)
6754a0cb85cSEd Tanous                             {
6764a0cb85cSEd Tanous                                 // convert it to the string
6772c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6784a0cb85cSEd Tanous                             }
6794a0cb85cSEd Tanous                         }
680889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
681889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
682889ff694SAsmitha Karunanithi                         {
683889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
684889ff694SAsmitha Karunanithi                         }
6854a0cb85cSEd Tanous                         else
6864a0cb85cSEd Tanous                         {
68762598e31SEd Tanous                             BMCWEB_LOG_ERROR(
68862598e31SEd Tanous                                 "Got extra property: {} on the {} object",
68962598e31SEd Tanous                                 property.first, objpath.first.str);
6904a0cb85cSEd Tanous                         }
6914a0cb85cSEd Tanous                     }
6924a0cb85cSEd Tanous                     // Check if given address is local, or global
6932c70f800SEd Tanous                     ipv4Address.linktype =
69411ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
69518659d10SJohnathan Mantey                             ? LinkType::Local
69618659d10SJohnathan Mantey                             : LinkType::Global;
6974a0cb85cSEd Tanous                 }
6984a0cb85cSEd Tanous             }
6994a0cb85cSEd Tanous         }
7004a0cb85cSEd Tanous     }
7014a0cb85cSEd Tanous }
702588c3f0dSKowalski, Kamil 
703588c3f0dSKowalski, Kamil /**
70401784826SJohnathan Mantey  * @brief Deletes given IPv4 interface
705179db1d7SKowalski, Kamil  *
706179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
707179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
708179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
709179db1d7SKowalski, Kamil  *
710179db1d7SKowalski, Kamil  * @return None
711179db1d7SKowalski, Kamil  */
7129c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
7139c5e585cSRavi Teja                             const std::string& ipHash,
7148d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7151abe55efSEd Tanous {
71655c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7175e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
7181abe55efSEd Tanous         if (ec)
7191abe55efSEd Tanous         {
720a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7211abe55efSEd Tanous         }
722179db1d7SKowalski, Kamil     },
723179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
7249c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
725179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
726179db1d7SKowalski, Kamil }
727179db1d7SKowalski, Kamil 
728244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway(
729244b6d5bSGunnar Mills     const std::string& ifaceId, const std::string& gateway,
730244b6d5bSGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7319010ec2eSRavi Teja {
7329ae226faSGeorge Liu     sdbusplus::asio::setProperty(
7339ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
7349ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
7359ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
7369ae226faSGeorge Liu         gateway, [asyncResp](const boost::system::error_code& ec) {
7379010ec2eSRavi Teja         if (ec)
7389010ec2eSRavi Teja         {
7399010ec2eSRavi Teja             messages::internalError(asyncResp->res);
7409010ec2eSRavi Teja             return;
7419010ec2eSRavi Teja         }
7429010ec2eSRavi Teja         asyncResp->res.result(boost::beast::http::status::no_content);
7439ae226faSGeorge Liu     });
7449010ec2eSRavi Teja }
745179db1d7SKowalski, Kamil /**
74601784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
747179db1d7SKowalski, Kamil  *
74801784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
74901784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
75001784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
75101784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
752179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
753179db1d7SKowalski, Kamil  *
754179db1d7SKowalski, Kamil  * @return None
755179db1d7SKowalski, Kamil  */
756cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
757cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7588d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7591abe55efSEd Tanous {
7605a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
7615a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
7621abe55efSEd Tanous         if (ec)
7631abe55efSEd Tanous         {
764a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7659010ec2eSRavi Teja             return;
766179db1d7SKowalski, Kamil         }
7679010ec2eSRavi Teja         updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
7689010ec2eSRavi Teja     };
7699010ec2eSRavi Teja 
7709010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7719010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
772179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
773179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
77401784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
775179db1d7SKowalski, Kamil         gateway);
776179db1d7SKowalski, Kamil }
777e48c0fc5SRavi Teja 
778e48c0fc5SRavi Teja /**
77901784826SJohnathan Mantey  * @brief Deletes the IPv6 entry for this interface and creates a replacement
78001784826SJohnathan Mantey  * static IPv6 entry
78101784826SJohnathan Mantey  *
78201784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv6 entry
78301784826SJohnathan Mantey  * @param[in] id           The unique hash entry identifying the DBus entry
78401784826SJohnathan Mantey  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
78501784826SJohnathan Mantey  * @param[in] address      IPv6 address to assign to this interface
78601784826SJohnathan Mantey  * @param[io] asyncResp    Response object that will be returned to client
78701784826SJohnathan Mantey  *
78801784826SJohnathan Mantey  * @return None
78901784826SJohnathan Mantey  */
7909c5e585cSRavi Teja 
7919c5e585cSRavi Teja enum class IpVersion
7929c5e585cSRavi Teja {
7939c5e585cSRavi Teja     IpV4,
7949c5e585cSRavi Teja     IpV6
7959c5e585cSRavi Teja };
7969c5e585cSRavi Teja 
7979c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
7989c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
7998d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
8009c5e585cSRavi Teja     const std::string& gateway,
8018d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
80201784826SJohnathan Mantey {
80301784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
8049c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
8059c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
80601784826SJohnathan Mantey         if (ec)
80701784826SJohnathan Mantey         {
80801784826SJohnathan Mantey             messages::internalError(asyncResp->res);
80901784826SJohnathan Mantey         }
8109c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
8119c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
81201784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
8135e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
81423a21a1cSEd Tanous             if (ec2)
81501784826SJohnathan Mantey             {
81601784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
81701784826SJohnathan Mantey             }
81801784826SJohnathan Mantey         },
81901784826SJohnathan Mantey             "xyz.openbmc_project.Network",
82001784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
8219c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
8229c5e585cSRavi Teja             prefixLength, gateway);
82301784826SJohnathan Mantey     },
82401784826SJohnathan Mantey         "xyz.openbmc_project.Network",
8259c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
82601784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
82701784826SJohnathan Mantey }
82801784826SJohnathan Mantey 
829ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData(
830ce73d5c8SSunitha Harish     const std::string& ethifaceId,
831ce73d5c8SSunitha Harish     const dbus::utility::ManagedObjectType& dbusData,
832ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>& staticGatewayConfig)
833ce73d5c8SSunitha Harish {
834ce73d5c8SSunitha Harish     std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
835ce73d5c8SSunitha Harish     staticGatewayPathStart += ethifaceId;
836ce73d5c8SSunitha Harish 
837ce73d5c8SSunitha Harish     for (const auto& objpath : dbusData)
838ce73d5c8SSunitha Harish     {
839ce73d5c8SSunitha Harish         if (!std::string_view(objpath.first.str)
840ce73d5c8SSunitha Harish                  .starts_with(staticGatewayPathStart))
841ce73d5c8SSunitha Harish         {
842ce73d5c8SSunitha Harish             continue;
843ce73d5c8SSunitha Harish         }
844ce73d5c8SSunitha Harish         for (const auto& interface : objpath.second)
845ce73d5c8SSunitha Harish         {
846ce73d5c8SSunitha Harish             if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
847ce73d5c8SSunitha Harish             {
848ce73d5c8SSunitha Harish                 continue;
849ce73d5c8SSunitha Harish             }
850ce73d5c8SSunitha Harish             StaticGatewayData& staticGateway =
851ce73d5c8SSunitha Harish                 staticGatewayConfig.emplace_back();
852ce73d5c8SSunitha Harish             staticGateway.id = objpath.first.filename();
853ce73d5c8SSunitha Harish 
854ce73d5c8SSunitha Harish             bool success = sdbusplus::unpackPropertiesNoThrow(
855ce73d5c8SSunitha Harish                 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
856ce73d5c8SSunitha Harish                 "Gateway", staticGateway.gateway, "PrefixLength",
857ce73d5c8SSunitha Harish                 staticGateway.prefixLength, "ProtocolType",
858ce73d5c8SSunitha Harish                 staticGateway.protocol);
859ce73d5c8SSunitha Harish             if (!success)
860ce73d5c8SSunitha Harish             {
861ce73d5c8SSunitha Harish                 return false;
862ce73d5c8SSunitha Harish             }
863ce73d5c8SSunitha Harish         }
864ce73d5c8SSunitha Harish     }
865ce73d5c8SSunitha Harish     return true;
866ce73d5c8SSunitha Harish }
867ce73d5c8SSunitha Harish 
86801784826SJohnathan Mantey /**
869e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
870e48c0fc5SRavi Teja  *
871e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
872e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
873e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
874e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
875e48c0fc5SRavi Teja  *
876e48c0fc5SRavi Teja  * @return None
877e48c0fc5SRavi Teja  */
87801784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
87901784826SJohnathan Mantey                        const std::string& address,
8808d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
881e48c0fc5SRavi Teja {
882ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
883ce73d5c8SSunitha Harish     path /= ifaceId;
884ce73d5c8SSunitha Harish 
8855a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
8865a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
887e48c0fc5SRavi Teja         if (ec)
888e48c0fc5SRavi Teja         {
889fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
890fc23ef8aSNitin Kumar Kotania             {
891fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
892fc23ef8aSNitin Kumar Kotania                                                    "Address");
893fc23ef8aSNitin Kumar Kotania             }
894fc23ef8aSNitin Kumar Kotania             else
895fc23ef8aSNitin Kumar Kotania             {
896e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
897e48c0fc5SRavi Teja             }
898fc23ef8aSNitin Kumar Kotania         }
899e48c0fc5SRavi Teja     };
900ce73d5c8SSunitha Harish     // Passing null for gateway, as per redfish spec IPv6StaticAddresses
901ce73d5c8SSunitha Harish     // object does not have associated gateway property
902e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
903ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
904e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
905e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
906e48c0fc5SRavi Teja         "");
907e48c0fc5SRavi Teja }
908e48c0fc5SRavi Teja 
909179db1d7SKowalski, Kamil /**
910ce73d5c8SSunitha Harish  * @brief Deletes given IPv6 Static Gateway
911ce73d5c8SSunitha Harish  *
912ce73d5c8SSunitha Harish  * @param[in] ifaceId     Id of interface whose IP should be deleted
913ce73d5c8SSunitha Harish  * @param[in] ipHash      DBus Hash id of IP that should be deleted
914ce73d5c8SSunitha Harish  * @param[io] asyncResp   Response object that will be returned to client
915ce73d5c8SSunitha Harish  *
916ce73d5c8SSunitha Harish  * @return None
917ce73d5c8SSunitha Harish  */
918ce73d5c8SSunitha Harish inline void
919ce73d5c8SSunitha Harish     deleteIPv6Gateway(std::string_view gatewayId,
920ce73d5c8SSunitha Harish                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
921ce73d5c8SSunitha Harish {
922ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
923ce73d5c8SSunitha Harish     path /= gatewayId;
924ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
925ce73d5c8SSunitha Harish         [asyncResp](const boost::system::error_code& ec) {
926ce73d5c8SSunitha Harish         if (ec)
927ce73d5c8SSunitha Harish         {
928ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
929ce73d5c8SSunitha Harish         }
930ce73d5c8SSunitha Harish     },
931ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
932ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
933ce73d5c8SSunitha Harish }
934ce73d5c8SSunitha Harish 
935ce73d5c8SSunitha Harish /**
936ce73d5c8SSunitha Harish  * @brief Creates IPv6 static default gateway with given data
937ce73d5c8SSunitha Harish  *
938ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose IP should be added
939ce73d5c8SSunitha Harish  * @param[in] prefixLength Prefix length that needs to be added
940ce73d5c8SSunitha Harish  * @param[in] gateway      Gateway address that needs to be added
941ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
942ce73d5c8SSunitha Harish  *
943ce73d5c8SSunitha Harish  * @return None
944ce73d5c8SSunitha Harish  */
945ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway(
946ce73d5c8SSunitha Harish     std::string_view ifaceId, size_t prefixLength, std::string_view gateway,
947ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
948ce73d5c8SSunitha Harish {
949ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
950ce73d5c8SSunitha Harish     path /= ifaceId;
951ce73d5c8SSunitha Harish     auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
952ce73d5c8SSunitha Harish         if (ec)
953ce73d5c8SSunitha Harish         {
954ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
955ce73d5c8SSunitha Harish         }
956ce73d5c8SSunitha Harish     };
957ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
958ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
959ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
960ce73d5c8SSunitha Harish         gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
961ce73d5c8SSunitha Harish }
962ce73d5c8SSunitha Harish 
963ce73d5c8SSunitha Harish /**
964ce73d5c8SSunitha Harish  * @brief Deletes the IPv6 default gateway entry for this interface and
965ce73d5c8SSunitha Harish  * creates a replacement IPv6 default gateway entry
966ce73d5c8SSunitha Harish  *
967ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface upon which to create the IPv6
968ce73d5c8SSunitha Harish  * entry
969ce73d5c8SSunitha Harish  * @param[in] gateway      IPv6 gateway to assign to this interface
970ce73d5c8SSunitha Harish  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
971ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
972ce73d5c8SSunitha Harish  *
973ce73d5c8SSunitha Harish  * @return None
974ce73d5c8SSunitha Harish  */
975ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway(
976ce73d5c8SSunitha Harish     std::string_view ifaceId, std::string_view gatewayId,
977ce73d5c8SSunitha Harish     std::string_view gateway, size_t prefixLength,
978ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
979ce73d5c8SSunitha Harish {
980ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
981ce73d5c8SSunitha Harish     path /= gatewayId;
982ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
983ce73d5c8SSunitha Harish         [asyncResp, ifaceId, gateway,
984ce73d5c8SSunitha Harish          prefixLength](const boost::system::error_code& ec) {
985ce73d5c8SSunitha Harish         if (ec)
986ce73d5c8SSunitha Harish         {
987ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
988ce73d5c8SSunitha Harish             return;
989ce73d5c8SSunitha Harish         }
990ce73d5c8SSunitha Harish         createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp);
991ce73d5c8SSunitha Harish     },
992ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
993ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
994ce73d5c8SSunitha Harish }
995ce73d5c8SSunitha Harish 
996ce73d5c8SSunitha Harish /**
997ce73d5c8SSunitha Harish  * @brief Sets IPv6 default gateway with given data
998ce73d5c8SSunitha Harish  *
999ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose gateway should be added
1000ce73d5c8SSunitha Harish  * @param[in] input        Contains address that needs to be added
1001ce73d5c8SSunitha Harish  * @param[in] staticGatewayData  Current static gateways in the system
1002ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
1003ce73d5c8SSunitha Harish  *
1004ce73d5c8SSunitha Harish  * @return None
1005ce73d5c8SSunitha Harish  */
1006ce73d5c8SSunitha Harish 
1007ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway(
1008ce73d5c8SSunitha Harish     const std::string& ifaceId, const nlohmann::json::array_t& input,
1009ce73d5c8SSunitha Harish     const std::vector<StaticGatewayData>& staticGatewayData,
1010ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1011ce73d5c8SSunitha Harish {
1012ce73d5c8SSunitha Harish     size_t entryIdx = 1;
1013ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>::const_iterator staticGatewayEntry =
1014ce73d5c8SSunitha Harish         staticGatewayData.begin();
1015ce73d5c8SSunitha Harish 
1016ce73d5c8SSunitha Harish     for (const nlohmann::json& thisJson : input)
1017ce73d5c8SSunitha Harish     {
1018ce73d5c8SSunitha Harish         // find the next gateway entry
1019ce73d5c8SSunitha Harish         while (staticGatewayEntry != staticGatewayData.end())
1020ce73d5c8SSunitha Harish         {
1021ce73d5c8SSunitha Harish             if (staticGatewayEntry->protocol ==
1022ce73d5c8SSunitha Harish                 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1023ce73d5c8SSunitha Harish             {
1024ce73d5c8SSunitha Harish                 break;
1025ce73d5c8SSunitha Harish             }
1026ce73d5c8SSunitha Harish             staticGatewayEntry++;
1027ce73d5c8SSunitha Harish         }
1028ce73d5c8SSunitha Harish         std::string pathString = "IPv6StaticDefaultGateways/" +
1029ce73d5c8SSunitha Harish                                  std::to_string(entryIdx);
1030ce73d5c8SSunitha Harish         if (thisJson.is_null())
1031ce73d5c8SSunitha Harish         {
1032ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1033ce73d5c8SSunitha Harish             {
1034ce73d5c8SSunitha Harish                 messages::resourceCannotBeDeleted(asyncResp->res);
1035ce73d5c8SSunitha Harish                 return;
1036ce73d5c8SSunitha Harish             }
1037ce73d5c8SSunitha Harish             deleteIPv6Gateway(staticGatewayEntry->id, asyncResp);
1038ce73d5c8SSunitha Harish             return;
1039ce73d5c8SSunitha Harish         }
1040ce73d5c8SSunitha Harish         if (thisJson.is_object() && thisJson.empty())
1041ce73d5c8SSunitha Harish         {
1042ce73d5c8SSunitha Harish             // Do nothing, but make sure the entry exists.
1043ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1044ce73d5c8SSunitha Harish             {
1045ce73d5c8SSunitha Harish                 messages::propertyValueFormatError(asyncResp->res, thisJson,
1046ce73d5c8SSunitha Harish                                                    pathString);
1047ce73d5c8SSunitha Harish                 return;
1048ce73d5c8SSunitha Harish             }
1049ce73d5c8SSunitha Harish         }
1050ce73d5c8SSunitha Harish         std::optional<std::string> address;
1051ce73d5c8SSunitha Harish         std::optional<size_t> prefixLength;
1052ce73d5c8SSunitha Harish 
1053ce73d5c8SSunitha Harish         nlohmann::json thisJsonCopy = thisJson;
1054ce73d5c8SSunitha Harish         if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1055ce73d5c8SSunitha Harish                                  address, "PrefixLength", prefixLength))
1056ce73d5c8SSunitha Harish         {
1057ce73d5c8SSunitha Harish             return;
1058ce73d5c8SSunitha Harish         }
1059ce73d5c8SSunitha Harish         const std::string* addr = nullptr;
1060ce73d5c8SSunitha Harish         size_t prefix = 0;
1061ce73d5c8SSunitha Harish         if (address)
1062ce73d5c8SSunitha Harish         {
1063ce73d5c8SSunitha Harish             addr = &(*address);
1064ce73d5c8SSunitha Harish         }
1065ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1066ce73d5c8SSunitha Harish         {
1067ce73d5c8SSunitha Harish             addr = &(staticGatewayEntry->gateway);
1068ce73d5c8SSunitha Harish         }
1069ce73d5c8SSunitha Harish         else
1070ce73d5c8SSunitha Harish         {
1071ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res, pathString + "/Address");
1072ce73d5c8SSunitha Harish             return;
1073ce73d5c8SSunitha Harish         }
1074ce73d5c8SSunitha Harish         if (prefixLength)
1075ce73d5c8SSunitha Harish         {
1076ce73d5c8SSunitha Harish             prefix = *prefixLength;
1077ce73d5c8SSunitha Harish         }
1078ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1079ce73d5c8SSunitha Harish         {
1080ce73d5c8SSunitha Harish             prefix = staticGatewayEntry->prefixLength;
1081ce73d5c8SSunitha Harish         }
1082ce73d5c8SSunitha Harish         else
1083ce73d5c8SSunitha Harish         {
1084ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res,
1085ce73d5c8SSunitha Harish                                       pathString + "/PrefixLength");
1086ce73d5c8SSunitha Harish             return;
1087ce73d5c8SSunitha Harish         }
1088ce73d5c8SSunitha Harish         if (staticGatewayEntry != staticGatewayData.end())
1089ce73d5c8SSunitha Harish         {
1090ce73d5c8SSunitha Harish             deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
1091ce73d5c8SSunitha Harish                                               *addr, prefix, asyncResp);
1092ce73d5c8SSunitha Harish             staticGatewayEntry++;
1093ce73d5c8SSunitha Harish         }
1094ce73d5c8SSunitha Harish         else
1095ce73d5c8SSunitha Harish         {
1096ce73d5c8SSunitha Harish             createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp);
1097ce73d5c8SSunitha Harish         }
1098ce73d5c8SSunitha Harish         entryIdx++;
1099ce73d5c8SSunitha Harish     }
1100ce73d5c8SSunitha Harish }
1101ce73d5c8SSunitha Harish 
1102ce73d5c8SSunitha Harish /**
1103179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
1104179db1d7SKowalski, Kamil  * Object
1105179db1d7SKowalski, Kamil  * from EntityManager Network Manager
11064a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
1107179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
1108179db1d7SKowalski, Kamil  * into JSON
1109179db1d7SKowalski, Kamil  */
1110179db1d7SKowalski, Kamil template <typename CallbackFunc>
111181ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
11121abe55efSEd Tanous                           CallbackFunc&& callback)
11131abe55efSEd Tanous {
1114f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1115f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1116f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1117f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
1118f94c4ecfSEd Tanous          callback{std::forward<CallbackFunc>(callback)}](
11198b24275dSEd Tanous             const boost::system::error_code& ec,
112002cad96eSEd Tanous             const dbus::utility::ManagedObjectType& resp) {
112155c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
112277179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
112377179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
1124ce73d5c8SSunitha Harish         std::vector<StaticGatewayData> ipv6GatewayData;
1125179db1d7SKowalski, Kamil 
11268b24275dSEd Tanous         if (ec)
11271abe55efSEd Tanous         {
1128ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1129179db1d7SKowalski, Kamil             return;
1130179db1d7SKowalski, Kamil         }
1131179db1d7SKowalski, Kamil 
1132002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
11334c9afe43SEd Tanous         if (!found)
11344c9afe43SEd Tanous         {
1135ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
11364c9afe43SEd Tanous             return;
11374c9afe43SEd Tanous         }
11384c9afe43SEd Tanous 
11392c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
1140179db1d7SKowalski, Kamil         // Fix global GW
11411abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
11421abe55efSEd Tanous         {
1143c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
1144c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
11459010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
11461abe55efSEd Tanous             {
114782695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
1148179db1d7SKowalski, Kamil             }
1149179db1d7SKowalski, Kamil         }
1150179db1d7SKowalski, Kamil 
11512c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
1152ce73d5c8SSunitha Harish         if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData))
1153ce73d5c8SSunitha Harish         {
1154ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1155ce73d5c8SSunitha Harish         }
11564e0453b1SGunnar Mills         // Finally make a callback with useful data
1157ce73d5c8SSunitha Harish         callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1158f5892d0dSGeorge Liu     });
1159271584abSEd Tanous }
1160179db1d7SKowalski, Kamil 
1161179db1d7SKowalski, Kamil /**
11629391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
11639391bb9cSRapkiewicz, Pawel  * Manager
11641abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
11651abe55efSEd Tanous  * into JSON.
11669391bb9cSRapkiewicz, Pawel  */
11679391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
11681abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
11691abe55efSEd Tanous {
1170f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1171f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1172f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1173f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
11748b24275dSEd Tanous             const boost::system::error_code& ec,
1175f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
11761abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
11771abe55efSEd Tanous         // ethernet interfaces
117877179532SEd Tanous         std::vector<std::string> ifaceList;
11792c70f800SEd Tanous         ifaceList.reserve(resp.size());
11808b24275dSEd Tanous         if (ec)
11811abe55efSEd Tanous         {
11822c70f800SEd Tanous             callback(false, ifaceList);
11839391bb9cSRapkiewicz, Pawel             return;
11849391bb9cSRapkiewicz, Pawel         }
11859391bb9cSRapkiewicz, Pawel 
11869391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
11874a0cb85cSEd Tanous         for (const auto& objpath : resp)
11881abe55efSEd Tanous         {
11899391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
11904a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
11911abe55efSEd Tanous             {
11921abe55efSEd Tanous                 // If interface is
11934a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
11944a0cb85cSEd Tanous                 // what we're looking for.
11959391bb9cSRapkiewicz, Pawel                 if (interface.first ==
11961abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
11971abe55efSEd Tanous                 {
11982dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
11992dfd18efSEd Tanous                     if (ifaceId.empty())
12001abe55efSEd Tanous                     {
12012dfd18efSEd Tanous                         continue;
12029391bb9cSRapkiewicz, Pawel                     }
12032dfd18efSEd Tanous                     // and put it into output vector.
120477179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
12059391bb9cSRapkiewicz, Pawel                 }
12069391bb9cSRapkiewicz, Pawel             }
12079391bb9cSRapkiewicz, Pawel         }
12082c5875a2SEd Tanous 
12093544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
12102c5875a2SEd Tanous 
1211a434f2bdSEd Tanous         // Finally make a callback with useful data
12122c70f800SEd Tanous         callback(true, ifaceList);
1213f5892d0dSGeorge Liu     });
1214271584abSEd Tanous }
12159391bb9cSRapkiewicz, Pawel 
12164f48d5f6SEd Tanous inline void
12174f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
12188d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12191abe55efSEd Tanous {
1220ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
1221ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
1222ab6554f1SJoshi-Mansi     {
1223ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
1224ab6554f1SJoshi-Mansi                                            "HostName");
1225ab6554f1SJoshi-Mansi         return;
1226ab6554f1SJoshi-Mansi     }
12279ae226faSGeorge Liu     sdbusplus::asio::setProperty(
12289ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
12299ae226faSGeorge Liu         "/xyz/openbmc_project/network/config",
12309ae226faSGeorge Liu         "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
12315e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
12324a0cb85cSEd Tanous         if (ec)
12334a0cb85cSEd Tanous         {
1234a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
12351abe55efSEd Tanous         }
12369ae226faSGeorge Liu     });
1237588c3f0dSKowalski, Kamil }
1238588c3f0dSKowalski, Kamil 
12394f48d5f6SEd Tanous inline void
124035fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
124135fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
124235fb5311STejas Patil {
124389492a15SPatrick Williams     sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
124489492a15SPatrick Williams                                               ifaceId;
12459ae226faSGeorge Liu     sdbusplus::asio::setProperty(
12469ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
12479ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
12485e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
124935fb5311STejas Patil         if (ec)
125035fb5311STejas Patil         {
125135fb5311STejas Patil             messages::internalError(asyncResp->res);
125235fb5311STejas Patil         }
12539ae226faSGeorge Liu     });
125435fb5311STejas Patil }
125535fb5311STejas Patil 
125635fb5311STejas Patil inline void
12574f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
1258bf648f77SEd Tanous                           const std::string& domainname,
12598d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1260ab6554f1SJoshi-Mansi {
1261ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
12629ae226faSGeorge Liu     sdbusplus::asio::setProperty(
12639ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
12649ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
12659ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
12669ae226faSGeorge Liu         vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
1267ab6554f1SJoshi-Mansi         if (ec)
1268ab6554f1SJoshi-Mansi         {
1269ab6554f1SJoshi-Mansi             messages::internalError(asyncResp->res);
1270ab6554f1SJoshi-Mansi         }
12719ae226faSGeorge Liu     });
1272ab6554f1SJoshi-Mansi }
1273ab6554f1SJoshi-Mansi 
12744f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1275bf648f77SEd Tanous {
1276bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
12773544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1278bf648f77SEd Tanous     {
1279bf648f77SEd Tanous         return false;
1280bf648f77SEd Tanous     }
1281bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1282bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1283bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1284bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
12854b242749SEd Tanous     const static std::regex pattern(
1286bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1287bf648f77SEd Tanous 
1288bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1289bf648f77SEd Tanous }
1290bf648f77SEd Tanous 
12914f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1292bf648f77SEd Tanous {
1293bf648f77SEd Tanous     // Can have multiple subdomains
1294bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
12954b242749SEd Tanous     const static std::regex pattern(
12960fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1297bf648f77SEd Tanous 
1298bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1299bf648f77SEd Tanous }
1300bf648f77SEd Tanous 
13014f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
13028d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1303ab6554f1SJoshi-Mansi {
1304ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1305ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1306ab6554f1SJoshi-Mansi     {
1307ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1308ab6554f1SJoshi-Mansi         return;
1309ab6554f1SJoshi-Mansi     }
1310ab6554f1SJoshi-Mansi 
1311ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1312ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1313ab6554f1SJoshi-Mansi     {
1314ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1315ab6554f1SJoshi-Mansi         return;
1316ab6554f1SJoshi-Mansi     }
1317ab6554f1SJoshi-Mansi 
1318ab6554f1SJoshi-Mansi     std::string hostname;
1319ab6554f1SJoshi-Mansi     std::string domainname;
1320ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1321ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1322ab6554f1SJoshi-Mansi 
1323ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1324ab6554f1SJoshi-Mansi     {
1325ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1326ab6554f1SJoshi-Mansi         return;
1327ab6554f1SJoshi-Mansi     }
1328ab6554f1SJoshi-Mansi 
1329ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1330ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1331ab6554f1SJoshi-Mansi }
1332ab6554f1SJoshi-Mansi 
13334f48d5f6SEd Tanous inline void
13344f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1335bf648f77SEd Tanous                           const std::string& macAddress,
13368d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1337d577665bSRatan Gupta {
133858283f41SJohnathan Mantey     static constexpr std::string_view dbusNotAllowedError =
133958283f41SJohnathan Mantey         "xyz.openbmc_project.Common.Error.NotAllowed";
134058283f41SJohnathan Mantey 
13419ae226faSGeorge Liu     sdbusplus::asio::setProperty(
13429ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
13439ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
13449ae226faSGeorge Liu         "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
13459ae226faSGeorge Liu         [asyncResp](const boost::system::error_code& ec,
13465b378546SPatrick Williams                     const sdbusplus::message_t& msg) {
1347d577665bSRatan Gupta         if (ec)
1348d577665bSRatan Gupta         {
134958283f41SJohnathan Mantey             const sd_bus_error* err = msg.get_error();
135058283f41SJohnathan Mantey             if (err == nullptr)
135158283f41SJohnathan Mantey             {
135258283f41SJohnathan Mantey                 messages::internalError(asyncResp->res);
135358283f41SJohnathan Mantey                 return;
135458283f41SJohnathan Mantey             }
135558283f41SJohnathan Mantey             if (err->name == dbusNotAllowedError)
135658283f41SJohnathan Mantey             {
135758283f41SJohnathan Mantey                 messages::propertyNotWritable(asyncResp->res, "MACAddress");
135858283f41SJohnathan Mantey                 return;
135958283f41SJohnathan Mantey             }
1360d577665bSRatan Gupta             messages::internalError(asyncResp->res);
1361d577665bSRatan Gupta             return;
1362d577665bSRatan Gupta         }
13639ae226faSGeorge Liu     });
1364d577665bSRatan Gupta }
1365286b9118SJohnathan Mantey 
13664f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
13674f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
13684f48d5f6SEd Tanous                            const bool v6Value,
13698d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1370da131a9aSJennifer Lee {
13712c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
13729ae226faSGeorge Liu     sdbusplus::asio::setProperty(
13739ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
13749ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
13759ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
13765e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1377da131a9aSJennifer Lee         if (ec)
1378da131a9aSJennifer Lee         {
137962598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1380da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1381da131a9aSJennifer Lee             return;
1382da131a9aSJennifer Lee         }
13838f7e9c19SJayaprakash Mutyala         messages::success(asyncResp->res);
13849ae226faSGeorge Liu     });
1385da131a9aSJennifer Lee }
13861f8c7b5dSJohnathan Mantey 
13874f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty(
1388eeedda23SJohnathan Mantey     const std::string& ifaceId, const std::string& propertyName,
13898d1b46d7Szhanghch05     const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1390eeedda23SJohnathan Mantey {
13919ae226faSGeorge Liu     sdbusplus::asio::setProperty(
13929ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
13939ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
13949ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
13955e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1396eeedda23SJohnathan Mantey         if (ec)
1397eeedda23SJohnathan Mantey         {
139862598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1399eeedda23SJohnathan Mantey             messages::internalError(asyncResp->res);
1400eeedda23SJohnathan Mantey             return;
1401eeedda23SJohnathan Mantey         }
14029ae226faSGeorge Liu     });
1403eeedda23SJohnathan Mantey }
1404eeedda23SJohnathan Mantey 
1405e4588158SJishnu CM enum class NetworkType
1406e4588158SJishnu CM {
1407e4588158SJishnu CM     dhcp4,
1408e4588158SJishnu CM     dhcp6
1409e4588158SJishnu CM };
1410e4588158SJishnu CM 
1411e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1412e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1413e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1414da131a9aSJennifer Lee {
141562598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
1416e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1417e4588158SJishnu CM     path /= ethifaceId;
1418e4588158SJishnu CM 
1419e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1420e4588158SJishnu CM     {
1421e4588158SJishnu CM         path /= "dhcp4";
1422e4588158SJishnu CM     }
1423e4588158SJishnu CM     else
1424e4588158SJishnu CM     {
1425e4588158SJishnu CM         path /= "dhcp6";
1426e4588158SJishnu CM     }
1427e4588158SJishnu CM 
14289ae226faSGeorge Liu     sdbusplus::asio::setProperty(
1429e4588158SJishnu CM         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
14309ae226faSGeorge Liu         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
14315e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1432da131a9aSJennifer Lee         if (ec)
1433da131a9aSJennifer Lee         {
143462598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1435da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1436da131a9aSJennifer Lee             return;
1437da131a9aSJennifer Lee         }
14389ae226faSGeorge Liu     });
1439da131a9aSJennifer Lee }
1440d577665bSRatan Gupta 
1441b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1442b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1443b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1444b10d8db0SRavi Teja {
1445b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1446b10d8db0SRavi Teja     path /= ifaceId;
1447b10d8db0SRavi Teja     sdbusplus::asio::setProperty(
1448b10d8db0SRavi Teja         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1449b10d8db0SRavi Teja         "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1450b10d8db0SRavi Teja         ipv6AutoConfigEnabled,
1451b10d8db0SRavi Teja         [asyncResp](const boost::system::error_code& ec) {
1452b10d8db0SRavi Teja         if (ec)
1453b10d8db0SRavi Teja         {
1454b10d8db0SRavi Teja             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1455b10d8db0SRavi Teja             messages::internalError(asyncResp->res);
1456b10d8db0SRavi Teja             return;
1457b10d8db0SRavi Teja         }
1458b10d8db0SRavi Teja         messages::success(asyncResp->res);
1459b10d8db0SRavi Teja     });
1460b10d8db0SRavi Teja }
1461b10d8db0SRavi Teja 
14624f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
14631f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1464f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1465f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
14668d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1467da131a9aSJennifer Lee {
146882695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
146982695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1470da131a9aSJennifer Lee 
14711f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
14721f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
14731f8c7b5dSJohnathan Mantey 
14741f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
14751f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1476da131a9aSJennifer Lee     {
1477b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
14781f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
14791f8c7b5dSJohnathan Mantey         {
1480bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1481bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
14821f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1483da131a9aSJennifer Lee             return;
1484da131a9aSJennifer Lee         }
1485b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
14861f8c7b5dSJohnathan Mantey     }
14871f8c7b5dSJohnathan Mantey     else
1488da131a9aSJennifer Lee     {
14891f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
14901f8c7b5dSJohnathan Mantey     }
14911f8c7b5dSJohnathan Mantey 
1492e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1493e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1494e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
14951f8c7b5dSJohnathan Mantey     {
1496e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
14971f8c7b5dSJohnathan Mantey     }
1498e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
14991f8c7b5dSJohnathan Mantey     {
1500e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
15011f8c7b5dSJohnathan Mantey     }
15021f8c7b5dSJohnathan Mantey 
1503e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1504e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1505e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
15061f8c7b5dSJohnathan Mantey     {
1507e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
15081f8c7b5dSJohnathan Mantey     }
1509e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
15101f8c7b5dSJohnathan Mantey     {
1511e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
15121f8c7b5dSJohnathan Mantey     }
15131f8c7b5dSJohnathan Mantey 
151491c441ecSRavi Teja     bool nextUsev4Domain = ethData.domainv4Enabled;
151591c441ecSRavi Teja     bool nextUsev6Domain = ethData.domainv6Enabled;
1516e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
15171f8c7b5dSJohnathan Mantey     {
1518e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
15191f8c7b5dSJohnathan Mantey     }
1520e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
15211f8c7b5dSJohnathan Mantey     {
1522e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
15231f8c7b5dSJohnathan Mantey     }
15241f8c7b5dSJohnathan Mantey 
152562598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
15261f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
15271f8c7b5dSJohnathan Mantey                    asyncResp);
152862598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1529e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1530e4588158SJishnu CM                   NetworkType::dhcp4);
153162598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1532e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1533e4588158SJishnu CM                   NetworkType::dhcp4);
153491c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled...");
153591c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
1536e4588158SJishnu CM                   NetworkType::dhcp4);
1537e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1538e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1539e4588158SJishnu CM                   NetworkType::dhcp6);
1540e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1541e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1542e4588158SJishnu CM                   NetworkType::dhcp6);
154391c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
154491c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
1545e4588158SJishnu CM                   NetworkType::dhcp6);
1546da131a9aSJennifer Lee }
154701784826SJohnathan Mantey 
154877179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
154977179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
155077179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
155101784826SJohnathan Mantey {
155217a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
155317a897dfSManojkiran Eda         return value.origin == "Static";
155417a897dfSManojkiran Eda     });
155501784826SJohnathan Mantey }
155601784826SJohnathan Mantey 
155777179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
155877179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
155977179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
156001784826SJohnathan Mantey {
156117a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
156217a897dfSManojkiran Eda         return value.origin == "Static";
156317a897dfSManojkiran Eda     });
156401784826SJohnathan Mantey }
156501784826SJohnathan Mantey 
156677179532SEd Tanous inline void
1567ddd70dcaSEd Tanous     handleIPv4StaticPatch(const std::string& ifaceId,
1568ddd70dcaSEd Tanous                           nlohmann::json::array_t& input,
156977179532SEd Tanous                           const std::vector<IPv4AddressData>& ipv4Data,
15708d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
15711abe55efSEd Tanous {
1572ddd70dcaSEd Tanous     if (input.empty())
1573f476acbfSRatan Gupta     {
15742e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1575d1d50814SRavi Teja                                          "IPv4StaticAddresses");
1576f476acbfSRatan Gupta         return;
1577f476acbfSRatan Gupta     }
1578f476acbfSRatan Gupta 
1579271584abSEd Tanous     unsigned entryIdx = 1;
158001784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
158101784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
158201784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
158301784826SJohnathan Mantey     // into the NIC.
158477179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
15852c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
158601784826SJohnathan Mantey 
1587537174c4SEd Tanous     for (nlohmann::json& thisJson : input)
15881abe55efSEd Tanous     {
158989492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
159089492a15SPatrick Williams                                  std::to_string(entryIdx);
1591179db1d7SKowalski, Kamil 
159201784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1593f476acbfSRatan Gupta         {
1594537174c4SEd Tanous             std::optional<std::string> address;
1595537174c4SEd Tanous             std::optional<std::string> subnetMask;
1596537174c4SEd Tanous             std::optional<std::string> gateway;
1597537174c4SEd Tanous 
1598537174c4SEd Tanous             if (!json_util::readJson(thisJson, asyncResp->res, "Address",
15997e27d832SJohnathan Mantey                                      address, "SubnetMask", subnetMask,
16007e27d832SJohnathan Mantey                                      "Gateway", gateway))
1601537174c4SEd Tanous             {
1602f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
160371f52d96SEd Tanous                                                    pathString);
1604537174c4SEd Tanous                 return;
1605179db1d7SKowalski, Kamil             }
1606179db1d7SKowalski, Kamil 
160701784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
160801784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
160901784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
161001784826SJohnathan Mantey             // current request.
1611537174c4SEd Tanous             if (address)
16121abe55efSEd Tanous             {
1613e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
161401784826SJohnathan Mantey                 {
1615bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1616bf648f77SEd Tanous                                                        pathString + "/Address");
1617e01d0c36SEd Tanous                     return;
161801784826SJohnathan Mantey                 }
161901784826SJohnathan Mantey             }
162085ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
162101784826SJohnathan Mantey             {
1622e01d0c36SEd Tanous                 address = (nicIpEntry->address);
162301784826SJohnathan Mantey             }
162401784826SJohnathan Mantey             else
162501784826SJohnathan Mantey             {
162601784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
162701784826SJohnathan Mantey                                           pathString + "/Address");
1628e01d0c36SEd Tanous                 return;
16294a0cb85cSEd Tanous             }
16304a0cb85cSEd Tanous 
1631e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1632537174c4SEd Tanous             if (subnetMask)
16334a0cb85cSEd Tanous             {
1634033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1635033f1e4dSEd Tanous                                                          &prefixLength))
16364a0cb85cSEd Tanous                 {
1637f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1638537174c4SEd Tanous                         asyncResp->res, *subnetMask,
16394a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1640e01d0c36SEd Tanous                     return;
16414a0cb85cSEd Tanous                 }
16424a0cb85cSEd Tanous             }
164385ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
16444a0cb85cSEd Tanous             {
1645033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
164601784826SJohnathan Mantey                                                          &prefixLength))
16474a0cb85cSEd Tanous                 {
164801784826SJohnathan Mantey                     messages::propertyValueFormatError(
164985ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
165001784826SJohnathan Mantey                         pathString + "/SubnetMask");
1651e01d0c36SEd Tanous                     return;
16524a0cb85cSEd Tanous                 }
16534a0cb85cSEd Tanous             }
16541abe55efSEd Tanous             else
16551abe55efSEd Tanous             {
165601784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
165701784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1658e01d0c36SEd Tanous                 return;
165901784826SJohnathan Mantey             }
166001784826SJohnathan Mantey 
166101784826SJohnathan Mantey             if (gateway)
166201784826SJohnathan Mantey             {
1663e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
166401784826SJohnathan Mantey                 {
1665bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1666bf648f77SEd Tanous                                                        pathString + "/Gateway");
1667e01d0c36SEd Tanous                     return;
166801784826SJohnathan Mantey                 }
166901784826SJohnathan Mantey             }
167085ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
167101784826SJohnathan Mantey             {
1672e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
167301784826SJohnathan Mantey             }
167401784826SJohnathan Mantey             else
16751abe55efSEd Tanous             {
1676a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
16774a0cb85cSEd Tanous                                           pathString + "/Gateway");
167801784826SJohnathan Mantey                 return;
16794a0cb85cSEd Tanous             }
16804a0cb85cSEd Tanous 
168185ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
16821abe55efSEd Tanous             {
16839c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
168477eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
168577eb0153SEd Tanous                                          *gateway, asyncResp);
168689492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
168789492a15SPatrick Williams                                                   ipv4Data.cend());
1688588c3f0dSKowalski, Kamil             }
168901784826SJohnathan Mantey             else
169001784826SJohnathan Mantey             {
1691cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1692cb13a392SEd Tanous                            asyncResp);
16934a0cb85cSEd Tanous             }
16944a0cb85cSEd Tanous             entryIdx++;
16954a0cb85cSEd Tanous         }
169601784826SJohnathan Mantey         else
169701784826SJohnathan Mantey         {
169885ffe86aSJiaqing Zhao             if (nicIpEntry == ipv4Data.cend())
169901784826SJohnathan Mantey             {
170001784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
170101784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
170201784826SJohnathan Mantey                 // in error, so bail out.
170301784826SJohnathan Mantey                 if (thisJson.is_null())
170401784826SJohnathan Mantey                 {
170501784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
170601784826SJohnathan Mantey                     return;
170701784826SJohnathan Mantey                 }
1708f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
170971f52d96SEd Tanous                                                    pathString);
171001784826SJohnathan Mantey                 return;
171101784826SJohnathan Mantey             }
171201784826SJohnathan Mantey 
171301784826SJohnathan Mantey             if (thisJson.is_null())
171401784826SJohnathan Mantey             {
17159c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
171601784826SJohnathan Mantey             }
171785ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
171801784826SJohnathan Mantey             {
171989492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
172089492a15SPatrick Williams                                                   ipv4Data.cend());
172101784826SJohnathan Mantey             }
172201784826SJohnathan Mantey             entryIdx++;
172301784826SJohnathan Mantey         }
172401784826SJohnathan Mantey     }
17254a0cb85cSEd Tanous }
17264a0cb85cSEd Tanous 
17274f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1728f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1729f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
17308d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1731f85837bfSRAJESWARAN THILLAIGOVINDAN {
17329ae226faSGeorge Liu     sdbusplus::asio::setProperty(
17339ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
17349ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
17359ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
17369ae226faSGeorge Liu         updatedStaticNameServers,
17375e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1738f85837bfSRAJESWARAN THILLAIGOVINDAN         if (ec)
1739f85837bfSRAJESWARAN THILLAIGOVINDAN         {
1740f85837bfSRAJESWARAN THILLAIGOVINDAN             messages::internalError(asyncResp->res);
1741f85837bfSRAJESWARAN THILLAIGOVINDAN             return;
1742f85837bfSRAJESWARAN THILLAIGOVINDAN         }
17439ae226faSGeorge Liu     });
1744f85837bfSRAJESWARAN THILLAIGOVINDAN }
1745f85837bfSRAJESWARAN THILLAIGOVINDAN 
17464f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
1747ddd70dcaSEd Tanous     const std::string& ifaceId, const nlohmann::json::array_t& input,
174877179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
17498d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1750e48c0fc5SRavi Teja {
1751ddd70dcaSEd Tanous     if (input.empty())
1752e48c0fc5SRavi Teja     {
17532e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1754e48c0fc5SRavi Teja                                          "IPv6StaticAddresses");
1755e48c0fc5SRavi Teja         return;
1756e48c0fc5SRavi Teja     }
1757271584abSEd Tanous     size_t entryIdx = 1;
175877179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
17592c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1760f23b7296SEd Tanous     for (const nlohmann::json& thisJson : input)
1761e48c0fc5SRavi Teja     {
176289492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
176389492a15SPatrick Williams                                  std::to_string(entryIdx);
1764e48c0fc5SRavi Teja 
176501784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1766e48c0fc5SRavi Teja         {
1767e48c0fc5SRavi Teja             std::optional<std::string> address;
1768e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
1769f23b7296SEd Tanous             nlohmann::json thisJsonCopy = thisJson;
1770bf648f77SEd Tanous             if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1771bf648f77SEd Tanous                                      address, "PrefixLength", prefixLength))
1772e48c0fc5SRavi Teja             {
1773f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
177471f52d96SEd Tanous                                                    pathString);
1775e48c0fc5SRavi Teja                 return;
1776e48c0fc5SRavi Teja             }
1777e48c0fc5SRavi Teja 
177801784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
177901784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
178001784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
178101784826SJohnathan Mantey             // current request.
1782*d547d8d2SEd Tanous             if (!address)
1783e48c0fc5SRavi Teja             {
1784*d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
178501784826SJohnathan Mantey                 {
178601784826SJohnathan Mantey                     messages::propertyMissing(asyncResp->res,
178701784826SJohnathan Mantey                                               pathString + "/Address");
178801784826SJohnathan Mantey                     return;
1789e48c0fc5SRavi Teja                 }
1790*d547d8d2SEd Tanous                 address = nicIpEntry->address;
1791*d547d8d2SEd Tanous             }
1792e48c0fc5SRavi Teja 
1793*d547d8d2SEd Tanous             if (!prefixLength)
1794e48c0fc5SRavi Teja             {
1795*d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
1796e48c0fc5SRavi Teja                 {
1797e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1798e48c0fc5SRavi Teja                                               pathString + "/PrefixLength");
179901784826SJohnathan Mantey                     return;
1800e48c0fc5SRavi Teja                 }
1801*d547d8d2SEd Tanous                 prefixLength = nicIpEntry->prefixLength;
1802*d547d8d2SEd Tanous             }
1803e48c0fc5SRavi Teja 
180485ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1805e48c0fc5SRavi Teja             {
18069c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1807*d547d8d2SEd Tanous                                          nicIpEntry->id, *prefixLength,
1808*d547d8d2SEd Tanous                                          *address, "", asyncResp);
180989492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
181089492a15SPatrick Williams                                                   ipv6Data.cend());
181101784826SJohnathan Mantey             }
181201784826SJohnathan Mantey             else
181301784826SJohnathan Mantey             {
1814*d547d8d2SEd Tanous                 createIPv6(ifaceId, *prefixLength, *address, asyncResp);
1815e48c0fc5SRavi Teja             }
1816e48c0fc5SRavi Teja             entryIdx++;
1817e48c0fc5SRavi Teja         }
181801784826SJohnathan Mantey         else
181901784826SJohnathan Mantey         {
182085ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
182101784826SJohnathan Mantey             {
182201784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
182301784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
182401784826SJohnathan Mantey                 // in error, so bail out.
182501784826SJohnathan Mantey                 if (thisJson.is_null())
182601784826SJohnathan Mantey                 {
182701784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
182801784826SJohnathan Mantey                     return;
182901784826SJohnathan Mantey                 }
1830f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
183171f52d96SEd Tanous                                                    pathString);
183201784826SJohnathan Mantey                 return;
183301784826SJohnathan Mantey             }
183401784826SJohnathan Mantey 
183501784826SJohnathan Mantey             if (thisJson.is_null())
183601784826SJohnathan Mantey             {
18379c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
183801784826SJohnathan Mantey             }
183985ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
184001784826SJohnathan Mantey             {
184189492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
184289492a15SPatrick Williams                                                   ipv6Data.cend());
184301784826SJohnathan Mantey             }
184401784826SJohnathan Mantey             entryIdx++;
184501784826SJohnathan Mantey         }
184601784826SJohnathan Mantey     }
1847e48c0fc5SRavi Teja }
1848e48c0fc5SRavi Teja 
18497857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
18507857cb8dSJiaqing Zhao {
18517857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
18527857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
18537857cb8dSJiaqing Zhao }
18547857cb8dSJiaqing Zhao 
185577179532SEd Tanous inline void
185677179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
185777179532SEd Tanous                        const std::string& ifaceId,
185877179532SEd Tanous                        const EthernetInterfaceData& ethData,
185977179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
1860ce73d5c8SSunitha Harish                        const std::vector<IPv6AddressData>& ipv6Data,
1861ce73d5c8SSunitha Harish                        const std::vector<StaticGatewayData>& ipv6GatewayData)
18624a0cb85cSEd Tanous {
18632c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
186481ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1865ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1866ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
18672c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1868eeedda23SJohnathan Mantey 
186913451e39SWilly Tu     if constexpr (bmcwebEnableHealthPopulate)
187013451e39SWilly Tu     {
187113451e39SWilly Tu         constexpr std::array<std::string_view, 1> inventoryForEthernet = {
187213451e39SWilly Tu             "xyz.openbmc_project.Inventory.Item.Ethernet"};
1873eeedda23SJohnathan Mantey         auto health = std::make_shared<HealthPopulate>(asyncResp);
18747a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
18757a1dbc48SGeorge Liu             "/", 0, inventoryForEthernet,
18767a1dbc48SGeorge Liu             [health](const boost::system::error_code& ec,
1877b9d36b47SEd Tanous                      const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1878eeedda23SJohnathan Mantey             if (ec)
1879029573d4SEd Tanous             {
1880eeedda23SJohnathan Mantey                 return;
1881eeedda23SJohnathan Mantey             }
1882eeedda23SJohnathan Mantey 
1883914e2d5dSEd Tanous             health->inventory = resp;
18847a1dbc48SGeorge Liu         });
1885eeedda23SJohnathan Mantey 
1886eeedda23SJohnathan Mantey         health->populate();
188713451e39SWilly Tu     }
1888eeedda23SJohnathan Mantey 
1889eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1890eeedda23SJohnathan Mantey     {
18910ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
18922c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1893029573d4SEd Tanous     }
1894029573d4SEd Tanous     else
1895029573d4SEd Tanous     {
18962c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
18972c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1898029573d4SEd Tanous     }
1899aa05fb27SJohnathan Mantey 
19002c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
190135fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
190282695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
19032c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
190482695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1905e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1906e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1907e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
19082c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1909b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
19101f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1911e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1912e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1913e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
1914b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1915b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
19162a133282Smanojkiraneda 
191782695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
19184a0cb85cSEd Tanous     {
191982695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1920ab6554f1SJoshi-Mansi 
1921ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1922ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1923ab6554f1SJoshi-Mansi         // FQDN
192482695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1925d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1926d24bfc7aSJennifer Lee         {
19272c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1928d24bfc7aSJennifer Lee         }
19292c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
19304a0cb85cSEd Tanous     }
19314a0cb85cSEd Tanous 
19327857cb8dSJiaqing Zhao     if (ethData.vlanId)
19337857cb8dSJiaqing Zhao     {
19347857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
19357857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
19367857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
19377857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
19387857cb8dSJiaqing Zhao 
19397857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
19407857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
19417857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
19427857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
19437857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
19447857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
19457857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
19467857cb8dSJiaqing Zhao     }
19477857cb8dSJiaqing Zhao     else
19487857cb8dSJiaqing Zhao     {
19497857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
19507857cb8dSJiaqing Zhao     }
19517857cb8dSJiaqing Zhao 
19522c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
19532c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
19544a0cb85cSEd Tanous 
19552c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
19562c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
19572c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
19582c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
19599eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
19604a0cb85cSEd Tanous     {
19612c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1962fa5053a6SGunnar Mills         if (gatewayStr.empty())
1963fa5053a6SGunnar Mills         {
1964fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1965fa5053a6SGunnar Mills         }
19661476687dSEd Tanous         nlohmann::json::object_t ipv4;
19671476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
19681476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
19691476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
19701476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1971fa5053a6SGunnar Mills 
19722c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1973d1d50814SRavi Teja         {
19741476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1975d1d50814SRavi Teja         }
19761476687dSEd Tanous 
1977b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
197801784826SJohnathan Mantey     }
1979d1d50814SRavi Teja 
198082695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
19817ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
19827ea79e5eSRavi Teja     {
19837ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
19847ea79e5eSRavi Teja     }
19857ea79e5eSRavi Teja 
19867ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1987e48c0fc5SRavi Teja 
1988ce73d5c8SSunitha Harish     nlohmann::json::array_t ipv6StaticGatewayArray;
1989ce73d5c8SSunitha Harish     for (const auto& ipv6GatewayConfig : ipv6GatewayData)
1990ce73d5c8SSunitha Harish     {
1991ce73d5c8SSunitha Harish         nlohmann::json::object_t ipv6Gateway;
1992ce73d5c8SSunitha Harish         ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
1993ce73d5c8SSunitha Harish         ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength;
1994ce73d5c8SSunitha Harish         ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
1995ce73d5c8SSunitha Harish     }
1996ce73d5c8SSunitha Harish     jsonResponse["IPv6StaticDefaultGateways"] =
1997ce73d5c8SSunitha Harish         std::move(ipv6StaticGatewayArray);
1998ce73d5c8SSunitha Harish 
19992c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
20002c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
20012c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
20022c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
20037f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
20042c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
20057f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
20069eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
2007e48c0fc5SRavi Teja     {
20081476687dSEd Tanous         nlohmann::json::object_t ipv6;
20091476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
20101476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
20111476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
2012f8361275SSunitha Harish 
2013b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
20142c70f800SEd Tanous         if (ipv6Config.origin == "Static")
2015e48c0fc5SRavi Teja         {
20161476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
20171476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
20181476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
2019b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
202001784826SJohnathan Mantey         }
2021e48c0fc5SRavi Teja     }
2022588c3f0dSKowalski, Kamil }
2023588c3f0dSKowalski, Kamil 
2024e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2025e7caf250SJiaqing Zhao                         const std::string& ifaceId,
2026e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
2027e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
2028e7caf250SJiaqing Zhao {
2029e7caf250SJiaqing Zhao     if (!ec)
2030e7caf250SJiaqing Zhao     {
2031e7caf250SJiaqing Zhao         return;
2032e7caf250SJiaqing Zhao     }
2033e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
2034e7caf250SJiaqing Zhao     if (dbusError == nullptr)
2035e7caf250SJiaqing Zhao     {
2036e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
2037e7caf250SJiaqing Zhao         return;
2038e7caf250SJiaqing Zhao     }
203962598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2040e7caf250SJiaqing Zhao 
2041e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
2042e7caf250SJiaqing Zhao         dbusError->name)
2043e7caf250SJiaqing Zhao     {
2044e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2045e7caf250SJiaqing Zhao                                    ifaceId);
2046e7caf250SJiaqing Zhao         return;
2047e7caf250SJiaqing Zhao     }
2048e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
2049e7caf250SJiaqing Zhao         dbusError->name)
2050e7caf250SJiaqing Zhao     {
2051e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
2052e7caf250SJiaqing Zhao         return;
2053e7caf250SJiaqing Zhao     }
2054e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
2055e7caf250SJiaqing Zhao }
2056e7caf250SJiaqing Zhao 
2057b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2058b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
2059b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
2060b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
2061b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
2062b5ca3fdcSJiaqing Zhao 
2063b5ca3fdcSJiaqing Zhao )
2064b5ca3fdcSJiaqing Zhao {
2065b5ca3fdcSJiaqing Zhao     if (ec)
2066b5ca3fdcSJiaqing Zhao     {
2067b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
2068b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
2069b5ca3fdcSJiaqing Zhao         {
2070b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
2071b5ca3fdcSJiaqing Zhao             return;
2072b5ca3fdcSJiaqing Zhao         }
207362598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2074b5ca3fdcSJiaqing Zhao 
2075b5ca3fdcSJiaqing Zhao         if (std::string_view(
2076b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
2077b5ca3fdcSJiaqing Zhao             dbusError->name)
2078b5ca3fdcSJiaqing Zhao         {
2079b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2080b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2081b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2082b5ca3fdcSJiaqing Zhao             return;
2083b5ca3fdcSJiaqing Zhao         }
2084b5ca3fdcSJiaqing Zhao         if (std::string_view(
2085b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
2086b5ca3fdcSJiaqing Zhao             dbusError->name)
2087b5ca3fdcSJiaqing Zhao         {
2088b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
2089b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
2090b5ca3fdcSJiaqing Zhao             return;
2091b5ca3fdcSJiaqing Zhao         }
2092b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
2093b5ca3fdcSJiaqing Zhao         return;
2094b5ca3fdcSJiaqing Zhao     }
2095b5ca3fdcSJiaqing Zhao 
2096b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
2097b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
2098b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
2099b5ca3fdcSJiaqing Zhao }
2100b5ca3fdcSJiaqing Zhao 
2101bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
2102bf648f77SEd Tanous {
2103bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2104ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
21051476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
21061476687dSEd Tanous             [&app](const crow::Request& req,
21071476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
21083ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
210945ca1b86SEd Tanous         {
211045ca1b86SEd Tanous             return;
211145ca1b86SEd Tanous         }
211245ca1b86SEd Tanous 
2113bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2114bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2115bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2116bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
2117bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
2118bf648f77SEd Tanous             "Ethernet Network Interface Collection";
2119bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
2120bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
2121bf648f77SEd Tanous 
2122bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
2123bf648f77SEd Tanous         // preparation
2124002d39b4SEd Tanous         getEthernetIfaceList(
212577179532SEd Tanous             [asyncResp](const bool& success,
212677179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
2127bf648f77SEd Tanous             if (!success)
21281abe55efSEd Tanous             {
2129f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
21309391bb9cSRapkiewicz, Pawel                 return;
21319391bb9cSRapkiewicz, Pawel             }
21329391bb9cSRapkiewicz, Pawel 
2133002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2134bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
2135bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
2136bf648f77SEd Tanous             {
21371476687dSEd Tanous                 nlohmann::json::object_t iface;
2138ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
2139ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
2140ef4c65b7SEd Tanous                     ifaceItem);
21417857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
2142bf648f77SEd Tanous             }
2143bf648f77SEd Tanous 
2144002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
2145bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2146bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
2147bf648f77SEd Tanous         });
2148bf648f77SEd Tanous     });
2149bf648f77SEd Tanous 
2150b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2151b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
2152b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
2153b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
2154b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2155b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2156b5ca3fdcSJiaqing Zhao         {
2157b5ca3fdcSJiaqing Zhao             return;
2158b5ca3fdcSJiaqing Zhao         }
2159b5ca3fdcSJiaqing Zhao 
2160b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
2161b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
2162b5ca3fdcSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
2163b5ca3fdcSJiaqing Zhao 
2164b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
2165b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
2166b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
2167b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
2168b5ca3fdcSJiaqing Zhao         {
2169b5ca3fdcSJiaqing Zhao             return;
2170b5ca3fdcSJiaqing Zhao         }
2171b5ca3fdcSJiaqing Zhao 
2172b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
2173b5ca3fdcSJiaqing Zhao         {
2174b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
2175b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
2176b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
2177b5ca3fdcSJiaqing Zhao             return;
2178b5ca3fdcSJiaqing Zhao         }
2179b5ca3fdcSJiaqing Zhao 
2180b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
2181b5ca3fdcSJiaqing Zhao         if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
2182b5ca3fdcSJiaqing Zhao                                  "@odata.id", parentInterfaceUri))
2183b5ca3fdcSJiaqing Zhao         {
2184b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
2185b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
2186b5ca3fdcSJiaqing Zhao             return;
2187b5ca3fdcSJiaqing Zhao         }
218862598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
2189b5ca3fdcSJiaqing Zhao 
21906fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
2191b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
2192b5ca3fdcSJiaqing Zhao         if (!parsedUri)
2193b5ca3fdcSJiaqing Zhao         {
2194b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
2195b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2196b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2197b5ca3fdcSJiaqing Zhao             return;
2198b5ca3fdcSJiaqing Zhao         }
2199b5ca3fdcSJiaqing Zhao 
2200b5ca3fdcSJiaqing Zhao         std::string parentInterface;
2201b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
2202b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
2203b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
2204b5ca3fdcSJiaqing Zhao         {
2205b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2206b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2207b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2208b5ca3fdcSJiaqing Zhao             return;
2209b5ca3fdcSJiaqing Zhao         }
2210b5ca3fdcSJiaqing Zhao 
2211b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
2212b5ca3fdcSJiaqing Zhao         {
2213b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
2214b5ca3fdcSJiaqing Zhao             // create
2215b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
2216b5ca3fdcSJiaqing Zhao                                              "false");
2217b5ca3fdcSJiaqing Zhao             return;
2218b5ca3fdcSJiaqing Zhao         }
2219b5ca3fdcSJiaqing Zhao 
2220b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
2221b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
2222b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
2223b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
2224b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
2225b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
2226b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
2227b5ca3fdcSJiaqing Zhao                             m);
2228b5ca3fdcSJiaqing Zhao         },
2229b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
2230b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
2231b5ca3fdcSJiaqing Zhao             vlanId);
2232b5ca3fdcSJiaqing Zhao     });
2233b5ca3fdcSJiaqing Zhao 
2234bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2235ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
2236bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
223745ca1b86SEd Tanous             [&app](const crow::Request& req,
2238bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2239bf648f77SEd Tanous                    const std::string& ifaceId) {
22403ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
224145ca1b86SEd Tanous         {
224245ca1b86SEd Tanous             return;
224345ca1b86SEd Tanous         }
22444a0cb85cSEd Tanous         getEthernetIfaceData(
2245bf648f77SEd Tanous             ifaceId,
2246ce73d5c8SSunitha Harish             [asyncResp,
2247ce73d5c8SSunitha Harish              ifaceId](const bool& success, const EthernetInterfaceData& ethData,
224877179532SEd Tanous                       const std::vector<IPv4AddressData>& ipv4Data,
2249ce73d5c8SSunitha Harish                       const std::vector<IPv6AddressData>& ipv6Data,
2250ce73d5c8SSunitha Harish                       const std::vector<StaticGatewayData>& ipv6GatewayData) {
22514a0cb85cSEd Tanous             if (!success)
22521abe55efSEd Tanous             {
2253bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2254bf648f77SEd Tanous                 // existing object, and other errors
2255002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2256002d39b4SEd Tanous                                            ifaceId);
22574a0cb85cSEd Tanous                 return;
22589391bb9cSRapkiewicz, Pawel             }
22594c9afe43SEd Tanous 
22600f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
226193bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
2262002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
22630f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
22640f74e643SEd Tanous                 "Management Network Interface";
22650f74e643SEd Tanous 
2266ce73d5c8SSunitha Harish             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data,
2267ce73d5c8SSunitha Harish                                ipv6GatewayData);
22689391bb9cSRapkiewicz, Pawel         });
2269bf648f77SEd Tanous     });
22709391bb9cSRapkiewicz, Pawel 
2271bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2272ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2273bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
227445ca1b86SEd Tanous             [&app](const crow::Request& req,
2275bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2276bf648f77SEd Tanous                    const std::string& ifaceId) {
22773ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
227845ca1b86SEd Tanous         {
227945ca1b86SEd Tanous             return;
228045ca1b86SEd Tanous         }
2281bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2282ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2283d577665bSRatan Gupta         std::optional<std::string> macAddress;
22849a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
2285ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
2286ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
2287ce73d5c8SSunitha Harish         std::optional<nlohmann::json::array_t> ipv6StaticDefaultGateways;
2288f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2289da131a9aSJennifer Lee         std::optional<nlohmann::json> dhcpv4;
22901f8c7b5dSJohnathan Mantey         std::optional<nlohmann::json> dhcpv6;
2291b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2292eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
229335fb5311STejas Patil         std::optional<size_t> mtuSize;
22941f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
22951f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2296b10d8db0SRavi Teja         // clang-format off
229715ed6780SWilly Tu         if (!json_util::readJsonPatch(
2298b10d8db0SRavi Teja                 req, asyncResp->res,
2299b10d8db0SRavi Teja                 "DHCPv4", dhcpv4,
2300b10d8db0SRavi Teja                 "DHCPv6", dhcpv6,
2301b10d8db0SRavi Teja                 "FQDN", fqdn,
2302b10d8db0SRavi Teja                 "HostName", hostname,
2303b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2304b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2305b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2306ce73d5c8SSunitha Harish                 "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways,
2307b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2308b10d8db0SRavi Teja                 "MACAddress", macAddress,
2309b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2310b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2311b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2312b10d8db0SRavi Teja                 )
2313b10d8db0SRavi Teja             )
23141abe55efSEd Tanous         {
2315588c3f0dSKowalski, Kamil             return;
2316588c3f0dSKowalski, Kamil         }
2317b10d8db0SRavi Teja         //clang-format on
2318da131a9aSJennifer Lee         if (dhcpv4)
2319da131a9aSJennifer Lee         {
2320002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
23211f8c7b5dSJohnathan Mantey                                      v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
232282695a5bSJiaqing Zhao                                      v4dhcpParms.useDnsServers, "UseNTPServers",
232382695a5bSJiaqing Zhao                                      v4dhcpParms.useNtpServers, "UseDomainName",
232482695a5bSJiaqing Zhao                                      v4dhcpParms.useDomainName))
23251f8c7b5dSJohnathan Mantey             {
23261f8c7b5dSJohnathan Mantey                 return;
23271f8c7b5dSJohnathan Mantey             }
23281f8c7b5dSJohnathan Mantey         }
23291f8c7b5dSJohnathan Mantey 
23301f8c7b5dSJohnathan Mantey         if (dhcpv6)
23311f8c7b5dSJohnathan Mantey         {
2332002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2333002d39b4SEd Tanous                                      v6dhcpParms.dhcpv6OperatingMode,
2334002d39b4SEd Tanous                                      "UseDNSServers", v6dhcpParms.useDnsServers,
2335002d39b4SEd Tanous                                      "UseNTPServers", v6dhcpParms.useNtpServers,
2336002d39b4SEd Tanous                                      "UseDomainName",
233782695a5bSJiaqing Zhao                                      v6dhcpParms.useDomainName))
23381f8c7b5dSJohnathan Mantey             {
23391f8c7b5dSJohnathan Mantey                 return;
23401f8c7b5dSJohnathan Mantey             }
2341da131a9aSJennifer Lee         }
2342da131a9aSJennifer Lee 
2343bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2344bf648f77SEd Tanous         // for JSON preparation
23454a0cb85cSEd Tanous         getEthernetIfaceData(
23462c70f800SEd Tanous             ifaceId,
2347bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2348ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2349d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
23509a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2351e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2352ce73d5c8SSunitha Harish              ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways),
23531f8c7b5dSJohnathan Mantey              staticNameServers = std::move(staticNameServers),
2354bc20089aSEd Tanous              dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
2355b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2356f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2357002d39b4SEd Tanous                 const bool& success, const EthernetInterfaceData& ethData,
235877179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
2359ce73d5c8SSunitha Harish                 const std::vector<IPv6AddressData>& ipv6Data,
2360ce73d5c8SSunitha Harish                 const std::vector<StaticGatewayData>& ipv6GatewayData) {
23611abe55efSEd Tanous             if (!success)
23621abe55efSEd Tanous             {
2363588c3f0dSKowalski, Kamil                 // ... otherwise return error
2364bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2365bf648f77SEd Tanous                 // existing object, and other errors
2366002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2367002d39b4SEd Tanous                                            ifaceId);
2368588c3f0dSKowalski, Kamil                 return;
2369588c3f0dSKowalski, Kamil             }
2370588c3f0dSKowalski, Kamil 
23711f8c7b5dSJohnathan Mantey             if (dhcpv4 || dhcpv6)
23721f8c7b5dSJohnathan Mantey             {
2373002d39b4SEd Tanous                 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2374002d39b4SEd Tanous                                 asyncResp);
23751f8c7b5dSJohnathan Mantey             }
23761f8c7b5dSJohnathan Mantey 
23770627a2c7SEd Tanous             if (hostname)
23781abe55efSEd Tanous             {
23790627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
23801abe55efSEd Tanous             }
23810627a2c7SEd Tanous 
2382b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2383b10d8db0SRavi Teja             {
2384b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2385b10d8db0SRavi Teja                                            asyncResp);
2386b10d8db0SRavi Teja             }
2387b10d8db0SRavi Teja 
2388ab6554f1SJoshi-Mansi             if (fqdn)
2389ab6554f1SJoshi-Mansi             {
23902c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2391ab6554f1SJoshi-Mansi             }
2392ab6554f1SJoshi-Mansi 
2393d577665bSRatan Gupta             if (macAddress)
2394d577665bSRatan Gupta             {
2395002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2396d577665bSRatan Gupta             }
2397d577665bSRatan Gupta 
2398d1d50814SRavi Teja             if (ipv4StaticAddresses)
2399d1d50814SRavi Teja             {
2400bf648f77SEd Tanous                 // TODO(ed) for some reason the capture of
2401bf648f77SEd Tanous                 // ipv4Addresses above is returning a const value,
2402bf648f77SEd Tanous                 // not a non-const value. This doesn't really work
2403bf648f77SEd Tanous                 // for us, as we need to be able to efficiently move
2404bf648f77SEd Tanous                 // out the intermedia nlohmann::json objects. This
2405bf648f77SEd Tanous                 // makes a copy of the structure, and operates on
2406bf648f77SEd Tanous                 // that, but could be done more efficiently
2407ddd70dcaSEd Tanous                 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
2408002d39b4SEd Tanous                 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
24091abe55efSEd Tanous             }
24100627a2c7SEd Tanous 
2411f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2412f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2413002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2414002d39b4SEd Tanous                                              asyncResp);
2415f85837bfSRAJESWARAN THILLAIGOVINDAN             }
24169a6fc6feSRavi Teja 
24179a6fc6feSRavi Teja             if (ipv6DefaultGateway)
24189a6fc6feSRavi Teja             {
24199a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
24209a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
24219a6fc6feSRavi Teja             }
2422e48c0fc5SRavi Teja 
2423e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2424e48c0fc5SRavi Teja             {
2425ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2426ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2427e48c0fc5SRavi Teja             }
2428eeedda23SJohnathan Mantey 
2429ce73d5c8SSunitha Harish             if (ipv6StaticDefaultGateway)
2430ce73d5c8SSunitha Harish             {
2431ce73d5c8SSunitha Harish                 handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway,
2432ce73d5c8SSunitha Harish                                          ipv6GatewayData, asyncResp);
2433ce73d5c8SSunitha Harish             }
2434ce73d5c8SSunitha Harish 
2435eeedda23SJohnathan Mantey             if (interfaceEnabled)
2436eeedda23SJohnathan Mantey             {
2437002d39b4SEd Tanous                 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2438002d39b4SEd Tanous                                                  *interfaceEnabled, asyncResp);
2439eeedda23SJohnathan Mantey             }
244035fb5311STejas Patil 
244135fb5311STejas Patil             if (mtuSize)
244235fb5311STejas Patil             {
244335fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
244435fb5311STejas Patil             }
2445588c3f0dSKowalski, Kamil             });
2446bf648f77SEd Tanous         });
2447e7caf250SJiaqing Zhao 
2448e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2449e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2450e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2451e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2452e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2453e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2454e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2455e7caf250SJiaqing Zhao         {
2456e7caf250SJiaqing Zhao             return;
2457e7caf250SJiaqing Zhao         }
2458e7caf250SJiaqing Zhao 
2459e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2460e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2461e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2462e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2463e7caf250SJiaqing Zhao             },
2464e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2465e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2466e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2467e7caf250SJiaqing Zhao         });
24684a0cb85cSEd Tanous }
2469bf648f77SEd Tanous 
24709391bb9cSRapkiewicz, Pawel } // namespace redfish
2471