xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision ce73d5c8517e0b85d85de345f10c82c24cbb067b)
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 
31*ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp>
32ef4c65b7SEd Tanous #include <boost/url/format.hpp>
331214b7e7SGunnar Mills 
347a1dbc48SGeorge Liu #include <array>
35*ce73d5c8SSunitha 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 };
76*ce73d5c8SSunitha Harish 
77*ce73d5c8SSunitha Harish /**
78*ce73d5c8SSunitha Harish  * Structure for keeping static route data required by Redfish
79*ce73d5c8SSunitha Harish  */
80*ce73d5c8SSunitha Harish struct StaticGatewayData
81*ce73d5c8SSunitha Harish {
82*ce73d5c8SSunitha Harish     std::string id;
83*ce73d5c8SSunitha Harish     std::string gateway;
84*ce73d5c8SSunitha Harish     size_t prefixLength = 0;
85*ce73d5c8SSunitha Harish     std::string protocol;
86*ce73d5c8SSunitha Harish };
87*ce73d5c8SSunitha 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;
113*ce73d5c8SSunitha 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 
829*ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData(
830*ce73d5c8SSunitha Harish     const std::string& ethifaceId,
831*ce73d5c8SSunitha Harish     const dbus::utility::ManagedObjectType& dbusData,
832*ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>& staticGatewayConfig)
833*ce73d5c8SSunitha Harish {
834*ce73d5c8SSunitha Harish     std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
835*ce73d5c8SSunitha Harish     staticGatewayPathStart += ethifaceId;
836*ce73d5c8SSunitha Harish 
837*ce73d5c8SSunitha Harish     for (const auto& objpath : dbusData)
838*ce73d5c8SSunitha Harish     {
839*ce73d5c8SSunitha Harish         if (!std::string_view(objpath.first.str)
840*ce73d5c8SSunitha Harish                  .starts_with(staticGatewayPathStart))
841*ce73d5c8SSunitha Harish         {
842*ce73d5c8SSunitha Harish             continue;
843*ce73d5c8SSunitha Harish         }
844*ce73d5c8SSunitha Harish         for (const auto& interface : objpath.second)
845*ce73d5c8SSunitha Harish         {
846*ce73d5c8SSunitha Harish             if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
847*ce73d5c8SSunitha Harish             {
848*ce73d5c8SSunitha Harish                 continue;
849*ce73d5c8SSunitha Harish             }
850*ce73d5c8SSunitha Harish             StaticGatewayData& staticGateway =
851*ce73d5c8SSunitha Harish                 staticGatewayConfig.emplace_back();
852*ce73d5c8SSunitha Harish             staticGateway.id = objpath.first.filename();
853*ce73d5c8SSunitha Harish 
854*ce73d5c8SSunitha Harish             bool success = sdbusplus::unpackPropertiesNoThrow(
855*ce73d5c8SSunitha Harish                 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
856*ce73d5c8SSunitha Harish                 "Gateway", staticGateway.gateway, "PrefixLength",
857*ce73d5c8SSunitha Harish                 staticGateway.prefixLength, "ProtocolType",
858*ce73d5c8SSunitha Harish                 staticGateway.protocol);
859*ce73d5c8SSunitha Harish             if (!success)
860*ce73d5c8SSunitha Harish             {
861*ce73d5c8SSunitha Harish                 return false;
862*ce73d5c8SSunitha Harish             }
863*ce73d5c8SSunitha Harish         }
864*ce73d5c8SSunitha Harish     }
865*ce73d5c8SSunitha Harish     return true;
866*ce73d5c8SSunitha Harish }
867*ce73d5c8SSunitha 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 {
882*ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
883*ce73d5c8SSunitha Harish     path /= ifaceId;
884*ce73d5c8SSunitha 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     };
900*ce73d5c8SSunitha Harish     // Passing null for gateway, as per redfish spec IPv6StaticAddresses
901*ce73d5c8SSunitha Harish     // object does not have associated gateway property
902e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
903*ce73d5c8SSunitha 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 /**
910*ce73d5c8SSunitha Harish  * @brief Deletes given IPv6 Static Gateway
911*ce73d5c8SSunitha Harish  *
912*ce73d5c8SSunitha Harish  * @param[in] ifaceId     Id of interface whose IP should be deleted
913*ce73d5c8SSunitha Harish  * @param[in] ipHash      DBus Hash id of IP that should be deleted
914*ce73d5c8SSunitha Harish  * @param[io] asyncResp   Response object that will be returned to client
915*ce73d5c8SSunitha Harish  *
916*ce73d5c8SSunitha Harish  * @return None
917*ce73d5c8SSunitha Harish  */
918*ce73d5c8SSunitha Harish inline void
919*ce73d5c8SSunitha Harish     deleteIPv6Gateway(std::string_view gatewayId,
920*ce73d5c8SSunitha Harish                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
921*ce73d5c8SSunitha Harish {
922*ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
923*ce73d5c8SSunitha Harish     path /= gatewayId;
924*ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
925*ce73d5c8SSunitha Harish         [asyncResp](const boost::system::error_code& ec) {
926*ce73d5c8SSunitha Harish         if (ec)
927*ce73d5c8SSunitha Harish         {
928*ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
929*ce73d5c8SSunitha Harish         }
930*ce73d5c8SSunitha Harish     },
931*ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
932*ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
933*ce73d5c8SSunitha Harish }
934*ce73d5c8SSunitha Harish 
935*ce73d5c8SSunitha Harish /**
936*ce73d5c8SSunitha Harish  * @brief Creates IPv6 static default gateway with given data
937*ce73d5c8SSunitha Harish  *
938*ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose IP should be added
939*ce73d5c8SSunitha Harish  * @param[in] prefixLength Prefix length that needs to be added
940*ce73d5c8SSunitha Harish  * @param[in] gateway      Gateway address that needs to be added
941*ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
942*ce73d5c8SSunitha Harish  *
943*ce73d5c8SSunitha Harish  * @return None
944*ce73d5c8SSunitha Harish  */
945*ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway(
946*ce73d5c8SSunitha Harish     std::string_view ifaceId, size_t prefixLength, std::string_view gateway,
947*ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
948*ce73d5c8SSunitha Harish {
949*ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
950*ce73d5c8SSunitha Harish     path /= ifaceId;
951*ce73d5c8SSunitha Harish     auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
952*ce73d5c8SSunitha Harish         if (ec)
953*ce73d5c8SSunitha Harish         {
954*ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
955*ce73d5c8SSunitha Harish         }
956*ce73d5c8SSunitha Harish     };
957*ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
958*ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
959*ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
960*ce73d5c8SSunitha Harish         gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
961*ce73d5c8SSunitha Harish }
962*ce73d5c8SSunitha Harish 
963*ce73d5c8SSunitha Harish /**
964*ce73d5c8SSunitha Harish  * @brief Deletes the IPv6 default gateway entry for this interface and
965*ce73d5c8SSunitha Harish  * creates a replacement IPv6 default gateway entry
966*ce73d5c8SSunitha Harish  *
967*ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface upon which to create the IPv6
968*ce73d5c8SSunitha Harish  * entry
969*ce73d5c8SSunitha Harish  * @param[in] gateway      IPv6 gateway to assign to this interface
970*ce73d5c8SSunitha Harish  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
971*ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
972*ce73d5c8SSunitha Harish  *
973*ce73d5c8SSunitha Harish  * @return None
974*ce73d5c8SSunitha Harish  */
975*ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway(
976*ce73d5c8SSunitha Harish     std::string_view ifaceId, std::string_view gatewayId,
977*ce73d5c8SSunitha Harish     std::string_view gateway, size_t prefixLength,
978*ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
979*ce73d5c8SSunitha Harish {
980*ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
981*ce73d5c8SSunitha Harish     path /= gatewayId;
982*ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
983*ce73d5c8SSunitha Harish         [asyncResp, ifaceId, gateway,
984*ce73d5c8SSunitha Harish          prefixLength](const boost::system::error_code& ec) {
985*ce73d5c8SSunitha Harish         if (ec)
986*ce73d5c8SSunitha Harish         {
987*ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
988*ce73d5c8SSunitha Harish             return;
989*ce73d5c8SSunitha Harish         }
990*ce73d5c8SSunitha Harish         createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp);
991*ce73d5c8SSunitha Harish     },
992*ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
993*ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
994*ce73d5c8SSunitha Harish }
995*ce73d5c8SSunitha Harish 
996*ce73d5c8SSunitha Harish /**
997*ce73d5c8SSunitha Harish  * @brief Sets IPv6 default gateway with given data
998*ce73d5c8SSunitha Harish  *
999*ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose gateway should be added
1000*ce73d5c8SSunitha Harish  * @param[in] input        Contains address that needs to be added
1001*ce73d5c8SSunitha Harish  * @param[in] staticGatewayData  Current static gateways in the system
1002*ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
1003*ce73d5c8SSunitha Harish  *
1004*ce73d5c8SSunitha Harish  * @return None
1005*ce73d5c8SSunitha Harish  */
1006*ce73d5c8SSunitha Harish 
1007*ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway(
1008*ce73d5c8SSunitha Harish     const std::string& ifaceId, const nlohmann::json::array_t& input,
1009*ce73d5c8SSunitha Harish     const std::vector<StaticGatewayData>& staticGatewayData,
1010*ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1011*ce73d5c8SSunitha Harish {
1012*ce73d5c8SSunitha Harish     size_t entryIdx = 1;
1013*ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>::const_iterator staticGatewayEntry =
1014*ce73d5c8SSunitha Harish         staticGatewayData.begin();
1015*ce73d5c8SSunitha Harish 
1016*ce73d5c8SSunitha Harish     for (const nlohmann::json& thisJson : input)
1017*ce73d5c8SSunitha Harish     {
1018*ce73d5c8SSunitha Harish         // find the next gateway entry
1019*ce73d5c8SSunitha Harish         while (staticGatewayEntry != staticGatewayData.end())
1020*ce73d5c8SSunitha Harish         {
1021*ce73d5c8SSunitha Harish             if (staticGatewayEntry->protocol ==
1022*ce73d5c8SSunitha Harish                 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1023*ce73d5c8SSunitha Harish             {
1024*ce73d5c8SSunitha Harish                 break;
1025*ce73d5c8SSunitha Harish             }
1026*ce73d5c8SSunitha Harish             staticGatewayEntry++;
1027*ce73d5c8SSunitha Harish         }
1028*ce73d5c8SSunitha Harish         std::string pathString = "IPv6StaticDefaultGateways/" +
1029*ce73d5c8SSunitha Harish                                  std::to_string(entryIdx);
1030*ce73d5c8SSunitha Harish         if (thisJson.is_null())
1031*ce73d5c8SSunitha Harish         {
1032*ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1033*ce73d5c8SSunitha Harish             {
1034*ce73d5c8SSunitha Harish                 messages::resourceCannotBeDeleted(asyncResp->res);
1035*ce73d5c8SSunitha Harish                 return;
1036*ce73d5c8SSunitha Harish             }
1037*ce73d5c8SSunitha Harish             deleteIPv6Gateway(staticGatewayEntry->id, asyncResp);
1038*ce73d5c8SSunitha Harish             return;
1039*ce73d5c8SSunitha Harish         }
1040*ce73d5c8SSunitha Harish         if (thisJson.is_object() && thisJson.empty())
1041*ce73d5c8SSunitha Harish         {
1042*ce73d5c8SSunitha Harish             // Do nothing, but make sure the entry exists.
1043*ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1044*ce73d5c8SSunitha Harish             {
1045*ce73d5c8SSunitha Harish                 messages::propertyValueFormatError(asyncResp->res, thisJson,
1046*ce73d5c8SSunitha Harish                                                    pathString);
1047*ce73d5c8SSunitha Harish                 return;
1048*ce73d5c8SSunitha Harish             }
1049*ce73d5c8SSunitha Harish         }
1050*ce73d5c8SSunitha Harish         std::optional<std::string> address;
1051*ce73d5c8SSunitha Harish         std::optional<size_t> prefixLength;
1052*ce73d5c8SSunitha Harish 
1053*ce73d5c8SSunitha Harish         nlohmann::json thisJsonCopy = thisJson;
1054*ce73d5c8SSunitha Harish         if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1055*ce73d5c8SSunitha Harish                                  address, "PrefixLength", prefixLength))
1056*ce73d5c8SSunitha Harish         {
1057*ce73d5c8SSunitha Harish             return;
1058*ce73d5c8SSunitha Harish         }
1059*ce73d5c8SSunitha Harish         const std::string* addr = nullptr;
1060*ce73d5c8SSunitha Harish         size_t prefix = 0;
1061*ce73d5c8SSunitha Harish         if (address)
1062*ce73d5c8SSunitha Harish         {
1063*ce73d5c8SSunitha Harish             addr = &(*address);
1064*ce73d5c8SSunitha Harish         }
1065*ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1066*ce73d5c8SSunitha Harish         {
1067*ce73d5c8SSunitha Harish             addr = &(staticGatewayEntry->gateway);
1068*ce73d5c8SSunitha Harish         }
1069*ce73d5c8SSunitha Harish         else
1070*ce73d5c8SSunitha Harish         {
1071*ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res, pathString + "/Address");
1072*ce73d5c8SSunitha Harish             return;
1073*ce73d5c8SSunitha Harish         }
1074*ce73d5c8SSunitha Harish         if (prefixLength)
1075*ce73d5c8SSunitha Harish         {
1076*ce73d5c8SSunitha Harish             prefix = *prefixLength;
1077*ce73d5c8SSunitha Harish         }
1078*ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1079*ce73d5c8SSunitha Harish         {
1080*ce73d5c8SSunitha Harish             prefix = staticGatewayEntry->prefixLength;
1081*ce73d5c8SSunitha Harish         }
1082*ce73d5c8SSunitha Harish         else
1083*ce73d5c8SSunitha Harish         {
1084*ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res,
1085*ce73d5c8SSunitha Harish                                       pathString + "/PrefixLength");
1086*ce73d5c8SSunitha Harish             return;
1087*ce73d5c8SSunitha Harish         }
1088*ce73d5c8SSunitha Harish         if (staticGatewayEntry != staticGatewayData.end())
1089*ce73d5c8SSunitha Harish         {
1090*ce73d5c8SSunitha Harish             deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
1091*ce73d5c8SSunitha Harish                                               *addr, prefix, asyncResp);
1092*ce73d5c8SSunitha Harish             staticGatewayEntry++;
1093*ce73d5c8SSunitha Harish         }
1094*ce73d5c8SSunitha Harish         else
1095*ce73d5c8SSunitha Harish         {
1096*ce73d5c8SSunitha Harish             createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp);
1097*ce73d5c8SSunitha Harish         }
1098*ce73d5c8SSunitha Harish         entryIdx++;
1099*ce73d5c8SSunitha Harish     }
1100*ce73d5c8SSunitha Harish }
1101*ce73d5c8SSunitha Harish 
1102*ce73d5c8SSunitha 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;
1124*ce73d5c8SSunitha Harish         std::vector<StaticGatewayData> ipv6GatewayData;
1125179db1d7SKowalski, Kamil 
11268b24275dSEd Tanous         if (ec)
11271abe55efSEd Tanous         {
1128*ce73d5c8SSunitha 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         {
1135*ce73d5c8SSunitha 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);
1152*ce73d5c8SSunitha Harish         if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData))
1153*ce73d5c8SSunitha Harish         {
1154*ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1155*ce73d5c8SSunitha Harish         }
11564e0453b1SGunnar Mills         // Finally make a callback with useful data
1157*ce73d5c8SSunitha 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 
1778543f4400SEd Tanous             const std::string* addr = nullptr;
1779543f4400SEd Tanous             uint8_t prefix = 0;
178001784826SJohnathan Mantey 
178101784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
178201784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
178301784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
178401784826SJohnathan Mantey             // current request.
1785e48c0fc5SRavi Teja             if (address)
1786e48c0fc5SRavi Teja             {
178701784826SJohnathan Mantey                 addr = &(*address);
1788e48c0fc5SRavi Teja             }
178985ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
179001784826SJohnathan Mantey             {
179185ffe86aSJiaqing Zhao                 addr = &(nicIpEntry->address);
179201784826SJohnathan Mantey             }
179301784826SJohnathan Mantey             else
179401784826SJohnathan Mantey             {
179501784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
179601784826SJohnathan Mantey                                           pathString + "/Address");
179701784826SJohnathan Mantey                 return;
1798e48c0fc5SRavi Teja             }
1799e48c0fc5SRavi Teja 
1800e48c0fc5SRavi Teja             if (prefixLength)
1801e48c0fc5SRavi Teja             {
180201784826SJohnathan Mantey                 prefix = *prefixLength;
180301784826SJohnathan Mantey             }
180485ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
1805e48c0fc5SRavi Teja             {
180685ffe86aSJiaqing Zhao                 prefix = nicIpEntry->prefixLength;
1807e48c0fc5SRavi Teja             }
1808e48c0fc5SRavi Teja             else
1809e48c0fc5SRavi Teja             {
1810e48c0fc5SRavi Teja                 messages::propertyMissing(asyncResp->res,
1811e48c0fc5SRavi Teja                                           pathString + "/PrefixLength");
181201784826SJohnathan Mantey                 return;
1813e48c0fc5SRavi Teja             }
1814e48c0fc5SRavi Teja 
181585ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1816e48c0fc5SRavi Teja             {
18179c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
181877eb0153SEd Tanous                                          nicIpEntry->id, prefix, *addr, "",
1819e48c0fc5SRavi Teja                                          asyncResp);
182089492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
182189492a15SPatrick Williams                                                   ipv6Data.cend());
182201784826SJohnathan Mantey             }
182301784826SJohnathan Mantey             else
182401784826SJohnathan Mantey             {
182501784826SJohnathan Mantey                 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1826e48c0fc5SRavi Teja             }
1827e48c0fc5SRavi Teja             entryIdx++;
1828e48c0fc5SRavi Teja         }
182901784826SJohnathan Mantey         else
183001784826SJohnathan Mantey         {
183185ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
183201784826SJohnathan Mantey             {
183301784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
183401784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
183501784826SJohnathan Mantey                 // in error, so bail out.
183601784826SJohnathan Mantey                 if (thisJson.is_null())
183701784826SJohnathan Mantey                 {
183801784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
183901784826SJohnathan Mantey                     return;
184001784826SJohnathan Mantey                 }
1841f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
184271f52d96SEd Tanous                                                    pathString);
184301784826SJohnathan Mantey                 return;
184401784826SJohnathan Mantey             }
184501784826SJohnathan Mantey 
184601784826SJohnathan Mantey             if (thisJson.is_null())
184701784826SJohnathan Mantey             {
18489c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
184901784826SJohnathan Mantey             }
185085ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
185101784826SJohnathan Mantey             {
185289492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
185389492a15SPatrick Williams                                                   ipv6Data.cend());
185401784826SJohnathan Mantey             }
185501784826SJohnathan Mantey             entryIdx++;
185601784826SJohnathan Mantey         }
185701784826SJohnathan Mantey     }
1858e48c0fc5SRavi Teja }
1859e48c0fc5SRavi Teja 
18607857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
18617857cb8dSJiaqing Zhao {
18627857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
18637857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
18647857cb8dSJiaqing Zhao }
18657857cb8dSJiaqing Zhao 
186677179532SEd Tanous inline void
186777179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
186877179532SEd Tanous                        const std::string& ifaceId,
186977179532SEd Tanous                        const EthernetInterfaceData& ethData,
187077179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
1871*ce73d5c8SSunitha Harish                        const std::vector<IPv6AddressData>& ipv6Data,
1872*ce73d5c8SSunitha Harish                        const std::vector<StaticGatewayData>& ipv6GatewayData)
18734a0cb85cSEd Tanous {
18742c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
187581ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1876ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1877ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
18782c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1879eeedda23SJohnathan Mantey 
188013451e39SWilly Tu     if constexpr (bmcwebEnableHealthPopulate)
188113451e39SWilly Tu     {
188213451e39SWilly Tu         constexpr std::array<std::string_view, 1> inventoryForEthernet = {
188313451e39SWilly Tu             "xyz.openbmc_project.Inventory.Item.Ethernet"};
1884eeedda23SJohnathan Mantey         auto health = std::make_shared<HealthPopulate>(asyncResp);
18857a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
18867a1dbc48SGeorge Liu             "/", 0, inventoryForEthernet,
18877a1dbc48SGeorge Liu             [health](const boost::system::error_code& ec,
1888b9d36b47SEd Tanous                      const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1889eeedda23SJohnathan Mantey             if (ec)
1890029573d4SEd Tanous             {
1891eeedda23SJohnathan Mantey                 return;
1892eeedda23SJohnathan Mantey             }
1893eeedda23SJohnathan Mantey 
1894914e2d5dSEd Tanous             health->inventory = resp;
18957a1dbc48SGeorge Liu         });
1896eeedda23SJohnathan Mantey 
1897eeedda23SJohnathan Mantey         health->populate();
189813451e39SWilly Tu     }
1899eeedda23SJohnathan Mantey 
1900eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1901eeedda23SJohnathan Mantey     {
19020ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
19032c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1904029573d4SEd Tanous     }
1905029573d4SEd Tanous     else
1906029573d4SEd Tanous     {
19072c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
19082c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1909029573d4SEd Tanous     }
1910aa05fb27SJohnathan Mantey 
19112c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
191235fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
191382695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
19142c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
191582695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1916e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1917e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1918e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
19192c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1920b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
19211f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1922e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1923e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1924e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
1925b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1926b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
19272a133282Smanojkiraneda 
192882695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
19294a0cb85cSEd Tanous     {
193082695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1931ab6554f1SJoshi-Mansi 
1932ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1933ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1934ab6554f1SJoshi-Mansi         // FQDN
193582695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1936d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1937d24bfc7aSJennifer Lee         {
19382c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1939d24bfc7aSJennifer Lee         }
19402c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
19414a0cb85cSEd Tanous     }
19424a0cb85cSEd Tanous 
19437857cb8dSJiaqing Zhao     if (ethData.vlanId)
19447857cb8dSJiaqing Zhao     {
19457857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
19467857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
19477857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
19487857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
19497857cb8dSJiaqing Zhao 
19507857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
19517857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
19527857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
19537857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
19547857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
19557857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
19567857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
19577857cb8dSJiaqing Zhao     }
19587857cb8dSJiaqing Zhao     else
19597857cb8dSJiaqing Zhao     {
19607857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
19617857cb8dSJiaqing Zhao     }
19627857cb8dSJiaqing Zhao 
19632c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
19642c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
19654a0cb85cSEd Tanous 
19662c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
19672c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
19682c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
19692c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
19709eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
19714a0cb85cSEd Tanous     {
19722c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1973fa5053a6SGunnar Mills         if (gatewayStr.empty())
1974fa5053a6SGunnar Mills         {
1975fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1976fa5053a6SGunnar Mills         }
19771476687dSEd Tanous         nlohmann::json::object_t ipv4;
19781476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
19791476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
19801476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
19811476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1982fa5053a6SGunnar Mills 
19832c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1984d1d50814SRavi Teja         {
19851476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1986d1d50814SRavi Teja         }
19871476687dSEd Tanous 
1988b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
198901784826SJohnathan Mantey     }
1990d1d50814SRavi Teja 
199182695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
19927ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
19937ea79e5eSRavi Teja     {
19947ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
19957ea79e5eSRavi Teja     }
19967ea79e5eSRavi Teja 
19977ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1998e48c0fc5SRavi Teja 
1999*ce73d5c8SSunitha Harish     nlohmann::json::array_t ipv6StaticGatewayArray;
2000*ce73d5c8SSunitha Harish     for (const auto& ipv6GatewayConfig : ipv6GatewayData)
2001*ce73d5c8SSunitha Harish     {
2002*ce73d5c8SSunitha Harish         nlohmann::json::object_t ipv6Gateway;
2003*ce73d5c8SSunitha Harish         ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
2004*ce73d5c8SSunitha Harish         ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength;
2005*ce73d5c8SSunitha Harish         ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
2006*ce73d5c8SSunitha Harish     }
2007*ce73d5c8SSunitha Harish     jsonResponse["IPv6StaticDefaultGateways"] =
2008*ce73d5c8SSunitha Harish         std::move(ipv6StaticGatewayArray);
2009*ce73d5c8SSunitha Harish 
20102c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
20112c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
20122c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
20132c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
20147f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
20152c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
20167f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
20179eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
2018e48c0fc5SRavi Teja     {
20191476687dSEd Tanous         nlohmann::json::object_t ipv6;
20201476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
20211476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
20221476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
2023f8361275SSunitha Harish 
2024b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
20252c70f800SEd Tanous         if (ipv6Config.origin == "Static")
2026e48c0fc5SRavi Teja         {
20271476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
20281476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
20291476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
2030b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
203101784826SJohnathan Mantey         }
2032e48c0fc5SRavi Teja     }
2033588c3f0dSKowalski, Kamil }
2034588c3f0dSKowalski, Kamil 
2035e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2036e7caf250SJiaqing Zhao                         const std::string& ifaceId,
2037e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
2038e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
2039e7caf250SJiaqing Zhao {
2040e7caf250SJiaqing Zhao     if (!ec)
2041e7caf250SJiaqing Zhao     {
2042e7caf250SJiaqing Zhao         return;
2043e7caf250SJiaqing Zhao     }
2044e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
2045e7caf250SJiaqing Zhao     if (dbusError == nullptr)
2046e7caf250SJiaqing Zhao     {
2047e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
2048e7caf250SJiaqing Zhao         return;
2049e7caf250SJiaqing Zhao     }
205062598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2051e7caf250SJiaqing Zhao 
2052e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
2053e7caf250SJiaqing Zhao         dbusError->name)
2054e7caf250SJiaqing Zhao     {
2055e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2056e7caf250SJiaqing Zhao                                    ifaceId);
2057e7caf250SJiaqing Zhao         return;
2058e7caf250SJiaqing Zhao     }
2059e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
2060e7caf250SJiaqing Zhao         dbusError->name)
2061e7caf250SJiaqing Zhao     {
2062e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
2063e7caf250SJiaqing Zhao         return;
2064e7caf250SJiaqing Zhao     }
2065e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
2066e7caf250SJiaqing Zhao }
2067e7caf250SJiaqing Zhao 
2068b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2069b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
2070b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
2071b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
2072b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
2073b5ca3fdcSJiaqing Zhao 
2074b5ca3fdcSJiaqing Zhao )
2075b5ca3fdcSJiaqing Zhao {
2076b5ca3fdcSJiaqing Zhao     if (ec)
2077b5ca3fdcSJiaqing Zhao     {
2078b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
2079b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
2080b5ca3fdcSJiaqing Zhao         {
2081b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
2082b5ca3fdcSJiaqing Zhao             return;
2083b5ca3fdcSJiaqing Zhao         }
208462598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2085b5ca3fdcSJiaqing Zhao 
2086b5ca3fdcSJiaqing Zhao         if (std::string_view(
2087b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
2088b5ca3fdcSJiaqing Zhao             dbusError->name)
2089b5ca3fdcSJiaqing Zhao         {
2090b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2091b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2092b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2093b5ca3fdcSJiaqing Zhao             return;
2094b5ca3fdcSJiaqing Zhao         }
2095b5ca3fdcSJiaqing Zhao         if (std::string_view(
2096b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
2097b5ca3fdcSJiaqing Zhao             dbusError->name)
2098b5ca3fdcSJiaqing Zhao         {
2099b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
2100b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
2101b5ca3fdcSJiaqing Zhao             return;
2102b5ca3fdcSJiaqing Zhao         }
2103b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
2104b5ca3fdcSJiaqing Zhao         return;
2105b5ca3fdcSJiaqing Zhao     }
2106b5ca3fdcSJiaqing Zhao 
2107b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
2108b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
2109b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
2110b5ca3fdcSJiaqing Zhao }
2111b5ca3fdcSJiaqing Zhao 
2112bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
2113bf648f77SEd Tanous {
2114bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2115ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
21161476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
21171476687dSEd Tanous             [&app](const crow::Request& req,
21181476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
21193ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
212045ca1b86SEd Tanous         {
212145ca1b86SEd Tanous             return;
212245ca1b86SEd Tanous         }
212345ca1b86SEd Tanous 
2124bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2125bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2126bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2127bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
2128bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
2129bf648f77SEd Tanous             "Ethernet Network Interface Collection";
2130bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
2131bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
2132bf648f77SEd Tanous 
2133bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
2134bf648f77SEd Tanous         // preparation
2135002d39b4SEd Tanous         getEthernetIfaceList(
213677179532SEd Tanous             [asyncResp](const bool& success,
213777179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
2138bf648f77SEd Tanous             if (!success)
21391abe55efSEd Tanous             {
2140f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
21419391bb9cSRapkiewicz, Pawel                 return;
21429391bb9cSRapkiewicz, Pawel             }
21439391bb9cSRapkiewicz, Pawel 
2144002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2145bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
2146bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
2147bf648f77SEd Tanous             {
21481476687dSEd Tanous                 nlohmann::json::object_t iface;
2149ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
2150ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
2151ef4c65b7SEd Tanous                     ifaceItem);
21527857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
2153bf648f77SEd Tanous             }
2154bf648f77SEd Tanous 
2155002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
2156bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2157bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
2158bf648f77SEd Tanous         });
2159bf648f77SEd Tanous     });
2160bf648f77SEd Tanous 
2161b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2162b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
2163b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
2164b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
2165b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2166b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2167b5ca3fdcSJiaqing Zhao         {
2168b5ca3fdcSJiaqing Zhao             return;
2169b5ca3fdcSJiaqing Zhao         }
2170b5ca3fdcSJiaqing Zhao 
2171b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
2172b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
2173b5ca3fdcSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
2174b5ca3fdcSJiaqing Zhao 
2175b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
2176b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
2177b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
2178b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
2179b5ca3fdcSJiaqing Zhao         {
2180b5ca3fdcSJiaqing Zhao             return;
2181b5ca3fdcSJiaqing Zhao         }
2182b5ca3fdcSJiaqing Zhao 
2183b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
2184b5ca3fdcSJiaqing Zhao         {
2185b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
2186b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
2187b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
2188b5ca3fdcSJiaqing Zhao             return;
2189b5ca3fdcSJiaqing Zhao         }
2190b5ca3fdcSJiaqing Zhao 
2191b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
2192b5ca3fdcSJiaqing Zhao         if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
2193b5ca3fdcSJiaqing Zhao                                  "@odata.id", parentInterfaceUri))
2194b5ca3fdcSJiaqing Zhao         {
2195b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
2196b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
2197b5ca3fdcSJiaqing Zhao             return;
2198b5ca3fdcSJiaqing Zhao         }
219962598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
2200b5ca3fdcSJiaqing Zhao 
22016fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
2202b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
2203b5ca3fdcSJiaqing Zhao         if (!parsedUri)
2204b5ca3fdcSJiaqing Zhao         {
2205b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
2206b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2207b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2208b5ca3fdcSJiaqing Zhao             return;
2209b5ca3fdcSJiaqing Zhao         }
2210b5ca3fdcSJiaqing Zhao 
2211b5ca3fdcSJiaqing Zhao         std::string parentInterface;
2212b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
2213b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
2214b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
2215b5ca3fdcSJiaqing Zhao         {
2216b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2217b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2218b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2219b5ca3fdcSJiaqing Zhao             return;
2220b5ca3fdcSJiaqing Zhao         }
2221b5ca3fdcSJiaqing Zhao 
2222b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
2223b5ca3fdcSJiaqing Zhao         {
2224b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
2225b5ca3fdcSJiaqing Zhao             // create
2226b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
2227b5ca3fdcSJiaqing Zhao                                              "false");
2228b5ca3fdcSJiaqing Zhao             return;
2229b5ca3fdcSJiaqing Zhao         }
2230b5ca3fdcSJiaqing Zhao 
2231b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
2232b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
2233b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
2234b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
2235b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
2236b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
2237b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
2238b5ca3fdcSJiaqing Zhao                             m);
2239b5ca3fdcSJiaqing Zhao         },
2240b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
2241b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
2242b5ca3fdcSJiaqing Zhao             vlanId);
2243b5ca3fdcSJiaqing Zhao     });
2244b5ca3fdcSJiaqing Zhao 
2245bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2246ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
2247bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
224845ca1b86SEd Tanous             [&app](const crow::Request& req,
2249bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2250bf648f77SEd Tanous                    const std::string& ifaceId) {
22513ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
225245ca1b86SEd Tanous         {
225345ca1b86SEd Tanous             return;
225445ca1b86SEd Tanous         }
22554a0cb85cSEd Tanous         getEthernetIfaceData(
2256bf648f77SEd Tanous             ifaceId,
2257*ce73d5c8SSunitha Harish             [asyncResp,
2258*ce73d5c8SSunitha Harish              ifaceId](const bool& success, const EthernetInterfaceData& ethData,
225977179532SEd Tanous                       const std::vector<IPv4AddressData>& ipv4Data,
2260*ce73d5c8SSunitha Harish                       const std::vector<IPv6AddressData>& ipv6Data,
2261*ce73d5c8SSunitha Harish                       const std::vector<StaticGatewayData>& ipv6GatewayData) {
22624a0cb85cSEd Tanous             if (!success)
22631abe55efSEd Tanous             {
2264bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2265bf648f77SEd Tanous                 // existing object, and other errors
2266002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2267002d39b4SEd Tanous                                            ifaceId);
22684a0cb85cSEd Tanous                 return;
22699391bb9cSRapkiewicz, Pawel             }
22704c9afe43SEd Tanous 
22710f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
227293bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
2273002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
22740f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
22750f74e643SEd Tanous                 "Management Network Interface";
22760f74e643SEd Tanous 
2277*ce73d5c8SSunitha Harish             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data,
2278*ce73d5c8SSunitha Harish                                ipv6GatewayData);
22799391bb9cSRapkiewicz, Pawel         });
2280bf648f77SEd Tanous     });
22819391bb9cSRapkiewicz, Pawel 
2282bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2283ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2284bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
228545ca1b86SEd Tanous             [&app](const crow::Request& req,
2286bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2287bf648f77SEd Tanous                    const std::string& ifaceId) {
22883ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
228945ca1b86SEd Tanous         {
229045ca1b86SEd Tanous             return;
229145ca1b86SEd Tanous         }
2292bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2293ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2294d577665bSRatan Gupta         std::optional<std::string> macAddress;
22959a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
2296ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
2297ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
2298*ce73d5c8SSunitha Harish         std::optional<nlohmann::json::array_t> ipv6StaticDefaultGateways;
2299f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2300da131a9aSJennifer Lee         std::optional<nlohmann::json> dhcpv4;
23011f8c7b5dSJohnathan Mantey         std::optional<nlohmann::json> dhcpv6;
2302b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2303eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
230435fb5311STejas Patil         std::optional<size_t> mtuSize;
23051f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
23061f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2307b10d8db0SRavi Teja         // clang-format off
230815ed6780SWilly Tu         if (!json_util::readJsonPatch(
2309b10d8db0SRavi Teja                 req, asyncResp->res,
2310b10d8db0SRavi Teja                 "DHCPv4", dhcpv4,
2311b10d8db0SRavi Teja                 "DHCPv6", dhcpv6,
2312b10d8db0SRavi Teja                 "FQDN", fqdn,
2313b10d8db0SRavi Teja                 "HostName", hostname,
2314b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2315b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2316b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2317*ce73d5c8SSunitha Harish                 "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways,
2318b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2319b10d8db0SRavi Teja                 "MACAddress", macAddress,
2320b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2321b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2322b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2323b10d8db0SRavi Teja                 )
2324b10d8db0SRavi Teja             )
23251abe55efSEd Tanous         {
2326588c3f0dSKowalski, Kamil             return;
2327588c3f0dSKowalski, Kamil         }
2328b10d8db0SRavi Teja         //clang-format on
2329da131a9aSJennifer Lee         if (dhcpv4)
2330da131a9aSJennifer Lee         {
2331002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
23321f8c7b5dSJohnathan Mantey                                      v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
233382695a5bSJiaqing Zhao                                      v4dhcpParms.useDnsServers, "UseNTPServers",
233482695a5bSJiaqing Zhao                                      v4dhcpParms.useNtpServers, "UseDomainName",
233582695a5bSJiaqing Zhao                                      v4dhcpParms.useDomainName))
23361f8c7b5dSJohnathan Mantey             {
23371f8c7b5dSJohnathan Mantey                 return;
23381f8c7b5dSJohnathan Mantey             }
23391f8c7b5dSJohnathan Mantey         }
23401f8c7b5dSJohnathan Mantey 
23411f8c7b5dSJohnathan Mantey         if (dhcpv6)
23421f8c7b5dSJohnathan Mantey         {
2343002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2344002d39b4SEd Tanous                                      v6dhcpParms.dhcpv6OperatingMode,
2345002d39b4SEd Tanous                                      "UseDNSServers", v6dhcpParms.useDnsServers,
2346002d39b4SEd Tanous                                      "UseNTPServers", v6dhcpParms.useNtpServers,
2347002d39b4SEd Tanous                                      "UseDomainName",
234882695a5bSJiaqing Zhao                                      v6dhcpParms.useDomainName))
23491f8c7b5dSJohnathan Mantey             {
23501f8c7b5dSJohnathan Mantey                 return;
23511f8c7b5dSJohnathan Mantey             }
2352da131a9aSJennifer Lee         }
2353da131a9aSJennifer Lee 
2354bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2355bf648f77SEd Tanous         // for JSON preparation
23564a0cb85cSEd Tanous         getEthernetIfaceData(
23572c70f800SEd Tanous             ifaceId,
2358bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2359ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2360d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
23619a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2362e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2363*ce73d5c8SSunitha Harish              ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways),
23641f8c7b5dSJohnathan Mantey              staticNameServers = std::move(staticNameServers),
2365bc20089aSEd Tanous              dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
2366b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2367f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2368002d39b4SEd Tanous                 const bool& success, const EthernetInterfaceData& ethData,
236977179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
2370*ce73d5c8SSunitha Harish                 const std::vector<IPv6AddressData>& ipv6Data,
2371*ce73d5c8SSunitha Harish                 const std::vector<StaticGatewayData>& ipv6GatewayData) {
23721abe55efSEd Tanous             if (!success)
23731abe55efSEd Tanous             {
2374588c3f0dSKowalski, Kamil                 // ... otherwise return error
2375bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2376bf648f77SEd Tanous                 // existing object, and other errors
2377002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2378002d39b4SEd Tanous                                            ifaceId);
2379588c3f0dSKowalski, Kamil                 return;
2380588c3f0dSKowalski, Kamil             }
2381588c3f0dSKowalski, Kamil 
23821f8c7b5dSJohnathan Mantey             if (dhcpv4 || dhcpv6)
23831f8c7b5dSJohnathan Mantey             {
2384002d39b4SEd Tanous                 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2385002d39b4SEd Tanous                                 asyncResp);
23861f8c7b5dSJohnathan Mantey             }
23871f8c7b5dSJohnathan Mantey 
23880627a2c7SEd Tanous             if (hostname)
23891abe55efSEd Tanous             {
23900627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
23911abe55efSEd Tanous             }
23920627a2c7SEd Tanous 
2393b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2394b10d8db0SRavi Teja             {
2395b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2396b10d8db0SRavi Teja                                            asyncResp);
2397b10d8db0SRavi Teja             }
2398b10d8db0SRavi Teja 
2399ab6554f1SJoshi-Mansi             if (fqdn)
2400ab6554f1SJoshi-Mansi             {
24012c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2402ab6554f1SJoshi-Mansi             }
2403ab6554f1SJoshi-Mansi 
2404d577665bSRatan Gupta             if (macAddress)
2405d577665bSRatan Gupta             {
2406002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2407d577665bSRatan Gupta             }
2408d577665bSRatan Gupta 
2409d1d50814SRavi Teja             if (ipv4StaticAddresses)
2410d1d50814SRavi Teja             {
2411bf648f77SEd Tanous                 // TODO(ed) for some reason the capture of
2412bf648f77SEd Tanous                 // ipv4Addresses above is returning a const value,
2413bf648f77SEd Tanous                 // not a non-const value. This doesn't really work
2414bf648f77SEd Tanous                 // for us, as we need to be able to efficiently move
2415bf648f77SEd Tanous                 // out the intermedia nlohmann::json objects. This
2416bf648f77SEd Tanous                 // makes a copy of the structure, and operates on
2417bf648f77SEd Tanous                 // that, but could be done more efficiently
2418ddd70dcaSEd Tanous                 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
2419002d39b4SEd Tanous                 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
24201abe55efSEd Tanous             }
24210627a2c7SEd Tanous 
2422f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2423f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2424002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2425002d39b4SEd Tanous                                              asyncResp);
2426f85837bfSRAJESWARAN THILLAIGOVINDAN             }
24279a6fc6feSRavi Teja 
24289a6fc6feSRavi Teja             if (ipv6DefaultGateway)
24299a6fc6feSRavi Teja             {
24309a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
24319a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
24329a6fc6feSRavi Teja             }
2433e48c0fc5SRavi Teja 
2434e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2435e48c0fc5SRavi Teja             {
2436ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2437ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2438e48c0fc5SRavi Teja             }
2439eeedda23SJohnathan Mantey 
2440*ce73d5c8SSunitha Harish             if (ipv6StaticDefaultGateway)
2441*ce73d5c8SSunitha Harish             {
2442*ce73d5c8SSunitha Harish                 handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway,
2443*ce73d5c8SSunitha Harish                                          ipv6GatewayData, asyncResp);
2444*ce73d5c8SSunitha Harish             }
2445*ce73d5c8SSunitha Harish 
2446eeedda23SJohnathan Mantey             if (interfaceEnabled)
2447eeedda23SJohnathan Mantey             {
2448002d39b4SEd Tanous                 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2449002d39b4SEd Tanous                                                  *interfaceEnabled, asyncResp);
2450eeedda23SJohnathan Mantey             }
245135fb5311STejas Patil 
245235fb5311STejas Patil             if (mtuSize)
245335fb5311STejas Patil             {
245435fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
245535fb5311STejas Patil             }
2456588c3f0dSKowalski, Kamil             });
2457bf648f77SEd Tanous         });
2458e7caf250SJiaqing Zhao 
2459e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2460e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2461e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2462e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2463e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2464e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2465e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2466e7caf250SJiaqing Zhao         {
2467e7caf250SJiaqing Zhao             return;
2468e7caf250SJiaqing Zhao         }
2469e7caf250SJiaqing Zhao 
2470e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2471e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2472e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2473e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2474e7caf250SJiaqing Zhao             },
2475e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2476e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2477e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2478e7caf250SJiaqing Zhao         });
24794a0cb85cSEd Tanous }
2480bf648f77SEd Tanous 
24819391bb9cSRapkiewicz, Pawel } // namespace redfish
2482