xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision d02aad3988620c648d6e696b67d6c542857f5bfc)
19391bb9cSRapkiewicz, Pawel /*
29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation
39391bb9cSRapkiewicz, Pawel //
49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License");
59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License.
69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at
79391bb9cSRapkiewicz, Pawel //
89391bb9cSRapkiewicz, Pawel //      http://www.apache.org/licenses/LICENSE-2.0
99391bb9cSRapkiewicz, Pawel //
109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software
119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS,
129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and
149391bb9cSRapkiewicz, Pawel // limitations under the License.
159391bb9cSRapkiewicz, Pawel */
169391bb9cSRapkiewicz, Pawel #pragma once
179391bb9cSRapkiewicz, Pawel 
1813451e39SWilly Tu #include "bmcweb_config.h"
1913451e39SWilly Tu 
203ccb3adbSEd Tanous #include "app.hpp"
213ccb3adbSEd Tanous #include "dbus_singleton.hpp"
227a1dbc48SGeorge Liu #include "dbus_utility.hpp"
233ccb3adbSEd Tanous #include "error_messages.hpp"
243ccb3adbSEd Tanous #include "health.hpp"
252c5875a2SEd Tanous #include "human_sort.hpp"
263ccb3adbSEd Tanous #include "query.hpp"
273ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
28033f1e4dSEd Tanous #include "utils/ip_utils.hpp"
293ccb3adbSEd Tanous #include "utils/json_utils.hpp"
30033f1e4dSEd Tanous 
31ce73d5c8SSunitha Harish #include <boost/system/error_code.hpp>
32ef4c65b7SEd Tanous #include <boost/url/format.hpp>
331214b7e7SGunnar Mills 
347a1dbc48SGeorge Liu #include <array>
35ce73d5c8SSunitha Harish #include <memory>
36a24526dcSEd Tanous #include <optional>
373544d2a7SEd Tanous #include <ranges>
38ab6554f1SJoshi-Mansi #include <regex>
397a1dbc48SGeorge Liu #include <string_view>
4077179532SEd Tanous #include <vector>
419391bb9cSRapkiewicz, Pawel 
421abe55efSEd Tanous namespace redfish
431abe55efSEd Tanous {
449391bb9cSRapkiewicz, Pawel 
454a0cb85cSEd Tanous enum class LinkType
464a0cb85cSEd Tanous {
474a0cb85cSEd Tanous     Local,
484a0cb85cSEd Tanous     Global
494a0cb85cSEd Tanous };
509391bb9cSRapkiewicz, Pawel 
519391bb9cSRapkiewicz, Pawel /**
529391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
539391bb9cSRapkiewicz, Pawel  */
541abe55efSEd Tanous struct IPv4AddressData
551abe55efSEd Tanous {
56179db1d7SKowalski, Kamil     std::string id;
574a0cb85cSEd Tanous     std::string address;
584a0cb85cSEd Tanous     std::string domain;
594a0cb85cSEd Tanous     std::string gateway;
609391bb9cSRapkiewicz, Pawel     std::string netmask;
619391bb9cSRapkiewicz, Pawel     std::string origin;
6277179532SEd Tanous     LinkType linktype{};
6377179532SEd Tanous     bool isActive{};
649391bb9cSRapkiewicz, Pawel };
659391bb9cSRapkiewicz, Pawel 
669391bb9cSRapkiewicz, Pawel /**
67e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
68e48c0fc5SRavi Teja  */
69e48c0fc5SRavi Teja struct IPv6AddressData
70e48c0fc5SRavi Teja {
71e48c0fc5SRavi Teja     std::string id;
72e48c0fc5SRavi Teja     std::string address;
73e48c0fc5SRavi Teja     std::string origin;
7477179532SEd Tanous     uint8_t prefixLength = 0;
75e48c0fc5SRavi Teja };
76ce73d5c8SSunitha Harish 
77ce73d5c8SSunitha Harish /**
78ce73d5c8SSunitha Harish  * Structure for keeping static route data required by Redfish
79ce73d5c8SSunitha Harish  */
80ce73d5c8SSunitha Harish struct StaticGatewayData
81ce73d5c8SSunitha Harish {
82ce73d5c8SSunitha Harish     std::string id;
83ce73d5c8SSunitha Harish     std::string gateway;
84ce73d5c8SSunitha Harish     size_t prefixLength = 0;
85ce73d5c8SSunitha Harish     std::string protocol;
86ce73d5c8SSunitha Harish };
87ce73d5c8SSunitha Harish 
88e48c0fc5SRavi Teja /**
899391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
909391bb9cSRapkiewicz, Pawel  * available from DBus
919391bb9cSRapkiewicz, Pawel  */
921abe55efSEd Tanous struct EthernetInterfaceData
931abe55efSEd Tanous {
944a0cb85cSEd Tanous     uint32_t speed;
9535fb5311STejas Patil     size_t mtuSize;
9682695a5bSJiaqing Zhao     bool autoNeg;
97e4588158SJishnu CM     bool dnsv4Enabled;
98e4588158SJishnu CM     bool dnsv6Enabled;
9991c441ecSRavi Teja     bool domainv4Enabled;
10091c441ecSRavi Teja     bool domainv6Enabled;
101e4588158SJishnu CM     bool ntpv4Enabled;
102e4588158SJishnu CM     bool ntpv6Enabled;
103e4588158SJishnu CM     bool hostNamev4Enabled;
104e4588158SJishnu CM     bool hostNamev6Enabled;
105aa05fb27SJohnathan Mantey     bool linkUp;
106eeedda23SJohnathan Mantey     bool nicEnabled;
107b10d8db0SRavi Teja     bool ipv6AcceptRa;
10882695a5bSJiaqing Zhao     std::string dhcpEnabled;
1091f8c7b5dSJohnathan Mantey     std::string operatingMode;
11082695a5bSJiaqing Zhao     std::string hostName;
11182695a5bSJiaqing Zhao     std::string defaultGateway;
11282695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
113ce73d5c8SSunitha Harish     std::string ipv6StaticDefaultGateway;
11482695a5bSJiaqing Zhao     std::string macAddress;
11517e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
1160f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1170f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
118d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1199391bb9cSRapkiewicz, Pawel };
1209391bb9cSRapkiewicz, Pawel 
1211f8c7b5dSJohnathan Mantey struct DHCPParameters
1221f8c7b5dSJohnathan Mantey {
1231f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
12482695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
12582695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
12682695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1271f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1281f8c7b5dSJohnathan Mantey };
1291f8c7b5dSJohnathan Mantey 
1309391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1319391bb9cSRapkiewicz, Pawel // into full dot notation
1321abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1331abe55efSEd Tanous {
1349391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1359391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1369391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1379391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1389391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1399391bb9cSRapkiewicz, Pawel     return netmask;
1409391bb9cSRapkiewicz, Pawel }
1419391bb9cSRapkiewicz, Pawel 
14282695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1431f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1441f8c7b5dSJohnathan Mantey {
1451f8c7b5dSJohnathan Mantey     if (isIPv4)
1461f8c7b5dSJohnathan Mantey     {
1471f8c7b5dSJohnathan Mantey         return (
1481f8c7b5dSJohnathan Mantey             (inputDHCP ==
1491f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1501f8c7b5dSJohnathan Mantey             (inputDHCP ==
1511f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1521f8c7b5dSJohnathan Mantey     }
1531f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1541f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1551f8c7b5dSJohnathan Mantey             (inputDHCP ==
1561f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1571f8c7b5dSJohnathan Mantey }
1581f8c7b5dSJohnathan Mantey 
1592c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1601f8c7b5dSJohnathan Mantey {
1611f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1621f8c7b5dSJohnathan Mantey     {
1631f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1641f8c7b5dSJohnathan Mantey     }
1653174e4dfSEd Tanous     if (isIPv4)
1661f8c7b5dSJohnathan Mantey     {
1671f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1681f8c7b5dSJohnathan Mantey     }
1693174e4dfSEd Tanous     if (isIPv6)
1701f8c7b5dSJohnathan Mantey     {
1711f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1721f8c7b5dSJohnathan Mantey     }
1731f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1741f8c7b5dSJohnathan Mantey }
1751f8c7b5dSJohnathan Mantey 
1764a0cb85cSEd Tanous inline std::string
1774a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1784a0cb85cSEd Tanous                                         bool isIPv4)
1791abe55efSEd Tanous {
1804a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1811abe55efSEd Tanous     {
1824a0cb85cSEd Tanous         return "Static";
1839391bb9cSRapkiewicz, Pawel     }
1844a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1851abe55efSEd Tanous     {
1864a0cb85cSEd Tanous         if (isIPv4)
1871abe55efSEd Tanous         {
1884a0cb85cSEd Tanous             return "IPv4LinkLocal";
1891abe55efSEd Tanous         }
1904a0cb85cSEd Tanous         return "LinkLocal";
1919391bb9cSRapkiewicz, Pawel     }
1924a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1931abe55efSEd Tanous     {
1944a0cb85cSEd Tanous         if (isIPv4)
1954a0cb85cSEd Tanous         {
1964a0cb85cSEd Tanous             return "DHCP";
1974a0cb85cSEd Tanous         }
1984a0cb85cSEd Tanous         return "DHCPv6";
1994a0cb85cSEd Tanous     }
2004a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
2014a0cb85cSEd Tanous     {
2024a0cb85cSEd Tanous         return "SLAAC";
2034a0cb85cSEd Tanous     }
2044a0cb85cSEd Tanous     return "";
2054a0cb85cSEd Tanous }
2064a0cb85cSEd Tanous 
20702cad96eSEd Tanous inline bool extractEthernetInterfaceData(
20802cad96eSEd Tanous     const std::string& ethifaceId,
20902cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
2104a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
2114a0cb85cSEd Tanous {
2124c9afe43SEd Tanous     bool idFound = false;
21302cad96eSEd Tanous     for (const auto& objpath : dbusData)
2144a0cb85cSEd Tanous     {
21502cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
2164a0cb85cSEd Tanous         {
21781ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
218029573d4SEd Tanous             {
2194c9afe43SEd Tanous                 idFound = true;
2204a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2214a0cb85cSEd Tanous                 {
2224a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2234a0cb85cSEd Tanous                     {
2244a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2254a0cb85cSEd Tanous                         {
2264a0cb85cSEd Tanous                             const std::string* mac =
227abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2284a0cb85cSEd Tanous                             if (mac != nullptr)
2294a0cb85cSEd Tanous                             {
23082695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2314a0cb85cSEd Tanous                             }
2324a0cb85cSEd Tanous                         }
2334a0cb85cSEd Tanous                     }
2344a0cb85cSEd Tanous                 }
2354a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2364a0cb85cSEd Tanous                 {
2374a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2384a0cb85cSEd Tanous                     {
2394a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2404a0cb85cSEd Tanous                         {
2411b6b96c5SEd Tanous                             const uint32_t* id =
242abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2434a0cb85cSEd Tanous                             if (id != nullptr)
2444a0cb85cSEd Tanous                             {
24517e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2464a0cb85cSEd Tanous                             }
2474a0cb85cSEd Tanous                         }
2484a0cb85cSEd Tanous                     }
2494a0cb85cSEd Tanous                 }
2504a0cb85cSEd Tanous                 else if (ifacePair.first ==
2514a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2524a0cb85cSEd Tanous                 {
2534a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2544a0cb85cSEd Tanous                     {
2554a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2564a0cb85cSEd Tanous                         {
2572c70f800SEd Tanous                             const bool* autoNeg =
258abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2592c70f800SEd Tanous                             if (autoNeg != nullptr)
2604a0cb85cSEd Tanous                             {
26182695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2624a0cb85cSEd Tanous                             }
2634a0cb85cSEd Tanous                         }
2644a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2654a0cb85cSEd Tanous                         {
2664a0cb85cSEd Tanous                             const uint32_t* speed =
267abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2684a0cb85cSEd Tanous                             if (speed != nullptr)
2694a0cb85cSEd Tanous                             {
2704a0cb85cSEd Tanous                                 ethData.speed = *speed;
2714a0cb85cSEd Tanous                             }
2724a0cb85cSEd Tanous                         }
27335fb5311STejas Patil                         else if (propertyPair.first == "MTU")
27435fb5311STejas Patil                         {
2753e7a8da6SAnthony                             const size_t* mtuSize =
2763e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
27735fb5311STejas Patil                             if (mtuSize != nullptr)
27835fb5311STejas Patil                             {
27935fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
28035fb5311STejas Patil                             }
28135fb5311STejas Patil                         }
282aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
283aa05fb27SJohnathan Mantey                         {
284aa05fb27SJohnathan Mantey                             const bool* linkUp =
285aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
286aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
287aa05fb27SJohnathan Mantey                             {
288aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
289aa05fb27SJohnathan Mantey                             }
290aa05fb27SJohnathan Mantey                         }
291eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
292eeedda23SJohnathan Mantey                         {
293eeedda23SJohnathan Mantey                             const bool* nicEnabled =
294eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
295eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
296eeedda23SJohnathan Mantey                             {
297eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
298eeedda23SJohnathan Mantey                             }
299eeedda23SJohnathan Mantey                         }
300b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
301b10d8db0SRavi Teja                         {
302b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
303b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
304b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
305b10d8db0SRavi Teja                             {
306b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
307b10d8db0SRavi Teja                             }
308b10d8db0SRavi Teja                         }
309f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
310029573d4SEd Tanous                         {
311029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
3128d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
313029573d4SEd Tanous                                     &propertyPair.second);
314029573d4SEd Tanous                             if (nameservers != nullptr)
315029573d4SEd Tanous                             {
316f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3170f6efdc1Smanojkiran.eda@gmail.com                             }
3180f6efdc1Smanojkiran.eda@gmail.com                         }
3190f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3200f6efdc1Smanojkiran.eda@gmail.com                         {
3210f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3228d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3230f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3240f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3250f6efdc1Smanojkiran.eda@gmail.com                             {
326f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3274a0cb85cSEd Tanous                             }
3284a0cb85cSEd Tanous                         }
3292a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3302a133282Smanojkiraneda                         {
3312c70f800SEd Tanous                             const std::string* dhcpEnabled =
3321f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3332c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3342a133282Smanojkiraneda                             {
33582695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3362a133282Smanojkiraneda                             }
3372a133282Smanojkiraneda                         }
338d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
339d24bfc7aSJennifer Lee                         {
340d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3418d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
342d24bfc7aSJennifer Lee                                     &propertyPair.second);
343d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
344d24bfc7aSJennifer Lee                             {
345f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
346d24bfc7aSJennifer Lee                             }
347d24bfc7aSJennifer Lee                         }
3489010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3499010ec2eSRavi Teja                         {
3509010ec2eSRavi Teja                             const std::string* defaultGateway =
3519010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3529010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3539010ec2eSRavi Teja                             {
3549010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3559010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3569010ec2eSRavi Teja                                 {
35782695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3589010ec2eSRavi Teja                                 }
3599010ec2eSRavi Teja                                 else
3609010ec2eSRavi Teja                                 {
36182695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3629010ec2eSRavi Teja                                 }
3639010ec2eSRavi Teja                             }
3649010ec2eSRavi Teja                         }
3659010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3669010ec2eSRavi Teja                         {
3679010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3689010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3699010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3709010ec2eSRavi Teja                             {
3719010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3729010ec2eSRavi Teja                                     *defaultGateway6;
3739010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3749010ec2eSRavi Teja                                 {
37582695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3769010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3779010ec2eSRavi Teja                                 }
3789010ec2eSRavi Teja                                 else
3799010ec2eSRavi Teja                                 {
38082695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3819010ec2eSRavi Teja                                         defaultGateway6Str;
3829010ec2eSRavi Teja                                 }
3839010ec2eSRavi Teja                             }
3849010ec2eSRavi Teja                         }
385029573d4SEd Tanous                     }
386029573d4SEd Tanous                 }
387029573d4SEd Tanous             }
3881f8c7b5dSJohnathan Mantey 
389e4588158SJishnu CM             sdbusplus::message::object_path path(
390e4588158SJishnu CM                 "/xyz/openbmc_project/network");
391e4588158SJishnu CM             sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
392e4588158SJishnu CM                                                         "dhcp4";
393e4588158SJishnu CM 
394e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
3951f8c7b5dSJohnathan Mantey             {
3961f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
3971f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
3981f8c7b5dSJohnathan Mantey                 {
3991f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
4001f8c7b5dSJohnathan Mantey                     {
4011f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
4021f8c7b5dSJohnathan Mantey                         {
4032c70f800SEd Tanous                             const bool* dnsEnabled =
4041f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4052c70f800SEd Tanous                             if (dnsEnabled != nullptr)
4061f8c7b5dSJohnathan Mantey                             {
407e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
4081f8c7b5dSJohnathan Mantey                             }
4091f8c7b5dSJohnathan Mantey                         }
41091c441ecSRavi Teja                         else if (propertyPair.first == "DomainEnabled")
41191c441ecSRavi Teja                         {
41291c441ecSRavi Teja                             const bool* domainEnabled =
41391c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
41491c441ecSRavi Teja                             if (domainEnabled != nullptr)
41591c441ecSRavi Teja                             {
41691c441ecSRavi Teja                                 ethData.domainv4Enabled = *domainEnabled;
41791c441ecSRavi Teja                             }
41891c441ecSRavi Teja                         }
4191f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
4201f8c7b5dSJohnathan Mantey                         {
4212c70f800SEd Tanous                             const bool* ntpEnabled =
4221f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4232c70f800SEd Tanous                             if (ntpEnabled != nullptr)
4241f8c7b5dSJohnathan Mantey                             {
425e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4261f8c7b5dSJohnathan Mantey                             }
4271f8c7b5dSJohnathan Mantey                         }
4281f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4291f8c7b5dSJohnathan Mantey                         {
4302c70f800SEd Tanous                             const bool* hostNameEnabled =
4311f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4322c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4331f8c7b5dSJohnathan Mantey                             {
434e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
435e4588158SJishnu CM                             }
436e4588158SJishnu CM                         }
437e4588158SJishnu CM                     }
438e4588158SJishnu CM                 }
439e4588158SJishnu CM             }
440e4588158SJishnu CM 
441e4588158SJishnu CM             sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
442e4588158SJishnu CM                                                         "dhcp6";
443e4588158SJishnu CM 
444e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
445e4588158SJishnu CM             {
446e4588158SJishnu CM                 if (ifacePair.first ==
447e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
448e4588158SJishnu CM                 {
449e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
450e4588158SJishnu CM                     {
451e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
452e4588158SJishnu CM                         {
453e4588158SJishnu CM                             const bool* dnsEnabled =
454e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
455e4588158SJishnu CM                             if (dnsEnabled != nullptr)
456e4588158SJishnu CM                             {
457e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
458e4588158SJishnu CM                             }
459e4588158SJishnu CM                         }
46091c441ecSRavi Teja                         if (propertyPair.first == "DomainEnabled")
46191c441ecSRavi Teja                         {
46291c441ecSRavi Teja                             const bool* domainEnabled =
46391c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
46491c441ecSRavi Teja                             if (domainEnabled != nullptr)
46591c441ecSRavi Teja                             {
46691c441ecSRavi Teja                                 ethData.domainv6Enabled = *domainEnabled;
46791c441ecSRavi Teja                             }
46891c441ecSRavi Teja                         }
469e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
470e4588158SJishnu CM                         {
471e4588158SJishnu CM                             const bool* ntpEnabled =
472e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
473e4588158SJishnu CM                             if (ntpEnabled != nullptr)
474e4588158SJishnu CM                             {
475e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
476e4588158SJishnu CM                             }
477e4588158SJishnu CM                         }
478e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
479e4588158SJishnu CM                         {
480e4588158SJishnu CM                             const bool* hostNameEnabled =
481e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
482e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
483e4588158SJishnu CM                             {
484e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
4851f8c7b5dSJohnathan Mantey                             }
4861f8c7b5dSJohnathan Mantey                         }
4871f8c7b5dSJohnathan Mantey                     }
4881f8c7b5dSJohnathan Mantey                 }
4891f8c7b5dSJohnathan Mantey             }
490029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
491029573d4SEd Tanous             // to check eth number
492029573d4SEd Tanous             if (ifacePair.first ==
4934a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4944a0cb85cSEd Tanous             {
4954a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
4964a0cb85cSEd Tanous                 {
4974a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
4984a0cb85cSEd Tanous                     {
4994a0cb85cSEd Tanous                         const std::string* hostname =
5008d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
5014a0cb85cSEd Tanous                         if (hostname != nullptr)
5024a0cb85cSEd Tanous                         {
50382695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
5044a0cb85cSEd Tanous                         }
5054a0cb85cSEd Tanous                     }
5064a0cb85cSEd Tanous                 }
5074a0cb85cSEd Tanous             }
5084a0cb85cSEd Tanous         }
5094a0cb85cSEd Tanous     }
5104c9afe43SEd Tanous     return idFound;
5114a0cb85cSEd Tanous }
5124a0cb85cSEd Tanous 
513e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
51477179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
515711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
51677179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
517e48c0fc5SRavi Teja {
51889492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
51989492a15SPatrick Williams                                     ethifaceId;
520e48c0fc5SRavi Teja 
521e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
522e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
52381ce609eSEd Tanous     for (const auto& objpath : dbusData)
524e48c0fc5SRavi Teja     {
525e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
526353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
527e48c0fc5SRavi Teja         {
5289eb808c1SEd Tanous             for (const auto& interface : objpath.second)
529e48c0fc5SRavi Teja             {
530e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
531e48c0fc5SRavi Teja                 {
5323544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
533353163e9STony Lee                                                      [](const auto& property) {
534353163e9STony Lee                         return property.first == "Type";
535353163e9STony Lee                     });
536353163e9STony Lee                     if (type == interface.second.end())
537353163e9STony Lee                     {
538353163e9STony Lee                         continue;
539353163e9STony Lee                     }
540353163e9STony Lee 
541353163e9STony Lee                     const std::string* typeStr =
542353163e9STony Lee                         std::get_if<std::string>(&type->second);
543353163e9STony Lee 
544353163e9STony Lee                     if (typeStr == nullptr ||
545353163e9STony Lee                         (*typeStr !=
546353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
547353163e9STony Lee                     {
548353163e9STony Lee                         continue;
549353163e9STony Lee                     }
550353163e9STony Lee 
551e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
552e48c0fc5SRavi Teja                     // appropriate
55377179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5542c70f800SEd Tanous                     ipv6Address.id =
555353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5569eb808c1SEd Tanous                     for (const auto& property : interface.second)
557e48c0fc5SRavi Teja                     {
558e48c0fc5SRavi Teja                         if (property.first == "Address")
559e48c0fc5SRavi Teja                         {
560e48c0fc5SRavi Teja                             const std::string* address =
561e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
562e48c0fc5SRavi Teja                             if (address != nullptr)
563e48c0fc5SRavi Teja                             {
5642c70f800SEd Tanous                                 ipv6Address.address = *address;
565e48c0fc5SRavi Teja                             }
566e48c0fc5SRavi Teja                         }
567e48c0fc5SRavi Teja                         else if (property.first == "Origin")
568e48c0fc5SRavi Teja                         {
569e48c0fc5SRavi Teja                             const std::string* origin =
570e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
571e48c0fc5SRavi Teja                             if (origin != nullptr)
572e48c0fc5SRavi Teja                             {
5732c70f800SEd Tanous                                 ipv6Address.origin =
574e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
575e48c0fc5SRavi Teja                                                                         false);
576e48c0fc5SRavi Teja                             }
577e48c0fc5SRavi Teja                         }
578e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
579e48c0fc5SRavi Teja                         {
580e48c0fc5SRavi Teja                             const uint8_t* prefix =
581e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
582e48c0fc5SRavi Teja                             if (prefix != nullptr)
583e48c0fc5SRavi Teja                             {
5842c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
585e48c0fc5SRavi Teja                             }
586e48c0fc5SRavi Teja                         }
587889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
588889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
589889ff694SAsmitha Karunanithi                         {
590889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
591889ff694SAsmitha Karunanithi                         }
592e48c0fc5SRavi Teja                         else
593e48c0fc5SRavi Teja                         {
59462598e31SEd Tanous                             BMCWEB_LOG_ERROR(
59562598e31SEd Tanous                                 "Got extra property: {} on the {} object",
59662598e31SEd Tanous                                 property.first, objpath.first.str);
597e48c0fc5SRavi Teja                         }
598e48c0fc5SRavi Teja                     }
599e48c0fc5SRavi Teja                 }
600e48c0fc5SRavi Teja             }
601e48c0fc5SRavi Teja         }
602e48c0fc5SRavi Teja     }
603e48c0fc5SRavi Teja }
604e48c0fc5SRavi Teja 
6054a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
60677179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
607711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
60877179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
6094a0cb85cSEd Tanous {
61089492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
61189492a15SPatrick Williams                                     ethifaceId;
6124a0cb85cSEd Tanous 
6134a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
6144a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
61581ce609eSEd Tanous     for (const auto& objpath : dbusData)
6164a0cb85cSEd Tanous     {
6174a0cb85cSEd Tanous         // Check if proper pattern for object path appears
618353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
6194a0cb85cSEd Tanous         {
6209eb808c1SEd Tanous             for (const auto& interface : objpath.second)
6214a0cb85cSEd Tanous             {
6224a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
6234a0cb85cSEd Tanous                 {
6243544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
625353163e9STony Lee                                                      [](const auto& property) {
626353163e9STony Lee                         return property.first == "Type";
627353163e9STony Lee                     });
628353163e9STony Lee                     if (type == interface.second.end())
629353163e9STony Lee                     {
630353163e9STony Lee                         continue;
631353163e9STony Lee                     }
632353163e9STony Lee 
633353163e9STony Lee                     const std::string* typeStr =
634353163e9STony Lee                         std::get_if<std::string>(&type->second);
635353163e9STony Lee 
636353163e9STony Lee                     if (typeStr == nullptr ||
637353163e9STony Lee                         (*typeStr !=
638353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
639353163e9STony Lee                     {
640353163e9STony Lee                         continue;
641353163e9STony Lee                     }
642353163e9STony Lee 
6434a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6444a0cb85cSEd Tanous                     // appropriate
64577179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6462c70f800SEd Tanous                     ipv4Address.id =
647353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6489eb808c1SEd Tanous                     for (const auto& property : interface.second)
6494a0cb85cSEd Tanous                     {
6504a0cb85cSEd Tanous                         if (property.first == "Address")
6514a0cb85cSEd Tanous                         {
6524a0cb85cSEd Tanous                             const std::string* address =
653abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6544a0cb85cSEd Tanous                             if (address != nullptr)
6554a0cb85cSEd Tanous                             {
6562c70f800SEd Tanous                                 ipv4Address.address = *address;
6574a0cb85cSEd Tanous                             }
6584a0cb85cSEd Tanous                         }
6594a0cb85cSEd Tanous                         else if (property.first == "Origin")
6604a0cb85cSEd Tanous                         {
6614a0cb85cSEd Tanous                             const std::string* origin =
662abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6634a0cb85cSEd Tanous                             if (origin != nullptr)
6644a0cb85cSEd Tanous                             {
6652c70f800SEd Tanous                                 ipv4Address.origin =
6664a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6674a0cb85cSEd Tanous                                                                         true);
6684a0cb85cSEd Tanous                             }
6694a0cb85cSEd Tanous                         }
6704a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6714a0cb85cSEd Tanous                         {
6724a0cb85cSEd Tanous                             const uint8_t* mask =
673abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6744a0cb85cSEd Tanous                             if (mask != nullptr)
6754a0cb85cSEd Tanous                             {
6764a0cb85cSEd Tanous                                 // convert it to the string
6772c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6784a0cb85cSEd Tanous                             }
6794a0cb85cSEd Tanous                         }
680889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
681889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
682889ff694SAsmitha Karunanithi                         {
683889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
684889ff694SAsmitha Karunanithi                         }
6854a0cb85cSEd Tanous                         else
6864a0cb85cSEd Tanous                         {
68762598e31SEd Tanous                             BMCWEB_LOG_ERROR(
68862598e31SEd Tanous                                 "Got extra property: {} on the {} object",
68962598e31SEd Tanous                                 property.first, objpath.first.str);
6904a0cb85cSEd Tanous                         }
6914a0cb85cSEd Tanous                     }
6924a0cb85cSEd Tanous                     // Check if given address is local, or global
6932c70f800SEd Tanous                     ipv4Address.linktype =
69411ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
69518659d10SJohnathan Mantey                             ? LinkType::Local
69618659d10SJohnathan Mantey                             : LinkType::Global;
6974a0cb85cSEd Tanous                 }
6984a0cb85cSEd Tanous             }
6994a0cb85cSEd Tanous         }
7004a0cb85cSEd Tanous     }
7014a0cb85cSEd Tanous }
702588c3f0dSKowalski, Kamil 
703588c3f0dSKowalski, Kamil /**
70401784826SJohnathan Mantey  * @brief Deletes given IPv4 interface
705179db1d7SKowalski, Kamil  *
706179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
707179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
708179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
709179db1d7SKowalski, Kamil  *
710179db1d7SKowalski, Kamil  * @return None
711179db1d7SKowalski, Kamil  */
7129c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
7139c5e585cSRavi Teja                             const std::string& ipHash,
7148d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7151abe55efSEd Tanous {
71655c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7175e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
7181abe55efSEd Tanous         if (ec)
7191abe55efSEd Tanous         {
720a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7211abe55efSEd Tanous         }
722179db1d7SKowalski, Kamil     },
723179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
7249c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
725179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
726179db1d7SKowalski, Kamil }
727179db1d7SKowalski, Kamil 
728244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway(
729244b6d5bSGunnar Mills     const std::string& ifaceId, const std::string& gateway,
730244b6d5bSGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7319010ec2eSRavi Teja {
732*d02aad39SEd Tanous     setDbusProperty(
733*d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
734*d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
735*d02aad39SEd Tanous             ifaceId,
7369ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
737*d02aad39SEd Tanous         "Gateway", gateway);
7389010ec2eSRavi Teja }
739179db1d7SKowalski, Kamil /**
74001784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
741179db1d7SKowalski, Kamil  *
74201784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
74301784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
74401784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
74501784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
746179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
747179db1d7SKowalski, Kamil  *
748179db1d7SKowalski, Kamil  * @return None
749179db1d7SKowalski, Kamil  */
750cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
751cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7528d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7531abe55efSEd Tanous {
7545a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
7555a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
7561abe55efSEd Tanous         if (ec)
7571abe55efSEd Tanous         {
758a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7599010ec2eSRavi Teja             return;
760179db1d7SKowalski, Kamil         }
7619010ec2eSRavi Teja         updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
7629010ec2eSRavi Teja     };
7639010ec2eSRavi Teja 
7649010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7659010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
766179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
767179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
76801784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
769179db1d7SKowalski, Kamil         gateway);
770179db1d7SKowalski, Kamil }
771e48c0fc5SRavi Teja 
772e48c0fc5SRavi Teja /**
77301784826SJohnathan Mantey  * @brief Deletes the IPv6 entry for this interface and creates a replacement
77401784826SJohnathan Mantey  * static IPv6 entry
77501784826SJohnathan Mantey  *
77601784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv6 entry
77701784826SJohnathan Mantey  * @param[in] id           The unique hash entry identifying the DBus entry
77801784826SJohnathan Mantey  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
77901784826SJohnathan Mantey  * @param[in] address      IPv6 address to assign to this interface
78001784826SJohnathan Mantey  * @param[io] asyncResp    Response object that will be returned to client
78101784826SJohnathan Mantey  *
78201784826SJohnathan Mantey  * @return None
78301784826SJohnathan Mantey  */
7849c5e585cSRavi Teja 
7859c5e585cSRavi Teja enum class IpVersion
7869c5e585cSRavi Teja {
7879c5e585cSRavi Teja     IpV4,
7889c5e585cSRavi Teja     IpV6
7899c5e585cSRavi Teja };
7909c5e585cSRavi Teja 
7919c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
7929c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
7938d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
7949c5e585cSRavi Teja     const std::string& gateway,
7958d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
79601784826SJohnathan Mantey {
79701784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
7989c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
7999c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
80001784826SJohnathan Mantey         if (ec)
80101784826SJohnathan Mantey         {
80201784826SJohnathan Mantey             messages::internalError(asyncResp->res);
80301784826SJohnathan Mantey         }
8049c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
8059c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
80601784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
8075e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
80823a21a1cSEd Tanous             if (ec2)
80901784826SJohnathan Mantey             {
81001784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
81101784826SJohnathan Mantey             }
81201784826SJohnathan Mantey         },
81301784826SJohnathan Mantey             "xyz.openbmc_project.Network",
81401784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
8159c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
8169c5e585cSRavi Teja             prefixLength, gateway);
81701784826SJohnathan Mantey     },
81801784826SJohnathan Mantey         "xyz.openbmc_project.Network",
8199c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
82001784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
82101784826SJohnathan Mantey }
82201784826SJohnathan Mantey 
823ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData(
824ce73d5c8SSunitha Harish     const std::string& ethifaceId,
825ce73d5c8SSunitha Harish     const dbus::utility::ManagedObjectType& dbusData,
826ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>& staticGatewayConfig)
827ce73d5c8SSunitha Harish {
828ce73d5c8SSunitha Harish     std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
829ce73d5c8SSunitha Harish     staticGatewayPathStart += ethifaceId;
830ce73d5c8SSunitha Harish 
831ce73d5c8SSunitha Harish     for (const auto& objpath : dbusData)
832ce73d5c8SSunitha Harish     {
833ce73d5c8SSunitha Harish         if (!std::string_view(objpath.first.str)
834ce73d5c8SSunitha Harish                  .starts_with(staticGatewayPathStart))
835ce73d5c8SSunitha Harish         {
836ce73d5c8SSunitha Harish             continue;
837ce73d5c8SSunitha Harish         }
838ce73d5c8SSunitha Harish         for (const auto& interface : objpath.second)
839ce73d5c8SSunitha Harish         {
840ce73d5c8SSunitha Harish             if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
841ce73d5c8SSunitha Harish             {
842ce73d5c8SSunitha Harish                 continue;
843ce73d5c8SSunitha Harish             }
844ce73d5c8SSunitha Harish             StaticGatewayData& staticGateway =
845ce73d5c8SSunitha Harish                 staticGatewayConfig.emplace_back();
846ce73d5c8SSunitha Harish             staticGateway.id = objpath.first.filename();
847ce73d5c8SSunitha Harish 
848ce73d5c8SSunitha Harish             bool success = sdbusplus::unpackPropertiesNoThrow(
849ce73d5c8SSunitha Harish                 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
850ce73d5c8SSunitha Harish                 "Gateway", staticGateway.gateway, "PrefixLength",
851ce73d5c8SSunitha Harish                 staticGateway.prefixLength, "ProtocolType",
852ce73d5c8SSunitha Harish                 staticGateway.protocol);
853ce73d5c8SSunitha Harish             if (!success)
854ce73d5c8SSunitha Harish             {
855ce73d5c8SSunitha Harish                 return false;
856ce73d5c8SSunitha Harish             }
857ce73d5c8SSunitha Harish         }
858ce73d5c8SSunitha Harish     }
859ce73d5c8SSunitha Harish     return true;
860ce73d5c8SSunitha Harish }
861ce73d5c8SSunitha Harish 
86201784826SJohnathan Mantey /**
863e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
864e48c0fc5SRavi Teja  *
865e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
866e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
867e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
868e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
869e48c0fc5SRavi Teja  *
870e48c0fc5SRavi Teja  * @return None
871e48c0fc5SRavi Teja  */
87201784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
87301784826SJohnathan Mantey                        const std::string& address,
8748d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
875e48c0fc5SRavi Teja {
876ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
877ce73d5c8SSunitha Harish     path /= ifaceId;
878ce73d5c8SSunitha Harish 
8795a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
8805a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
881e48c0fc5SRavi Teja         if (ec)
882e48c0fc5SRavi Teja         {
883fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
884fc23ef8aSNitin Kumar Kotania             {
885fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
886fc23ef8aSNitin Kumar Kotania                                                    "Address");
887fc23ef8aSNitin Kumar Kotania             }
888fc23ef8aSNitin Kumar Kotania             else
889fc23ef8aSNitin Kumar Kotania             {
890e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
891e48c0fc5SRavi Teja             }
892fc23ef8aSNitin Kumar Kotania         }
893e48c0fc5SRavi Teja     };
894ce73d5c8SSunitha Harish     // Passing null for gateway, as per redfish spec IPv6StaticAddresses
895ce73d5c8SSunitha Harish     // object does not have associated gateway property
896e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
897ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
898e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
899e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
900e48c0fc5SRavi Teja         "");
901e48c0fc5SRavi Teja }
902e48c0fc5SRavi Teja 
903179db1d7SKowalski, Kamil /**
904ce73d5c8SSunitha Harish  * @brief Deletes given IPv6 Static Gateway
905ce73d5c8SSunitha Harish  *
906ce73d5c8SSunitha Harish  * @param[in] ifaceId     Id of interface whose IP should be deleted
907ce73d5c8SSunitha Harish  * @param[in] ipHash      DBus Hash id of IP that should be deleted
908ce73d5c8SSunitha Harish  * @param[io] asyncResp   Response object that will be returned to client
909ce73d5c8SSunitha Harish  *
910ce73d5c8SSunitha Harish  * @return None
911ce73d5c8SSunitha Harish  */
912ce73d5c8SSunitha Harish inline void
913ce73d5c8SSunitha Harish     deleteIPv6Gateway(std::string_view gatewayId,
914ce73d5c8SSunitha Harish                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
915ce73d5c8SSunitha Harish {
916ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
917ce73d5c8SSunitha Harish     path /= gatewayId;
918ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
919ce73d5c8SSunitha Harish         [asyncResp](const boost::system::error_code& ec) {
920ce73d5c8SSunitha Harish         if (ec)
921ce73d5c8SSunitha Harish         {
922ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
923ce73d5c8SSunitha Harish         }
924ce73d5c8SSunitha Harish     },
925ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
926ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
927ce73d5c8SSunitha Harish }
928ce73d5c8SSunitha Harish 
929ce73d5c8SSunitha Harish /**
930ce73d5c8SSunitha Harish  * @brief Creates IPv6 static default gateway with given data
931ce73d5c8SSunitha Harish  *
932ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose IP should be added
933ce73d5c8SSunitha Harish  * @param[in] prefixLength Prefix length that needs to be added
934ce73d5c8SSunitha Harish  * @param[in] gateway      Gateway address that needs to be added
935ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
936ce73d5c8SSunitha Harish  *
937ce73d5c8SSunitha Harish  * @return None
938ce73d5c8SSunitha Harish  */
939ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway(
940ce73d5c8SSunitha Harish     std::string_view ifaceId, size_t prefixLength, std::string_view gateway,
941ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
942ce73d5c8SSunitha Harish {
943ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
944ce73d5c8SSunitha Harish     path /= ifaceId;
945ce73d5c8SSunitha Harish     auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
946ce73d5c8SSunitha Harish         if (ec)
947ce73d5c8SSunitha Harish         {
948ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
949ce73d5c8SSunitha Harish         }
950ce73d5c8SSunitha Harish     };
951ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
952ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
953ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
954ce73d5c8SSunitha Harish         gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
955ce73d5c8SSunitha Harish }
956ce73d5c8SSunitha Harish 
957ce73d5c8SSunitha Harish /**
958ce73d5c8SSunitha Harish  * @brief Deletes the IPv6 default gateway entry for this interface and
959ce73d5c8SSunitha Harish  * creates a replacement IPv6 default gateway entry
960ce73d5c8SSunitha Harish  *
961ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface upon which to create the IPv6
962ce73d5c8SSunitha Harish  * entry
963ce73d5c8SSunitha Harish  * @param[in] gateway      IPv6 gateway to assign to this interface
964ce73d5c8SSunitha Harish  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
965ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
966ce73d5c8SSunitha Harish  *
967ce73d5c8SSunitha Harish  * @return None
968ce73d5c8SSunitha Harish  */
969ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway(
970ce73d5c8SSunitha Harish     std::string_view ifaceId, std::string_view gatewayId,
971ce73d5c8SSunitha Harish     std::string_view gateway, size_t prefixLength,
972ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
973ce73d5c8SSunitha Harish {
974ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
975ce73d5c8SSunitha Harish     path /= gatewayId;
976ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
977ce73d5c8SSunitha Harish         [asyncResp, ifaceId, gateway,
978ce73d5c8SSunitha Harish          prefixLength](const boost::system::error_code& ec) {
979ce73d5c8SSunitha Harish         if (ec)
980ce73d5c8SSunitha Harish         {
981ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
982ce73d5c8SSunitha Harish             return;
983ce73d5c8SSunitha Harish         }
984ce73d5c8SSunitha Harish         createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp);
985ce73d5c8SSunitha Harish     },
986ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
987ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
988ce73d5c8SSunitha Harish }
989ce73d5c8SSunitha Harish 
990ce73d5c8SSunitha Harish /**
991ce73d5c8SSunitha Harish  * @brief Sets IPv6 default gateway with given data
992ce73d5c8SSunitha Harish  *
993ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose gateway should be added
994ce73d5c8SSunitha Harish  * @param[in] input        Contains address that needs to be added
995ce73d5c8SSunitha Harish  * @param[in] staticGatewayData  Current static gateways in the system
996ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
997ce73d5c8SSunitha Harish  *
998ce73d5c8SSunitha Harish  * @return None
999ce73d5c8SSunitha Harish  */
1000ce73d5c8SSunitha Harish 
1001ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway(
1002ce73d5c8SSunitha Harish     const std::string& ifaceId, const nlohmann::json::array_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 
1010ce73d5c8SSunitha Harish     for (const nlohmann::json& thisJson : input)
1011ce73d5c8SSunitha Harish     {
1012ce73d5c8SSunitha Harish         // find the next gateway entry
1013ce73d5c8SSunitha Harish         while (staticGatewayEntry != staticGatewayData.end())
1014ce73d5c8SSunitha Harish         {
1015ce73d5c8SSunitha Harish             if (staticGatewayEntry->protocol ==
1016ce73d5c8SSunitha Harish                 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1017ce73d5c8SSunitha Harish             {
1018ce73d5c8SSunitha Harish                 break;
1019ce73d5c8SSunitha Harish             }
1020ce73d5c8SSunitha Harish             staticGatewayEntry++;
1021ce73d5c8SSunitha Harish         }
1022ce73d5c8SSunitha Harish         std::string pathString = "IPv6StaticDefaultGateways/" +
1023ce73d5c8SSunitha Harish                                  std::to_string(entryIdx);
1024ce73d5c8SSunitha Harish         if (thisJson.is_null())
1025ce73d5c8SSunitha Harish         {
1026ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1027ce73d5c8SSunitha Harish             {
1028ce73d5c8SSunitha Harish                 messages::resourceCannotBeDeleted(asyncResp->res);
1029ce73d5c8SSunitha Harish                 return;
1030ce73d5c8SSunitha Harish             }
1031ce73d5c8SSunitha Harish             deleteIPv6Gateway(staticGatewayEntry->id, asyncResp);
1032ce73d5c8SSunitha Harish             return;
1033ce73d5c8SSunitha Harish         }
1034ce73d5c8SSunitha Harish         if (thisJson.is_object() && thisJson.empty())
1035ce73d5c8SSunitha Harish         {
1036ce73d5c8SSunitha Harish             // Do nothing, but make sure the entry exists.
1037ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1038ce73d5c8SSunitha Harish             {
1039ce73d5c8SSunitha Harish                 messages::propertyValueFormatError(asyncResp->res, thisJson,
1040ce73d5c8SSunitha Harish                                                    pathString);
1041ce73d5c8SSunitha Harish                 return;
1042ce73d5c8SSunitha Harish             }
1043ce73d5c8SSunitha Harish         }
1044ce73d5c8SSunitha Harish         std::optional<std::string> address;
1045ce73d5c8SSunitha Harish         std::optional<size_t> prefixLength;
1046ce73d5c8SSunitha Harish 
1047ce73d5c8SSunitha Harish         nlohmann::json thisJsonCopy = thisJson;
1048ce73d5c8SSunitha Harish         if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1049ce73d5c8SSunitha Harish                                  address, "PrefixLength", prefixLength))
1050ce73d5c8SSunitha Harish         {
1051ce73d5c8SSunitha Harish             return;
1052ce73d5c8SSunitha Harish         }
1053ce73d5c8SSunitha Harish         const std::string* addr = nullptr;
1054ce73d5c8SSunitha Harish         size_t prefix = 0;
1055ce73d5c8SSunitha Harish         if (address)
1056ce73d5c8SSunitha Harish         {
1057ce73d5c8SSunitha Harish             addr = &(*address);
1058ce73d5c8SSunitha Harish         }
1059ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1060ce73d5c8SSunitha Harish         {
1061ce73d5c8SSunitha Harish             addr = &(staticGatewayEntry->gateway);
1062ce73d5c8SSunitha Harish         }
1063ce73d5c8SSunitha Harish         else
1064ce73d5c8SSunitha Harish         {
1065ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res, pathString + "/Address");
1066ce73d5c8SSunitha Harish             return;
1067ce73d5c8SSunitha Harish         }
1068ce73d5c8SSunitha Harish         if (prefixLength)
1069ce73d5c8SSunitha Harish         {
1070ce73d5c8SSunitha Harish             prefix = *prefixLength;
1071ce73d5c8SSunitha Harish         }
1072ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1073ce73d5c8SSunitha Harish         {
1074ce73d5c8SSunitha Harish             prefix = staticGatewayEntry->prefixLength;
1075ce73d5c8SSunitha Harish         }
1076ce73d5c8SSunitha Harish         else
1077ce73d5c8SSunitha Harish         {
1078ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res,
1079ce73d5c8SSunitha Harish                                       pathString + "/PrefixLength");
1080ce73d5c8SSunitha Harish             return;
1081ce73d5c8SSunitha Harish         }
1082ce73d5c8SSunitha Harish         if (staticGatewayEntry != staticGatewayData.end())
1083ce73d5c8SSunitha Harish         {
1084ce73d5c8SSunitha Harish             deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
1085ce73d5c8SSunitha Harish                                               *addr, prefix, asyncResp);
1086ce73d5c8SSunitha Harish             staticGatewayEntry++;
1087ce73d5c8SSunitha Harish         }
1088ce73d5c8SSunitha Harish         else
1089ce73d5c8SSunitha Harish         {
1090ce73d5c8SSunitha Harish             createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp);
1091ce73d5c8SSunitha Harish         }
1092ce73d5c8SSunitha Harish         entryIdx++;
1093ce73d5c8SSunitha Harish     }
1094ce73d5c8SSunitha Harish }
1095ce73d5c8SSunitha Harish 
1096ce73d5c8SSunitha Harish /**
1097179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
1098179db1d7SKowalski, Kamil  * Object
1099179db1d7SKowalski, Kamil  * from EntityManager Network Manager
11004a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
1101179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
1102179db1d7SKowalski, Kamil  * into JSON
1103179db1d7SKowalski, Kamil  */
1104179db1d7SKowalski, Kamil template <typename CallbackFunc>
110581ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
11061abe55efSEd Tanous                           CallbackFunc&& callback)
11071abe55efSEd Tanous {
1108f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1109f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1110f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1111f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
1112f94c4ecfSEd Tanous          callback{std::forward<CallbackFunc>(callback)}](
11138b24275dSEd Tanous             const boost::system::error_code& ec,
111402cad96eSEd Tanous             const dbus::utility::ManagedObjectType& resp) {
111555c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
111677179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
111777179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
1118ce73d5c8SSunitha Harish         std::vector<StaticGatewayData> ipv6GatewayData;
1119179db1d7SKowalski, Kamil 
11208b24275dSEd Tanous         if (ec)
11211abe55efSEd Tanous         {
1122ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1123179db1d7SKowalski, Kamil             return;
1124179db1d7SKowalski, Kamil         }
1125179db1d7SKowalski, Kamil 
1126002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
11274c9afe43SEd Tanous         if (!found)
11284c9afe43SEd Tanous         {
1129ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
11304c9afe43SEd Tanous             return;
11314c9afe43SEd Tanous         }
11324c9afe43SEd Tanous 
11332c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
1134179db1d7SKowalski, Kamil         // Fix global GW
11351abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
11361abe55efSEd Tanous         {
1137c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
1138c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
11399010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
11401abe55efSEd Tanous             {
114182695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
1142179db1d7SKowalski, Kamil             }
1143179db1d7SKowalski, Kamil         }
1144179db1d7SKowalski, Kamil 
11452c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
1146ce73d5c8SSunitha Harish         if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData))
1147ce73d5c8SSunitha Harish         {
1148ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1149ce73d5c8SSunitha Harish         }
11504e0453b1SGunnar Mills         // Finally make a callback with useful data
1151ce73d5c8SSunitha Harish         callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1152f5892d0dSGeorge Liu     });
1153271584abSEd Tanous }
1154179db1d7SKowalski, Kamil 
1155179db1d7SKowalski, Kamil /**
11569391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
11579391bb9cSRapkiewicz, Pawel  * Manager
11581abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
11591abe55efSEd Tanous  * into JSON.
11609391bb9cSRapkiewicz, Pawel  */
11619391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
11621abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
11631abe55efSEd Tanous {
1164f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1165f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1166f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1167f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
11688b24275dSEd Tanous             const boost::system::error_code& ec,
1169f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
11701abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
11711abe55efSEd Tanous         // ethernet interfaces
117277179532SEd Tanous         std::vector<std::string> ifaceList;
11732c70f800SEd Tanous         ifaceList.reserve(resp.size());
11748b24275dSEd Tanous         if (ec)
11751abe55efSEd Tanous         {
11762c70f800SEd Tanous             callback(false, ifaceList);
11779391bb9cSRapkiewicz, Pawel             return;
11789391bb9cSRapkiewicz, Pawel         }
11799391bb9cSRapkiewicz, Pawel 
11809391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
11814a0cb85cSEd Tanous         for (const auto& objpath : resp)
11821abe55efSEd Tanous         {
11839391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
11844a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
11851abe55efSEd Tanous             {
11861abe55efSEd Tanous                 // If interface is
11874a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
11884a0cb85cSEd Tanous                 // what we're looking for.
11899391bb9cSRapkiewicz, Pawel                 if (interface.first ==
11901abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
11911abe55efSEd Tanous                 {
11922dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
11932dfd18efSEd Tanous                     if (ifaceId.empty())
11941abe55efSEd Tanous                     {
11952dfd18efSEd Tanous                         continue;
11969391bb9cSRapkiewicz, Pawel                     }
11972dfd18efSEd Tanous                     // and put it into output vector.
119877179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
11999391bb9cSRapkiewicz, Pawel                 }
12009391bb9cSRapkiewicz, Pawel             }
12019391bb9cSRapkiewicz, Pawel         }
12022c5875a2SEd Tanous 
12033544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
12042c5875a2SEd Tanous 
1205a434f2bdSEd Tanous         // Finally make a callback with useful data
12062c70f800SEd Tanous         callback(true, ifaceList);
1207f5892d0dSGeorge Liu     });
1208271584abSEd Tanous }
12099391bb9cSRapkiewicz, Pawel 
12104f48d5f6SEd Tanous inline void
12114f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
12128d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12131abe55efSEd Tanous {
1214ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
1215ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
1216ab6554f1SJoshi-Mansi     {
1217ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
1218ab6554f1SJoshi-Mansi                                            "HostName");
1219ab6554f1SJoshi-Mansi         return;
1220ab6554f1SJoshi-Mansi     }
1221*d02aad39SEd Tanous     setDbusProperty(
1222*d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1223*d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network/config"),
1224*d02aad39SEd Tanous         "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
1225*d02aad39SEd Tanous         "HostName", hostname);
1226588c3f0dSKowalski, Kamil }
1227588c3f0dSKowalski, Kamil 
12284f48d5f6SEd Tanous inline void
122935fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
123035fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
123135fb5311STejas Patil {
1232*d02aad39SEd Tanous     sdbusplus::message::object_path objPath("/xyz/openbmc_project/network");
1233*d02aad39SEd Tanous     objPath /= ifaceId;
1234*d02aad39SEd Tanous     setDbusProperty(asyncResp, "xyz.openbmc_project.Network", objPath,
1235*d02aad39SEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface", "MTU",
1236*d02aad39SEd Tanous                     "MTUSize", mtuSize);
123735fb5311STejas Patil }
123835fb5311STejas Patil 
123935fb5311STejas Patil inline void
12404f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
1241bf648f77SEd Tanous                           const std::string& domainname,
12428d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1243ab6554f1SJoshi-Mansi {
1244ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
1245*d02aad39SEd Tanous     setDbusProperty(
1246*d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1247*d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1248*d02aad39SEd Tanous             ifaceId,
1249*d02aad39SEd Tanous         "xyz.openbmc_project.Network.EthernetInterface", "DomainName", "FQDN",
1250*d02aad39SEd Tanous         vectorDomainname);
1251ab6554f1SJoshi-Mansi }
1252ab6554f1SJoshi-Mansi 
12534f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1254bf648f77SEd Tanous {
1255bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
12563544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1257bf648f77SEd Tanous     {
1258bf648f77SEd Tanous         return false;
1259bf648f77SEd Tanous     }
1260bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1261bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1262bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1263bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
12644b242749SEd Tanous     const static std::regex pattern(
1265bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1266bf648f77SEd Tanous 
1267bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1268bf648f77SEd Tanous }
1269bf648f77SEd Tanous 
12704f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1271bf648f77SEd Tanous {
1272bf648f77SEd Tanous     // Can have multiple subdomains
1273bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
12744b242749SEd Tanous     const static std::regex pattern(
12750fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1276bf648f77SEd Tanous 
1277bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1278bf648f77SEd Tanous }
1279bf648f77SEd Tanous 
12804f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
12818d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1282ab6554f1SJoshi-Mansi {
1283ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1284ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1285ab6554f1SJoshi-Mansi     {
1286ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1287ab6554f1SJoshi-Mansi         return;
1288ab6554f1SJoshi-Mansi     }
1289ab6554f1SJoshi-Mansi 
1290ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1291ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1292ab6554f1SJoshi-Mansi     {
1293ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1294ab6554f1SJoshi-Mansi         return;
1295ab6554f1SJoshi-Mansi     }
1296ab6554f1SJoshi-Mansi 
1297ab6554f1SJoshi-Mansi     std::string hostname;
1298ab6554f1SJoshi-Mansi     std::string domainname;
1299ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1300ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1301ab6554f1SJoshi-Mansi 
1302ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1303ab6554f1SJoshi-Mansi     {
1304ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1305ab6554f1SJoshi-Mansi         return;
1306ab6554f1SJoshi-Mansi     }
1307ab6554f1SJoshi-Mansi 
1308ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1309ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1310ab6554f1SJoshi-Mansi }
1311ab6554f1SJoshi-Mansi 
13124f48d5f6SEd Tanous inline void
13134f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1314bf648f77SEd Tanous                           const std::string& macAddress,
13158d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1316d577665bSRatan Gupta {
1317*d02aad39SEd Tanous     setDbusProperty(
1318*d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1319*d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1320*d02aad39SEd Tanous             ifaceId,
1321*d02aad39SEd Tanous         "xyz.openbmc_project.Network.MACAddress", "MACAddress", "MACAddress",
1322*d02aad39SEd Tanous         macAddress);
1323d577665bSRatan Gupta }
1324286b9118SJohnathan Mantey 
13254f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
13264f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
13274f48d5f6SEd Tanous                            const bool v6Value,
13288d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1329da131a9aSJennifer Lee {
13302c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
1331*d02aad39SEd Tanous     setDbusProperty(
1332*d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1333*d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1334*d02aad39SEd Tanous             ifaceId,
1335*d02aad39SEd Tanous         "xyz.openbmc_project.Network.EthernetInterface", propertyName, "DHCPv4",
1336*d02aad39SEd Tanous         dhcp);
1337eeedda23SJohnathan Mantey }
1338eeedda23SJohnathan Mantey 
1339e4588158SJishnu CM enum class NetworkType
1340e4588158SJishnu CM {
1341e4588158SJishnu CM     dhcp4,
1342e4588158SJishnu CM     dhcp6
1343e4588158SJishnu CM };
1344e4588158SJishnu CM 
1345e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1346e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1347e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1348da131a9aSJennifer Lee {
134962598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
1350e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1351e4588158SJishnu CM     path /= ethifaceId;
1352e4588158SJishnu CM 
1353e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1354e4588158SJishnu CM     {
1355e4588158SJishnu CM         path /= "dhcp4";
1356e4588158SJishnu CM     }
1357e4588158SJishnu CM     else
1358e4588158SJishnu CM     {
1359e4588158SJishnu CM         path /= "dhcp6";
1360e4588158SJishnu CM     }
1361e4588158SJishnu CM 
13629ae226faSGeorge Liu     sdbusplus::asio::setProperty(
1363e4588158SJishnu CM         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
13649ae226faSGeorge Liu         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
13655e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1366da131a9aSJennifer Lee         if (ec)
1367da131a9aSJennifer Lee         {
136862598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1369da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1370da131a9aSJennifer Lee             return;
1371da131a9aSJennifer Lee         }
13729ae226faSGeorge Liu     });
1373da131a9aSJennifer Lee }
1374d577665bSRatan Gupta 
1375b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1376b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1377b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1378b10d8db0SRavi Teja {
1379b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1380b10d8db0SRavi Teja     path /= ifaceId;
1381b10d8db0SRavi Teja     sdbusplus::asio::setProperty(
1382b10d8db0SRavi Teja         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1383b10d8db0SRavi Teja         "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1384b10d8db0SRavi Teja         ipv6AutoConfigEnabled,
1385b10d8db0SRavi Teja         [asyncResp](const boost::system::error_code& ec) {
1386b10d8db0SRavi Teja         if (ec)
1387b10d8db0SRavi Teja         {
1388b10d8db0SRavi Teja             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1389b10d8db0SRavi Teja             messages::internalError(asyncResp->res);
1390b10d8db0SRavi Teja             return;
1391b10d8db0SRavi Teja         }
1392b10d8db0SRavi Teja         messages::success(asyncResp->res);
1393b10d8db0SRavi Teja     });
1394b10d8db0SRavi Teja }
1395b10d8db0SRavi Teja 
13964f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
13971f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1398f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1399f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
14008d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1401da131a9aSJennifer Lee {
140282695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
140382695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1404da131a9aSJennifer Lee 
14051f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
14061f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
14071f8c7b5dSJohnathan Mantey 
14081f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
14091f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1410da131a9aSJennifer Lee     {
1411b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
14121f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
14131f8c7b5dSJohnathan Mantey         {
1414bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1415bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
14161f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1417da131a9aSJennifer Lee             return;
1418da131a9aSJennifer Lee         }
1419b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
14201f8c7b5dSJohnathan Mantey     }
14211f8c7b5dSJohnathan Mantey     else
1422da131a9aSJennifer Lee     {
14231f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
14241f8c7b5dSJohnathan Mantey     }
14251f8c7b5dSJohnathan Mantey 
1426e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1427e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1428e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
14291f8c7b5dSJohnathan Mantey     {
1430e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
14311f8c7b5dSJohnathan Mantey     }
1432e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
14331f8c7b5dSJohnathan Mantey     {
1434e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
14351f8c7b5dSJohnathan Mantey     }
14361f8c7b5dSJohnathan Mantey 
1437e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1438e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1439e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
14401f8c7b5dSJohnathan Mantey     {
1441e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
14421f8c7b5dSJohnathan Mantey     }
1443e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
14441f8c7b5dSJohnathan Mantey     {
1445e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
14461f8c7b5dSJohnathan Mantey     }
14471f8c7b5dSJohnathan Mantey 
144891c441ecSRavi Teja     bool nextUsev4Domain = ethData.domainv4Enabled;
144991c441ecSRavi Teja     bool nextUsev6Domain = ethData.domainv6Enabled;
1450e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
14511f8c7b5dSJohnathan Mantey     {
1452e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
14531f8c7b5dSJohnathan Mantey     }
1454e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
14551f8c7b5dSJohnathan Mantey     {
1456e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
14571f8c7b5dSJohnathan Mantey     }
14581f8c7b5dSJohnathan Mantey 
145962598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
14601f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
14611f8c7b5dSJohnathan Mantey                    asyncResp);
146262598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1463e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1464e4588158SJishnu CM                   NetworkType::dhcp4);
146562598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1466e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1467e4588158SJishnu CM                   NetworkType::dhcp4);
146891c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled...");
146991c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
1470e4588158SJishnu CM                   NetworkType::dhcp4);
1471e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1472e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1473e4588158SJishnu CM                   NetworkType::dhcp6);
1474e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1475e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1476e4588158SJishnu CM                   NetworkType::dhcp6);
147791c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
147891c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
1479e4588158SJishnu CM                   NetworkType::dhcp6);
1480da131a9aSJennifer Lee }
148101784826SJohnathan Mantey 
148277179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
148377179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
148477179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
148501784826SJohnathan Mantey {
148617a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
148717a897dfSManojkiran Eda         return value.origin == "Static";
148817a897dfSManojkiran Eda     });
148901784826SJohnathan Mantey }
149001784826SJohnathan Mantey 
149177179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
149277179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
149377179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
149401784826SJohnathan Mantey {
149517a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
149617a897dfSManojkiran Eda         return value.origin == "Static";
149717a897dfSManojkiran Eda     });
149801784826SJohnathan Mantey }
149901784826SJohnathan Mantey 
150077179532SEd Tanous inline void
1501ddd70dcaSEd Tanous     handleIPv4StaticPatch(const std::string& ifaceId,
1502ddd70dcaSEd Tanous                           nlohmann::json::array_t& input,
150377179532SEd Tanous                           const std::vector<IPv4AddressData>& ipv4Data,
15048d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
15051abe55efSEd Tanous {
1506ddd70dcaSEd Tanous     if (input.empty())
1507f476acbfSRatan Gupta     {
15082e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1509d1d50814SRavi Teja                                          "IPv4StaticAddresses");
1510f476acbfSRatan Gupta         return;
1511f476acbfSRatan Gupta     }
1512f476acbfSRatan Gupta 
1513271584abSEd Tanous     unsigned entryIdx = 1;
151401784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
151501784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
151601784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
151701784826SJohnathan Mantey     // into the NIC.
151877179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
15192c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
152001784826SJohnathan Mantey 
1521537174c4SEd Tanous     for (nlohmann::json& thisJson : input)
15221abe55efSEd Tanous     {
152389492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
152489492a15SPatrick Williams                                  std::to_string(entryIdx);
1525179db1d7SKowalski, Kamil 
152601784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1527f476acbfSRatan Gupta         {
1528537174c4SEd Tanous             std::optional<std::string> address;
1529537174c4SEd Tanous             std::optional<std::string> subnetMask;
1530537174c4SEd Tanous             std::optional<std::string> gateway;
1531537174c4SEd Tanous 
1532537174c4SEd Tanous             if (!json_util::readJson(thisJson, asyncResp->res, "Address",
15337e27d832SJohnathan Mantey                                      address, "SubnetMask", subnetMask,
15347e27d832SJohnathan Mantey                                      "Gateway", gateway))
1535537174c4SEd Tanous             {
1536f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
153771f52d96SEd Tanous                                                    pathString);
1538537174c4SEd Tanous                 return;
1539179db1d7SKowalski, Kamil             }
1540179db1d7SKowalski, Kamil 
154101784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
154201784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
154301784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
154401784826SJohnathan Mantey             // current request.
1545537174c4SEd Tanous             if (address)
15461abe55efSEd Tanous             {
1547e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
154801784826SJohnathan Mantey                 {
1549bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1550bf648f77SEd Tanous                                                        pathString + "/Address");
1551e01d0c36SEd Tanous                     return;
155201784826SJohnathan Mantey                 }
155301784826SJohnathan Mantey             }
155485ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
155501784826SJohnathan Mantey             {
1556e01d0c36SEd Tanous                 address = (nicIpEntry->address);
155701784826SJohnathan Mantey             }
155801784826SJohnathan Mantey             else
155901784826SJohnathan Mantey             {
156001784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
156101784826SJohnathan Mantey                                           pathString + "/Address");
1562e01d0c36SEd Tanous                 return;
15634a0cb85cSEd Tanous             }
15644a0cb85cSEd Tanous 
1565e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1566537174c4SEd Tanous             if (subnetMask)
15674a0cb85cSEd Tanous             {
1568033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1569033f1e4dSEd Tanous                                                          &prefixLength))
15704a0cb85cSEd Tanous                 {
1571f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1572537174c4SEd Tanous                         asyncResp->res, *subnetMask,
15734a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1574e01d0c36SEd Tanous                     return;
15754a0cb85cSEd Tanous                 }
15764a0cb85cSEd Tanous             }
157785ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
15784a0cb85cSEd Tanous             {
1579033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
158001784826SJohnathan Mantey                                                          &prefixLength))
15814a0cb85cSEd Tanous                 {
158201784826SJohnathan Mantey                     messages::propertyValueFormatError(
158385ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
158401784826SJohnathan Mantey                         pathString + "/SubnetMask");
1585e01d0c36SEd Tanous                     return;
15864a0cb85cSEd Tanous                 }
15874a0cb85cSEd Tanous             }
15881abe55efSEd Tanous             else
15891abe55efSEd Tanous             {
159001784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
159101784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1592e01d0c36SEd Tanous                 return;
159301784826SJohnathan Mantey             }
159401784826SJohnathan Mantey 
159501784826SJohnathan Mantey             if (gateway)
159601784826SJohnathan Mantey             {
1597e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
159801784826SJohnathan Mantey                 {
1599bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1600bf648f77SEd Tanous                                                        pathString + "/Gateway");
1601e01d0c36SEd Tanous                     return;
160201784826SJohnathan Mantey                 }
160301784826SJohnathan Mantey             }
160485ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
160501784826SJohnathan Mantey             {
1606e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
160701784826SJohnathan Mantey             }
160801784826SJohnathan Mantey             else
16091abe55efSEd Tanous             {
1610a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
16114a0cb85cSEd Tanous                                           pathString + "/Gateway");
161201784826SJohnathan Mantey                 return;
16134a0cb85cSEd Tanous             }
16144a0cb85cSEd Tanous 
161585ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
16161abe55efSEd Tanous             {
16179c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
161877eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
161977eb0153SEd Tanous                                          *gateway, asyncResp);
162089492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
162189492a15SPatrick Williams                                                   ipv4Data.cend());
1622588c3f0dSKowalski, Kamil             }
162301784826SJohnathan Mantey             else
162401784826SJohnathan Mantey             {
1625cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1626cb13a392SEd Tanous                            asyncResp);
16274a0cb85cSEd Tanous             }
16284a0cb85cSEd Tanous             entryIdx++;
16294a0cb85cSEd Tanous         }
163001784826SJohnathan Mantey         else
163101784826SJohnathan Mantey         {
163285ffe86aSJiaqing Zhao             if (nicIpEntry == ipv4Data.cend())
163301784826SJohnathan Mantey             {
163401784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
163501784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
163601784826SJohnathan Mantey                 // in error, so bail out.
163701784826SJohnathan Mantey                 if (thisJson.is_null())
163801784826SJohnathan Mantey                 {
163901784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
164001784826SJohnathan Mantey                     return;
164101784826SJohnathan Mantey                 }
1642f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
164371f52d96SEd Tanous                                                    pathString);
164401784826SJohnathan Mantey                 return;
164501784826SJohnathan Mantey             }
164601784826SJohnathan Mantey 
164701784826SJohnathan Mantey             if (thisJson.is_null())
164801784826SJohnathan Mantey             {
16499c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
165001784826SJohnathan Mantey             }
165185ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
165201784826SJohnathan Mantey             {
165389492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
165489492a15SPatrick Williams                                                   ipv4Data.cend());
165501784826SJohnathan Mantey             }
165601784826SJohnathan Mantey             entryIdx++;
165701784826SJohnathan Mantey         }
165801784826SJohnathan Mantey     }
16594a0cb85cSEd Tanous }
16604a0cb85cSEd Tanous 
16614f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1662f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1663f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
16648d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1665f85837bfSRAJESWARAN THILLAIGOVINDAN {
16669ae226faSGeorge Liu     sdbusplus::asio::setProperty(
16679ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
16689ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
16699ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
16709ae226faSGeorge Liu         updatedStaticNameServers,
16715e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1672f85837bfSRAJESWARAN THILLAIGOVINDAN         if (ec)
1673f85837bfSRAJESWARAN THILLAIGOVINDAN         {
1674f85837bfSRAJESWARAN THILLAIGOVINDAN             messages::internalError(asyncResp->res);
1675f85837bfSRAJESWARAN THILLAIGOVINDAN             return;
1676f85837bfSRAJESWARAN THILLAIGOVINDAN         }
16779ae226faSGeorge Liu     });
1678f85837bfSRAJESWARAN THILLAIGOVINDAN }
1679f85837bfSRAJESWARAN THILLAIGOVINDAN 
16804f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
1681ddd70dcaSEd Tanous     const std::string& ifaceId, const nlohmann::json::array_t& input,
168277179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
16838d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1684e48c0fc5SRavi Teja {
1685ddd70dcaSEd Tanous     if (input.empty())
1686e48c0fc5SRavi Teja     {
16872e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1688e48c0fc5SRavi Teja                                          "IPv6StaticAddresses");
1689e48c0fc5SRavi Teja         return;
1690e48c0fc5SRavi Teja     }
1691271584abSEd Tanous     size_t entryIdx = 1;
169277179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
16932c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1694f23b7296SEd Tanous     for (const nlohmann::json& thisJson : input)
1695e48c0fc5SRavi Teja     {
169689492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
169789492a15SPatrick Williams                                  std::to_string(entryIdx);
1698e48c0fc5SRavi Teja 
169901784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1700e48c0fc5SRavi Teja         {
1701e48c0fc5SRavi Teja             std::optional<std::string> address;
1702e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
1703f23b7296SEd Tanous             nlohmann::json thisJsonCopy = thisJson;
1704bf648f77SEd Tanous             if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1705bf648f77SEd Tanous                                      address, "PrefixLength", prefixLength))
1706e48c0fc5SRavi Teja             {
1707f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
170871f52d96SEd Tanous                                                    pathString);
1709e48c0fc5SRavi Teja                 return;
1710e48c0fc5SRavi Teja             }
1711e48c0fc5SRavi Teja 
171201784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
171301784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
171401784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
171501784826SJohnathan Mantey             // current request.
1716d547d8d2SEd Tanous             if (!address)
1717e48c0fc5SRavi Teja             {
1718d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
171901784826SJohnathan Mantey                 {
172001784826SJohnathan Mantey                     messages::propertyMissing(asyncResp->res,
172101784826SJohnathan Mantey                                               pathString + "/Address");
172201784826SJohnathan Mantey                     return;
1723e48c0fc5SRavi Teja                 }
1724d547d8d2SEd Tanous                 address = nicIpEntry->address;
1725d547d8d2SEd Tanous             }
1726e48c0fc5SRavi Teja 
1727d547d8d2SEd Tanous             if (!prefixLength)
1728e48c0fc5SRavi Teja             {
1729d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
1730e48c0fc5SRavi Teja                 {
1731e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1732e48c0fc5SRavi Teja                                               pathString + "/PrefixLength");
173301784826SJohnathan Mantey                     return;
1734e48c0fc5SRavi Teja                 }
1735d547d8d2SEd Tanous                 prefixLength = nicIpEntry->prefixLength;
1736d547d8d2SEd Tanous             }
1737e48c0fc5SRavi Teja 
173885ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1739e48c0fc5SRavi Teja             {
17409c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1741d547d8d2SEd Tanous                                          nicIpEntry->id, *prefixLength,
1742d547d8d2SEd Tanous                                          *address, "", asyncResp);
174389492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
174489492a15SPatrick Williams                                                   ipv6Data.cend());
174501784826SJohnathan Mantey             }
174601784826SJohnathan Mantey             else
174701784826SJohnathan Mantey             {
1748d547d8d2SEd Tanous                 createIPv6(ifaceId, *prefixLength, *address, asyncResp);
1749e48c0fc5SRavi Teja             }
1750e48c0fc5SRavi Teja             entryIdx++;
1751e48c0fc5SRavi Teja         }
175201784826SJohnathan Mantey         else
175301784826SJohnathan Mantey         {
175485ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
175501784826SJohnathan Mantey             {
175601784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
175701784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
175801784826SJohnathan Mantey                 // in error, so bail out.
175901784826SJohnathan Mantey                 if (thisJson.is_null())
176001784826SJohnathan Mantey                 {
176101784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
176201784826SJohnathan Mantey                     return;
176301784826SJohnathan Mantey                 }
1764f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
176571f52d96SEd Tanous                                                    pathString);
176601784826SJohnathan Mantey                 return;
176701784826SJohnathan Mantey             }
176801784826SJohnathan Mantey 
176901784826SJohnathan Mantey             if (thisJson.is_null())
177001784826SJohnathan Mantey             {
17719c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
177201784826SJohnathan Mantey             }
177385ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
177401784826SJohnathan Mantey             {
177589492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
177689492a15SPatrick Williams                                                   ipv6Data.cend());
177701784826SJohnathan Mantey             }
177801784826SJohnathan Mantey             entryIdx++;
177901784826SJohnathan Mantey         }
178001784826SJohnathan Mantey     }
1781e48c0fc5SRavi Teja }
1782e48c0fc5SRavi Teja 
17837857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
17847857cb8dSJiaqing Zhao {
17857857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
17867857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
17877857cb8dSJiaqing Zhao }
17887857cb8dSJiaqing Zhao 
178977179532SEd Tanous inline void
179077179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
179177179532SEd Tanous                        const std::string& ifaceId,
179277179532SEd Tanous                        const EthernetInterfaceData& ethData,
179377179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
1794ce73d5c8SSunitha Harish                        const std::vector<IPv6AddressData>& ipv6Data,
1795ce73d5c8SSunitha Harish                        const std::vector<StaticGatewayData>& ipv6GatewayData)
17964a0cb85cSEd Tanous {
17972c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
179881ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1799ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1800ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
18012c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1802eeedda23SJohnathan Mantey 
180313451e39SWilly Tu     if constexpr (bmcwebEnableHealthPopulate)
180413451e39SWilly Tu     {
180513451e39SWilly Tu         constexpr std::array<std::string_view, 1> inventoryForEthernet = {
180613451e39SWilly Tu             "xyz.openbmc_project.Inventory.Item.Ethernet"};
1807eeedda23SJohnathan Mantey         auto health = std::make_shared<HealthPopulate>(asyncResp);
18087a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
18097a1dbc48SGeorge Liu             "/", 0, inventoryForEthernet,
18107a1dbc48SGeorge Liu             [health](const boost::system::error_code& ec,
1811b9d36b47SEd Tanous                      const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1812eeedda23SJohnathan Mantey             if (ec)
1813029573d4SEd Tanous             {
1814eeedda23SJohnathan Mantey                 return;
1815eeedda23SJohnathan Mantey             }
1816eeedda23SJohnathan Mantey 
1817914e2d5dSEd Tanous             health->inventory = resp;
18187a1dbc48SGeorge Liu         });
1819eeedda23SJohnathan Mantey 
1820eeedda23SJohnathan Mantey         health->populate();
182113451e39SWilly Tu     }
1822eeedda23SJohnathan Mantey 
1823eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1824eeedda23SJohnathan Mantey     {
18250ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
18262c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1827029573d4SEd Tanous     }
1828029573d4SEd Tanous     else
1829029573d4SEd Tanous     {
18302c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
18312c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1832029573d4SEd Tanous     }
1833aa05fb27SJohnathan Mantey 
18342c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
183535fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
183682695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
18372c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
183882695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1839e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1840e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1841e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
18422c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1843b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
18441f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1845e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1846e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1847e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
1848b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1849b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
18502a133282Smanojkiraneda 
185182695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
18524a0cb85cSEd Tanous     {
185382695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1854ab6554f1SJoshi-Mansi 
1855ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1856ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1857ab6554f1SJoshi-Mansi         // FQDN
185882695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1859d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1860d24bfc7aSJennifer Lee         {
18612c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1862d24bfc7aSJennifer Lee         }
18632c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
18644a0cb85cSEd Tanous     }
18654a0cb85cSEd Tanous 
18667857cb8dSJiaqing Zhao     if (ethData.vlanId)
18677857cb8dSJiaqing Zhao     {
18687857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
18697857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
18707857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
18717857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
18727857cb8dSJiaqing Zhao 
18737857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
18747857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
18757857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
18767857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
18777857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
18787857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
18797857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
18807857cb8dSJiaqing Zhao     }
18817857cb8dSJiaqing Zhao     else
18827857cb8dSJiaqing Zhao     {
18837857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
18847857cb8dSJiaqing Zhao     }
18857857cb8dSJiaqing Zhao 
18862c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
18872c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
18884a0cb85cSEd Tanous 
18892c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
18902c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
18912c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
18922c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
18939eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
18944a0cb85cSEd Tanous     {
18952c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1896fa5053a6SGunnar Mills         if (gatewayStr.empty())
1897fa5053a6SGunnar Mills         {
1898fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1899fa5053a6SGunnar Mills         }
19001476687dSEd Tanous         nlohmann::json::object_t ipv4;
19011476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
19021476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
19031476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
19041476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1905fa5053a6SGunnar Mills 
19062c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1907d1d50814SRavi Teja         {
19081476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1909d1d50814SRavi Teja         }
19101476687dSEd Tanous 
1911b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
191201784826SJohnathan Mantey     }
1913d1d50814SRavi Teja 
191482695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
19157ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
19167ea79e5eSRavi Teja     {
19177ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
19187ea79e5eSRavi Teja     }
19197ea79e5eSRavi Teja 
19207ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1921e48c0fc5SRavi Teja 
1922ce73d5c8SSunitha Harish     nlohmann::json::array_t ipv6StaticGatewayArray;
1923ce73d5c8SSunitha Harish     for (const auto& ipv6GatewayConfig : ipv6GatewayData)
1924ce73d5c8SSunitha Harish     {
1925ce73d5c8SSunitha Harish         nlohmann::json::object_t ipv6Gateway;
1926ce73d5c8SSunitha Harish         ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
1927ce73d5c8SSunitha Harish         ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength;
1928ce73d5c8SSunitha Harish         ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
1929ce73d5c8SSunitha Harish     }
1930ce73d5c8SSunitha Harish     jsonResponse["IPv6StaticDefaultGateways"] =
1931ce73d5c8SSunitha Harish         std::move(ipv6StaticGatewayArray);
1932ce73d5c8SSunitha Harish 
19332c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
19342c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
19352c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
19362c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
19377f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
19382c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
19397f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
19409eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1941e48c0fc5SRavi Teja     {
19421476687dSEd Tanous         nlohmann::json::object_t ipv6;
19431476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
19441476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
19451476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1946f8361275SSunitha Harish 
1947b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
19482c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1949e48c0fc5SRavi Teja         {
19501476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
19511476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
19521476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1953b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
195401784826SJohnathan Mantey         }
1955e48c0fc5SRavi Teja     }
1956588c3f0dSKowalski, Kamil }
1957588c3f0dSKowalski, Kamil 
1958e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1959e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1960e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1961e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1962e7caf250SJiaqing Zhao {
1963e7caf250SJiaqing Zhao     if (!ec)
1964e7caf250SJiaqing Zhao     {
1965e7caf250SJiaqing Zhao         return;
1966e7caf250SJiaqing Zhao     }
1967e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
1968e7caf250SJiaqing Zhao     if (dbusError == nullptr)
1969e7caf250SJiaqing Zhao     {
1970e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
1971e7caf250SJiaqing Zhao         return;
1972e7caf250SJiaqing Zhao     }
197362598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1974e7caf250SJiaqing Zhao 
1975e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1976e7caf250SJiaqing Zhao         dbusError->name)
1977e7caf250SJiaqing Zhao     {
1978e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1979e7caf250SJiaqing Zhao                                    ifaceId);
1980e7caf250SJiaqing Zhao         return;
1981e7caf250SJiaqing Zhao     }
1982e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1983e7caf250SJiaqing Zhao         dbusError->name)
1984e7caf250SJiaqing Zhao     {
1985e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
1986e7caf250SJiaqing Zhao         return;
1987e7caf250SJiaqing Zhao     }
1988e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
1989e7caf250SJiaqing Zhao }
1990e7caf250SJiaqing Zhao 
1991b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1992b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
1993b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
1994b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
1995b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
1996b5ca3fdcSJiaqing Zhao 
1997b5ca3fdcSJiaqing Zhao )
1998b5ca3fdcSJiaqing Zhao {
1999b5ca3fdcSJiaqing Zhao     if (ec)
2000b5ca3fdcSJiaqing Zhao     {
2001b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
2002b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
2003b5ca3fdcSJiaqing Zhao         {
2004b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
2005b5ca3fdcSJiaqing Zhao             return;
2006b5ca3fdcSJiaqing Zhao         }
200762598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2008b5ca3fdcSJiaqing Zhao 
2009b5ca3fdcSJiaqing Zhao         if (std::string_view(
2010b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
2011b5ca3fdcSJiaqing Zhao             dbusError->name)
2012b5ca3fdcSJiaqing Zhao         {
2013b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2014b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2015b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2016b5ca3fdcSJiaqing Zhao             return;
2017b5ca3fdcSJiaqing Zhao         }
2018b5ca3fdcSJiaqing Zhao         if (std::string_view(
2019b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
2020b5ca3fdcSJiaqing Zhao             dbusError->name)
2021b5ca3fdcSJiaqing Zhao         {
2022b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
2023b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
2024b5ca3fdcSJiaqing Zhao             return;
2025b5ca3fdcSJiaqing Zhao         }
2026b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
2027b5ca3fdcSJiaqing Zhao         return;
2028b5ca3fdcSJiaqing Zhao     }
2029b5ca3fdcSJiaqing Zhao 
2030b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
2031b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
2032b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
2033b5ca3fdcSJiaqing Zhao }
2034b5ca3fdcSJiaqing Zhao 
2035bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
2036bf648f77SEd Tanous {
2037bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2038ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
20391476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
20401476687dSEd Tanous             [&app](const crow::Request& req,
20411476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
20423ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
204345ca1b86SEd Tanous         {
204445ca1b86SEd Tanous             return;
204545ca1b86SEd Tanous         }
204645ca1b86SEd Tanous 
2047bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2048bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2049bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2050bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
2051bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
2052bf648f77SEd Tanous             "Ethernet Network Interface Collection";
2053bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
2054bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
2055bf648f77SEd Tanous 
2056bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
2057bf648f77SEd Tanous         // preparation
2058002d39b4SEd Tanous         getEthernetIfaceList(
205977179532SEd Tanous             [asyncResp](const bool& success,
206077179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
2061bf648f77SEd Tanous             if (!success)
20621abe55efSEd Tanous             {
2063f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
20649391bb9cSRapkiewicz, Pawel                 return;
20659391bb9cSRapkiewicz, Pawel             }
20669391bb9cSRapkiewicz, Pawel 
2067002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2068bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
2069bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
2070bf648f77SEd Tanous             {
20711476687dSEd Tanous                 nlohmann::json::object_t iface;
2072ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
2073ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
2074ef4c65b7SEd Tanous                     ifaceItem);
20757857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
2076bf648f77SEd Tanous             }
2077bf648f77SEd Tanous 
2078002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
2079bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2080bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
2081bf648f77SEd Tanous         });
2082bf648f77SEd Tanous     });
2083bf648f77SEd Tanous 
2084b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2085b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
2086b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
2087b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
2088b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2089b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2090b5ca3fdcSJiaqing Zhao         {
2091b5ca3fdcSJiaqing Zhao             return;
2092b5ca3fdcSJiaqing Zhao         }
2093b5ca3fdcSJiaqing Zhao 
2094b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
2095b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
2096b5ca3fdcSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
2097b5ca3fdcSJiaqing Zhao 
2098b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
2099b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
2100b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
2101b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
2102b5ca3fdcSJiaqing Zhao         {
2103b5ca3fdcSJiaqing Zhao             return;
2104b5ca3fdcSJiaqing Zhao         }
2105b5ca3fdcSJiaqing Zhao 
2106b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
2107b5ca3fdcSJiaqing Zhao         {
2108b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
2109b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
2110b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
2111b5ca3fdcSJiaqing Zhao             return;
2112b5ca3fdcSJiaqing Zhao         }
2113b5ca3fdcSJiaqing Zhao 
2114b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
2115b5ca3fdcSJiaqing Zhao         if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
2116b5ca3fdcSJiaqing Zhao                                  "@odata.id", parentInterfaceUri))
2117b5ca3fdcSJiaqing Zhao         {
2118b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
2119b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
2120b5ca3fdcSJiaqing Zhao             return;
2121b5ca3fdcSJiaqing Zhao         }
212262598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
2123b5ca3fdcSJiaqing Zhao 
21246fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
2125b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
2126b5ca3fdcSJiaqing Zhao         if (!parsedUri)
2127b5ca3fdcSJiaqing Zhao         {
2128b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
2129b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2130b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2131b5ca3fdcSJiaqing Zhao             return;
2132b5ca3fdcSJiaqing Zhao         }
2133b5ca3fdcSJiaqing Zhao 
2134b5ca3fdcSJiaqing Zhao         std::string parentInterface;
2135b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
2136b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
2137b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
2138b5ca3fdcSJiaqing Zhao         {
2139b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2140b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2141b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2142b5ca3fdcSJiaqing Zhao             return;
2143b5ca3fdcSJiaqing Zhao         }
2144b5ca3fdcSJiaqing Zhao 
2145b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
2146b5ca3fdcSJiaqing Zhao         {
2147b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
2148b5ca3fdcSJiaqing Zhao             // create
2149b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
2150b5ca3fdcSJiaqing Zhao                                              "false");
2151b5ca3fdcSJiaqing Zhao             return;
2152b5ca3fdcSJiaqing Zhao         }
2153b5ca3fdcSJiaqing Zhao 
2154b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
2155b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
2156b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
2157b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
2158b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
2159b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
2160b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
2161b5ca3fdcSJiaqing Zhao                             m);
2162b5ca3fdcSJiaqing Zhao         },
2163b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
2164b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
2165b5ca3fdcSJiaqing Zhao             vlanId);
2166b5ca3fdcSJiaqing Zhao     });
2167b5ca3fdcSJiaqing Zhao 
2168bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2169ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
2170bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
217145ca1b86SEd Tanous             [&app](const crow::Request& req,
2172bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2173bf648f77SEd Tanous                    const std::string& ifaceId) {
21743ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
217545ca1b86SEd Tanous         {
217645ca1b86SEd Tanous             return;
217745ca1b86SEd Tanous         }
21784a0cb85cSEd Tanous         getEthernetIfaceData(
2179bf648f77SEd Tanous             ifaceId,
2180ce73d5c8SSunitha Harish             [asyncResp,
2181ce73d5c8SSunitha Harish              ifaceId](const bool& success, const EthernetInterfaceData& ethData,
218277179532SEd Tanous                       const std::vector<IPv4AddressData>& ipv4Data,
2183ce73d5c8SSunitha Harish                       const std::vector<IPv6AddressData>& ipv6Data,
2184ce73d5c8SSunitha Harish                       const std::vector<StaticGatewayData>& ipv6GatewayData) {
21854a0cb85cSEd Tanous             if (!success)
21861abe55efSEd Tanous             {
2187bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2188bf648f77SEd Tanous                 // existing object, and other errors
2189002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2190002d39b4SEd Tanous                                            ifaceId);
21914a0cb85cSEd Tanous                 return;
21929391bb9cSRapkiewicz, Pawel             }
21934c9afe43SEd Tanous 
21940f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
219593bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
2196002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
21970f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
21980f74e643SEd Tanous                 "Management Network Interface";
21990f74e643SEd Tanous 
2200ce73d5c8SSunitha Harish             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data,
2201ce73d5c8SSunitha Harish                                ipv6GatewayData);
22029391bb9cSRapkiewicz, Pawel         });
2203bf648f77SEd Tanous     });
22049391bb9cSRapkiewicz, Pawel 
2205bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2206ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2207bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
220845ca1b86SEd Tanous             [&app](const crow::Request& req,
2209bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2210bf648f77SEd Tanous                    const std::string& ifaceId) {
22113ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
221245ca1b86SEd Tanous         {
221345ca1b86SEd Tanous             return;
221445ca1b86SEd Tanous         }
2215bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2216ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2217d577665bSRatan Gupta         std::optional<std::string> macAddress;
22189a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
2219ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
2220ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
2221ce73d5c8SSunitha Harish         std::optional<nlohmann::json::array_t> ipv6StaticDefaultGateways;
2222f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2223da131a9aSJennifer Lee         std::optional<nlohmann::json> dhcpv4;
22241f8c7b5dSJohnathan Mantey         std::optional<nlohmann::json> dhcpv6;
2225b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2226eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
222735fb5311STejas Patil         std::optional<size_t> mtuSize;
22281f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
22291f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2230b10d8db0SRavi Teja         // clang-format off
223115ed6780SWilly Tu         if (!json_util::readJsonPatch(
2232b10d8db0SRavi Teja                 req, asyncResp->res,
2233b10d8db0SRavi Teja                 "DHCPv4", dhcpv4,
2234b10d8db0SRavi Teja                 "DHCPv6", dhcpv6,
2235b10d8db0SRavi Teja                 "FQDN", fqdn,
2236b10d8db0SRavi Teja                 "HostName", hostname,
2237b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2238b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2239b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2240ce73d5c8SSunitha Harish                 "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways,
2241b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2242b10d8db0SRavi Teja                 "MACAddress", macAddress,
2243b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2244b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2245b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2246b10d8db0SRavi Teja                 )
2247b10d8db0SRavi Teja             )
22481abe55efSEd Tanous         {
2249588c3f0dSKowalski, Kamil             return;
2250588c3f0dSKowalski, Kamil         }
2251b10d8db0SRavi Teja         // clang-format on
2252da131a9aSJennifer Lee         if (dhcpv4)
2253da131a9aSJennifer Lee         {
2254002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
22551f8c7b5dSJohnathan Mantey                                      v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
225682695a5bSJiaqing Zhao                                      v4dhcpParms.useDnsServers, "UseNTPServers",
225782695a5bSJiaqing Zhao                                      v4dhcpParms.useNtpServers, "UseDomainName",
225882695a5bSJiaqing Zhao                                      v4dhcpParms.useDomainName))
22591f8c7b5dSJohnathan Mantey             {
22601f8c7b5dSJohnathan Mantey                 return;
22611f8c7b5dSJohnathan Mantey             }
22621f8c7b5dSJohnathan Mantey         }
22631f8c7b5dSJohnathan Mantey 
22641f8c7b5dSJohnathan Mantey         if (dhcpv6)
22651f8c7b5dSJohnathan Mantey         {
2266002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2267002d39b4SEd Tanous                                      v6dhcpParms.dhcpv6OperatingMode,
2268002d39b4SEd Tanous                                      "UseDNSServers", v6dhcpParms.useDnsServers,
2269002d39b4SEd Tanous                                      "UseNTPServers", v6dhcpParms.useNtpServers,
2270002d39b4SEd Tanous                                      "UseDomainName",
227182695a5bSJiaqing Zhao                                      v6dhcpParms.useDomainName))
22721f8c7b5dSJohnathan Mantey             {
22731f8c7b5dSJohnathan Mantey                 return;
22741f8c7b5dSJohnathan Mantey             }
2275da131a9aSJennifer Lee         }
2276da131a9aSJennifer Lee 
2277bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2278bf648f77SEd Tanous         // for JSON preparation
22794a0cb85cSEd Tanous         getEthernetIfaceData(
22802c70f800SEd Tanous             ifaceId,
2281bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2282ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2283d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
22849a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2285e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2286ce73d5c8SSunitha Harish              ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways),
22871f8c7b5dSJohnathan Mantey              staticNameServers = std::move(staticNameServers),
2288bc20089aSEd Tanous              dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
2289b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2290f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2291002d39b4SEd Tanous                 const bool& success, const EthernetInterfaceData& ethData,
229277179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
2293ce73d5c8SSunitha Harish                 const std::vector<IPv6AddressData>& ipv6Data,
2294ce73d5c8SSunitha Harish                 const std::vector<StaticGatewayData>& ipv6GatewayData) {
22951abe55efSEd Tanous             if (!success)
22961abe55efSEd Tanous             {
2297588c3f0dSKowalski, Kamil                 // ... otherwise return error
2298bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2299bf648f77SEd Tanous                 // existing object, and other errors
2300002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2301002d39b4SEd Tanous                                            ifaceId);
2302588c3f0dSKowalski, Kamil                 return;
2303588c3f0dSKowalski, Kamil             }
2304588c3f0dSKowalski, Kamil 
23051f8c7b5dSJohnathan Mantey             if (dhcpv4 || dhcpv6)
23061f8c7b5dSJohnathan Mantey             {
2307002d39b4SEd Tanous                 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2308002d39b4SEd Tanous                                 asyncResp);
23091f8c7b5dSJohnathan Mantey             }
23101f8c7b5dSJohnathan Mantey 
23110627a2c7SEd Tanous             if (hostname)
23121abe55efSEd Tanous             {
23130627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
23141abe55efSEd Tanous             }
23150627a2c7SEd Tanous 
2316b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2317b10d8db0SRavi Teja             {
2318b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2319b10d8db0SRavi Teja                                            asyncResp);
2320b10d8db0SRavi Teja             }
2321b10d8db0SRavi Teja 
2322ab6554f1SJoshi-Mansi             if (fqdn)
2323ab6554f1SJoshi-Mansi             {
23242c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2325ab6554f1SJoshi-Mansi             }
2326ab6554f1SJoshi-Mansi 
2327d577665bSRatan Gupta             if (macAddress)
2328d577665bSRatan Gupta             {
2329002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2330d577665bSRatan Gupta             }
2331d577665bSRatan Gupta 
2332d1d50814SRavi Teja             if (ipv4StaticAddresses)
2333d1d50814SRavi Teja             {
2334bf648f77SEd Tanous                 // TODO(ed) for some reason the capture of
2335bf648f77SEd Tanous                 // ipv4Addresses above is returning a const value,
2336bf648f77SEd Tanous                 // not a non-const value. This doesn't really work
2337bf648f77SEd Tanous                 // for us, as we need to be able to efficiently move
2338bf648f77SEd Tanous                 // out the intermedia nlohmann::json objects. This
2339bf648f77SEd Tanous                 // makes a copy of the structure, and operates on
2340bf648f77SEd Tanous                 // that, but could be done more efficiently
2341ddd70dcaSEd Tanous                 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
2342002d39b4SEd Tanous                 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
23431abe55efSEd Tanous             }
23440627a2c7SEd Tanous 
2345f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2346f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2347002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2348002d39b4SEd Tanous                                              asyncResp);
2349f85837bfSRAJESWARAN THILLAIGOVINDAN             }
23509a6fc6feSRavi Teja 
23519a6fc6feSRavi Teja             if (ipv6DefaultGateway)
23529a6fc6feSRavi Teja             {
23539a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
23549a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
23559a6fc6feSRavi Teja             }
2356e48c0fc5SRavi Teja 
2357e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2358e48c0fc5SRavi Teja             {
2359ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2360ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2361e48c0fc5SRavi Teja             }
2362eeedda23SJohnathan Mantey 
2363ce73d5c8SSunitha Harish             if (ipv6StaticDefaultGateway)
2364ce73d5c8SSunitha Harish             {
2365ce73d5c8SSunitha Harish                 handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway,
2366ce73d5c8SSunitha Harish                                          ipv6GatewayData, asyncResp);
2367ce73d5c8SSunitha Harish             }
2368ce73d5c8SSunitha Harish 
2369eeedda23SJohnathan Mantey             if (interfaceEnabled)
2370eeedda23SJohnathan Mantey             {
2371*d02aad39SEd Tanous                 setDbusProperty(asyncResp, "xyz.openbmc_project.Network",
2372*d02aad39SEd Tanous                                 sdbusplus::message::object_path(
2373*d02aad39SEd Tanous                                     "/xyz/openbmc_project/network") /
2374*d02aad39SEd Tanous                                     ifaceId,
2375*d02aad39SEd Tanous                                 "xyz.openbmc_project.Network.EthernetInterface",
2376*d02aad39SEd Tanous                                 "NICEnabled", "InterfaceEnabled",
2377*d02aad39SEd Tanous                                 *interfaceEnabled);
2378eeedda23SJohnathan Mantey             }
237935fb5311STejas Patil 
238035fb5311STejas Patil             if (mtuSize)
238135fb5311STejas Patil             {
238235fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
238335fb5311STejas Patil             }
2384588c3f0dSKowalski, Kamil         });
2385bf648f77SEd Tanous     });
2386e7caf250SJiaqing Zhao 
2387e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2388e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2389e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2390e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2391e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2392e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2393e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2394e7caf250SJiaqing Zhao         {
2395e7caf250SJiaqing Zhao             return;
2396e7caf250SJiaqing Zhao         }
2397e7caf250SJiaqing Zhao 
2398e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2399e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2400e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2401e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2402e7caf250SJiaqing Zhao         },
2403e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2404e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2405e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2406e7caf250SJiaqing Zhao     });
24074a0cb85cSEd Tanous }
2408bf648f77SEd Tanous 
24099391bb9cSRapkiewicz, Pawel } // namespace redfish
2410