xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision 8cb2c024c4625e2fe2f0b107a865faffcd4bb770)
19391bb9cSRapkiewicz, Pawel /*
29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation
39391bb9cSRapkiewicz, Pawel //
49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License");
59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License.
69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at
79391bb9cSRapkiewicz, Pawel //
89391bb9cSRapkiewicz, Pawel //      http://www.apache.org/licenses/LICENSE-2.0
99391bb9cSRapkiewicz, Pawel //
109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software
119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS,
129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and
149391bb9cSRapkiewicz, Pawel // limitations under the License.
159391bb9cSRapkiewicz, Pawel */
169391bb9cSRapkiewicz, Pawel #pragma once
179391bb9cSRapkiewicz, Pawel 
183ccb3adbSEd Tanous #include "app.hpp"
193ccb3adbSEd Tanous #include "dbus_singleton.hpp"
207a1dbc48SGeorge Liu #include "dbus_utility.hpp"
213ccb3adbSEd Tanous #include "error_messages.hpp"
222c5875a2SEd Tanous #include "human_sort.hpp"
233ccb3adbSEd Tanous #include "query.hpp"
243ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
25033f1e4dSEd Tanous #include "utils/ip_utils.hpp"
263ccb3adbSEd Tanous #include "utils/json_utils.hpp"
27033f1e4dSEd Tanous 
28ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp>
29ef4c65b7SEd Tanous #include <boost/url/format.hpp>
301214b7e7SGunnar Mills 
317a1dbc48SGeorge Liu #include <array>
323dfed536SEd Tanous #include <cstddef>
33ce73d5c8SSunitha Harish #include <memory>
34a24526dcSEd Tanous #include <optional>
353544d2a7SEd Tanous #include <ranges>
36ab6554f1SJoshi-Mansi #include <regex>
377a1dbc48SGeorge Liu #include <string_view>
383dfed536SEd Tanous #include <variant>
3977179532SEd Tanous #include <vector>
409391bb9cSRapkiewicz, Pawel 
411abe55efSEd Tanous namespace redfish
421abe55efSEd Tanous {
439391bb9cSRapkiewicz, Pawel 
444a0cb85cSEd Tanous enum class LinkType
454a0cb85cSEd Tanous {
464a0cb85cSEd Tanous     Local,
474a0cb85cSEd Tanous     Global
484a0cb85cSEd Tanous };
499391bb9cSRapkiewicz, Pawel 
509391bb9cSRapkiewicz, Pawel /**
519391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
529391bb9cSRapkiewicz, Pawel  */
531abe55efSEd Tanous struct IPv4AddressData
541abe55efSEd Tanous {
55179db1d7SKowalski, Kamil     std::string id;
564a0cb85cSEd Tanous     std::string address;
574a0cb85cSEd Tanous     std::string domain;
584a0cb85cSEd Tanous     std::string gateway;
599391bb9cSRapkiewicz, Pawel     std::string netmask;
609391bb9cSRapkiewicz, Pawel     std::string origin;
6177179532SEd Tanous     LinkType linktype{};
6277179532SEd Tanous     bool isActive{};
639391bb9cSRapkiewicz, Pawel };
649391bb9cSRapkiewicz, Pawel 
659391bb9cSRapkiewicz, Pawel /**
66e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
67e48c0fc5SRavi Teja  */
68e48c0fc5SRavi Teja struct IPv6AddressData
69e48c0fc5SRavi Teja {
70e48c0fc5SRavi Teja     std::string id;
71e48c0fc5SRavi Teja     std::string address;
72e48c0fc5SRavi Teja     std::string origin;
7377179532SEd Tanous     uint8_t prefixLength = 0;
74e48c0fc5SRavi Teja };
75ce73d5c8SSunitha Harish 
76ce73d5c8SSunitha Harish /**
77ce73d5c8SSunitha Harish  * Structure for keeping static route data required by Redfish
78ce73d5c8SSunitha Harish  */
79ce73d5c8SSunitha Harish struct StaticGatewayData
80ce73d5c8SSunitha Harish {
81ce73d5c8SSunitha Harish     std::string id;
82ce73d5c8SSunitha Harish     std::string gateway;
83ce73d5c8SSunitha Harish     size_t prefixLength = 0;
84ce73d5c8SSunitha Harish     std::string protocol;
85ce73d5c8SSunitha Harish };
86ce73d5c8SSunitha Harish 
87e48c0fc5SRavi Teja /**
889391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
899391bb9cSRapkiewicz, Pawel  * available from DBus
909391bb9cSRapkiewicz, Pawel  */
911abe55efSEd Tanous struct EthernetInterfaceData
921abe55efSEd Tanous {
934a0cb85cSEd Tanous     uint32_t speed;
9435fb5311STejas Patil     size_t mtuSize;
9582695a5bSJiaqing Zhao     bool autoNeg;
96e4588158SJishnu CM     bool dnsv4Enabled;
97e4588158SJishnu CM     bool dnsv6Enabled;
9891c441ecSRavi Teja     bool domainv4Enabled;
9991c441ecSRavi Teja     bool domainv6Enabled;
100e4588158SJishnu CM     bool ntpv4Enabled;
101e4588158SJishnu CM     bool ntpv6Enabled;
102e4588158SJishnu CM     bool hostNamev4Enabled;
103e4588158SJishnu CM     bool hostNamev6Enabled;
104aa05fb27SJohnathan Mantey     bool linkUp;
105eeedda23SJohnathan Mantey     bool nicEnabled;
106b10d8db0SRavi Teja     bool ipv6AcceptRa;
10782695a5bSJiaqing Zhao     std::string dhcpEnabled;
1081f8c7b5dSJohnathan Mantey     std::string operatingMode;
10982695a5bSJiaqing Zhao     std::string hostName;
11082695a5bSJiaqing Zhao     std::string defaultGateway;
11182695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
112ce73d5c8SSunitha Harish     std::string ipv6StaticDefaultGateway;
11382695a5bSJiaqing Zhao     std::string macAddress;
11417e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
1150f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1160f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
117d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1189391bb9cSRapkiewicz, Pawel };
1199391bb9cSRapkiewicz, Pawel 
1201f8c7b5dSJohnathan Mantey struct DHCPParameters
1211f8c7b5dSJohnathan Mantey {
1221f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
12382695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
12482695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
12582695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1261f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1271f8c7b5dSJohnathan Mantey };
1281f8c7b5dSJohnathan Mantey 
1299391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1309391bb9cSRapkiewicz, Pawel // into full dot notation
1311abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1321abe55efSEd Tanous {
1339391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1349391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1359391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1369391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1379391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1389391bb9cSRapkiewicz, Pawel     return netmask;
1399391bb9cSRapkiewicz, Pawel }
1409391bb9cSRapkiewicz, Pawel 
14182695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1421f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1431f8c7b5dSJohnathan Mantey {
1441f8c7b5dSJohnathan Mantey     if (isIPv4)
1451f8c7b5dSJohnathan Mantey     {
1461f8c7b5dSJohnathan Mantey         return (
1471f8c7b5dSJohnathan Mantey             (inputDHCP ==
1481f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1491f8c7b5dSJohnathan Mantey             (inputDHCP ==
1501f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1511f8c7b5dSJohnathan Mantey     }
1521f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1531f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1541f8c7b5dSJohnathan Mantey             (inputDHCP ==
1551f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1561f8c7b5dSJohnathan Mantey }
1571f8c7b5dSJohnathan Mantey 
1582c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1591f8c7b5dSJohnathan Mantey {
1601f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1611f8c7b5dSJohnathan Mantey     {
1621f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1631f8c7b5dSJohnathan Mantey     }
1643174e4dfSEd Tanous     if (isIPv4)
1651f8c7b5dSJohnathan Mantey     {
1661f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1671f8c7b5dSJohnathan Mantey     }
1683174e4dfSEd Tanous     if (isIPv6)
1691f8c7b5dSJohnathan Mantey     {
1701f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1711f8c7b5dSJohnathan Mantey     }
1721f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1731f8c7b5dSJohnathan Mantey }
1741f8c7b5dSJohnathan Mantey 
1754a0cb85cSEd Tanous inline std::string
1764a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1774a0cb85cSEd Tanous                                         bool isIPv4)
1781abe55efSEd Tanous {
1794a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1801abe55efSEd Tanous     {
1814a0cb85cSEd Tanous         return "Static";
1829391bb9cSRapkiewicz, Pawel     }
1834a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1841abe55efSEd Tanous     {
1854a0cb85cSEd Tanous         if (isIPv4)
1861abe55efSEd Tanous         {
1874a0cb85cSEd Tanous             return "IPv4LinkLocal";
1881abe55efSEd Tanous         }
1894a0cb85cSEd Tanous         return "LinkLocal";
1909391bb9cSRapkiewicz, Pawel     }
1914a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1921abe55efSEd Tanous     {
1934a0cb85cSEd Tanous         if (isIPv4)
1944a0cb85cSEd Tanous         {
1954a0cb85cSEd Tanous             return "DHCP";
1964a0cb85cSEd Tanous         }
1974a0cb85cSEd Tanous         return "DHCPv6";
1984a0cb85cSEd Tanous     }
1994a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
2004a0cb85cSEd Tanous     {
2014a0cb85cSEd Tanous         return "SLAAC";
2024a0cb85cSEd Tanous     }
2034a0cb85cSEd Tanous     return "";
2044a0cb85cSEd Tanous }
2054a0cb85cSEd Tanous 
20602cad96eSEd Tanous inline bool extractEthernetInterfaceData(
20702cad96eSEd Tanous     const std::string& ethifaceId,
20802cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
2094a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
2104a0cb85cSEd Tanous {
2114c9afe43SEd Tanous     bool idFound = false;
21202cad96eSEd Tanous     for (const auto& objpath : dbusData)
2134a0cb85cSEd Tanous     {
21402cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
2154a0cb85cSEd Tanous         {
21681ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
217029573d4SEd Tanous             {
2184c9afe43SEd Tanous                 idFound = true;
2194a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2204a0cb85cSEd Tanous                 {
2214a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2224a0cb85cSEd Tanous                     {
2234a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2244a0cb85cSEd Tanous                         {
2254a0cb85cSEd Tanous                             const std::string* mac =
226abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2274a0cb85cSEd Tanous                             if (mac != nullptr)
2284a0cb85cSEd Tanous                             {
22982695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2304a0cb85cSEd Tanous                             }
2314a0cb85cSEd Tanous                         }
2324a0cb85cSEd Tanous                     }
2334a0cb85cSEd Tanous                 }
2344a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2354a0cb85cSEd Tanous                 {
2364a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2374a0cb85cSEd Tanous                     {
2384a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2394a0cb85cSEd Tanous                         {
2401b6b96c5SEd Tanous                             const uint32_t* id =
241abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2424a0cb85cSEd Tanous                             if (id != nullptr)
2434a0cb85cSEd Tanous                             {
24417e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2454a0cb85cSEd Tanous                             }
2464a0cb85cSEd Tanous                         }
2474a0cb85cSEd Tanous                     }
2484a0cb85cSEd Tanous                 }
2494a0cb85cSEd Tanous                 else if (ifacePair.first ==
2504a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2514a0cb85cSEd Tanous                 {
2524a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2534a0cb85cSEd Tanous                     {
2544a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2554a0cb85cSEd Tanous                         {
2562c70f800SEd Tanous                             const bool* autoNeg =
257abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2582c70f800SEd Tanous                             if (autoNeg != nullptr)
2594a0cb85cSEd Tanous                             {
26082695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2614a0cb85cSEd Tanous                             }
2624a0cb85cSEd Tanous                         }
2634a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2644a0cb85cSEd Tanous                         {
2654a0cb85cSEd Tanous                             const uint32_t* speed =
266abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2674a0cb85cSEd Tanous                             if (speed != nullptr)
2684a0cb85cSEd Tanous                             {
2694a0cb85cSEd Tanous                                 ethData.speed = *speed;
2704a0cb85cSEd Tanous                             }
2714a0cb85cSEd Tanous                         }
27235fb5311STejas Patil                         else if (propertyPair.first == "MTU")
27335fb5311STejas Patil                         {
2743e7a8da6SAnthony                             const size_t* mtuSize =
2753e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
27635fb5311STejas Patil                             if (mtuSize != nullptr)
27735fb5311STejas Patil                             {
27835fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
27935fb5311STejas Patil                             }
28035fb5311STejas Patil                         }
281aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
282aa05fb27SJohnathan Mantey                         {
283aa05fb27SJohnathan Mantey                             const bool* linkUp =
284aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
285aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
286aa05fb27SJohnathan Mantey                             {
287aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
288aa05fb27SJohnathan Mantey                             }
289aa05fb27SJohnathan Mantey                         }
290eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
291eeedda23SJohnathan Mantey                         {
292eeedda23SJohnathan Mantey                             const bool* nicEnabled =
293eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
294eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
295eeedda23SJohnathan Mantey                             {
296eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
297eeedda23SJohnathan Mantey                             }
298eeedda23SJohnathan Mantey                         }
299b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
300b10d8db0SRavi Teja                         {
301b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
302b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
303b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
304b10d8db0SRavi Teja                             {
305b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
306b10d8db0SRavi Teja                             }
307b10d8db0SRavi Teja                         }
308f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
309029573d4SEd Tanous                         {
310029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
3118d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
312029573d4SEd Tanous                                     &propertyPair.second);
313029573d4SEd Tanous                             if (nameservers != nullptr)
314029573d4SEd Tanous                             {
315f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3160f6efdc1Smanojkiran.eda@gmail.com                             }
3170f6efdc1Smanojkiran.eda@gmail.com                         }
3180f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3190f6efdc1Smanojkiran.eda@gmail.com                         {
3200f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3218d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3220f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3230f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3240f6efdc1Smanojkiran.eda@gmail.com                             {
325f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3264a0cb85cSEd Tanous                             }
3274a0cb85cSEd Tanous                         }
3282a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3292a133282Smanojkiraneda                         {
3302c70f800SEd Tanous                             const std::string* dhcpEnabled =
3311f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3322c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3332a133282Smanojkiraneda                             {
33482695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3352a133282Smanojkiraneda                             }
3362a133282Smanojkiraneda                         }
337d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
338d24bfc7aSJennifer Lee                         {
339d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3408d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
341d24bfc7aSJennifer Lee                                     &propertyPair.second);
342d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
343d24bfc7aSJennifer Lee                             {
344f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
345d24bfc7aSJennifer Lee                             }
346d24bfc7aSJennifer Lee                         }
3479010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3489010ec2eSRavi Teja                         {
3499010ec2eSRavi Teja                             const std::string* defaultGateway =
3509010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3519010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3529010ec2eSRavi Teja                             {
3539010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3549010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3559010ec2eSRavi Teja                                 {
35682695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3579010ec2eSRavi Teja                                 }
3589010ec2eSRavi Teja                                 else
3599010ec2eSRavi Teja                                 {
36082695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3619010ec2eSRavi Teja                                 }
3629010ec2eSRavi Teja                             }
3639010ec2eSRavi Teja                         }
3649010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3659010ec2eSRavi Teja                         {
3669010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3679010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3689010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3699010ec2eSRavi Teja                             {
3709010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3719010ec2eSRavi Teja                                     *defaultGateway6;
3729010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3739010ec2eSRavi Teja                                 {
37482695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3759010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3769010ec2eSRavi Teja                                 }
3779010ec2eSRavi Teja                                 else
3789010ec2eSRavi Teja                                 {
37982695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3809010ec2eSRavi Teja                                         defaultGateway6Str;
3819010ec2eSRavi Teja                                 }
3829010ec2eSRavi Teja                             }
3839010ec2eSRavi Teja                         }
384029573d4SEd Tanous                     }
385029573d4SEd Tanous                 }
386029573d4SEd Tanous             }
3871f8c7b5dSJohnathan Mantey 
388e4588158SJishnu CM             sdbusplus::message::object_path path(
389e4588158SJishnu CM                 "/xyz/openbmc_project/network");
390e4588158SJishnu CM             sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
391e4588158SJishnu CM                                                         "dhcp4";
392e4588158SJishnu CM 
393e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
3941f8c7b5dSJohnathan Mantey             {
3951f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
3961f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
3971f8c7b5dSJohnathan Mantey                 {
3981f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
3991f8c7b5dSJohnathan Mantey                     {
4001f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
4011f8c7b5dSJohnathan Mantey                         {
4022c70f800SEd Tanous                             const bool* dnsEnabled =
4031f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4042c70f800SEd Tanous                             if (dnsEnabled != nullptr)
4051f8c7b5dSJohnathan Mantey                             {
406e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
4071f8c7b5dSJohnathan Mantey                             }
4081f8c7b5dSJohnathan Mantey                         }
40991c441ecSRavi Teja                         else if (propertyPair.first == "DomainEnabled")
41091c441ecSRavi Teja                         {
41191c441ecSRavi Teja                             const bool* domainEnabled =
41291c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
41391c441ecSRavi Teja                             if (domainEnabled != nullptr)
41491c441ecSRavi Teja                             {
41591c441ecSRavi Teja                                 ethData.domainv4Enabled = *domainEnabled;
41691c441ecSRavi Teja                             }
41791c441ecSRavi Teja                         }
4181f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
4191f8c7b5dSJohnathan Mantey                         {
4202c70f800SEd Tanous                             const bool* ntpEnabled =
4211f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4222c70f800SEd Tanous                             if (ntpEnabled != nullptr)
4231f8c7b5dSJohnathan Mantey                             {
424e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4251f8c7b5dSJohnathan Mantey                             }
4261f8c7b5dSJohnathan Mantey                         }
4271f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4281f8c7b5dSJohnathan Mantey                         {
4292c70f800SEd Tanous                             const bool* hostNameEnabled =
4301f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4312c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4321f8c7b5dSJohnathan Mantey                             {
433e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
434e4588158SJishnu CM                             }
435e4588158SJishnu CM                         }
436e4588158SJishnu CM                     }
437e4588158SJishnu CM                 }
438e4588158SJishnu CM             }
439e4588158SJishnu CM 
440e4588158SJishnu CM             sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
441e4588158SJishnu CM                                                         "dhcp6";
442e4588158SJishnu CM 
443e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
444e4588158SJishnu CM             {
445e4588158SJishnu CM                 if (ifacePair.first ==
446e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
447e4588158SJishnu CM                 {
448e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
449e4588158SJishnu CM                     {
450e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
451e4588158SJishnu CM                         {
452e4588158SJishnu CM                             const bool* dnsEnabled =
453e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
454e4588158SJishnu CM                             if (dnsEnabled != nullptr)
455e4588158SJishnu CM                             {
456e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
457e4588158SJishnu CM                             }
458e4588158SJishnu CM                         }
45991c441ecSRavi Teja                         if (propertyPair.first == "DomainEnabled")
46091c441ecSRavi Teja                         {
46191c441ecSRavi Teja                             const bool* domainEnabled =
46291c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
46391c441ecSRavi Teja                             if (domainEnabled != nullptr)
46491c441ecSRavi Teja                             {
46591c441ecSRavi Teja                                 ethData.domainv6Enabled = *domainEnabled;
46691c441ecSRavi Teja                             }
46791c441ecSRavi Teja                         }
468e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
469e4588158SJishnu CM                         {
470e4588158SJishnu CM                             const bool* ntpEnabled =
471e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
472e4588158SJishnu CM                             if (ntpEnabled != nullptr)
473e4588158SJishnu CM                             {
474e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
475e4588158SJishnu CM                             }
476e4588158SJishnu CM                         }
477e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
478e4588158SJishnu CM                         {
479e4588158SJishnu CM                             const bool* hostNameEnabled =
480e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
481e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
482e4588158SJishnu CM                             {
483e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
4841f8c7b5dSJohnathan Mantey                             }
4851f8c7b5dSJohnathan Mantey                         }
4861f8c7b5dSJohnathan Mantey                     }
4871f8c7b5dSJohnathan Mantey                 }
4881f8c7b5dSJohnathan Mantey             }
489029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
490029573d4SEd Tanous             // to check eth number
491029573d4SEd Tanous             if (ifacePair.first ==
4924a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4934a0cb85cSEd Tanous             {
4944a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
4954a0cb85cSEd Tanous                 {
4964a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
4974a0cb85cSEd Tanous                     {
4984a0cb85cSEd Tanous                         const std::string* hostname =
4998d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
5004a0cb85cSEd Tanous                         if (hostname != nullptr)
5014a0cb85cSEd Tanous                         {
50282695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
5034a0cb85cSEd Tanous                         }
5044a0cb85cSEd Tanous                     }
5054a0cb85cSEd Tanous                 }
5064a0cb85cSEd Tanous             }
5074a0cb85cSEd Tanous         }
5084a0cb85cSEd Tanous     }
5094c9afe43SEd Tanous     return idFound;
5104a0cb85cSEd Tanous }
5114a0cb85cSEd Tanous 
512e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
51377179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
514711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
51577179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
516e48c0fc5SRavi Teja {
51789492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
51889492a15SPatrick Williams                                     ethifaceId;
519e48c0fc5SRavi Teja 
520e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
521e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
52281ce609eSEd Tanous     for (const auto& objpath : dbusData)
523e48c0fc5SRavi Teja     {
524e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
525353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
526e48c0fc5SRavi Teja         {
5279eb808c1SEd Tanous             for (const auto& interface : objpath.second)
528e48c0fc5SRavi Teja             {
529e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
530e48c0fc5SRavi Teja                 {
5313544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
532353163e9STony Lee                                                      [](const auto& property) {
533353163e9STony Lee                         return property.first == "Type";
534353163e9STony Lee                     });
535353163e9STony Lee                     if (type == interface.second.end())
536353163e9STony Lee                     {
537353163e9STony Lee                         continue;
538353163e9STony Lee                     }
539353163e9STony Lee 
540353163e9STony Lee                     const std::string* typeStr =
541353163e9STony Lee                         std::get_if<std::string>(&type->second);
542353163e9STony Lee 
543353163e9STony Lee                     if (typeStr == nullptr ||
544353163e9STony Lee                         (*typeStr !=
545353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
546353163e9STony Lee                     {
547353163e9STony Lee                         continue;
548353163e9STony Lee                     }
549353163e9STony Lee 
550e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
551e48c0fc5SRavi Teja                     // appropriate
55277179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5532c70f800SEd Tanous                     ipv6Address.id =
554353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5559eb808c1SEd Tanous                     for (const auto& property : interface.second)
556e48c0fc5SRavi Teja                     {
557e48c0fc5SRavi Teja                         if (property.first == "Address")
558e48c0fc5SRavi Teja                         {
559e48c0fc5SRavi Teja                             const std::string* address =
560e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
561e48c0fc5SRavi Teja                             if (address != nullptr)
562e48c0fc5SRavi Teja                             {
5632c70f800SEd Tanous                                 ipv6Address.address = *address;
564e48c0fc5SRavi Teja                             }
565e48c0fc5SRavi Teja                         }
566e48c0fc5SRavi Teja                         else if (property.first == "Origin")
567e48c0fc5SRavi Teja                         {
568e48c0fc5SRavi Teja                             const std::string* origin =
569e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
570e48c0fc5SRavi Teja                             if (origin != nullptr)
571e48c0fc5SRavi Teja                             {
5722c70f800SEd Tanous                                 ipv6Address.origin =
573e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
574e48c0fc5SRavi Teja                                                                         false);
575e48c0fc5SRavi Teja                             }
576e48c0fc5SRavi Teja                         }
577e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
578e48c0fc5SRavi Teja                         {
579e48c0fc5SRavi Teja                             const uint8_t* prefix =
580e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
581e48c0fc5SRavi Teja                             if (prefix != nullptr)
582e48c0fc5SRavi Teja                             {
5832c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
584e48c0fc5SRavi Teja                             }
585e48c0fc5SRavi Teja                         }
586889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
587889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
588889ff694SAsmitha Karunanithi                         {
589889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
590889ff694SAsmitha Karunanithi                         }
591e48c0fc5SRavi Teja                         else
592e48c0fc5SRavi Teja                         {
59362598e31SEd Tanous                             BMCWEB_LOG_ERROR(
59462598e31SEd Tanous                                 "Got extra property: {} on the {} object",
59562598e31SEd Tanous                                 property.first, objpath.first.str);
596e48c0fc5SRavi Teja                         }
597e48c0fc5SRavi Teja                     }
598e48c0fc5SRavi Teja                 }
599e48c0fc5SRavi Teja             }
600e48c0fc5SRavi Teja         }
601e48c0fc5SRavi Teja     }
602e48c0fc5SRavi Teja }
603e48c0fc5SRavi Teja 
6044a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
60577179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
606711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
60777179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
6084a0cb85cSEd Tanous {
60989492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
61089492a15SPatrick Williams                                     ethifaceId;
6114a0cb85cSEd Tanous 
6124a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
6134a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
61481ce609eSEd Tanous     for (const auto& objpath : dbusData)
6154a0cb85cSEd Tanous     {
6164a0cb85cSEd Tanous         // Check if proper pattern for object path appears
617353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
6184a0cb85cSEd Tanous         {
6199eb808c1SEd Tanous             for (const auto& interface : objpath.second)
6204a0cb85cSEd Tanous             {
6214a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
6224a0cb85cSEd Tanous                 {
6233544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
624353163e9STony Lee                                                      [](const auto& property) {
625353163e9STony Lee                         return property.first == "Type";
626353163e9STony Lee                     });
627353163e9STony Lee                     if (type == interface.second.end())
628353163e9STony Lee                     {
629353163e9STony Lee                         continue;
630353163e9STony Lee                     }
631353163e9STony Lee 
632353163e9STony Lee                     const std::string* typeStr =
633353163e9STony Lee                         std::get_if<std::string>(&type->second);
634353163e9STony Lee 
635353163e9STony Lee                     if (typeStr == nullptr ||
636353163e9STony Lee                         (*typeStr !=
637353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
638353163e9STony Lee                     {
639353163e9STony Lee                         continue;
640353163e9STony Lee                     }
641353163e9STony Lee 
6424a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6434a0cb85cSEd Tanous                     // appropriate
64477179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6452c70f800SEd Tanous                     ipv4Address.id =
646353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6479eb808c1SEd Tanous                     for (const auto& property : interface.second)
6484a0cb85cSEd Tanous                     {
6494a0cb85cSEd Tanous                         if (property.first == "Address")
6504a0cb85cSEd Tanous                         {
6514a0cb85cSEd Tanous                             const std::string* address =
652abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6534a0cb85cSEd Tanous                             if (address != nullptr)
6544a0cb85cSEd Tanous                             {
6552c70f800SEd Tanous                                 ipv4Address.address = *address;
6564a0cb85cSEd Tanous                             }
6574a0cb85cSEd Tanous                         }
6584a0cb85cSEd Tanous                         else if (property.first == "Origin")
6594a0cb85cSEd Tanous                         {
6604a0cb85cSEd Tanous                             const std::string* origin =
661abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6624a0cb85cSEd Tanous                             if (origin != nullptr)
6634a0cb85cSEd Tanous                             {
6642c70f800SEd Tanous                                 ipv4Address.origin =
6654a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6664a0cb85cSEd Tanous                                                                         true);
6674a0cb85cSEd Tanous                             }
6684a0cb85cSEd Tanous                         }
6694a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6704a0cb85cSEd Tanous                         {
6714a0cb85cSEd Tanous                             const uint8_t* mask =
672abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6734a0cb85cSEd Tanous                             if (mask != nullptr)
6744a0cb85cSEd Tanous                             {
6754a0cb85cSEd Tanous                                 // convert it to the string
6762c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6774a0cb85cSEd Tanous                             }
6784a0cb85cSEd Tanous                         }
679889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
680889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
681889ff694SAsmitha Karunanithi                         {
682889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
683889ff694SAsmitha Karunanithi                         }
6844a0cb85cSEd Tanous                         else
6854a0cb85cSEd Tanous                         {
68662598e31SEd Tanous                             BMCWEB_LOG_ERROR(
68762598e31SEd Tanous                                 "Got extra property: {} on the {} object",
68862598e31SEd Tanous                                 property.first, objpath.first.str);
6894a0cb85cSEd Tanous                         }
6904a0cb85cSEd Tanous                     }
6914a0cb85cSEd Tanous                     // Check if given address is local, or global
6922c70f800SEd Tanous                     ipv4Address.linktype =
69311ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
69418659d10SJohnathan Mantey                             ? LinkType::Local
69518659d10SJohnathan Mantey                             : LinkType::Global;
6964a0cb85cSEd Tanous                 }
6974a0cb85cSEd Tanous             }
6984a0cb85cSEd Tanous         }
6994a0cb85cSEd Tanous     }
7004a0cb85cSEd Tanous }
701588c3f0dSKowalski, Kamil 
702588c3f0dSKowalski, Kamil /**
70301784826SJohnathan Mantey  * @brief Deletes given IPv4 interface
704179db1d7SKowalski, Kamil  *
705179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
706179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
707179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
708179db1d7SKowalski, Kamil  *
709179db1d7SKowalski, Kamil  * @return None
710179db1d7SKowalski, Kamil  */
7119c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
7129c5e585cSRavi Teja                             const std::string& ipHash,
7138d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7141abe55efSEd Tanous {
71555c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7165e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
7171abe55efSEd Tanous         if (ec)
7181abe55efSEd Tanous         {
719a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7201abe55efSEd Tanous         }
721179db1d7SKowalski, Kamil     },
722179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
7239c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
724179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
725179db1d7SKowalski, Kamil }
726179db1d7SKowalski, Kamil 
727244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway(
728244b6d5bSGunnar Mills     const std::string& ifaceId, const std::string& gateway,
729244b6d5bSGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7309010ec2eSRavi Teja {
731d02aad39SEd Tanous     setDbusProperty(
732d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
733d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
734d02aad39SEd Tanous             ifaceId,
7359ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
736d02aad39SEd Tanous         "Gateway", gateway);
7379010ec2eSRavi Teja }
738179db1d7SKowalski, Kamil /**
73901784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
740179db1d7SKowalski, Kamil  *
74101784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
74201784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
74301784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
74401784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
745179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
746179db1d7SKowalski, Kamil  *
747179db1d7SKowalski, Kamil  * @return None
748179db1d7SKowalski, Kamil  */
749cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
750cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7518d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7521abe55efSEd Tanous {
7535a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
7545a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
7551abe55efSEd Tanous         if (ec)
7561abe55efSEd Tanous         {
757a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7589010ec2eSRavi Teja             return;
759179db1d7SKowalski, Kamil         }
7609010ec2eSRavi Teja         updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
7619010ec2eSRavi Teja     };
7629010ec2eSRavi Teja 
7639010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7649010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
765179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
766179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
76701784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
768179db1d7SKowalski, Kamil         gateway);
769179db1d7SKowalski, Kamil }
770e48c0fc5SRavi Teja 
771e48c0fc5SRavi Teja /**
77201784826SJohnathan Mantey  * @brief Deletes the IPv6 entry for this interface and creates a replacement
77301784826SJohnathan Mantey  * static IPv6 entry
77401784826SJohnathan Mantey  *
77501784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv6 entry
77601784826SJohnathan Mantey  * @param[in] id           The unique hash entry identifying the DBus entry
77701784826SJohnathan Mantey  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
77801784826SJohnathan Mantey  * @param[in] address      IPv6 address to assign to this interface
77901784826SJohnathan Mantey  * @param[io] asyncResp    Response object that will be returned to client
78001784826SJohnathan Mantey  *
78101784826SJohnathan Mantey  * @return None
78201784826SJohnathan Mantey  */
7839c5e585cSRavi Teja 
7849c5e585cSRavi Teja enum class IpVersion
7859c5e585cSRavi Teja {
7869c5e585cSRavi Teja     IpV4,
7879c5e585cSRavi Teja     IpV6
7889c5e585cSRavi Teja };
7899c5e585cSRavi Teja 
7909c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
7919c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
7928d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
7939c5e585cSRavi Teja     const std::string& gateway,
7948d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
79501784826SJohnathan Mantey {
79601784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
7979c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
7989c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
79901784826SJohnathan Mantey         if (ec)
80001784826SJohnathan Mantey         {
80101784826SJohnathan Mantey             messages::internalError(asyncResp->res);
80201784826SJohnathan Mantey         }
8039c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
8049c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
80501784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
8065e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
80723a21a1cSEd Tanous             if (ec2)
80801784826SJohnathan Mantey             {
80901784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
81001784826SJohnathan Mantey             }
81101784826SJohnathan Mantey         },
81201784826SJohnathan Mantey             "xyz.openbmc_project.Network",
81301784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
8149c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
8159c5e585cSRavi Teja             prefixLength, gateway);
81601784826SJohnathan Mantey     },
81701784826SJohnathan Mantey         "xyz.openbmc_project.Network",
8189c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
81901784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
82001784826SJohnathan Mantey }
82101784826SJohnathan Mantey 
822ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData(
823ce73d5c8SSunitha Harish     const std::string& ethifaceId,
824ce73d5c8SSunitha Harish     const dbus::utility::ManagedObjectType& dbusData,
825ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>& staticGatewayConfig)
826ce73d5c8SSunitha Harish {
827ce73d5c8SSunitha Harish     std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
828ce73d5c8SSunitha Harish     staticGatewayPathStart += ethifaceId;
829ce73d5c8SSunitha Harish 
830ce73d5c8SSunitha Harish     for (const auto& objpath : dbusData)
831ce73d5c8SSunitha Harish     {
832ce73d5c8SSunitha Harish         if (!std::string_view(objpath.first.str)
833ce73d5c8SSunitha Harish                  .starts_with(staticGatewayPathStart))
834ce73d5c8SSunitha Harish         {
835ce73d5c8SSunitha Harish             continue;
836ce73d5c8SSunitha Harish         }
837ce73d5c8SSunitha Harish         for (const auto& interface : objpath.second)
838ce73d5c8SSunitha Harish         {
839ce73d5c8SSunitha Harish             if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
840ce73d5c8SSunitha Harish             {
841ce73d5c8SSunitha Harish                 continue;
842ce73d5c8SSunitha Harish             }
843ce73d5c8SSunitha Harish             StaticGatewayData& staticGateway =
844ce73d5c8SSunitha Harish                 staticGatewayConfig.emplace_back();
845ce73d5c8SSunitha Harish             staticGateway.id = objpath.first.filename();
846ce73d5c8SSunitha Harish 
847ce73d5c8SSunitha Harish             bool success = sdbusplus::unpackPropertiesNoThrow(
848ce73d5c8SSunitha Harish                 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
849ce73d5c8SSunitha Harish                 "Gateway", staticGateway.gateway, "PrefixLength",
850ce73d5c8SSunitha Harish                 staticGateway.prefixLength, "ProtocolType",
851ce73d5c8SSunitha Harish                 staticGateway.protocol);
852ce73d5c8SSunitha Harish             if (!success)
853ce73d5c8SSunitha Harish             {
854ce73d5c8SSunitha Harish                 return false;
855ce73d5c8SSunitha Harish             }
856ce73d5c8SSunitha Harish         }
857ce73d5c8SSunitha Harish     }
858ce73d5c8SSunitha Harish     return true;
859ce73d5c8SSunitha Harish }
860ce73d5c8SSunitha Harish 
86101784826SJohnathan Mantey /**
862e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
863e48c0fc5SRavi Teja  *
864e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
865e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
866e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
867e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
868e48c0fc5SRavi Teja  *
869e48c0fc5SRavi Teja  * @return None
870e48c0fc5SRavi Teja  */
87101784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
87201784826SJohnathan Mantey                        const std::string& address,
8738d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
874e48c0fc5SRavi Teja {
875ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
876ce73d5c8SSunitha Harish     path /= ifaceId;
877ce73d5c8SSunitha Harish 
8785a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
8795a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
880e48c0fc5SRavi Teja         if (ec)
881e48c0fc5SRavi Teja         {
882fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
883fc23ef8aSNitin Kumar Kotania             {
884fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
885fc23ef8aSNitin Kumar Kotania                                                    "Address");
886fc23ef8aSNitin Kumar Kotania             }
887fc23ef8aSNitin Kumar Kotania             else
888fc23ef8aSNitin Kumar Kotania             {
889e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
890e48c0fc5SRavi Teja             }
891fc23ef8aSNitin Kumar Kotania         }
892e48c0fc5SRavi Teja     };
893ce73d5c8SSunitha Harish     // Passing null for gateway, as per redfish spec IPv6StaticAddresses
894ce73d5c8SSunitha Harish     // object does not have associated gateway property
895e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
896ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
897e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
898e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
899e48c0fc5SRavi Teja         "");
900e48c0fc5SRavi Teja }
901e48c0fc5SRavi Teja 
902179db1d7SKowalski, Kamil /**
903ce73d5c8SSunitha Harish  * @brief Deletes given IPv6 Static Gateway
904ce73d5c8SSunitha Harish  *
905ce73d5c8SSunitha Harish  * @param[in] ifaceId     Id of interface whose IP should be deleted
906ce73d5c8SSunitha Harish  * @param[in] ipHash      DBus Hash id of IP that should be deleted
907ce73d5c8SSunitha Harish  * @param[io] asyncResp   Response object that will be returned to client
908ce73d5c8SSunitha Harish  *
909ce73d5c8SSunitha Harish  * @return None
910ce73d5c8SSunitha Harish  */
911ce73d5c8SSunitha Harish inline void
912ce73d5c8SSunitha Harish     deleteIPv6Gateway(std::string_view gatewayId,
913ce73d5c8SSunitha Harish                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
914ce73d5c8SSunitha Harish {
915ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
916ce73d5c8SSunitha Harish     path /= gatewayId;
917ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
918ce73d5c8SSunitha Harish         [asyncResp](const boost::system::error_code& ec) {
919ce73d5c8SSunitha Harish         if (ec)
920ce73d5c8SSunitha Harish         {
921ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
922ce73d5c8SSunitha Harish         }
923ce73d5c8SSunitha Harish     },
924ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
925ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
926ce73d5c8SSunitha Harish }
927ce73d5c8SSunitha Harish 
928ce73d5c8SSunitha Harish /**
929ce73d5c8SSunitha Harish  * @brief Creates IPv6 static default gateway with given data
930ce73d5c8SSunitha Harish  *
931ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose IP should be added
932ce73d5c8SSunitha Harish  * @param[in] prefixLength Prefix length that needs to be added
933ce73d5c8SSunitha Harish  * @param[in] gateway      Gateway address that needs to be added
934ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
935ce73d5c8SSunitha Harish  *
936ce73d5c8SSunitha Harish  * @return None
937ce73d5c8SSunitha Harish  */
938ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway(
939ce73d5c8SSunitha Harish     std::string_view ifaceId, size_t prefixLength, std::string_view gateway,
940ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
941ce73d5c8SSunitha Harish {
942ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
943ce73d5c8SSunitha Harish     path /= ifaceId;
944ce73d5c8SSunitha Harish     auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
945ce73d5c8SSunitha Harish         if (ec)
946ce73d5c8SSunitha Harish         {
947ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
948ce73d5c8SSunitha Harish         }
949ce73d5c8SSunitha Harish     };
950ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
951ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
952ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
953ce73d5c8SSunitha Harish         gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
954ce73d5c8SSunitha Harish }
955ce73d5c8SSunitha Harish 
956ce73d5c8SSunitha Harish /**
957ce73d5c8SSunitha Harish  * @brief Deletes the IPv6 default gateway entry for this interface and
958ce73d5c8SSunitha Harish  * creates a replacement IPv6 default gateway entry
959ce73d5c8SSunitha Harish  *
960ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface upon which to create the IPv6
961ce73d5c8SSunitha Harish  * entry
962ce73d5c8SSunitha Harish  * @param[in] gateway      IPv6 gateway to assign to this interface
963ce73d5c8SSunitha Harish  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
964ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
965ce73d5c8SSunitha Harish  *
966ce73d5c8SSunitha Harish  * @return None
967ce73d5c8SSunitha Harish  */
968ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway(
969ce73d5c8SSunitha Harish     std::string_view ifaceId, std::string_view gatewayId,
970ce73d5c8SSunitha Harish     std::string_view gateway, size_t prefixLength,
971ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
972ce73d5c8SSunitha Harish {
973ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
974ce73d5c8SSunitha Harish     path /= gatewayId;
975ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
976ce73d5c8SSunitha Harish         [asyncResp, ifaceId, gateway,
977ce73d5c8SSunitha Harish          prefixLength](const boost::system::error_code& ec) {
978ce73d5c8SSunitha Harish         if (ec)
979ce73d5c8SSunitha Harish         {
980ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
981ce73d5c8SSunitha Harish             return;
982ce73d5c8SSunitha Harish         }
983ce73d5c8SSunitha Harish         createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp);
984ce73d5c8SSunitha Harish     },
985ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
986ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
987ce73d5c8SSunitha Harish }
988ce73d5c8SSunitha Harish 
989ce73d5c8SSunitha Harish /**
990ce73d5c8SSunitha Harish  * @brief Sets IPv6 default gateway with given data
991ce73d5c8SSunitha Harish  *
992ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose gateway should be added
993ce73d5c8SSunitha Harish  * @param[in] input        Contains address that needs to be added
994ce73d5c8SSunitha Harish  * @param[in] staticGatewayData  Current static gateways in the system
995ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
996ce73d5c8SSunitha Harish  *
997ce73d5c8SSunitha Harish  * @return None
998ce73d5c8SSunitha Harish  */
999ce73d5c8SSunitha Harish 
1000ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway(
10013dfed536SEd Tanous     const std::string& ifaceId,
10023dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1003ce73d5c8SSunitha Harish     const std::vector<StaticGatewayData>& staticGatewayData,
1004ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1005ce73d5c8SSunitha Harish {
1006ce73d5c8SSunitha Harish     size_t entryIdx = 1;
1007ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>::const_iterator staticGatewayEntry =
1008ce73d5c8SSunitha Harish         staticGatewayData.begin();
1009ce73d5c8SSunitha Harish 
10103dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
10113dfed536SEd Tanous          input)
1012ce73d5c8SSunitha Harish     {
1013ce73d5c8SSunitha Harish         // find the next gateway entry
1014ce73d5c8SSunitha Harish         while (staticGatewayEntry != staticGatewayData.end())
1015ce73d5c8SSunitha Harish         {
1016ce73d5c8SSunitha Harish             if (staticGatewayEntry->protocol ==
1017ce73d5c8SSunitha Harish                 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1018ce73d5c8SSunitha Harish             {
1019ce73d5c8SSunitha Harish                 break;
1020ce73d5c8SSunitha Harish             }
1021ce73d5c8SSunitha Harish             staticGatewayEntry++;
1022ce73d5c8SSunitha Harish         }
1023ce73d5c8SSunitha Harish         std::string pathString = "IPv6StaticDefaultGateways/" +
1024ce73d5c8SSunitha Harish                                  std::to_string(entryIdx);
10253dfed536SEd Tanous         nlohmann::json::object_t* obj =
10263dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
10273dfed536SEd Tanous         if (obj == nullptr)
1028ce73d5c8SSunitha Harish         {
1029ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1030ce73d5c8SSunitha Harish             {
1031ce73d5c8SSunitha Harish                 messages::resourceCannotBeDeleted(asyncResp->res);
1032ce73d5c8SSunitha Harish                 return;
1033ce73d5c8SSunitha Harish             }
1034ce73d5c8SSunitha Harish             deleteIPv6Gateway(staticGatewayEntry->id, asyncResp);
1035ce73d5c8SSunitha Harish             return;
1036ce73d5c8SSunitha Harish         }
10373dfed536SEd Tanous         if (obj->empty())
1038ce73d5c8SSunitha Harish         {
1039ce73d5c8SSunitha Harish             // Do nothing, but make sure the entry exists.
1040ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1041ce73d5c8SSunitha Harish             {
10423dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
1043ce73d5c8SSunitha Harish                                                    pathString);
1044ce73d5c8SSunitha Harish                 return;
1045ce73d5c8SSunitha Harish             }
1046ce73d5c8SSunitha Harish         }
1047ce73d5c8SSunitha Harish         std::optional<std::string> address;
1048ce73d5c8SSunitha Harish         std::optional<size_t> prefixLength;
1049ce73d5c8SSunitha Harish 
10503dfed536SEd Tanous         if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address,
10513dfed536SEd Tanous                                        "PrefixLength", prefixLength))
1052ce73d5c8SSunitha Harish         {
1053ce73d5c8SSunitha Harish             return;
1054ce73d5c8SSunitha Harish         }
1055ce73d5c8SSunitha Harish         const std::string* addr = nullptr;
1056ce73d5c8SSunitha Harish         size_t prefix = 0;
1057ce73d5c8SSunitha Harish         if (address)
1058ce73d5c8SSunitha Harish         {
1059ce73d5c8SSunitha Harish             addr = &(*address);
1060ce73d5c8SSunitha Harish         }
1061ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1062ce73d5c8SSunitha Harish         {
1063ce73d5c8SSunitha Harish             addr = &(staticGatewayEntry->gateway);
1064ce73d5c8SSunitha Harish         }
1065ce73d5c8SSunitha Harish         else
1066ce73d5c8SSunitha Harish         {
1067ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res, pathString + "/Address");
1068ce73d5c8SSunitha Harish             return;
1069ce73d5c8SSunitha Harish         }
1070ce73d5c8SSunitha Harish         if (prefixLength)
1071ce73d5c8SSunitha Harish         {
1072ce73d5c8SSunitha Harish             prefix = *prefixLength;
1073ce73d5c8SSunitha Harish         }
1074ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1075ce73d5c8SSunitha Harish         {
1076ce73d5c8SSunitha Harish             prefix = staticGatewayEntry->prefixLength;
1077ce73d5c8SSunitha Harish         }
1078ce73d5c8SSunitha Harish         else
1079ce73d5c8SSunitha Harish         {
1080ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res,
1081ce73d5c8SSunitha Harish                                       pathString + "/PrefixLength");
1082ce73d5c8SSunitha Harish             return;
1083ce73d5c8SSunitha Harish         }
1084ce73d5c8SSunitha Harish         if (staticGatewayEntry != staticGatewayData.end())
1085ce73d5c8SSunitha Harish         {
1086ce73d5c8SSunitha Harish             deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
1087ce73d5c8SSunitha Harish                                               *addr, prefix, asyncResp);
1088ce73d5c8SSunitha Harish             staticGatewayEntry++;
1089ce73d5c8SSunitha Harish         }
1090ce73d5c8SSunitha Harish         else
1091ce73d5c8SSunitha Harish         {
1092ce73d5c8SSunitha Harish             createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp);
1093ce73d5c8SSunitha Harish         }
1094ce73d5c8SSunitha Harish         entryIdx++;
1095ce73d5c8SSunitha Harish     }
1096ce73d5c8SSunitha Harish }
1097ce73d5c8SSunitha Harish 
1098ce73d5c8SSunitha Harish /**
1099179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
1100179db1d7SKowalski, Kamil  * Object
1101179db1d7SKowalski, Kamil  * from EntityManager Network Manager
11024a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
1103179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
1104179db1d7SKowalski, Kamil  * into JSON
1105179db1d7SKowalski, Kamil  */
1106179db1d7SKowalski, Kamil template <typename CallbackFunc>
110781ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
11081abe55efSEd Tanous                           CallbackFunc&& callback)
11091abe55efSEd Tanous {
1110f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1111f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1112f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1113f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
1114*8cb2c024SEd Tanous          callback = std::forward<CallbackFunc>(callback)](
11158b24275dSEd Tanous             const boost::system::error_code& ec,
11163dfed536SEd Tanous             const dbus::utility::ManagedObjectType& resp) mutable {
111755c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
111877179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
111977179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
1120ce73d5c8SSunitha Harish         std::vector<StaticGatewayData> ipv6GatewayData;
1121179db1d7SKowalski, Kamil 
11228b24275dSEd Tanous         if (ec)
11231abe55efSEd Tanous         {
1124ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1125179db1d7SKowalski, Kamil             return;
1126179db1d7SKowalski, Kamil         }
1127179db1d7SKowalski, Kamil 
1128002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
11294c9afe43SEd Tanous         if (!found)
11304c9afe43SEd Tanous         {
1131ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
11324c9afe43SEd Tanous             return;
11334c9afe43SEd Tanous         }
11344c9afe43SEd Tanous 
11352c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
1136179db1d7SKowalski, Kamil         // Fix global GW
11371abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
11381abe55efSEd Tanous         {
1139c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
1140c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
11419010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
11421abe55efSEd Tanous             {
114382695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
1144179db1d7SKowalski, Kamil             }
1145179db1d7SKowalski, Kamil         }
1146179db1d7SKowalski, Kamil 
11472c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
1148ce73d5c8SSunitha Harish         if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData))
1149ce73d5c8SSunitha Harish         {
1150ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1151ce73d5c8SSunitha Harish         }
11524e0453b1SGunnar Mills         // Finally make a callback with useful data
1153ce73d5c8SSunitha Harish         callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1154f5892d0dSGeorge Liu     });
1155271584abSEd Tanous }
1156179db1d7SKowalski, Kamil 
1157179db1d7SKowalski, Kamil /**
11589391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
11599391bb9cSRapkiewicz, Pawel  * Manager
11601abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
11611abe55efSEd Tanous  * into JSON.
11629391bb9cSRapkiewicz, Pawel  */
11639391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
11641abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
11651abe55efSEd Tanous {
1166f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1167f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1168f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1169*8cb2c024SEd Tanous         [callback = std::forward<CallbackFunc>(callback)](
11708b24275dSEd Tanous             const boost::system::error_code& ec,
1171f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
11721abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
11731abe55efSEd Tanous         // ethernet interfaces
117477179532SEd Tanous         std::vector<std::string> ifaceList;
11752c70f800SEd Tanous         ifaceList.reserve(resp.size());
11768b24275dSEd Tanous         if (ec)
11771abe55efSEd Tanous         {
11782c70f800SEd Tanous             callback(false, ifaceList);
11799391bb9cSRapkiewicz, Pawel             return;
11809391bb9cSRapkiewicz, Pawel         }
11819391bb9cSRapkiewicz, Pawel 
11829391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
11834a0cb85cSEd Tanous         for (const auto& objpath : resp)
11841abe55efSEd Tanous         {
11859391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
11864a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
11871abe55efSEd Tanous             {
11881abe55efSEd Tanous                 // If interface is
11894a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
11904a0cb85cSEd Tanous                 // what we're looking for.
11919391bb9cSRapkiewicz, Pawel                 if (interface.first ==
11921abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
11931abe55efSEd Tanous                 {
11942dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
11952dfd18efSEd Tanous                     if (ifaceId.empty())
11961abe55efSEd Tanous                     {
11972dfd18efSEd Tanous                         continue;
11989391bb9cSRapkiewicz, Pawel                     }
11992dfd18efSEd Tanous                     // and put it into output vector.
120077179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
12019391bb9cSRapkiewicz, Pawel                 }
12029391bb9cSRapkiewicz, Pawel             }
12039391bb9cSRapkiewicz, Pawel         }
12042c5875a2SEd Tanous 
12053544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
12062c5875a2SEd Tanous 
1207a434f2bdSEd Tanous         // Finally make a callback with useful data
12082c70f800SEd Tanous         callback(true, ifaceList);
1209f5892d0dSGeorge Liu     });
1210271584abSEd Tanous }
12119391bb9cSRapkiewicz, Pawel 
12124f48d5f6SEd Tanous inline void
12134f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
12148d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12151abe55efSEd Tanous {
1216ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
1217ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
1218ab6554f1SJoshi-Mansi     {
1219ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
1220ab6554f1SJoshi-Mansi                                            "HostName");
1221ab6554f1SJoshi-Mansi         return;
1222ab6554f1SJoshi-Mansi     }
1223d02aad39SEd Tanous     setDbusProperty(
1224d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1225d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network/config"),
1226d02aad39SEd Tanous         "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
1227d02aad39SEd Tanous         "HostName", hostname);
1228588c3f0dSKowalski, Kamil }
1229588c3f0dSKowalski, Kamil 
12304f48d5f6SEd Tanous inline void
123135fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
123235fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
123335fb5311STejas Patil {
1234d02aad39SEd Tanous     sdbusplus::message::object_path objPath("/xyz/openbmc_project/network");
1235d02aad39SEd Tanous     objPath /= ifaceId;
1236d02aad39SEd Tanous     setDbusProperty(asyncResp, "xyz.openbmc_project.Network", objPath,
1237d02aad39SEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface", "MTU",
1238d02aad39SEd Tanous                     "MTUSize", mtuSize);
123935fb5311STejas Patil }
124035fb5311STejas Patil 
124135fb5311STejas Patil inline void
12424f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
1243bf648f77SEd Tanous                           const std::string& domainname,
12448d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1245ab6554f1SJoshi-Mansi {
1246ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
1247d02aad39SEd Tanous     setDbusProperty(
1248d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1249d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1250d02aad39SEd Tanous             ifaceId,
1251d02aad39SEd Tanous         "xyz.openbmc_project.Network.EthernetInterface", "DomainName", "FQDN",
1252d02aad39SEd Tanous         vectorDomainname);
1253ab6554f1SJoshi-Mansi }
1254ab6554f1SJoshi-Mansi 
12554f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1256bf648f77SEd Tanous {
1257bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
12583544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1259bf648f77SEd Tanous     {
1260bf648f77SEd Tanous         return false;
1261bf648f77SEd Tanous     }
1262bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1263bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1264bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1265bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
12664b242749SEd Tanous     const static std::regex pattern(
1267bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1268bf648f77SEd Tanous 
1269bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1270bf648f77SEd Tanous }
1271bf648f77SEd Tanous 
12724f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1273bf648f77SEd Tanous {
1274bf648f77SEd Tanous     // Can have multiple subdomains
1275bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
12764b242749SEd Tanous     const static std::regex pattern(
12770fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1278bf648f77SEd Tanous 
1279bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1280bf648f77SEd Tanous }
1281bf648f77SEd Tanous 
12824f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
12838d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1284ab6554f1SJoshi-Mansi {
1285ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1286ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1287ab6554f1SJoshi-Mansi     {
1288ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1289ab6554f1SJoshi-Mansi         return;
1290ab6554f1SJoshi-Mansi     }
1291ab6554f1SJoshi-Mansi 
1292ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1293ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1294ab6554f1SJoshi-Mansi     {
1295ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1296ab6554f1SJoshi-Mansi         return;
1297ab6554f1SJoshi-Mansi     }
1298ab6554f1SJoshi-Mansi 
1299ab6554f1SJoshi-Mansi     std::string hostname;
1300ab6554f1SJoshi-Mansi     std::string domainname;
1301ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1302ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1303ab6554f1SJoshi-Mansi 
1304ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1305ab6554f1SJoshi-Mansi     {
1306ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1307ab6554f1SJoshi-Mansi         return;
1308ab6554f1SJoshi-Mansi     }
1309ab6554f1SJoshi-Mansi 
1310ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1311ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1312ab6554f1SJoshi-Mansi }
1313ab6554f1SJoshi-Mansi 
13144f48d5f6SEd Tanous inline void
13154f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1316bf648f77SEd Tanous                           const std::string& macAddress,
13178d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1318d577665bSRatan Gupta {
1319d02aad39SEd Tanous     setDbusProperty(
1320d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1321d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1322d02aad39SEd Tanous             ifaceId,
1323d02aad39SEd Tanous         "xyz.openbmc_project.Network.MACAddress", "MACAddress", "MACAddress",
1324d02aad39SEd Tanous         macAddress);
1325d577665bSRatan Gupta }
1326286b9118SJohnathan Mantey 
13274f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
13284f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
13294f48d5f6SEd Tanous                            const bool v6Value,
13308d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1331da131a9aSJennifer Lee {
13322c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
1333d02aad39SEd Tanous     setDbusProperty(
1334d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1335d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1336d02aad39SEd Tanous             ifaceId,
1337d02aad39SEd Tanous         "xyz.openbmc_project.Network.EthernetInterface", propertyName, "DHCPv4",
1338d02aad39SEd Tanous         dhcp);
1339eeedda23SJohnathan Mantey }
1340eeedda23SJohnathan Mantey 
1341e4588158SJishnu CM enum class NetworkType
1342e4588158SJishnu CM {
1343e4588158SJishnu CM     dhcp4,
1344e4588158SJishnu CM     dhcp6
1345e4588158SJishnu CM };
1346e4588158SJishnu CM 
1347e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1348e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1349e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1350da131a9aSJennifer Lee {
135162598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
13521847f2a0SAsmitha Karunanithi     std::string redfishPropertyName;
1353e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1354e4588158SJishnu CM     path /= ethifaceId;
1355e4588158SJishnu CM 
1356e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1357e4588158SJishnu CM     {
1358e4588158SJishnu CM         path /= "dhcp4";
13591847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv4";
1360e4588158SJishnu CM     }
1361e4588158SJishnu CM     else
1362e4588158SJishnu CM     {
1363e4588158SJishnu CM         path /= "dhcp6";
13641847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv6";
1365e4588158SJishnu CM     }
1366e4588158SJishnu CM 
13671847f2a0SAsmitha Karunanithi     setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path,
13681847f2a0SAsmitha Karunanithi                     "xyz.openbmc_project.Network.DHCPConfiguration",
13691847f2a0SAsmitha Karunanithi                     propertyName, redfishPropertyName, value);
1370da131a9aSJennifer Lee }
1371d577665bSRatan Gupta 
1372b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1373b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1374b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1375b10d8db0SRavi Teja {
1376b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1377b10d8db0SRavi Teja     path /= ifaceId;
13781847f2a0SAsmitha Karunanithi     setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path,
13791847f2a0SAsmitha Karunanithi                     "xyz.openbmc_project.Network.EthernetInterface",
13801847f2a0SAsmitha Karunanithi                     "IPv6AcceptRA",
13811847f2a0SAsmitha Karunanithi                     "StatelessAddressAutoConfig/IPv6AutoConfigEnabled",
13821847f2a0SAsmitha Karunanithi                     ipv6AutoConfigEnabled);
1383b10d8db0SRavi Teja }
1384b10d8db0SRavi Teja 
13854f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
13861f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1387f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1388f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
13898d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1390da131a9aSJennifer Lee {
139182695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
139282695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1393da131a9aSJennifer Lee 
13941f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
13951f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
13961f8c7b5dSJohnathan Mantey 
13971f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
13981f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1399da131a9aSJennifer Lee     {
1400b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
14011f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
14021f8c7b5dSJohnathan Mantey         {
1403bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1404bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
14051f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1406da131a9aSJennifer Lee             return;
1407da131a9aSJennifer Lee         }
1408b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
14091f8c7b5dSJohnathan Mantey     }
14101f8c7b5dSJohnathan Mantey     else
1411da131a9aSJennifer Lee     {
14121f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
14131f8c7b5dSJohnathan Mantey     }
14141f8c7b5dSJohnathan Mantey 
1415e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1416e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1417e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
14181f8c7b5dSJohnathan Mantey     {
1419e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
14201f8c7b5dSJohnathan Mantey     }
1421e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
14221f8c7b5dSJohnathan Mantey     {
1423e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
14241f8c7b5dSJohnathan Mantey     }
14251f8c7b5dSJohnathan Mantey 
1426e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1427e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1428e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
14291f8c7b5dSJohnathan Mantey     {
1430e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
14311f8c7b5dSJohnathan Mantey     }
1432e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
14331f8c7b5dSJohnathan Mantey     {
1434e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
14351f8c7b5dSJohnathan Mantey     }
14361f8c7b5dSJohnathan Mantey 
143791c441ecSRavi Teja     bool nextUsev4Domain = ethData.domainv4Enabled;
143891c441ecSRavi Teja     bool nextUsev6Domain = ethData.domainv6Enabled;
1439e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
14401f8c7b5dSJohnathan Mantey     {
1441e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
14421f8c7b5dSJohnathan Mantey     }
1443e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
14441f8c7b5dSJohnathan Mantey     {
1445e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
14461f8c7b5dSJohnathan Mantey     }
14471f8c7b5dSJohnathan Mantey 
144862598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
14491f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
14501f8c7b5dSJohnathan Mantey                    asyncResp);
145162598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1452e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1453e4588158SJishnu CM                   NetworkType::dhcp4);
145462598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1455e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1456e4588158SJishnu CM                   NetworkType::dhcp4);
145791c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled...");
145891c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
1459e4588158SJishnu CM                   NetworkType::dhcp4);
1460e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1461e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1462e4588158SJishnu CM                   NetworkType::dhcp6);
1463e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1464e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1465e4588158SJishnu CM                   NetworkType::dhcp6);
146691c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
146791c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
1468e4588158SJishnu CM                   NetworkType::dhcp6);
1469da131a9aSJennifer Lee }
147001784826SJohnathan Mantey 
147177179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
147277179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
147377179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
147401784826SJohnathan Mantey {
147517a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
147617a897dfSManojkiran Eda         return value.origin == "Static";
147717a897dfSManojkiran Eda     });
147801784826SJohnathan Mantey }
147901784826SJohnathan Mantey 
148077179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
148177179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
148277179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
148301784826SJohnathan Mantey {
148417a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
148517a897dfSManojkiran Eda         return value.origin == "Static";
148617a897dfSManojkiran Eda     });
148701784826SJohnathan Mantey }
148801784826SJohnathan Mantey 
14893dfed536SEd Tanous inline void handleIPv4StaticPatch(
14903dfed536SEd Tanous     const std::string& ifaceId,
14913dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
149277179532SEd Tanous     const std::vector<IPv4AddressData>& ipv4Data,
14938d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
14941abe55efSEd Tanous {
1495271584abSEd Tanous     unsigned entryIdx = 1;
149601784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
149701784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
149801784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
149901784826SJohnathan Mantey     // into the NIC.
150077179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
15012c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
150201784826SJohnathan Mantey 
15033dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
15043dfed536SEd Tanous          input)
15051abe55efSEd Tanous     {
150689492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
150789492a15SPatrick Williams                                  std::to_string(entryIdx);
15083dfed536SEd Tanous         nlohmann::json::object_t* obj =
15093dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
15103dfed536SEd Tanous         if (obj != nullptr && !obj->empty())
1511f476acbfSRatan Gupta         {
1512537174c4SEd Tanous             std::optional<std::string> address;
1513537174c4SEd Tanous             std::optional<std::string> subnetMask;
1514537174c4SEd Tanous             std::optional<std::string> gateway;
1515537174c4SEd Tanous 
15163dfed536SEd Tanous             if (!json_util::readJsonObject(*obj, asyncResp->res, "Address",
15177e27d832SJohnathan Mantey                                            address, "SubnetMask", subnetMask,
15187e27d832SJohnathan Mantey                                            "Gateway", gateway))
1519537174c4SEd Tanous             {
15203dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
152171f52d96SEd Tanous                                                    pathString);
1522537174c4SEd Tanous                 return;
1523179db1d7SKowalski, Kamil             }
1524179db1d7SKowalski, Kamil 
152501784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
152601784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
152701784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
152801784826SJohnathan Mantey             // current request.
1529537174c4SEd Tanous             if (address)
15301abe55efSEd Tanous             {
1531e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
153201784826SJohnathan Mantey                 {
1533bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1534bf648f77SEd Tanous                                                        pathString + "/Address");
1535e01d0c36SEd Tanous                     return;
153601784826SJohnathan Mantey                 }
153701784826SJohnathan Mantey             }
153885ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
153901784826SJohnathan Mantey             {
1540e01d0c36SEd Tanous                 address = (nicIpEntry->address);
154101784826SJohnathan Mantey             }
154201784826SJohnathan Mantey             else
154301784826SJohnathan Mantey             {
154401784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
154501784826SJohnathan Mantey                                           pathString + "/Address");
1546e01d0c36SEd Tanous                 return;
15474a0cb85cSEd Tanous             }
15484a0cb85cSEd Tanous 
1549e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1550537174c4SEd Tanous             if (subnetMask)
15514a0cb85cSEd Tanous             {
1552033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1553033f1e4dSEd Tanous                                                          &prefixLength))
15544a0cb85cSEd Tanous                 {
1555f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1556537174c4SEd Tanous                         asyncResp->res, *subnetMask,
15574a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1558e01d0c36SEd Tanous                     return;
15594a0cb85cSEd Tanous                 }
15604a0cb85cSEd Tanous             }
156185ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
15624a0cb85cSEd Tanous             {
1563033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
156401784826SJohnathan Mantey                                                          &prefixLength))
15654a0cb85cSEd Tanous                 {
156601784826SJohnathan Mantey                     messages::propertyValueFormatError(
156785ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
156801784826SJohnathan Mantey                         pathString + "/SubnetMask");
1569e01d0c36SEd Tanous                     return;
15704a0cb85cSEd Tanous                 }
15714a0cb85cSEd Tanous             }
15721abe55efSEd Tanous             else
15731abe55efSEd Tanous             {
157401784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
157501784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1576e01d0c36SEd Tanous                 return;
157701784826SJohnathan Mantey             }
157801784826SJohnathan Mantey 
157901784826SJohnathan Mantey             if (gateway)
158001784826SJohnathan Mantey             {
1581e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
158201784826SJohnathan Mantey                 {
1583bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1584bf648f77SEd Tanous                                                        pathString + "/Gateway");
1585e01d0c36SEd Tanous                     return;
158601784826SJohnathan Mantey                 }
158701784826SJohnathan Mantey             }
158885ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
158901784826SJohnathan Mantey             {
1590e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
159101784826SJohnathan Mantey             }
159201784826SJohnathan Mantey             else
15931abe55efSEd Tanous             {
1594a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
15954a0cb85cSEd Tanous                                           pathString + "/Gateway");
159601784826SJohnathan Mantey                 return;
15974a0cb85cSEd Tanous             }
15984a0cb85cSEd Tanous 
159985ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
16001abe55efSEd Tanous             {
16019c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
160277eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
160377eb0153SEd Tanous                                          *gateway, asyncResp);
160489492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
160589492a15SPatrick Williams                                                   ipv4Data.cend());
1606588c3f0dSKowalski, Kamil             }
160701784826SJohnathan Mantey             else
160801784826SJohnathan Mantey             {
1609cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1610cb13a392SEd Tanous                            asyncResp);
16114a0cb85cSEd Tanous             }
16124a0cb85cSEd Tanous             entryIdx++;
16134a0cb85cSEd Tanous         }
161401784826SJohnathan Mantey         else
161501784826SJohnathan Mantey         {
161685ffe86aSJiaqing Zhao             if (nicIpEntry == ipv4Data.cend())
161701784826SJohnathan Mantey             {
161801784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
161901784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
162001784826SJohnathan Mantey                 // in error, so bail out.
16213dfed536SEd Tanous                 if (obj == nullptr)
162201784826SJohnathan Mantey                 {
162301784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
162401784826SJohnathan Mantey                     return;
162501784826SJohnathan Mantey                 }
16263dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
162771f52d96SEd Tanous                                                    pathString);
162801784826SJohnathan Mantey                 return;
162901784826SJohnathan Mantey             }
163001784826SJohnathan Mantey 
16313dfed536SEd Tanous             if (obj == nullptr)
163201784826SJohnathan Mantey             {
16339c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
163401784826SJohnathan Mantey             }
163585ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
163601784826SJohnathan Mantey             {
163789492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
163889492a15SPatrick Williams                                                   ipv4Data.cend());
163901784826SJohnathan Mantey             }
164001784826SJohnathan Mantey             entryIdx++;
164101784826SJohnathan Mantey         }
164201784826SJohnathan Mantey     }
16434a0cb85cSEd Tanous }
16444a0cb85cSEd Tanous 
16454f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1646f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1647f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
16488d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1649f85837bfSRAJESWARAN THILLAIGOVINDAN {
16501847f2a0SAsmitha Karunanithi     setDbusProperty(
16511847f2a0SAsmitha Karunanithi         asyncResp, "xyz.openbmc_project.Network",
16521847f2a0SAsmitha Karunanithi         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
16531847f2a0SAsmitha Karunanithi             ifaceId,
16549ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
16551847f2a0SAsmitha Karunanithi         "StaticNameServers", updatedStaticNameServers);
1656f85837bfSRAJESWARAN THILLAIGOVINDAN }
1657f85837bfSRAJESWARAN THILLAIGOVINDAN 
16584f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
16593dfed536SEd Tanous     const std::string& ifaceId,
16603dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
166177179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
16628d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1663e48c0fc5SRavi Teja {
1664271584abSEd Tanous     size_t entryIdx = 1;
166577179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
16662c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
16673dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
16683dfed536SEd Tanous          input)
1669e48c0fc5SRavi Teja     {
167089492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
167189492a15SPatrick Williams                                  std::to_string(entryIdx);
16723dfed536SEd Tanous         nlohmann::json::object_t* obj =
16733dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
16743dfed536SEd Tanous         if (obj != nullptr && !obj->empty())
1675e48c0fc5SRavi Teja         {
1676e48c0fc5SRavi Teja             std::optional<std::string> address;
1677e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
16783dfed536SEd Tanous             nlohmann::json::object_t thisJsonCopy = *obj;
16793dfed536SEd Tanous             if (!json_util::readJsonObject(thisJsonCopy, asyncResp->res,
16803dfed536SEd Tanous                                            "Address", address, "PrefixLength",
16813dfed536SEd Tanous                                            prefixLength))
1682e48c0fc5SRavi Teja             {
16833dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJsonCopy,
168471f52d96SEd Tanous                                                    pathString);
1685e48c0fc5SRavi Teja                 return;
1686e48c0fc5SRavi Teja             }
1687e48c0fc5SRavi Teja 
168801784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
168901784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
169001784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
169101784826SJohnathan Mantey             // current request.
1692d547d8d2SEd Tanous             if (!address)
1693e48c0fc5SRavi Teja             {
1694d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
169501784826SJohnathan Mantey                 {
169601784826SJohnathan Mantey                     messages::propertyMissing(asyncResp->res,
169701784826SJohnathan Mantey                                               pathString + "/Address");
169801784826SJohnathan Mantey                     return;
1699e48c0fc5SRavi Teja                 }
1700d547d8d2SEd Tanous                 address = nicIpEntry->address;
1701d547d8d2SEd Tanous             }
1702e48c0fc5SRavi Teja 
1703d547d8d2SEd Tanous             if (!prefixLength)
1704e48c0fc5SRavi Teja             {
1705d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
1706e48c0fc5SRavi Teja                 {
1707e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1708e48c0fc5SRavi Teja                                               pathString + "/PrefixLength");
170901784826SJohnathan Mantey                     return;
1710e48c0fc5SRavi Teja                 }
1711d547d8d2SEd Tanous                 prefixLength = nicIpEntry->prefixLength;
1712d547d8d2SEd Tanous             }
1713e48c0fc5SRavi Teja 
171485ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1715e48c0fc5SRavi Teja             {
17169c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1717d547d8d2SEd Tanous                                          nicIpEntry->id, *prefixLength,
1718d547d8d2SEd Tanous                                          *address, "", asyncResp);
171989492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
172089492a15SPatrick Williams                                                   ipv6Data.cend());
172101784826SJohnathan Mantey             }
172201784826SJohnathan Mantey             else
172301784826SJohnathan Mantey             {
1724d547d8d2SEd Tanous                 createIPv6(ifaceId, *prefixLength, *address, asyncResp);
1725e48c0fc5SRavi Teja             }
1726e48c0fc5SRavi Teja             entryIdx++;
1727e48c0fc5SRavi Teja         }
172801784826SJohnathan Mantey         else
172901784826SJohnathan Mantey         {
173085ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
173101784826SJohnathan Mantey             {
173201784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
173301784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
173401784826SJohnathan Mantey                 // in error, so bail out.
17353dfed536SEd Tanous                 if (obj == nullptr)
173601784826SJohnathan Mantey                 {
173701784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
173801784826SJohnathan Mantey                     return;
173901784826SJohnathan Mantey                 }
17403dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
174171f52d96SEd Tanous                                                    pathString);
174201784826SJohnathan Mantey                 return;
174301784826SJohnathan Mantey             }
174401784826SJohnathan Mantey 
17453dfed536SEd Tanous             if (obj == nullptr)
174601784826SJohnathan Mantey             {
17479c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
174801784826SJohnathan Mantey             }
174985ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
175001784826SJohnathan Mantey             {
175189492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
175289492a15SPatrick Williams                                                   ipv6Data.cend());
175301784826SJohnathan Mantey             }
175401784826SJohnathan Mantey             entryIdx++;
175501784826SJohnathan Mantey         }
175601784826SJohnathan Mantey     }
1757e48c0fc5SRavi Teja }
1758e48c0fc5SRavi Teja 
17597857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
17607857cb8dSJiaqing Zhao {
17617857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
17627857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
17637857cb8dSJiaqing Zhao }
17647857cb8dSJiaqing Zhao 
176577179532SEd Tanous inline void
176677179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
176777179532SEd Tanous                        const std::string& ifaceId,
176877179532SEd Tanous                        const EthernetInterfaceData& ethData,
176977179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
1770ce73d5c8SSunitha Harish                        const std::vector<IPv6AddressData>& ipv6Data,
1771ce73d5c8SSunitha Harish                        const std::vector<StaticGatewayData>& ipv6GatewayData)
17724a0cb85cSEd Tanous {
17732c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
177481ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1775ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1776ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
17772c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1778eeedda23SJohnathan Mantey 
1779eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1780eeedda23SJohnathan Mantey     {
17810ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
17822c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1783029573d4SEd Tanous     }
1784029573d4SEd Tanous     else
1785029573d4SEd Tanous     {
17862c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
17872c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1788029573d4SEd Tanous     }
1789aa05fb27SJohnathan Mantey 
17902c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
179135fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
179282695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
17932c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
179482695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1795e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1796e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1797e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
17982c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1799b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
18001f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1801e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1802e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1803e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
1804b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1805b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
18062a133282Smanojkiraneda 
180782695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
18084a0cb85cSEd Tanous     {
180982695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1810ab6554f1SJoshi-Mansi 
1811ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1812ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1813ab6554f1SJoshi-Mansi         // FQDN
181482695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1815d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1816d24bfc7aSJennifer Lee         {
18172c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1818d24bfc7aSJennifer Lee         }
18192c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
18204a0cb85cSEd Tanous     }
18214a0cb85cSEd Tanous 
18227857cb8dSJiaqing Zhao     if (ethData.vlanId)
18237857cb8dSJiaqing Zhao     {
18247857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
18257857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
18267857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
18277857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
18287857cb8dSJiaqing Zhao 
18297857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
18307857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
18317857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
18327857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
18337857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
18347857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
18357857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
18367857cb8dSJiaqing Zhao     }
18377857cb8dSJiaqing Zhao     else
18387857cb8dSJiaqing Zhao     {
18397857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
18407857cb8dSJiaqing Zhao     }
18417857cb8dSJiaqing Zhao 
18422c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
18432c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
18444a0cb85cSEd Tanous 
18452c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
18462c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
18472c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
18482c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
18499eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
18504a0cb85cSEd Tanous     {
18512c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1852fa5053a6SGunnar Mills         if (gatewayStr.empty())
1853fa5053a6SGunnar Mills         {
1854fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1855fa5053a6SGunnar Mills         }
18561476687dSEd Tanous         nlohmann::json::object_t ipv4;
18571476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
18581476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
18591476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
18601476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1861fa5053a6SGunnar Mills 
18622c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1863d1d50814SRavi Teja         {
18641476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1865d1d50814SRavi Teja         }
18661476687dSEd Tanous 
1867b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
186801784826SJohnathan Mantey     }
1869d1d50814SRavi Teja 
187082695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
18717ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
18727ea79e5eSRavi Teja     {
18737ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
18747ea79e5eSRavi Teja     }
18757ea79e5eSRavi Teja 
18767ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1877e48c0fc5SRavi Teja 
1878ce73d5c8SSunitha Harish     nlohmann::json::array_t ipv6StaticGatewayArray;
1879ce73d5c8SSunitha Harish     for (const auto& ipv6GatewayConfig : ipv6GatewayData)
1880ce73d5c8SSunitha Harish     {
1881ce73d5c8SSunitha Harish         nlohmann::json::object_t ipv6Gateway;
1882ce73d5c8SSunitha Harish         ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
1883ce73d5c8SSunitha Harish         ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength;
1884ce73d5c8SSunitha Harish         ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
1885ce73d5c8SSunitha Harish     }
1886ce73d5c8SSunitha Harish     jsonResponse["IPv6StaticDefaultGateways"] =
1887ce73d5c8SSunitha Harish         std::move(ipv6StaticGatewayArray);
1888ce73d5c8SSunitha Harish 
18892c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
18902c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
18912c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
18922c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
18937f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
18942c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
18957f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
18969eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1897e48c0fc5SRavi Teja     {
18981476687dSEd Tanous         nlohmann::json::object_t ipv6;
18991476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
19001476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
19011476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1902f8361275SSunitha Harish 
1903b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
19042c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1905e48c0fc5SRavi Teja         {
19061476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
19071476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
19081476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1909b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
191001784826SJohnathan Mantey         }
1911e48c0fc5SRavi Teja     }
1912588c3f0dSKowalski, Kamil }
1913588c3f0dSKowalski, Kamil 
1914e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1915e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1916e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1917e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1918e7caf250SJiaqing Zhao {
1919e7caf250SJiaqing Zhao     if (!ec)
1920e7caf250SJiaqing Zhao     {
1921e7caf250SJiaqing Zhao         return;
1922e7caf250SJiaqing Zhao     }
1923e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
1924e7caf250SJiaqing Zhao     if (dbusError == nullptr)
1925e7caf250SJiaqing Zhao     {
1926e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
1927e7caf250SJiaqing Zhao         return;
1928e7caf250SJiaqing Zhao     }
192962598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1930e7caf250SJiaqing Zhao 
1931e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1932e7caf250SJiaqing Zhao         dbusError->name)
1933e7caf250SJiaqing Zhao     {
1934e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1935e7caf250SJiaqing Zhao                                    ifaceId);
1936e7caf250SJiaqing Zhao         return;
1937e7caf250SJiaqing Zhao     }
1938e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1939e7caf250SJiaqing Zhao         dbusError->name)
1940e7caf250SJiaqing Zhao     {
1941e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
1942e7caf250SJiaqing Zhao         return;
1943e7caf250SJiaqing Zhao     }
1944e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
1945e7caf250SJiaqing Zhao }
1946e7caf250SJiaqing Zhao 
1947b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1948b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
1949b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
1950b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
1951b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
1952b5ca3fdcSJiaqing Zhao 
1953b5ca3fdcSJiaqing Zhao )
1954b5ca3fdcSJiaqing Zhao {
1955b5ca3fdcSJiaqing Zhao     if (ec)
1956b5ca3fdcSJiaqing Zhao     {
1957b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
1958b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
1959b5ca3fdcSJiaqing Zhao         {
1960b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
1961b5ca3fdcSJiaqing Zhao             return;
1962b5ca3fdcSJiaqing Zhao         }
196362598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1964b5ca3fdcSJiaqing Zhao 
1965b5ca3fdcSJiaqing Zhao         if (std::string_view(
1966b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1967b5ca3fdcSJiaqing Zhao             dbusError->name)
1968b5ca3fdcSJiaqing Zhao         {
1969b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1970b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1971b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1972b5ca3fdcSJiaqing Zhao             return;
1973b5ca3fdcSJiaqing Zhao         }
1974b5ca3fdcSJiaqing Zhao         if (std::string_view(
1975b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1976b5ca3fdcSJiaqing Zhao             dbusError->name)
1977b5ca3fdcSJiaqing Zhao         {
1978b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1979b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
1980b5ca3fdcSJiaqing Zhao             return;
1981b5ca3fdcSJiaqing Zhao         }
1982b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
1983b5ca3fdcSJiaqing Zhao         return;
1984b5ca3fdcSJiaqing Zhao     }
1985b5ca3fdcSJiaqing Zhao 
1986b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
1987b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1988b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1989b5ca3fdcSJiaqing Zhao }
1990b5ca3fdcSJiaqing Zhao 
1991bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
1992bf648f77SEd Tanous {
1993bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1994ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
19951476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
19961476687dSEd Tanous             [&app](const crow::Request& req,
19971476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
19983ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
199945ca1b86SEd Tanous         {
200045ca1b86SEd Tanous             return;
200145ca1b86SEd Tanous         }
200245ca1b86SEd Tanous 
2003bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2004bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2005bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2006bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
2007bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
2008bf648f77SEd Tanous             "Ethernet Network Interface Collection";
2009bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
2010bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
2011bf648f77SEd Tanous 
2012bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
2013bf648f77SEd Tanous         // preparation
2014002d39b4SEd Tanous         getEthernetIfaceList(
201577179532SEd Tanous             [asyncResp](const bool& success,
201677179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
2017bf648f77SEd Tanous             if (!success)
20181abe55efSEd Tanous             {
2019f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
20209391bb9cSRapkiewicz, Pawel                 return;
20219391bb9cSRapkiewicz, Pawel             }
20229391bb9cSRapkiewicz, Pawel 
2023002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2024bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
2025bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
2026bf648f77SEd Tanous             {
20271476687dSEd Tanous                 nlohmann::json::object_t iface;
2028ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
2029ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
2030ef4c65b7SEd Tanous                     ifaceItem);
20317857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
2032bf648f77SEd Tanous             }
2033bf648f77SEd Tanous 
2034002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
2035bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2036bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
2037bf648f77SEd Tanous         });
2038bf648f77SEd Tanous     });
2039bf648f77SEd Tanous 
2040b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2041b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
2042b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
2043b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
2044b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2045b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2046b5ca3fdcSJiaqing Zhao         {
2047b5ca3fdcSJiaqing Zhao             return;
2048b5ca3fdcSJiaqing Zhao         }
2049b5ca3fdcSJiaqing Zhao 
2050b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
2051b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
20523dfed536SEd Tanous         std::vector<nlohmann::json::object_t> relatedInterfaces;
2053b5ca3fdcSJiaqing Zhao 
2054b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
2055b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
2056b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
2057b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
2058b5ca3fdcSJiaqing Zhao         {
2059b5ca3fdcSJiaqing Zhao             return;
2060b5ca3fdcSJiaqing Zhao         }
2061b5ca3fdcSJiaqing Zhao 
2062b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
2063b5ca3fdcSJiaqing Zhao         {
2064b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
2065b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
2066b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
2067b5ca3fdcSJiaqing Zhao             return;
2068b5ca3fdcSJiaqing Zhao         }
2069b5ca3fdcSJiaqing Zhao 
2070b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
20713dfed536SEd Tanous         if (!json_util::readJsonObject(relatedInterfaces[0], asyncResp->res,
2072b5ca3fdcSJiaqing Zhao                                        "@odata.id", parentInterfaceUri))
2073b5ca3fdcSJiaqing Zhao         {
2074b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
2075b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
2076b5ca3fdcSJiaqing Zhao             return;
2077b5ca3fdcSJiaqing Zhao         }
207862598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
2079b5ca3fdcSJiaqing Zhao 
20806fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
2081b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
2082b5ca3fdcSJiaqing Zhao         if (!parsedUri)
2083b5ca3fdcSJiaqing Zhao         {
2084b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
2085b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2086b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2087b5ca3fdcSJiaqing Zhao             return;
2088b5ca3fdcSJiaqing Zhao         }
2089b5ca3fdcSJiaqing Zhao 
2090b5ca3fdcSJiaqing Zhao         std::string parentInterface;
2091b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
2092b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
2093b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
2094b5ca3fdcSJiaqing Zhao         {
2095b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2096b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2097b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2098b5ca3fdcSJiaqing Zhao             return;
2099b5ca3fdcSJiaqing Zhao         }
2100b5ca3fdcSJiaqing Zhao 
2101b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
2102b5ca3fdcSJiaqing Zhao         {
2103b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
2104b5ca3fdcSJiaqing Zhao             // create
2105b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
2106b5ca3fdcSJiaqing Zhao                                              "false");
2107b5ca3fdcSJiaqing Zhao             return;
2108b5ca3fdcSJiaqing Zhao         }
2109b5ca3fdcSJiaqing Zhao 
2110b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
2111b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
2112b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
2113b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
2114b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
2115b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
2116b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
2117b5ca3fdcSJiaqing Zhao                             m);
2118b5ca3fdcSJiaqing Zhao         },
2119b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
2120b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
2121b5ca3fdcSJiaqing Zhao             vlanId);
2122b5ca3fdcSJiaqing Zhao     });
2123b5ca3fdcSJiaqing Zhao 
2124bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2125ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
2126bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
212745ca1b86SEd Tanous             [&app](const crow::Request& req,
2128bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2129bf648f77SEd Tanous                    const std::string& ifaceId) {
21303ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
213145ca1b86SEd Tanous         {
213245ca1b86SEd Tanous             return;
213345ca1b86SEd Tanous         }
21344a0cb85cSEd Tanous         getEthernetIfaceData(
2135bf648f77SEd Tanous             ifaceId,
2136ce73d5c8SSunitha Harish             [asyncResp,
2137ce73d5c8SSunitha Harish              ifaceId](const bool& success, const EthernetInterfaceData& ethData,
213877179532SEd Tanous                       const std::vector<IPv4AddressData>& ipv4Data,
2139ce73d5c8SSunitha Harish                       const std::vector<IPv6AddressData>& ipv6Data,
2140ce73d5c8SSunitha Harish                       const std::vector<StaticGatewayData>& ipv6GatewayData) {
21414a0cb85cSEd Tanous             if (!success)
21421abe55efSEd Tanous             {
2143bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2144bf648f77SEd Tanous                 // existing object, and other errors
2145002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2146002d39b4SEd Tanous                                            ifaceId);
21474a0cb85cSEd Tanous                 return;
21489391bb9cSRapkiewicz, Pawel             }
21494c9afe43SEd Tanous 
21500f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
215193bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
2152002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
21530f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
21540f74e643SEd Tanous                 "Management Network Interface";
21550f74e643SEd Tanous 
2156ce73d5c8SSunitha Harish             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data,
2157ce73d5c8SSunitha Harish                                ipv6GatewayData);
21589391bb9cSRapkiewicz, Pawel         });
2159bf648f77SEd Tanous     });
21609391bb9cSRapkiewicz, Pawel 
2161bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2162ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2163bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
216445ca1b86SEd Tanous             [&app](const crow::Request& req,
2165bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2166bf648f77SEd Tanous                    const std::string& ifaceId) {
21673ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
216845ca1b86SEd Tanous         {
216945ca1b86SEd Tanous             return;
217045ca1b86SEd Tanous         }
2171bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2172ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2173d577665bSRatan Gupta         std::optional<std::string> macAddress;
21749a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
21753dfed536SEd Tanous         std::optional<
21763dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
21773dfed536SEd Tanous             ipv4StaticAddresses;
21783dfed536SEd Tanous         std::optional<
21793dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
21803dfed536SEd Tanous             ipv6StaticAddresses;
21813dfed536SEd Tanous         std::optional<
21823dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
21833dfed536SEd Tanous             ipv6StaticDefaultGateways;
2184f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2185b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2186eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
218735fb5311STejas Patil         std::optional<size_t> mtuSize;
21881f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
21891f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2190b10d8db0SRavi Teja         // clang-format off
21913dfed536SEd Tanous         if (!json_util::readJsonPatch(req, asyncResp->res,
21923dfed536SEd Tanous                 "DHCPv4/DHCPEnabled",   v4dhcpParms.dhcpv4Enabled,
21933dfed536SEd Tanous                 "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers,
21943dfed536SEd Tanous                 "DHCPv4/UseDomainName", v4dhcpParms.useDomainName,
21953dfed536SEd Tanous                 "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers,
21963dfed536SEd Tanous                 "DHCPv6/OperatingMode", v6dhcpParms.dhcpv6OperatingMode,
21973dfed536SEd Tanous                 "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers,
21983dfed536SEd Tanous                 "DHCPv6/UseDomainName", v6dhcpParms.useDomainName,
21993dfed536SEd Tanous                 "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers,
2200b10d8db0SRavi Teja                 "FQDN", fqdn,
2201b10d8db0SRavi Teja                 "HostName", hostname,
2202b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2203b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2204b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2205ce73d5c8SSunitha Harish                 "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways,
2206b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2207b10d8db0SRavi Teja                 "MACAddress", macAddress,
2208b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2209b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2210b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2211b10d8db0SRavi Teja                 )
2212b10d8db0SRavi Teja             )
22131abe55efSEd Tanous         {
2214588c3f0dSKowalski, Kamil             return;
2215588c3f0dSKowalski, Kamil         }
2216b10d8db0SRavi Teja         // clang-format on
2217da131a9aSJennifer Lee 
2218bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2219bf648f77SEd Tanous         // for JSON preparation
22204a0cb85cSEd Tanous         getEthernetIfaceData(
22212c70f800SEd Tanous             ifaceId,
2222bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2223ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2224d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
22259a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2226e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2227ce73d5c8SSunitha Harish              ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways),
22283dfed536SEd Tanous              staticNameServers = std::move(staticNameServers), mtuSize,
2229b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2230f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
22313dfed536SEd Tanous                 const bool success, const EthernetInterfaceData& ethData,
223277179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
2233ce73d5c8SSunitha Harish                 const std::vector<IPv6AddressData>& ipv6Data,
22343dfed536SEd Tanous                 const std::vector<StaticGatewayData>& ipv6GatewayData) mutable {
22351abe55efSEd Tanous             if (!success)
22361abe55efSEd Tanous             {
2237588c3f0dSKowalski, Kamil                 // ... otherwise return error
2238bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2239bf648f77SEd Tanous                 // existing object, and other errors
2240002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2241002d39b4SEd Tanous                                            ifaceId);
2242588c3f0dSKowalski, Kamil                 return;
2243588c3f0dSKowalski, Kamil             }
2244588c3f0dSKowalski, Kamil 
2245002d39b4SEd Tanous             handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2246002d39b4SEd Tanous                             asyncResp);
22471f8c7b5dSJohnathan Mantey 
22480627a2c7SEd Tanous             if (hostname)
22491abe55efSEd Tanous             {
22500627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
22511abe55efSEd Tanous             }
22520627a2c7SEd Tanous 
2253b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2254b10d8db0SRavi Teja             {
2255b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2256b10d8db0SRavi Teja                                            asyncResp);
2257b10d8db0SRavi Teja             }
2258b10d8db0SRavi Teja 
2259ab6554f1SJoshi-Mansi             if (fqdn)
2260ab6554f1SJoshi-Mansi             {
22612c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2262ab6554f1SJoshi-Mansi             }
2263ab6554f1SJoshi-Mansi 
2264d577665bSRatan Gupta             if (macAddress)
2265d577665bSRatan Gupta             {
2266002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2267d577665bSRatan Gupta             }
2268d577665bSRatan Gupta 
2269d1d50814SRavi Teja             if (ipv4StaticAddresses)
2270d1d50814SRavi Teja             {
22713dfed536SEd Tanous                 handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ipv4Data,
22723dfed536SEd Tanous                                       asyncResp);
22731abe55efSEd Tanous             }
22740627a2c7SEd Tanous 
2275f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2276f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2277002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2278002d39b4SEd Tanous                                              asyncResp);
2279f85837bfSRAJESWARAN THILLAIGOVINDAN             }
22809a6fc6feSRavi Teja 
22819a6fc6feSRavi Teja             if (ipv6DefaultGateway)
22829a6fc6feSRavi Teja             {
22839a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
22849a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
22859a6fc6feSRavi Teja             }
2286e48c0fc5SRavi Teja 
2287e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2288e48c0fc5SRavi Teja             {
2289ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2290ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2291e48c0fc5SRavi Teja             }
2292eeedda23SJohnathan Mantey 
2293ce73d5c8SSunitha Harish             if (ipv6StaticDefaultGateway)
2294ce73d5c8SSunitha Harish             {
2295ce73d5c8SSunitha Harish                 handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway,
2296ce73d5c8SSunitha Harish                                          ipv6GatewayData, asyncResp);
2297ce73d5c8SSunitha Harish             }
2298ce73d5c8SSunitha Harish 
2299eeedda23SJohnathan Mantey             if (interfaceEnabled)
2300eeedda23SJohnathan Mantey             {
2301d02aad39SEd Tanous                 setDbusProperty(asyncResp, "xyz.openbmc_project.Network",
2302d02aad39SEd Tanous                                 sdbusplus::message::object_path(
2303d02aad39SEd Tanous                                     "/xyz/openbmc_project/network") /
2304d02aad39SEd Tanous                                     ifaceId,
2305d02aad39SEd Tanous                                 "xyz.openbmc_project.Network.EthernetInterface",
2306d02aad39SEd Tanous                                 "NICEnabled", "InterfaceEnabled",
2307d02aad39SEd Tanous                                 *interfaceEnabled);
2308eeedda23SJohnathan Mantey             }
230935fb5311STejas Patil 
231035fb5311STejas Patil             if (mtuSize)
231135fb5311STejas Patil             {
231235fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
231335fb5311STejas Patil             }
2314588c3f0dSKowalski, Kamil         });
2315bf648f77SEd Tanous     });
2316e7caf250SJiaqing Zhao 
2317e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2318e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2319e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2320e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2321e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2322e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2323e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2324e7caf250SJiaqing Zhao         {
2325e7caf250SJiaqing Zhao             return;
2326e7caf250SJiaqing Zhao         }
2327e7caf250SJiaqing Zhao 
2328e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2329e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2330e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2331e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2332e7caf250SJiaqing Zhao         },
2333e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2334e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2335e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2336e7caf250SJiaqing Zhao     });
23374a0cb85cSEd Tanous }
2338bf648f77SEd Tanous 
23399391bb9cSRapkiewicz, Pawel } // namespace redfish
2340