xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision 3dfed536df173ea6d37ac93f428b9094b6a736d1)
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>
35*3dfed536SEd Tanous #include <cstddef>
36ce73d5c8SSunitha Harish #include <memory>
37a24526dcSEd Tanous #include <optional>
383544d2a7SEd Tanous #include <ranges>
39ab6554f1SJoshi-Mansi #include <regex>
407a1dbc48SGeorge Liu #include <string_view>
41*3dfed536SEd Tanous #include <variant>
4277179532SEd Tanous #include <vector>
439391bb9cSRapkiewicz, Pawel 
441abe55efSEd Tanous namespace redfish
451abe55efSEd Tanous {
469391bb9cSRapkiewicz, Pawel 
474a0cb85cSEd Tanous enum class LinkType
484a0cb85cSEd Tanous {
494a0cb85cSEd Tanous     Local,
504a0cb85cSEd Tanous     Global
514a0cb85cSEd Tanous };
529391bb9cSRapkiewicz, Pawel 
539391bb9cSRapkiewicz, Pawel /**
549391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
559391bb9cSRapkiewicz, Pawel  */
561abe55efSEd Tanous struct IPv4AddressData
571abe55efSEd Tanous {
58179db1d7SKowalski, Kamil     std::string id;
594a0cb85cSEd Tanous     std::string address;
604a0cb85cSEd Tanous     std::string domain;
614a0cb85cSEd Tanous     std::string gateway;
629391bb9cSRapkiewicz, Pawel     std::string netmask;
639391bb9cSRapkiewicz, Pawel     std::string origin;
6477179532SEd Tanous     LinkType linktype{};
6577179532SEd Tanous     bool isActive{};
669391bb9cSRapkiewicz, Pawel };
679391bb9cSRapkiewicz, Pawel 
689391bb9cSRapkiewicz, Pawel /**
69e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
70e48c0fc5SRavi Teja  */
71e48c0fc5SRavi Teja struct IPv6AddressData
72e48c0fc5SRavi Teja {
73e48c0fc5SRavi Teja     std::string id;
74e48c0fc5SRavi Teja     std::string address;
75e48c0fc5SRavi Teja     std::string origin;
7677179532SEd Tanous     uint8_t prefixLength = 0;
77e48c0fc5SRavi Teja };
78ce73d5c8SSunitha Harish 
79ce73d5c8SSunitha Harish /**
80ce73d5c8SSunitha Harish  * Structure for keeping static route data required by Redfish
81ce73d5c8SSunitha Harish  */
82ce73d5c8SSunitha Harish struct StaticGatewayData
83ce73d5c8SSunitha Harish {
84ce73d5c8SSunitha Harish     std::string id;
85ce73d5c8SSunitha Harish     std::string gateway;
86ce73d5c8SSunitha Harish     size_t prefixLength = 0;
87ce73d5c8SSunitha Harish     std::string protocol;
88ce73d5c8SSunitha Harish };
89ce73d5c8SSunitha Harish 
90e48c0fc5SRavi Teja /**
919391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
929391bb9cSRapkiewicz, Pawel  * available from DBus
939391bb9cSRapkiewicz, Pawel  */
941abe55efSEd Tanous struct EthernetInterfaceData
951abe55efSEd Tanous {
964a0cb85cSEd Tanous     uint32_t speed;
9735fb5311STejas Patil     size_t mtuSize;
9882695a5bSJiaqing Zhao     bool autoNeg;
99e4588158SJishnu CM     bool dnsv4Enabled;
100e4588158SJishnu CM     bool dnsv6Enabled;
10191c441ecSRavi Teja     bool domainv4Enabled;
10291c441ecSRavi Teja     bool domainv6Enabled;
103e4588158SJishnu CM     bool ntpv4Enabled;
104e4588158SJishnu CM     bool ntpv6Enabled;
105e4588158SJishnu CM     bool hostNamev4Enabled;
106e4588158SJishnu CM     bool hostNamev6Enabled;
107aa05fb27SJohnathan Mantey     bool linkUp;
108eeedda23SJohnathan Mantey     bool nicEnabled;
109b10d8db0SRavi Teja     bool ipv6AcceptRa;
11082695a5bSJiaqing Zhao     std::string dhcpEnabled;
1111f8c7b5dSJohnathan Mantey     std::string operatingMode;
11282695a5bSJiaqing Zhao     std::string hostName;
11382695a5bSJiaqing Zhao     std::string defaultGateway;
11482695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
115ce73d5c8SSunitha Harish     std::string ipv6StaticDefaultGateway;
11682695a5bSJiaqing Zhao     std::string macAddress;
11717e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
1180f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1190f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
120d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1219391bb9cSRapkiewicz, Pawel };
1229391bb9cSRapkiewicz, Pawel 
1231f8c7b5dSJohnathan Mantey struct DHCPParameters
1241f8c7b5dSJohnathan Mantey {
1251f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
12682695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
12782695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
12882695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1291f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1301f8c7b5dSJohnathan Mantey };
1311f8c7b5dSJohnathan Mantey 
1329391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1339391bb9cSRapkiewicz, Pawel // into full dot notation
1341abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1351abe55efSEd Tanous {
1369391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1379391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1389391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1399391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1409391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1419391bb9cSRapkiewicz, Pawel     return netmask;
1429391bb9cSRapkiewicz, Pawel }
1439391bb9cSRapkiewicz, Pawel 
14482695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1451f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1461f8c7b5dSJohnathan Mantey {
1471f8c7b5dSJohnathan Mantey     if (isIPv4)
1481f8c7b5dSJohnathan Mantey     {
1491f8c7b5dSJohnathan Mantey         return (
1501f8c7b5dSJohnathan Mantey             (inputDHCP ==
1511f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1521f8c7b5dSJohnathan Mantey             (inputDHCP ==
1531f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1541f8c7b5dSJohnathan Mantey     }
1551f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1561f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1571f8c7b5dSJohnathan Mantey             (inputDHCP ==
1581f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1591f8c7b5dSJohnathan Mantey }
1601f8c7b5dSJohnathan Mantey 
1612c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1621f8c7b5dSJohnathan Mantey {
1631f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1641f8c7b5dSJohnathan Mantey     {
1651f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1661f8c7b5dSJohnathan Mantey     }
1673174e4dfSEd Tanous     if (isIPv4)
1681f8c7b5dSJohnathan Mantey     {
1691f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1701f8c7b5dSJohnathan Mantey     }
1713174e4dfSEd Tanous     if (isIPv6)
1721f8c7b5dSJohnathan Mantey     {
1731f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1741f8c7b5dSJohnathan Mantey     }
1751f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1761f8c7b5dSJohnathan Mantey }
1771f8c7b5dSJohnathan Mantey 
1784a0cb85cSEd Tanous inline std::string
1794a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1804a0cb85cSEd Tanous                                         bool isIPv4)
1811abe55efSEd Tanous {
1824a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1831abe55efSEd Tanous     {
1844a0cb85cSEd Tanous         return "Static";
1859391bb9cSRapkiewicz, Pawel     }
1864a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1871abe55efSEd Tanous     {
1884a0cb85cSEd Tanous         if (isIPv4)
1891abe55efSEd Tanous         {
1904a0cb85cSEd Tanous             return "IPv4LinkLocal";
1911abe55efSEd Tanous         }
1924a0cb85cSEd Tanous         return "LinkLocal";
1939391bb9cSRapkiewicz, Pawel     }
1944a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1951abe55efSEd Tanous     {
1964a0cb85cSEd Tanous         if (isIPv4)
1974a0cb85cSEd Tanous         {
1984a0cb85cSEd Tanous             return "DHCP";
1994a0cb85cSEd Tanous         }
2004a0cb85cSEd Tanous         return "DHCPv6";
2014a0cb85cSEd Tanous     }
2024a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
2034a0cb85cSEd Tanous     {
2044a0cb85cSEd Tanous         return "SLAAC";
2054a0cb85cSEd Tanous     }
2064a0cb85cSEd Tanous     return "";
2074a0cb85cSEd Tanous }
2084a0cb85cSEd Tanous 
20902cad96eSEd Tanous inline bool extractEthernetInterfaceData(
21002cad96eSEd Tanous     const std::string& ethifaceId,
21102cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
2124a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
2134a0cb85cSEd Tanous {
2144c9afe43SEd Tanous     bool idFound = false;
21502cad96eSEd Tanous     for (const auto& objpath : dbusData)
2164a0cb85cSEd Tanous     {
21702cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
2184a0cb85cSEd Tanous         {
21981ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
220029573d4SEd Tanous             {
2214c9afe43SEd Tanous                 idFound = true;
2224a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2234a0cb85cSEd Tanous                 {
2244a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2254a0cb85cSEd Tanous                     {
2264a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2274a0cb85cSEd Tanous                         {
2284a0cb85cSEd Tanous                             const std::string* mac =
229abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2304a0cb85cSEd Tanous                             if (mac != nullptr)
2314a0cb85cSEd Tanous                             {
23282695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2334a0cb85cSEd Tanous                             }
2344a0cb85cSEd Tanous                         }
2354a0cb85cSEd Tanous                     }
2364a0cb85cSEd Tanous                 }
2374a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2384a0cb85cSEd Tanous                 {
2394a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2404a0cb85cSEd Tanous                     {
2414a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2424a0cb85cSEd Tanous                         {
2431b6b96c5SEd Tanous                             const uint32_t* id =
244abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2454a0cb85cSEd Tanous                             if (id != nullptr)
2464a0cb85cSEd Tanous                             {
24717e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2484a0cb85cSEd Tanous                             }
2494a0cb85cSEd Tanous                         }
2504a0cb85cSEd Tanous                     }
2514a0cb85cSEd Tanous                 }
2524a0cb85cSEd Tanous                 else if (ifacePair.first ==
2534a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2544a0cb85cSEd Tanous                 {
2554a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2564a0cb85cSEd Tanous                     {
2574a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2584a0cb85cSEd Tanous                         {
2592c70f800SEd Tanous                             const bool* autoNeg =
260abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2612c70f800SEd Tanous                             if (autoNeg != nullptr)
2624a0cb85cSEd Tanous                             {
26382695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2644a0cb85cSEd Tanous                             }
2654a0cb85cSEd Tanous                         }
2664a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2674a0cb85cSEd Tanous                         {
2684a0cb85cSEd Tanous                             const uint32_t* speed =
269abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2704a0cb85cSEd Tanous                             if (speed != nullptr)
2714a0cb85cSEd Tanous                             {
2724a0cb85cSEd Tanous                                 ethData.speed = *speed;
2734a0cb85cSEd Tanous                             }
2744a0cb85cSEd Tanous                         }
27535fb5311STejas Patil                         else if (propertyPair.first == "MTU")
27635fb5311STejas Patil                         {
2773e7a8da6SAnthony                             const size_t* mtuSize =
2783e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
27935fb5311STejas Patil                             if (mtuSize != nullptr)
28035fb5311STejas Patil                             {
28135fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
28235fb5311STejas Patil                             }
28335fb5311STejas Patil                         }
284aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
285aa05fb27SJohnathan Mantey                         {
286aa05fb27SJohnathan Mantey                             const bool* linkUp =
287aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
288aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
289aa05fb27SJohnathan Mantey                             {
290aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
291aa05fb27SJohnathan Mantey                             }
292aa05fb27SJohnathan Mantey                         }
293eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
294eeedda23SJohnathan Mantey                         {
295eeedda23SJohnathan Mantey                             const bool* nicEnabled =
296eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
297eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
298eeedda23SJohnathan Mantey                             {
299eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
300eeedda23SJohnathan Mantey                             }
301eeedda23SJohnathan Mantey                         }
302b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
303b10d8db0SRavi Teja                         {
304b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
305b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
306b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
307b10d8db0SRavi Teja                             {
308b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
309b10d8db0SRavi Teja                             }
310b10d8db0SRavi Teja                         }
311f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
312029573d4SEd Tanous                         {
313029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
3148d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
315029573d4SEd Tanous                                     &propertyPair.second);
316029573d4SEd Tanous                             if (nameservers != nullptr)
317029573d4SEd Tanous                             {
318f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3190f6efdc1Smanojkiran.eda@gmail.com                             }
3200f6efdc1Smanojkiran.eda@gmail.com                         }
3210f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3220f6efdc1Smanojkiran.eda@gmail.com                         {
3230f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3248d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3250f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3260f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3270f6efdc1Smanojkiran.eda@gmail.com                             {
328f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3294a0cb85cSEd Tanous                             }
3304a0cb85cSEd Tanous                         }
3312a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3322a133282Smanojkiraneda                         {
3332c70f800SEd Tanous                             const std::string* dhcpEnabled =
3341f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3352c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3362a133282Smanojkiraneda                             {
33782695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3382a133282Smanojkiraneda                             }
3392a133282Smanojkiraneda                         }
340d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
341d24bfc7aSJennifer Lee                         {
342d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3438d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
344d24bfc7aSJennifer Lee                                     &propertyPair.second);
345d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
346d24bfc7aSJennifer Lee                             {
347f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
348d24bfc7aSJennifer Lee                             }
349d24bfc7aSJennifer Lee                         }
3509010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3519010ec2eSRavi Teja                         {
3529010ec2eSRavi Teja                             const std::string* defaultGateway =
3539010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3549010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3559010ec2eSRavi Teja                             {
3569010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3579010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3589010ec2eSRavi Teja                                 {
35982695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3609010ec2eSRavi Teja                                 }
3619010ec2eSRavi Teja                                 else
3629010ec2eSRavi Teja                                 {
36382695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3649010ec2eSRavi Teja                                 }
3659010ec2eSRavi Teja                             }
3669010ec2eSRavi Teja                         }
3679010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3689010ec2eSRavi Teja                         {
3699010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3709010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3719010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3729010ec2eSRavi Teja                             {
3739010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3749010ec2eSRavi Teja                                     *defaultGateway6;
3759010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3769010ec2eSRavi Teja                                 {
37782695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3789010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3799010ec2eSRavi Teja                                 }
3809010ec2eSRavi Teja                                 else
3819010ec2eSRavi Teja                                 {
38282695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3839010ec2eSRavi Teja                                         defaultGateway6Str;
3849010ec2eSRavi Teja                                 }
3859010ec2eSRavi Teja                             }
3869010ec2eSRavi Teja                         }
387029573d4SEd Tanous                     }
388029573d4SEd Tanous                 }
389029573d4SEd Tanous             }
3901f8c7b5dSJohnathan Mantey 
391e4588158SJishnu CM             sdbusplus::message::object_path path(
392e4588158SJishnu CM                 "/xyz/openbmc_project/network");
393e4588158SJishnu CM             sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
394e4588158SJishnu CM                                                         "dhcp4";
395e4588158SJishnu CM 
396e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
3971f8c7b5dSJohnathan Mantey             {
3981f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
3991f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
4001f8c7b5dSJohnathan Mantey                 {
4011f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
4021f8c7b5dSJohnathan Mantey                     {
4031f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
4041f8c7b5dSJohnathan Mantey                         {
4052c70f800SEd Tanous                             const bool* dnsEnabled =
4061f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4072c70f800SEd Tanous                             if (dnsEnabled != nullptr)
4081f8c7b5dSJohnathan Mantey                             {
409e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
4101f8c7b5dSJohnathan Mantey                             }
4111f8c7b5dSJohnathan Mantey                         }
41291c441ecSRavi Teja                         else if (propertyPair.first == "DomainEnabled")
41391c441ecSRavi Teja                         {
41491c441ecSRavi Teja                             const bool* domainEnabled =
41591c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
41691c441ecSRavi Teja                             if (domainEnabled != nullptr)
41791c441ecSRavi Teja                             {
41891c441ecSRavi Teja                                 ethData.domainv4Enabled = *domainEnabled;
41991c441ecSRavi Teja                             }
42091c441ecSRavi Teja                         }
4211f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
4221f8c7b5dSJohnathan Mantey                         {
4232c70f800SEd Tanous                             const bool* ntpEnabled =
4241f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4252c70f800SEd Tanous                             if (ntpEnabled != nullptr)
4261f8c7b5dSJohnathan Mantey                             {
427e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4281f8c7b5dSJohnathan Mantey                             }
4291f8c7b5dSJohnathan Mantey                         }
4301f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4311f8c7b5dSJohnathan Mantey                         {
4322c70f800SEd Tanous                             const bool* hostNameEnabled =
4331f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4342c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4351f8c7b5dSJohnathan Mantey                             {
436e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
437e4588158SJishnu CM                             }
438e4588158SJishnu CM                         }
439e4588158SJishnu CM                     }
440e4588158SJishnu CM                 }
441e4588158SJishnu CM             }
442e4588158SJishnu CM 
443e4588158SJishnu CM             sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
444e4588158SJishnu CM                                                         "dhcp6";
445e4588158SJishnu CM 
446e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
447e4588158SJishnu CM             {
448e4588158SJishnu CM                 if (ifacePair.first ==
449e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
450e4588158SJishnu CM                 {
451e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
452e4588158SJishnu CM                     {
453e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
454e4588158SJishnu CM                         {
455e4588158SJishnu CM                             const bool* dnsEnabled =
456e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
457e4588158SJishnu CM                             if (dnsEnabled != nullptr)
458e4588158SJishnu CM                             {
459e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
460e4588158SJishnu CM                             }
461e4588158SJishnu CM                         }
46291c441ecSRavi Teja                         if (propertyPair.first == "DomainEnabled")
46391c441ecSRavi Teja                         {
46491c441ecSRavi Teja                             const bool* domainEnabled =
46591c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
46691c441ecSRavi Teja                             if (domainEnabled != nullptr)
46791c441ecSRavi Teja                             {
46891c441ecSRavi Teja                                 ethData.domainv6Enabled = *domainEnabled;
46991c441ecSRavi Teja                             }
47091c441ecSRavi Teja                         }
471e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
472e4588158SJishnu CM                         {
473e4588158SJishnu CM                             const bool* ntpEnabled =
474e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
475e4588158SJishnu CM                             if (ntpEnabled != nullptr)
476e4588158SJishnu CM                             {
477e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
478e4588158SJishnu CM                             }
479e4588158SJishnu CM                         }
480e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
481e4588158SJishnu CM                         {
482e4588158SJishnu CM                             const bool* hostNameEnabled =
483e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
484e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
485e4588158SJishnu CM                             {
486e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
4871f8c7b5dSJohnathan Mantey                             }
4881f8c7b5dSJohnathan Mantey                         }
4891f8c7b5dSJohnathan Mantey                     }
4901f8c7b5dSJohnathan Mantey                 }
4911f8c7b5dSJohnathan Mantey             }
492029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
493029573d4SEd Tanous             // to check eth number
494029573d4SEd Tanous             if (ifacePair.first ==
4954a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4964a0cb85cSEd Tanous             {
4974a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
4984a0cb85cSEd Tanous                 {
4994a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
5004a0cb85cSEd Tanous                     {
5014a0cb85cSEd Tanous                         const std::string* hostname =
5028d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
5034a0cb85cSEd Tanous                         if (hostname != nullptr)
5044a0cb85cSEd Tanous                         {
50582695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
5064a0cb85cSEd Tanous                         }
5074a0cb85cSEd Tanous                     }
5084a0cb85cSEd Tanous                 }
5094a0cb85cSEd Tanous             }
5104a0cb85cSEd Tanous         }
5114a0cb85cSEd Tanous     }
5124c9afe43SEd Tanous     return idFound;
5134a0cb85cSEd Tanous }
5144a0cb85cSEd Tanous 
515e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
51677179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
517711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
51877179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
519e48c0fc5SRavi Teja {
52089492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
52189492a15SPatrick Williams                                     ethifaceId;
522e48c0fc5SRavi Teja 
523e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
524e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
52581ce609eSEd Tanous     for (const auto& objpath : dbusData)
526e48c0fc5SRavi Teja     {
527e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
528353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
529e48c0fc5SRavi Teja         {
5309eb808c1SEd Tanous             for (const auto& interface : objpath.second)
531e48c0fc5SRavi Teja             {
532e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
533e48c0fc5SRavi Teja                 {
5343544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
535353163e9STony Lee                                                      [](const auto& property) {
536353163e9STony Lee                         return property.first == "Type";
537353163e9STony Lee                     });
538353163e9STony Lee                     if (type == interface.second.end())
539353163e9STony Lee                     {
540353163e9STony Lee                         continue;
541353163e9STony Lee                     }
542353163e9STony Lee 
543353163e9STony Lee                     const std::string* typeStr =
544353163e9STony Lee                         std::get_if<std::string>(&type->second);
545353163e9STony Lee 
546353163e9STony Lee                     if (typeStr == nullptr ||
547353163e9STony Lee                         (*typeStr !=
548353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
549353163e9STony Lee                     {
550353163e9STony Lee                         continue;
551353163e9STony Lee                     }
552353163e9STony Lee 
553e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
554e48c0fc5SRavi Teja                     // appropriate
55577179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5562c70f800SEd Tanous                     ipv6Address.id =
557353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5589eb808c1SEd Tanous                     for (const auto& property : interface.second)
559e48c0fc5SRavi Teja                     {
560e48c0fc5SRavi Teja                         if (property.first == "Address")
561e48c0fc5SRavi Teja                         {
562e48c0fc5SRavi Teja                             const std::string* address =
563e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
564e48c0fc5SRavi Teja                             if (address != nullptr)
565e48c0fc5SRavi Teja                             {
5662c70f800SEd Tanous                                 ipv6Address.address = *address;
567e48c0fc5SRavi Teja                             }
568e48c0fc5SRavi Teja                         }
569e48c0fc5SRavi Teja                         else if (property.first == "Origin")
570e48c0fc5SRavi Teja                         {
571e48c0fc5SRavi Teja                             const std::string* origin =
572e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
573e48c0fc5SRavi Teja                             if (origin != nullptr)
574e48c0fc5SRavi Teja                             {
5752c70f800SEd Tanous                                 ipv6Address.origin =
576e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
577e48c0fc5SRavi Teja                                                                         false);
578e48c0fc5SRavi Teja                             }
579e48c0fc5SRavi Teja                         }
580e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
581e48c0fc5SRavi Teja                         {
582e48c0fc5SRavi Teja                             const uint8_t* prefix =
583e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
584e48c0fc5SRavi Teja                             if (prefix != nullptr)
585e48c0fc5SRavi Teja                             {
5862c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
587e48c0fc5SRavi Teja                             }
588e48c0fc5SRavi Teja                         }
589889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
590889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
591889ff694SAsmitha Karunanithi                         {
592889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
593889ff694SAsmitha Karunanithi                         }
594e48c0fc5SRavi Teja                         else
595e48c0fc5SRavi Teja                         {
59662598e31SEd Tanous                             BMCWEB_LOG_ERROR(
59762598e31SEd Tanous                                 "Got extra property: {} on the {} object",
59862598e31SEd Tanous                                 property.first, objpath.first.str);
599e48c0fc5SRavi Teja                         }
600e48c0fc5SRavi Teja                     }
601e48c0fc5SRavi Teja                 }
602e48c0fc5SRavi Teja             }
603e48c0fc5SRavi Teja         }
604e48c0fc5SRavi Teja     }
605e48c0fc5SRavi Teja }
606e48c0fc5SRavi Teja 
6074a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
60877179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
609711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
61077179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
6114a0cb85cSEd Tanous {
61289492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
61389492a15SPatrick Williams                                     ethifaceId;
6144a0cb85cSEd Tanous 
6154a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
6164a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
61781ce609eSEd Tanous     for (const auto& objpath : dbusData)
6184a0cb85cSEd Tanous     {
6194a0cb85cSEd Tanous         // Check if proper pattern for object path appears
620353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
6214a0cb85cSEd Tanous         {
6229eb808c1SEd Tanous             for (const auto& interface : objpath.second)
6234a0cb85cSEd Tanous             {
6244a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
6254a0cb85cSEd Tanous                 {
6263544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
627353163e9STony Lee                                                      [](const auto& property) {
628353163e9STony Lee                         return property.first == "Type";
629353163e9STony Lee                     });
630353163e9STony Lee                     if (type == interface.second.end())
631353163e9STony Lee                     {
632353163e9STony Lee                         continue;
633353163e9STony Lee                     }
634353163e9STony Lee 
635353163e9STony Lee                     const std::string* typeStr =
636353163e9STony Lee                         std::get_if<std::string>(&type->second);
637353163e9STony Lee 
638353163e9STony Lee                     if (typeStr == nullptr ||
639353163e9STony Lee                         (*typeStr !=
640353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
641353163e9STony Lee                     {
642353163e9STony Lee                         continue;
643353163e9STony Lee                     }
644353163e9STony Lee 
6454a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6464a0cb85cSEd Tanous                     // appropriate
64777179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6482c70f800SEd Tanous                     ipv4Address.id =
649353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6509eb808c1SEd Tanous                     for (const auto& property : interface.second)
6514a0cb85cSEd Tanous                     {
6524a0cb85cSEd Tanous                         if (property.first == "Address")
6534a0cb85cSEd Tanous                         {
6544a0cb85cSEd Tanous                             const std::string* address =
655abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6564a0cb85cSEd Tanous                             if (address != nullptr)
6574a0cb85cSEd Tanous                             {
6582c70f800SEd Tanous                                 ipv4Address.address = *address;
6594a0cb85cSEd Tanous                             }
6604a0cb85cSEd Tanous                         }
6614a0cb85cSEd Tanous                         else if (property.first == "Origin")
6624a0cb85cSEd Tanous                         {
6634a0cb85cSEd Tanous                             const std::string* origin =
664abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6654a0cb85cSEd Tanous                             if (origin != nullptr)
6664a0cb85cSEd Tanous                             {
6672c70f800SEd Tanous                                 ipv4Address.origin =
6684a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6694a0cb85cSEd Tanous                                                                         true);
6704a0cb85cSEd Tanous                             }
6714a0cb85cSEd Tanous                         }
6724a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6734a0cb85cSEd Tanous                         {
6744a0cb85cSEd Tanous                             const uint8_t* mask =
675abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6764a0cb85cSEd Tanous                             if (mask != nullptr)
6774a0cb85cSEd Tanous                             {
6784a0cb85cSEd Tanous                                 // convert it to the string
6792c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6804a0cb85cSEd Tanous                             }
6814a0cb85cSEd Tanous                         }
682889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
683889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
684889ff694SAsmitha Karunanithi                         {
685889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
686889ff694SAsmitha Karunanithi                         }
6874a0cb85cSEd Tanous                         else
6884a0cb85cSEd Tanous                         {
68962598e31SEd Tanous                             BMCWEB_LOG_ERROR(
69062598e31SEd Tanous                                 "Got extra property: {} on the {} object",
69162598e31SEd Tanous                                 property.first, objpath.first.str);
6924a0cb85cSEd Tanous                         }
6934a0cb85cSEd Tanous                     }
6944a0cb85cSEd Tanous                     // Check if given address is local, or global
6952c70f800SEd Tanous                     ipv4Address.linktype =
69611ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
69718659d10SJohnathan Mantey                             ? LinkType::Local
69818659d10SJohnathan Mantey                             : LinkType::Global;
6994a0cb85cSEd Tanous                 }
7004a0cb85cSEd Tanous             }
7014a0cb85cSEd Tanous         }
7024a0cb85cSEd Tanous     }
7034a0cb85cSEd Tanous }
704588c3f0dSKowalski, Kamil 
705588c3f0dSKowalski, Kamil /**
70601784826SJohnathan Mantey  * @brief Deletes given IPv4 interface
707179db1d7SKowalski, Kamil  *
708179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
709179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
710179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
711179db1d7SKowalski, Kamil  *
712179db1d7SKowalski, Kamil  * @return None
713179db1d7SKowalski, Kamil  */
7149c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
7159c5e585cSRavi Teja                             const std::string& ipHash,
7168d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7171abe55efSEd Tanous {
71855c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7195e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
7201abe55efSEd Tanous         if (ec)
7211abe55efSEd Tanous         {
722a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7231abe55efSEd Tanous         }
724179db1d7SKowalski, Kamil     },
725179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
7269c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
727179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
728179db1d7SKowalski, Kamil }
729179db1d7SKowalski, Kamil 
730244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway(
731244b6d5bSGunnar Mills     const std::string& ifaceId, const std::string& gateway,
732244b6d5bSGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7339010ec2eSRavi Teja {
734d02aad39SEd Tanous     setDbusProperty(
735d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
736d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
737d02aad39SEd Tanous             ifaceId,
7389ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
739d02aad39SEd Tanous         "Gateway", gateway);
7409010ec2eSRavi Teja }
741179db1d7SKowalski, Kamil /**
74201784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
743179db1d7SKowalski, Kamil  *
74401784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
74501784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
74601784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
74701784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
748179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
749179db1d7SKowalski, Kamil  *
750179db1d7SKowalski, Kamil  * @return None
751179db1d7SKowalski, Kamil  */
752cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
753cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7548d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7551abe55efSEd Tanous {
7565a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
7575a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
7581abe55efSEd Tanous         if (ec)
7591abe55efSEd Tanous         {
760a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7619010ec2eSRavi Teja             return;
762179db1d7SKowalski, Kamil         }
7639010ec2eSRavi Teja         updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
7649010ec2eSRavi Teja     };
7659010ec2eSRavi Teja 
7669010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7679010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
768179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
769179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
77001784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
771179db1d7SKowalski, Kamil         gateway);
772179db1d7SKowalski, Kamil }
773e48c0fc5SRavi Teja 
774e48c0fc5SRavi Teja /**
77501784826SJohnathan Mantey  * @brief Deletes the IPv6 entry for this interface and creates a replacement
77601784826SJohnathan Mantey  * static IPv6 entry
77701784826SJohnathan Mantey  *
77801784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv6 entry
77901784826SJohnathan Mantey  * @param[in] id           The unique hash entry identifying the DBus entry
78001784826SJohnathan Mantey  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
78101784826SJohnathan Mantey  * @param[in] address      IPv6 address to assign to this interface
78201784826SJohnathan Mantey  * @param[io] asyncResp    Response object that will be returned to client
78301784826SJohnathan Mantey  *
78401784826SJohnathan Mantey  * @return None
78501784826SJohnathan Mantey  */
7869c5e585cSRavi Teja 
7879c5e585cSRavi Teja enum class IpVersion
7889c5e585cSRavi Teja {
7899c5e585cSRavi Teja     IpV4,
7909c5e585cSRavi Teja     IpV6
7919c5e585cSRavi Teja };
7929c5e585cSRavi Teja 
7939c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
7949c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
7958d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
7969c5e585cSRavi Teja     const std::string& gateway,
7978d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
79801784826SJohnathan Mantey {
79901784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
8009c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
8019c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
80201784826SJohnathan Mantey         if (ec)
80301784826SJohnathan Mantey         {
80401784826SJohnathan Mantey             messages::internalError(asyncResp->res);
80501784826SJohnathan Mantey         }
8069c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
8079c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
80801784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
8095e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
81023a21a1cSEd Tanous             if (ec2)
81101784826SJohnathan Mantey             {
81201784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
81301784826SJohnathan Mantey             }
81401784826SJohnathan Mantey         },
81501784826SJohnathan Mantey             "xyz.openbmc_project.Network",
81601784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
8179c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
8189c5e585cSRavi Teja             prefixLength, gateway);
81901784826SJohnathan Mantey     },
82001784826SJohnathan Mantey         "xyz.openbmc_project.Network",
8219c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
82201784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
82301784826SJohnathan Mantey }
82401784826SJohnathan Mantey 
825ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData(
826ce73d5c8SSunitha Harish     const std::string& ethifaceId,
827ce73d5c8SSunitha Harish     const dbus::utility::ManagedObjectType& dbusData,
828ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>& staticGatewayConfig)
829ce73d5c8SSunitha Harish {
830ce73d5c8SSunitha Harish     std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
831ce73d5c8SSunitha Harish     staticGatewayPathStart += ethifaceId;
832ce73d5c8SSunitha Harish 
833ce73d5c8SSunitha Harish     for (const auto& objpath : dbusData)
834ce73d5c8SSunitha Harish     {
835ce73d5c8SSunitha Harish         if (!std::string_view(objpath.first.str)
836ce73d5c8SSunitha Harish                  .starts_with(staticGatewayPathStart))
837ce73d5c8SSunitha Harish         {
838ce73d5c8SSunitha Harish             continue;
839ce73d5c8SSunitha Harish         }
840ce73d5c8SSunitha Harish         for (const auto& interface : objpath.second)
841ce73d5c8SSunitha Harish         {
842ce73d5c8SSunitha Harish             if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
843ce73d5c8SSunitha Harish             {
844ce73d5c8SSunitha Harish                 continue;
845ce73d5c8SSunitha Harish             }
846ce73d5c8SSunitha Harish             StaticGatewayData& staticGateway =
847ce73d5c8SSunitha Harish                 staticGatewayConfig.emplace_back();
848ce73d5c8SSunitha Harish             staticGateway.id = objpath.first.filename();
849ce73d5c8SSunitha Harish 
850ce73d5c8SSunitha Harish             bool success = sdbusplus::unpackPropertiesNoThrow(
851ce73d5c8SSunitha Harish                 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
852ce73d5c8SSunitha Harish                 "Gateway", staticGateway.gateway, "PrefixLength",
853ce73d5c8SSunitha Harish                 staticGateway.prefixLength, "ProtocolType",
854ce73d5c8SSunitha Harish                 staticGateway.protocol);
855ce73d5c8SSunitha Harish             if (!success)
856ce73d5c8SSunitha Harish             {
857ce73d5c8SSunitha Harish                 return false;
858ce73d5c8SSunitha Harish             }
859ce73d5c8SSunitha Harish         }
860ce73d5c8SSunitha Harish     }
861ce73d5c8SSunitha Harish     return true;
862ce73d5c8SSunitha Harish }
863ce73d5c8SSunitha Harish 
86401784826SJohnathan Mantey /**
865e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
866e48c0fc5SRavi Teja  *
867e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
868e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
869e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
870e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
871e48c0fc5SRavi Teja  *
872e48c0fc5SRavi Teja  * @return None
873e48c0fc5SRavi Teja  */
87401784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
87501784826SJohnathan Mantey                        const std::string& address,
8768d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
877e48c0fc5SRavi Teja {
878ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
879ce73d5c8SSunitha Harish     path /= ifaceId;
880ce73d5c8SSunitha Harish 
8815a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
8825a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
883e48c0fc5SRavi Teja         if (ec)
884e48c0fc5SRavi Teja         {
885fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
886fc23ef8aSNitin Kumar Kotania             {
887fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
888fc23ef8aSNitin Kumar Kotania                                                    "Address");
889fc23ef8aSNitin Kumar Kotania             }
890fc23ef8aSNitin Kumar Kotania             else
891fc23ef8aSNitin Kumar Kotania             {
892e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
893e48c0fc5SRavi Teja             }
894fc23ef8aSNitin Kumar Kotania         }
895e48c0fc5SRavi Teja     };
896ce73d5c8SSunitha Harish     // Passing null for gateway, as per redfish spec IPv6StaticAddresses
897ce73d5c8SSunitha Harish     // object does not have associated gateway property
898e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
899ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
900e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
901e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
902e48c0fc5SRavi Teja         "");
903e48c0fc5SRavi Teja }
904e48c0fc5SRavi Teja 
905179db1d7SKowalski, Kamil /**
906ce73d5c8SSunitha Harish  * @brief Deletes given IPv6 Static Gateway
907ce73d5c8SSunitha Harish  *
908ce73d5c8SSunitha Harish  * @param[in] ifaceId     Id of interface whose IP should be deleted
909ce73d5c8SSunitha Harish  * @param[in] ipHash      DBus Hash id of IP that should be deleted
910ce73d5c8SSunitha Harish  * @param[io] asyncResp   Response object that will be returned to client
911ce73d5c8SSunitha Harish  *
912ce73d5c8SSunitha Harish  * @return None
913ce73d5c8SSunitha Harish  */
914ce73d5c8SSunitha Harish inline void
915ce73d5c8SSunitha Harish     deleteIPv6Gateway(std::string_view gatewayId,
916ce73d5c8SSunitha Harish                       const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
917ce73d5c8SSunitha Harish {
918ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
919ce73d5c8SSunitha Harish     path /= gatewayId;
920ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
921ce73d5c8SSunitha Harish         [asyncResp](const boost::system::error_code& ec) {
922ce73d5c8SSunitha Harish         if (ec)
923ce73d5c8SSunitha Harish         {
924ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
925ce73d5c8SSunitha Harish         }
926ce73d5c8SSunitha Harish     },
927ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
928ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
929ce73d5c8SSunitha Harish }
930ce73d5c8SSunitha Harish 
931ce73d5c8SSunitha Harish /**
932ce73d5c8SSunitha Harish  * @brief Creates IPv6 static default gateway with given data
933ce73d5c8SSunitha Harish  *
934ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose IP should be added
935ce73d5c8SSunitha Harish  * @param[in] prefixLength Prefix length that needs to be added
936ce73d5c8SSunitha Harish  * @param[in] gateway      Gateway address that needs to be added
937ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
938ce73d5c8SSunitha Harish  *
939ce73d5c8SSunitha Harish  * @return None
940ce73d5c8SSunitha Harish  */
941ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway(
942ce73d5c8SSunitha Harish     std::string_view ifaceId, size_t prefixLength, std::string_view gateway,
943ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
944ce73d5c8SSunitha Harish {
945ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
946ce73d5c8SSunitha Harish     path /= ifaceId;
947ce73d5c8SSunitha Harish     auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
948ce73d5c8SSunitha Harish         if (ec)
949ce73d5c8SSunitha Harish         {
950ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
951ce73d5c8SSunitha Harish         }
952ce73d5c8SSunitha Harish     };
953ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
954ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
955ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
956ce73d5c8SSunitha Harish         gateway, prefixLength, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
957ce73d5c8SSunitha Harish }
958ce73d5c8SSunitha Harish 
959ce73d5c8SSunitha Harish /**
960ce73d5c8SSunitha Harish  * @brief Deletes the IPv6 default gateway entry for this interface and
961ce73d5c8SSunitha Harish  * creates a replacement IPv6 default gateway entry
962ce73d5c8SSunitha Harish  *
963ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface upon which to create the IPv6
964ce73d5c8SSunitha Harish  * entry
965ce73d5c8SSunitha Harish  * @param[in] gateway      IPv6 gateway to assign to this interface
966ce73d5c8SSunitha Harish  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
967ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
968ce73d5c8SSunitha Harish  *
969ce73d5c8SSunitha Harish  * @return None
970ce73d5c8SSunitha Harish  */
971ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway(
972ce73d5c8SSunitha Harish     std::string_view ifaceId, std::string_view gatewayId,
973ce73d5c8SSunitha Harish     std::string_view gateway, size_t prefixLength,
974ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
975ce73d5c8SSunitha Harish {
976ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
977ce73d5c8SSunitha Harish     path /= gatewayId;
978ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
979ce73d5c8SSunitha Harish         [asyncResp, ifaceId, gateway,
980ce73d5c8SSunitha Harish          prefixLength](const boost::system::error_code& ec) {
981ce73d5c8SSunitha Harish         if (ec)
982ce73d5c8SSunitha Harish         {
983ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
984ce73d5c8SSunitha Harish             return;
985ce73d5c8SSunitha Harish         }
986ce73d5c8SSunitha Harish         createIPv6DefaultGateway(ifaceId, prefixLength, gateway, asyncResp);
987ce73d5c8SSunitha Harish     },
988ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
989ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
990ce73d5c8SSunitha Harish }
991ce73d5c8SSunitha Harish 
992ce73d5c8SSunitha Harish /**
993ce73d5c8SSunitha Harish  * @brief Sets IPv6 default gateway with given data
994ce73d5c8SSunitha Harish  *
995ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose gateway should be added
996ce73d5c8SSunitha Harish  * @param[in] input        Contains address that needs to be added
997ce73d5c8SSunitha Harish  * @param[in] staticGatewayData  Current static gateways in the system
998ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
999ce73d5c8SSunitha Harish  *
1000ce73d5c8SSunitha Harish  * @return None
1001ce73d5c8SSunitha Harish  */
1002ce73d5c8SSunitha Harish 
1003ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway(
1004*3dfed536SEd Tanous     const std::string& ifaceId,
1005*3dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1006ce73d5c8SSunitha Harish     const std::vector<StaticGatewayData>& staticGatewayData,
1007ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1008ce73d5c8SSunitha Harish {
1009ce73d5c8SSunitha Harish     size_t entryIdx = 1;
1010ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>::const_iterator staticGatewayEntry =
1011ce73d5c8SSunitha Harish         staticGatewayData.begin();
1012ce73d5c8SSunitha Harish 
1013*3dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
1014*3dfed536SEd Tanous          input)
1015ce73d5c8SSunitha Harish     {
1016ce73d5c8SSunitha Harish         // find the next gateway entry
1017ce73d5c8SSunitha Harish         while (staticGatewayEntry != staticGatewayData.end())
1018ce73d5c8SSunitha Harish         {
1019ce73d5c8SSunitha Harish             if (staticGatewayEntry->protocol ==
1020ce73d5c8SSunitha Harish                 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1021ce73d5c8SSunitha Harish             {
1022ce73d5c8SSunitha Harish                 break;
1023ce73d5c8SSunitha Harish             }
1024ce73d5c8SSunitha Harish             staticGatewayEntry++;
1025ce73d5c8SSunitha Harish         }
1026ce73d5c8SSunitha Harish         std::string pathString = "IPv6StaticDefaultGateways/" +
1027ce73d5c8SSunitha Harish                                  std::to_string(entryIdx);
1028*3dfed536SEd Tanous         nlohmann::json::object_t* obj =
1029*3dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
1030*3dfed536SEd Tanous         if (obj == nullptr)
1031ce73d5c8SSunitha Harish         {
1032ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1033ce73d5c8SSunitha Harish             {
1034ce73d5c8SSunitha Harish                 messages::resourceCannotBeDeleted(asyncResp->res);
1035ce73d5c8SSunitha Harish                 return;
1036ce73d5c8SSunitha Harish             }
1037ce73d5c8SSunitha Harish             deleteIPv6Gateway(staticGatewayEntry->id, asyncResp);
1038ce73d5c8SSunitha Harish             return;
1039ce73d5c8SSunitha Harish         }
1040*3dfed536SEd Tanous         if (obj->empty())
1041ce73d5c8SSunitha Harish         {
1042ce73d5c8SSunitha Harish             // Do nothing, but make sure the entry exists.
1043ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1044ce73d5c8SSunitha Harish             {
1045*3dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
1046ce73d5c8SSunitha Harish                                                    pathString);
1047ce73d5c8SSunitha Harish                 return;
1048ce73d5c8SSunitha Harish             }
1049ce73d5c8SSunitha Harish         }
1050ce73d5c8SSunitha Harish         std::optional<std::string> address;
1051ce73d5c8SSunitha Harish         std::optional<size_t> prefixLength;
1052ce73d5c8SSunitha Harish 
1053*3dfed536SEd Tanous         if (!json_util::readJsonObject(*obj, asyncResp->res, "Address", address,
1054*3dfed536SEd Tanous                                        "PrefixLength", prefixLength))
1055ce73d5c8SSunitha Harish         {
1056ce73d5c8SSunitha Harish             return;
1057ce73d5c8SSunitha Harish         }
1058ce73d5c8SSunitha Harish         const std::string* addr = nullptr;
1059ce73d5c8SSunitha Harish         size_t prefix = 0;
1060ce73d5c8SSunitha Harish         if (address)
1061ce73d5c8SSunitha Harish         {
1062ce73d5c8SSunitha Harish             addr = &(*address);
1063ce73d5c8SSunitha Harish         }
1064ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1065ce73d5c8SSunitha Harish         {
1066ce73d5c8SSunitha Harish             addr = &(staticGatewayEntry->gateway);
1067ce73d5c8SSunitha Harish         }
1068ce73d5c8SSunitha Harish         else
1069ce73d5c8SSunitha Harish         {
1070ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res, pathString + "/Address");
1071ce73d5c8SSunitha Harish             return;
1072ce73d5c8SSunitha Harish         }
1073ce73d5c8SSunitha Harish         if (prefixLength)
1074ce73d5c8SSunitha Harish         {
1075ce73d5c8SSunitha Harish             prefix = *prefixLength;
1076ce73d5c8SSunitha Harish         }
1077ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1078ce73d5c8SSunitha Harish         {
1079ce73d5c8SSunitha Harish             prefix = staticGatewayEntry->prefixLength;
1080ce73d5c8SSunitha Harish         }
1081ce73d5c8SSunitha Harish         else
1082ce73d5c8SSunitha Harish         {
1083ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res,
1084ce73d5c8SSunitha Harish                                       pathString + "/PrefixLength");
1085ce73d5c8SSunitha Harish             return;
1086ce73d5c8SSunitha Harish         }
1087ce73d5c8SSunitha Harish         if (staticGatewayEntry != staticGatewayData.end())
1088ce73d5c8SSunitha Harish         {
1089ce73d5c8SSunitha Harish             deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
1090ce73d5c8SSunitha Harish                                               *addr, prefix, asyncResp);
1091ce73d5c8SSunitha Harish             staticGatewayEntry++;
1092ce73d5c8SSunitha Harish         }
1093ce73d5c8SSunitha Harish         else
1094ce73d5c8SSunitha Harish         {
1095ce73d5c8SSunitha Harish             createIPv6DefaultGateway(ifaceId, prefix, *addr, asyncResp);
1096ce73d5c8SSunitha Harish         }
1097ce73d5c8SSunitha Harish         entryIdx++;
1098ce73d5c8SSunitha Harish     }
1099ce73d5c8SSunitha Harish }
1100ce73d5c8SSunitha Harish 
1101ce73d5c8SSunitha Harish /**
1102179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
1103179db1d7SKowalski, Kamil  * Object
1104179db1d7SKowalski, Kamil  * from EntityManager Network Manager
11054a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
1106179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
1107179db1d7SKowalski, Kamil  * into JSON
1108179db1d7SKowalski, Kamil  */
1109179db1d7SKowalski, Kamil template <typename CallbackFunc>
111081ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
11111abe55efSEd Tanous                           CallbackFunc&& callback)
11121abe55efSEd Tanous {
1113f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1114f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1115f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1116f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
1117f94c4ecfSEd Tanous          callback{std::forward<CallbackFunc>(callback)}](
11188b24275dSEd Tanous             const boost::system::error_code& ec,
1119*3dfed536SEd Tanous             const dbus::utility::ManagedObjectType& resp) mutable {
112055c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
112177179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
112277179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
1123ce73d5c8SSunitha Harish         std::vector<StaticGatewayData> ipv6GatewayData;
1124179db1d7SKowalski, Kamil 
11258b24275dSEd Tanous         if (ec)
11261abe55efSEd Tanous         {
1127ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1128179db1d7SKowalski, Kamil             return;
1129179db1d7SKowalski, Kamil         }
1130179db1d7SKowalski, Kamil 
1131002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
11324c9afe43SEd Tanous         if (!found)
11334c9afe43SEd Tanous         {
1134ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
11354c9afe43SEd Tanous             return;
11364c9afe43SEd Tanous         }
11374c9afe43SEd Tanous 
11382c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
1139179db1d7SKowalski, Kamil         // Fix global GW
11401abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
11411abe55efSEd Tanous         {
1142c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
1143c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
11449010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
11451abe55efSEd Tanous             {
114682695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
1147179db1d7SKowalski, Kamil             }
1148179db1d7SKowalski, Kamil         }
1149179db1d7SKowalski, Kamil 
11502c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
1151ce73d5c8SSunitha Harish         if (!extractIPv6DefaultGatewayData(ethifaceId, resp, ipv6GatewayData))
1152ce73d5c8SSunitha Harish         {
1153ce73d5c8SSunitha Harish             callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1154ce73d5c8SSunitha Harish         }
11554e0453b1SGunnar Mills         // Finally make a callback with useful data
1156ce73d5c8SSunitha Harish         callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1157f5892d0dSGeorge Liu     });
1158271584abSEd Tanous }
1159179db1d7SKowalski, Kamil 
1160179db1d7SKowalski, Kamil /**
11619391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
11629391bb9cSRapkiewicz, Pawel  * Manager
11631abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
11641abe55efSEd Tanous  * into JSON.
11659391bb9cSRapkiewicz, Pawel  */
11669391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
11671abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
11681abe55efSEd Tanous {
1169f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1170f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1171f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1172f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
11738b24275dSEd Tanous             const boost::system::error_code& ec,
1174f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
11751abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
11761abe55efSEd Tanous         // ethernet interfaces
117777179532SEd Tanous         std::vector<std::string> ifaceList;
11782c70f800SEd Tanous         ifaceList.reserve(resp.size());
11798b24275dSEd Tanous         if (ec)
11801abe55efSEd Tanous         {
11812c70f800SEd Tanous             callback(false, ifaceList);
11829391bb9cSRapkiewicz, Pawel             return;
11839391bb9cSRapkiewicz, Pawel         }
11849391bb9cSRapkiewicz, Pawel 
11859391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
11864a0cb85cSEd Tanous         for (const auto& objpath : resp)
11871abe55efSEd Tanous         {
11889391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
11894a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
11901abe55efSEd Tanous             {
11911abe55efSEd Tanous                 // If interface is
11924a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
11934a0cb85cSEd Tanous                 // what we're looking for.
11949391bb9cSRapkiewicz, Pawel                 if (interface.first ==
11951abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
11961abe55efSEd Tanous                 {
11972dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
11982dfd18efSEd Tanous                     if (ifaceId.empty())
11991abe55efSEd Tanous                     {
12002dfd18efSEd Tanous                         continue;
12019391bb9cSRapkiewicz, Pawel                     }
12022dfd18efSEd Tanous                     // and put it into output vector.
120377179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
12049391bb9cSRapkiewicz, Pawel                 }
12059391bb9cSRapkiewicz, Pawel             }
12069391bb9cSRapkiewicz, Pawel         }
12072c5875a2SEd Tanous 
12083544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
12092c5875a2SEd Tanous 
1210a434f2bdSEd Tanous         // Finally make a callback with useful data
12112c70f800SEd Tanous         callback(true, ifaceList);
1212f5892d0dSGeorge Liu     });
1213271584abSEd Tanous }
12149391bb9cSRapkiewicz, Pawel 
12154f48d5f6SEd Tanous inline void
12164f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
12178d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12181abe55efSEd Tanous {
1219ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
1220ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
1221ab6554f1SJoshi-Mansi     {
1222ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
1223ab6554f1SJoshi-Mansi                                            "HostName");
1224ab6554f1SJoshi-Mansi         return;
1225ab6554f1SJoshi-Mansi     }
1226d02aad39SEd Tanous     setDbusProperty(
1227d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1228d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network/config"),
1229d02aad39SEd Tanous         "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
1230d02aad39SEd Tanous         "HostName", hostname);
1231588c3f0dSKowalski, Kamil }
1232588c3f0dSKowalski, Kamil 
12334f48d5f6SEd Tanous inline void
123435fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
123535fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
123635fb5311STejas Patil {
1237d02aad39SEd Tanous     sdbusplus::message::object_path objPath("/xyz/openbmc_project/network");
1238d02aad39SEd Tanous     objPath /= ifaceId;
1239d02aad39SEd Tanous     setDbusProperty(asyncResp, "xyz.openbmc_project.Network", objPath,
1240d02aad39SEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface", "MTU",
1241d02aad39SEd Tanous                     "MTUSize", mtuSize);
124235fb5311STejas Patil }
124335fb5311STejas Patil 
124435fb5311STejas Patil inline void
12454f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
1246bf648f77SEd Tanous                           const std::string& domainname,
12478d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1248ab6554f1SJoshi-Mansi {
1249ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
1250d02aad39SEd Tanous     setDbusProperty(
1251d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1252d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1253d02aad39SEd Tanous             ifaceId,
1254d02aad39SEd Tanous         "xyz.openbmc_project.Network.EthernetInterface", "DomainName", "FQDN",
1255d02aad39SEd Tanous         vectorDomainname);
1256ab6554f1SJoshi-Mansi }
1257ab6554f1SJoshi-Mansi 
12584f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1259bf648f77SEd Tanous {
1260bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
12613544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1262bf648f77SEd Tanous     {
1263bf648f77SEd Tanous         return false;
1264bf648f77SEd Tanous     }
1265bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1266bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1267bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1268bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
12694b242749SEd Tanous     const static std::regex pattern(
1270bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1271bf648f77SEd Tanous 
1272bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1273bf648f77SEd Tanous }
1274bf648f77SEd Tanous 
12754f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1276bf648f77SEd Tanous {
1277bf648f77SEd Tanous     // Can have multiple subdomains
1278bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
12794b242749SEd Tanous     const static std::regex pattern(
12800fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1281bf648f77SEd Tanous 
1282bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1283bf648f77SEd Tanous }
1284bf648f77SEd Tanous 
12854f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
12868d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1287ab6554f1SJoshi-Mansi {
1288ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1289ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1290ab6554f1SJoshi-Mansi     {
1291ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1292ab6554f1SJoshi-Mansi         return;
1293ab6554f1SJoshi-Mansi     }
1294ab6554f1SJoshi-Mansi 
1295ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1296ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1297ab6554f1SJoshi-Mansi     {
1298ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1299ab6554f1SJoshi-Mansi         return;
1300ab6554f1SJoshi-Mansi     }
1301ab6554f1SJoshi-Mansi 
1302ab6554f1SJoshi-Mansi     std::string hostname;
1303ab6554f1SJoshi-Mansi     std::string domainname;
1304ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1305ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1306ab6554f1SJoshi-Mansi 
1307ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1308ab6554f1SJoshi-Mansi     {
1309ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1310ab6554f1SJoshi-Mansi         return;
1311ab6554f1SJoshi-Mansi     }
1312ab6554f1SJoshi-Mansi 
1313ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1314ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1315ab6554f1SJoshi-Mansi }
1316ab6554f1SJoshi-Mansi 
13174f48d5f6SEd Tanous inline void
13184f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1319bf648f77SEd Tanous                           const std::string& macAddress,
13208d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1321d577665bSRatan Gupta {
1322d02aad39SEd Tanous     setDbusProperty(
1323d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1324d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1325d02aad39SEd Tanous             ifaceId,
1326d02aad39SEd Tanous         "xyz.openbmc_project.Network.MACAddress", "MACAddress", "MACAddress",
1327d02aad39SEd Tanous         macAddress);
1328d577665bSRatan Gupta }
1329286b9118SJohnathan Mantey 
13304f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
13314f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
13324f48d5f6SEd Tanous                            const bool v6Value,
13338d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1334da131a9aSJennifer Lee {
13352c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
1336d02aad39SEd Tanous     setDbusProperty(
1337d02aad39SEd Tanous         asyncResp, "xyz.openbmc_project.Network",
1338d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1339d02aad39SEd Tanous             ifaceId,
1340d02aad39SEd Tanous         "xyz.openbmc_project.Network.EthernetInterface", propertyName, "DHCPv4",
1341d02aad39SEd Tanous         dhcp);
1342eeedda23SJohnathan Mantey }
1343eeedda23SJohnathan Mantey 
1344e4588158SJishnu CM enum class NetworkType
1345e4588158SJishnu CM {
1346e4588158SJishnu CM     dhcp4,
1347e4588158SJishnu CM     dhcp6
1348e4588158SJishnu CM };
1349e4588158SJishnu CM 
1350e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1351e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1352e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1353da131a9aSJennifer Lee {
135462598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
13551847f2a0SAsmitha Karunanithi     std::string redfishPropertyName;
1356e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1357e4588158SJishnu CM     path /= ethifaceId;
1358e4588158SJishnu CM 
1359e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1360e4588158SJishnu CM     {
1361e4588158SJishnu CM         path /= "dhcp4";
13621847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv4";
1363e4588158SJishnu CM     }
1364e4588158SJishnu CM     else
1365e4588158SJishnu CM     {
1366e4588158SJishnu CM         path /= "dhcp6";
13671847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv6";
1368e4588158SJishnu CM     }
1369e4588158SJishnu CM 
13701847f2a0SAsmitha Karunanithi     setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path,
13711847f2a0SAsmitha Karunanithi                     "xyz.openbmc_project.Network.DHCPConfiguration",
13721847f2a0SAsmitha Karunanithi                     propertyName, redfishPropertyName, value);
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;
13811847f2a0SAsmitha Karunanithi     setDbusProperty(asyncResp, "xyz.openbmc_project.Network", path,
13821847f2a0SAsmitha Karunanithi                     "xyz.openbmc_project.Network.EthernetInterface",
13831847f2a0SAsmitha Karunanithi                     "IPv6AcceptRA",
13841847f2a0SAsmitha Karunanithi                     "StatelessAddressAutoConfig/IPv6AutoConfigEnabled",
13851847f2a0SAsmitha Karunanithi                     ipv6AutoConfigEnabled);
1386b10d8db0SRavi Teja }
1387b10d8db0SRavi Teja 
13884f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
13891f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1390f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1391f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
13928d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1393da131a9aSJennifer Lee {
139482695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
139582695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1396da131a9aSJennifer Lee 
13971f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
13981f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
13991f8c7b5dSJohnathan Mantey 
14001f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
14011f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1402da131a9aSJennifer Lee     {
1403b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
14041f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
14051f8c7b5dSJohnathan Mantey         {
1406bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1407bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
14081f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1409da131a9aSJennifer Lee             return;
1410da131a9aSJennifer Lee         }
1411b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
14121f8c7b5dSJohnathan Mantey     }
14131f8c7b5dSJohnathan Mantey     else
1414da131a9aSJennifer Lee     {
14151f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
14161f8c7b5dSJohnathan Mantey     }
14171f8c7b5dSJohnathan Mantey 
1418e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1419e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1420e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
14211f8c7b5dSJohnathan Mantey     {
1422e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
14231f8c7b5dSJohnathan Mantey     }
1424e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
14251f8c7b5dSJohnathan Mantey     {
1426e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
14271f8c7b5dSJohnathan Mantey     }
14281f8c7b5dSJohnathan Mantey 
1429e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1430e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1431e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
14321f8c7b5dSJohnathan Mantey     {
1433e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
14341f8c7b5dSJohnathan Mantey     }
1435e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
14361f8c7b5dSJohnathan Mantey     {
1437e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
14381f8c7b5dSJohnathan Mantey     }
14391f8c7b5dSJohnathan Mantey 
144091c441ecSRavi Teja     bool nextUsev4Domain = ethData.domainv4Enabled;
144191c441ecSRavi Teja     bool nextUsev6Domain = ethData.domainv6Enabled;
1442e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
14431f8c7b5dSJohnathan Mantey     {
1444e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
14451f8c7b5dSJohnathan Mantey     }
1446e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
14471f8c7b5dSJohnathan Mantey     {
1448e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
14491f8c7b5dSJohnathan Mantey     }
14501f8c7b5dSJohnathan Mantey 
145162598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
14521f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
14531f8c7b5dSJohnathan Mantey                    asyncResp);
145462598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1455e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1456e4588158SJishnu CM                   NetworkType::dhcp4);
145762598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1458e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1459e4588158SJishnu CM                   NetworkType::dhcp4);
146091c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled...");
146191c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
1462e4588158SJishnu CM                   NetworkType::dhcp4);
1463e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1464e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1465e4588158SJishnu CM                   NetworkType::dhcp6);
1466e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1467e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1468e4588158SJishnu CM                   NetworkType::dhcp6);
146991c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
147091c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
1471e4588158SJishnu CM                   NetworkType::dhcp6);
1472da131a9aSJennifer Lee }
147301784826SJohnathan Mantey 
147477179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
147577179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
147677179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
147701784826SJohnathan Mantey {
147817a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
147917a897dfSManojkiran Eda         return value.origin == "Static";
148017a897dfSManojkiran Eda     });
148101784826SJohnathan Mantey }
148201784826SJohnathan Mantey 
148377179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
148477179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
148577179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
148601784826SJohnathan Mantey {
148717a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
148817a897dfSManojkiran Eda         return value.origin == "Static";
148917a897dfSManojkiran Eda     });
149001784826SJohnathan Mantey }
149101784826SJohnathan Mantey 
1492*3dfed536SEd Tanous inline void handleIPv4StaticPatch(
1493*3dfed536SEd Tanous     const std::string& ifaceId,
1494*3dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
149577179532SEd Tanous     const std::vector<IPv4AddressData>& ipv4Data,
14968d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
14971abe55efSEd Tanous {
1498271584abSEd Tanous     unsigned entryIdx = 1;
149901784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
150001784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
150101784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
150201784826SJohnathan Mantey     // into the NIC.
150377179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
15042c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
150501784826SJohnathan Mantey 
1506*3dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
1507*3dfed536SEd Tanous          input)
15081abe55efSEd Tanous     {
150989492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
151089492a15SPatrick Williams                                  std::to_string(entryIdx);
1511*3dfed536SEd Tanous         nlohmann::json::object_t* obj =
1512*3dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
1513*3dfed536SEd Tanous         if (obj != nullptr && !obj->empty())
1514f476acbfSRatan Gupta         {
1515537174c4SEd Tanous             std::optional<std::string> address;
1516537174c4SEd Tanous             std::optional<std::string> subnetMask;
1517537174c4SEd Tanous             std::optional<std::string> gateway;
1518537174c4SEd Tanous 
1519*3dfed536SEd Tanous             if (!json_util::readJsonObject(*obj, asyncResp->res, "Address",
15207e27d832SJohnathan Mantey                                            address, "SubnetMask", subnetMask,
15217e27d832SJohnathan Mantey                                            "Gateway", gateway))
1522537174c4SEd Tanous             {
1523*3dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
152471f52d96SEd Tanous                                                    pathString);
1525537174c4SEd Tanous                 return;
1526179db1d7SKowalski, Kamil             }
1527179db1d7SKowalski, Kamil 
152801784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
152901784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
153001784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
153101784826SJohnathan Mantey             // current request.
1532537174c4SEd Tanous             if (address)
15331abe55efSEd Tanous             {
1534e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
153501784826SJohnathan Mantey                 {
1536bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1537bf648f77SEd Tanous                                                        pathString + "/Address");
1538e01d0c36SEd Tanous                     return;
153901784826SJohnathan Mantey                 }
154001784826SJohnathan Mantey             }
154185ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
154201784826SJohnathan Mantey             {
1543e01d0c36SEd Tanous                 address = (nicIpEntry->address);
154401784826SJohnathan Mantey             }
154501784826SJohnathan Mantey             else
154601784826SJohnathan Mantey             {
154701784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
154801784826SJohnathan Mantey                                           pathString + "/Address");
1549e01d0c36SEd Tanous                 return;
15504a0cb85cSEd Tanous             }
15514a0cb85cSEd Tanous 
1552e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1553537174c4SEd Tanous             if (subnetMask)
15544a0cb85cSEd Tanous             {
1555033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1556033f1e4dSEd Tanous                                                          &prefixLength))
15574a0cb85cSEd Tanous                 {
1558f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1559537174c4SEd Tanous                         asyncResp->res, *subnetMask,
15604a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1561e01d0c36SEd Tanous                     return;
15624a0cb85cSEd Tanous                 }
15634a0cb85cSEd Tanous             }
156485ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
15654a0cb85cSEd Tanous             {
1566033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
156701784826SJohnathan Mantey                                                          &prefixLength))
15684a0cb85cSEd Tanous                 {
156901784826SJohnathan Mantey                     messages::propertyValueFormatError(
157085ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
157101784826SJohnathan Mantey                         pathString + "/SubnetMask");
1572e01d0c36SEd Tanous                     return;
15734a0cb85cSEd Tanous                 }
15744a0cb85cSEd Tanous             }
15751abe55efSEd Tanous             else
15761abe55efSEd Tanous             {
157701784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
157801784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1579e01d0c36SEd Tanous                 return;
158001784826SJohnathan Mantey             }
158101784826SJohnathan Mantey 
158201784826SJohnathan Mantey             if (gateway)
158301784826SJohnathan Mantey             {
1584e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
158501784826SJohnathan Mantey                 {
1586bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1587bf648f77SEd Tanous                                                        pathString + "/Gateway");
1588e01d0c36SEd Tanous                     return;
158901784826SJohnathan Mantey                 }
159001784826SJohnathan Mantey             }
159185ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
159201784826SJohnathan Mantey             {
1593e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
159401784826SJohnathan Mantey             }
159501784826SJohnathan Mantey             else
15961abe55efSEd Tanous             {
1597a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
15984a0cb85cSEd Tanous                                           pathString + "/Gateway");
159901784826SJohnathan Mantey                 return;
16004a0cb85cSEd Tanous             }
16014a0cb85cSEd Tanous 
160285ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
16031abe55efSEd Tanous             {
16049c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
160577eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
160677eb0153SEd Tanous                                          *gateway, asyncResp);
160789492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
160889492a15SPatrick Williams                                                   ipv4Data.cend());
1609588c3f0dSKowalski, Kamil             }
161001784826SJohnathan Mantey             else
161101784826SJohnathan Mantey             {
1612cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1613cb13a392SEd Tanous                            asyncResp);
16144a0cb85cSEd Tanous             }
16154a0cb85cSEd Tanous             entryIdx++;
16164a0cb85cSEd Tanous         }
161701784826SJohnathan Mantey         else
161801784826SJohnathan Mantey         {
161985ffe86aSJiaqing Zhao             if (nicIpEntry == ipv4Data.cend())
162001784826SJohnathan Mantey             {
162101784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
162201784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
162301784826SJohnathan Mantey                 // in error, so bail out.
1624*3dfed536SEd Tanous                 if (obj == nullptr)
162501784826SJohnathan Mantey                 {
162601784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
162701784826SJohnathan Mantey                     return;
162801784826SJohnathan Mantey                 }
1629*3dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
163071f52d96SEd Tanous                                                    pathString);
163101784826SJohnathan Mantey                 return;
163201784826SJohnathan Mantey             }
163301784826SJohnathan Mantey 
1634*3dfed536SEd Tanous             if (obj == nullptr)
163501784826SJohnathan Mantey             {
16369c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
163701784826SJohnathan Mantey             }
163885ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
163901784826SJohnathan Mantey             {
164089492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
164189492a15SPatrick Williams                                                   ipv4Data.cend());
164201784826SJohnathan Mantey             }
164301784826SJohnathan Mantey             entryIdx++;
164401784826SJohnathan Mantey         }
164501784826SJohnathan Mantey     }
16464a0cb85cSEd Tanous }
16474a0cb85cSEd Tanous 
16484f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1649f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1650f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
16518d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1652f85837bfSRAJESWARAN THILLAIGOVINDAN {
16531847f2a0SAsmitha Karunanithi     setDbusProperty(
16541847f2a0SAsmitha Karunanithi         asyncResp, "xyz.openbmc_project.Network",
16551847f2a0SAsmitha Karunanithi         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
16561847f2a0SAsmitha Karunanithi             ifaceId,
16579ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
16581847f2a0SAsmitha Karunanithi         "StaticNameServers", updatedStaticNameServers);
1659f85837bfSRAJESWARAN THILLAIGOVINDAN }
1660f85837bfSRAJESWARAN THILLAIGOVINDAN 
16614f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
1662*3dfed536SEd Tanous     const std::string& ifaceId,
1663*3dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
166477179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
16658d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1666e48c0fc5SRavi Teja {
1667271584abSEd Tanous     size_t entryIdx = 1;
166877179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
16692c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1670*3dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
1671*3dfed536SEd Tanous          input)
1672e48c0fc5SRavi Teja     {
167389492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
167489492a15SPatrick Williams                                  std::to_string(entryIdx);
1675*3dfed536SEd Tanous         nlohmann::json::object_t* obj =
1676*3dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
1677*3dfed536SEd Tanous         if (obj != nullptr && !obj->empty())
1678e48c0fc5SRavi Teja         {
1679e48c0fc5SRavi Teja             std::optional<std::string> address;
1680e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
1681*3dfed536SEd Tanous             nlohmann::json::object_t thisJsonCopy = *obj;
1682*3dfed536SEd Tanous             if (!json_util::readJsonObject(thisJsonCopy, asyncResp->res,
1683*3dfed536SEd Tanous                                            "Address", address, "PrefixLength",
1684*3dfed536SEd Tanous                                            prefixLength))
1685e48c0fc5SRavi Teja             {
1686*3dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJsonCopy,
168771f52d96SEd Tanous                                                    pathString);
1688e48c0fc5SRavi Teja                 return;
1689e48c0fc5SRavi Teja             }
1690e48c0fc5SRavi Teja 
169101784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
169201784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
169301784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
169401784826SJohnathan Mantey             // current request.
1695d547d8d2SEd Tanous             if (!address)
1696e48c0fc5SRavi Teja             {
1697d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
169801784826SJohnathan Mantey                 {
169901784826SJohnathan Mantey                     messages::propertyMissing(asyncResp->res,
170001784826SJohnathan Mantey                                               pathString + "/Address");
170101784826SJohnathan Mantey                     return;
1702e48c0fc5SRavi Teja                 }
1703d547d8d2SEd Tanous                 address = nicIpEntry->address;
1704d547d8d2SEd Tanous             }
1705e48c0fc5SRavi Teja 
1706d547d8d2SEd Tanous             if (!prefixLength)
1707e48c0fc5SRavi Teja             {
1708d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
1709e48c0fc5SRavi Teja                 {
1710e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1711e48c0fc5SRavi Teja                                               pathString + "/PrefixLength");
171201784826SJohnathan Mantey                     return;
1713e48c0fc5SRavi Teja                 }
1714d547d8d2SEd Tanous                 prefixLength = nicIpEntry->prefixLength;
1715d547d8d2SEd Tanous             }
1716e48c0fc5SRavi Teja 
171785ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1718e48c0fc5SRavi Teja             {
17199c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1720d547d8d2SEd Tanous                                          nicIpEntry->id, *prefixLength,
1721d547d8d2SEd Tanous                                          *address, "", asyncResp);
172289492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
172389492a15SPatrick Williams                                                   ipv6Data.cend());
172401784826SJohnathan Mantey             }
172501784826SJohnathan Mantey             else
172601784826SJohnathan Mantey             {
1727d547d8d2SEd Tanous                 createIPv6(ifaceId, *prefixLength, *address, asyncResp);
1728e48c0fc5SRavi Teja             }
1729e48c0fc5SRavi Teja             entryIdx++;
1730e48c0fc5SRavi Teja         }
173101784826SJohnathan Mantey         else
173201784826SJohnathan Mantey         {
173385ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
173401784826SJohnathan Mantey             {
173501784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
173601784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
173701784826SJohnathan Mantey                 // in error, so bail out.
1738*3dfed536SEd Tanous                 if (obj == nullptr)
173901784826SJohnathan Mantey                 {
174001784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
174101784826SJohnathan Mantey                     return;
174201784826SJohnathan Mantey                 }
1743*3dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
174471f52d96SEd Tanous                                                    pathString);
174501784826SJohnathan Mantey                 return;
174601784826SJohnathan Mantey             }
174701784826SJohnathan Mantey 
1748*3dfed536SEd Tanous             if (obj == nullptr)
174901784826SJohnathan Mantey             {
17509c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
175101784826SJohnathan Mantey             }
175285ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
175301784826SJohnathan Mantey             {
175489492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
175589492a15SPatrick Williams                                                   ipv6Data.cend());
175601784826SJohnathan Mantey             }
175701784826SJohnathan Mantey             entryIdx++;
175801784826SJohnathan Mantey         }
175901784826SJohnathan Mantey     }
1760e48c0fc5SRavi Teja }
1761e48c0fc5SRavi Teja 
17627857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
17637857cb8dSJiaqing Zhao {
17647857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
17657857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
17667857cb8dSJiaqing Zhao }
17677857cb8dSJiaqing Zhao 
176877179532SEd Tanous inline void
176977179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
177077179532SEd Tanous                        const std::string& ifaceId,
177177179532SEd Tanous                        const EthernetInterfaceData& ethData,
177277179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
1773ce73d5c8SSunitha Harish                        const std::vector<IPv6AddressData>& ipv6Data,
1774ce73d5c8SSunitha Harish                        const std::vector<StaticGatewayData>& ipv6GatewayData)
17754a0cb85cSEd Tanous {
17762c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
177781ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1778ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1779ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
17802c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1781eeedda23SJohnathan Mantey 
178213451e39SWilly Tu     if constexpr (bmcwebEnableHealthPopulate)
178313451e39SWilly Tu     {
178413451e39SWilly Tu         constexpr std::array<std::string_view, 1> inventoryForEthernet = {
178513451e39SWilly Tu             "xyz.openbmc_project.Inventory.Item.Ethernet"};
1786eeedda23SJohnathan Mantey         auto health = std::make_shared<HealthPopulate>(asyncResp);
17877a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
17887a1dbc48SGeorge Liu             "/", 0, inventoryForEthernet,
17897a1dbc48SGeorge Liu             [health](const boost::system::error_code& ec,
1790b9d36b47SEd Tanous                      const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1791eeedda23SJohnathan Mantey             if (ec)
1792029573d4SEd Tanous             {
1793eeedda23SJohnathan Mantey                 return;
1794eeedda23SJohnathan Mantey             }
1795eeedda23SJohnathan Mantey 
1796914e2d5dSEd Tanous             health->inventory = resp;
17977a1dbc48SGeorge Liu         });
1798eeedda23SJohnathan Mantey 
1799eeedda23SJohnathan Mantey         health->populate();
180013451e39SWilly Tu     }
1801eeedda23SJohnathan Mantey 
1802eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1803eeedda23SJohnathan Mantey     {
18040ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
18052c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1806029573d4SEd Tanous     }
1807029573d4SEd Tanous     else
1808029573d4SEd Tanous     {
18092c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
18102c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1811029573d4SEd Tanous     }
1812aa05fb27SJohnathan Mantey 
18132c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
181435fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
181582695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
18162c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
181782695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1818e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1819e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1820e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
18212c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1822b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
18231f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1824e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1825e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1826e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
1827b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1828b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
18292a133282Smanojkiraneda 
183082695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
18314a0cb85cSEd Tanous     {
183282695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1833ab6554f1SJoshi-Mansi 
1834ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1835ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1836ab6554f1SJoshi-Mansi         // FQDN
183782695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1838d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1839d24bfc7aSJennifer Lee         {
18402c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1841d24bfc7aSJennifer Lee         }
18422c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
18434a0cb85cSEd Tanous     }
18444a0cb85cSEd Tanous 
18457857cb8dSJiaqing Zhao     if (ethData.vlanId)
18467857cb8dSJiaqing Zhao     {
18477857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
18487857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
18497857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
18507857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
18517857cb8dSJiaqing Zhao 
18527857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
18537857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
18547857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
18557857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
18567857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
18577857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
18587857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
18597857cb8dSJiaqing Zhao     }
18607857cb8dSJiaqing Zhao     else
18617857cb8dSJiaqing Zhao     {
18627857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
18637857cb8dSJiaqing Zhao     }
18647857cb8dSJiaqing Zhao 
18652c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
18662c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
18674a0cb85cSEd Tanous 
18682c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
18692c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
18702c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
18712c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
18729eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
18734a0cb85cSEd Tanous     {
18742c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1875fa5053a6SGunnar Mills         if (gatewayStr.empty())
1876fa5053a6SGunnar Mills         {
1877fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1878fa5053a6SGunnar Mills         }
18791476687dSEd Tanous         nlohmann::json::object_t ipv4;
18801476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
18811476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
18821476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
18831476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1884fa5053a6SGunnar Mills 
18852c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1886d1d50814SRavi Teja         {
18871476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1888d1d50814SRavi Teja         }
18891476687dSEd Tanous 
1890b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
189101784826SJohnathan Mantey     }
1892d1d50814SRavi Teja 
189382695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
18947ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
18957ea79e5eSRavi Teja     {
18967ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
18977ea79e5eSRavi Teja     }
18987ea79e5eSRavi Teja 
18997ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1900e48c0fc5SRavi Teja 
1901ce73d5c8SSunitha Harish     nlohmann::json::array_t ipv6StaticGatewayArray;
1902ce73d5c8SSunitha Harish     for (const auto& ipv6GatewayConfig : ipv6GatewayData)
1903ce73d5c8SSunitha Harish     {
1904ce73d5c8SSunitha Harish         nlohmann::json::object_t ipv6Gateway;
1905ce73d5c8SSunitha Harish         ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
1906ce73d5c8SSunitha Harish         ipv6Gateway["PrefixLength"] = ipv6GatewayConfig.prefixLength;
1907ce73d5c8SSunitha Harish         ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
1908ce73d5c8SSunitha Harish     }
1909ce73d5c8SSunitha Harish     jsonResponse["IPv6StaticDefaultGateways"] =
1910ce73d5c8SSunitha Harish         std::move(ipv6StaticGatewayArray);
1911ce73d5c8SSunitha Harish 
19122c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
19132c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
19142c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
19152c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
19167f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
19172c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
19187f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
19199eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1920e48c0fc5SRavi Teja     {
19211476687dSEd Tanous         nlohmann::json::object_t ipv6;
19221476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
19231476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
19241476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1925f8361275SSunitha Harish 
1926b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
19272c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1928e48c0fc5SRavi Teja         {
19291476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
19301476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
19311476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1932b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
193301784826SJohnathan Mantey         }
1934e48c0fc5SRavi Teja     }
1935588c3f0dSKowalski, Kamil }
1936588c3f0dSKowalski, Kamil 
1937e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1938e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1939e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1940e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1941e7caf250SJiaqing Zhao {
1942e7caf250SJiaqing Zhao     if (!ec)
1943e7caf250SJiaqing Zhao     {
1944e7caf250SJiaqing Zhao         return;
1945e7caf250SJiaqing Zhao     }
1946e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
1947e7caf250SJiaqing Zhao     if (dbusError == nullptr)
1948e7caf250SJiaqing Zhao     {
1949e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
1950e7caf250SJiaqing Zhao         return;
1951e7caf250SJiaqing Zhao     }
195262598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1953e7caf250SJiaqing Zhao 
1954e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1955e7caf250SJiaqing Zhao         dbusError->name)
1956e7caf250SJiaqing Zhao     {
1957e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1958e7caf250SJiaqing Zhao                                    ifaceId);
1959e7caf250SJiaqing Zhao         return;
1960e7caf250SJiaqing Zhao     }
1961e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1962e7caf250SJiaqing Zhao         dbusError->name)
1963e7caf250SJiaqing Zhao     {
1964e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
1965e7caf250SJiaqing Zhao         return;
1966e7caf250SJiaqing Zhao     }
1967e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
1968e7caf250SJiaqing Zhao }
1969e7caf250SJiaqing Zhao 
1970b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1971b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
1972b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
1973b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
1974b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
1975b5ca3fdcSJiaqing Zhao 
1976b5ca3fdcSJiaqing Zhao )
1977b5ca3fdcSJiaqing Zhao {
1978b5ca3fdcSJiaqing Zhao     if (ec)
1979b5ca3fdcSJiaqing Zhao     {
1980b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
1981b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
1982b5ca3fdcSJiaqing Zhao         {
1983b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
1984b5ca3fdcSJiaqing Zhao             return;
1985b5ca3fdcSJiaqing Zhao         }
198662598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1987b5ca3fdcSJiaqing Zhao 
1988b5ca3fdcSJiaqing Zhao         if (std::string_view(
1989b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1990b5ca3fdcSJiaqing Zhao             dbusError->name)
1991b5ca3fdcSJiaqing Zhao         {
1992b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1993b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1994b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1995b5ca3fdcSJiaqing Zhao             return;
1996b5ca3fdcSJiaqing Zhao         }
1997b5ca3fdcSJiaqing Zhao         if (std::string_view(
1998b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1999b5ca3fdcSJiaqing Zhao             dbusError->name)
2000b5ca3fdcSJiaqing Zhao         {
2001b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
2002b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
2003b5ca3fdcSJiaqing Zhao             return;
2004b5ca3fdcSJiaqing Zhao         }
2005b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
2006b5ca3fdcSJiaqing Zhao         return;
2007b5ca3fdcSJiaqing Zhao     }
2008b5ca3fdcSJiaqing Zhao 
2009b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
2010b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
2011b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
2012b5ca3fdcSJiaqing Zhao }
2013b5ca3fdcSJiaqing Zhao 
2014bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
2015bf648f77SEd Tanous {
2016bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2017ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
20181476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
20191476687dSEd Tanous             [&app](const crow::Request& req,
20201476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
20213ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
202245ca1b86SEd Tanous         {
202345ca1b86SEd Tanous             return;
202445ca1b86SEd Tanous         }
202545ca1b86SEd Tanous 
2026bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
2027bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2028bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
2029bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
2030bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
2031bf648f77SEd Tanous             "Ethernet Network Interface Collection";
2032bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
2033bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
2034bf648f77SEd Tanous 
2035bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
2036bf648f77SEd Tanous         // preparation
2037002d39b4SEd Tanous         getEthernetIfaceList(
203877179532SEd Tanous             [asyncResp](const bool& success,
203977179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
2040bf648f77SEd Tanous             if (!success)
20411abe55efSEd Tanous             {
2042f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
20439391bb9cSRapkiewicz, Pawel                 return;
20449391bb9cSRapkiewicz, Pawel             }
20459391bb9cSRapkiewicz, Pawel 
2046002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
2047bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
2048bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
2049bf648f77SEd Tanous             {
20501476687dSEd Tanous                 nlohmann::json::object_t iface;
2051ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
2052ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
2053ef4c65b7SEd Tanous                     ifaceItem);
20547857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
2055bf648f77SEd Tanous             }
2056bf648f77SEd Tanous 
2057002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
2058bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
2059bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
2060bf648f77SEd Tanous         });
2061bf648f77SEd Tanous     });
2062bf648f77SEd Tanous 
2063b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
2064b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
2065b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
2066b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
2067b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2068b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2069b5ca3fdcSJiaqing Zhao         {
2070b5ca3fdcSJiaqing Zhao             return;
2071b5ca3fdcSJiaqing Zhao         }
2072b5ca3fdcSJiaqing Zhao 
2073b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
2074b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
2075*3dfed536SEd Tanous         std::vector<nlohmann::json::object_t> relatedInterfaces;
2076b5ca3fdcSJiaqing Zhao 
2077b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
2078b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
2079b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
2080b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
2081b5ca3fdcSJiaqing Zhao         {
2082b5ca3fdcSJiaqing Zhao             return;
2083b5ca3fdcSJiaqing Zhao         }
2084b5ca3fdcSJiaqing Zhao 
2085b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
2086b5ca3fdcSJiaqing Zhao         {
2087b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
2088b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
2089b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
2090b5ca3fdcSJiaqing Zhao             return;
2091b5ca3fdcSJiaqing Zhao         }
2092b5ca3fdcSJiaqing Zhao 
2093b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
2094*3dfed536SEd Tanous         if (!json_util::readJsonObject(relatedInterfaces[0], asyncResp->res,
2095b5ca3fdcSJiaqing Zhao                                        "@odata.id", parentInterfaceUri))
2096b5ca3fdcSJiaqing Zhao         {
2097b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
2098b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
2099b5ca3fdcSJiaqing Zhao             return;
2100b5ca3fdcSJiaqing Zhao         }
210162598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
2102b5ca3fdcSJiaqing Zhao 
21036fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
2104b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
2105b5ca3fdcSJiaqing Zhao         if (!parsedUri)
2106b5ca3fdcSJiaqing Zhao         {
2107b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
2108b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2109b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2110b5ca3fdcSJiaqing Zhao             return;
2111b5ca3fdcSJiaqing Zhao         }
2112b5ca3fdcSJiaqing Zhao 
2113b5ca3fdcSJiaqing Zhao         std::string parentInterface;
2114b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
2115b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
2116b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
2117b5ca3fdcSJiaqing Zhao         {
2118b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2119b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2120b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2121b5ca3fdcSJiaqing Zhao             return;
2122b5ca3fdcSJiaqing Zhao         }
2123b5ca3fdcSJiaqing Zhao 
2124b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
2125b5ca3fdcSJiaqing Zhao         {
2126b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
2127b5ca3fdcSJiaqing Zhao             // create
2128b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
2129b5ca3fdcSJiaqing Zhao                                              "false");
2130b5ca3fdcSJiaqing Zhao             return;
2131b5ca3fdcSJiaqing Zhao         }
2132b5ca3fdcSJiaqing Zhao 
2133b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
2134b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
2135b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
2136b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
2137b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
2138b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
2139b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
2140b5ca3fdcSJiaqing Zhao                             m);
2141b5ca3fdcSJiaqing Zhao         },
2142b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
2143b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
2144b5ca3fdcSJiaqing Zhao             vlanId);
2145b5ca3fdcSJiaqing Zhao     });
2146b5ca3fdcSJiaqing Zhao 
2147bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2148ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
2149bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
215045ca1b86SEd Tanous             [&app](const crow::Request& req,
2151bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2152bf648f77SEd Tanous                    const std::string& ifaceId) {
21533ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
215445ca1b86SEd Tanous         {
215545ca1b86SEd Tanous             return;
215645ca1b86SEd Tanous         }
21574a0cb85cSEd Tanous         getEthernetIfaceData(
2158bf648f77SEd Tanous             ifaceId,
2159ce73d5c8SSunitha Harish             [asyncResp,
2160ce73d5c8SSunitha Harish              ifaceId](const bool& success, const EthernetInterfaceData& ethData,
216177179532SEd Tanous                       const std::vector<IPv4AddressData>& ipv4Data,
2162ce73d5c8SSunitha Harish                       const std::vector<IPv6AddressData>& ipv6Data,
2163ce73d5c8SSunitha Harish                       const std::vector<StaticGatewayData>& ipv6GatewayData) {
21644a0cb85cSEd Tanous             if (!success)
21651abe55efSEd Tanous             {
2166bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2167bf648f77SEd Tanous                 // existing object, and other errors
2168002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2169002d39b4SEd Tanous                                            ifaceId);
21704a0cb85cSEd Tanous                 return;
21719391bb9cSRapkiewicz, Pawel             }
21724c9afe43SEd Tanous 
21730f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
217493bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
2175002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
21760f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
21770f74e643SEd Tanous                 "Management Network Interface";
21780f74e643SEd Tanous 
2179ce73d5c8SSunitha Harish             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data,
2180ce73d5c8SSunitha Harish                                ipv6GatewayData);
21819391bb9cSRapkiewicz, Pawel         });
2182bf648f77SEd Tanous     });
21839391bb9cSRapkiewicz, Pawel 
2184bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2185ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2186bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
218745ca1b86SEd Tanous             [&app](const crow::Request& req,
2188bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2189bf648f77SEd Tanous                    const std::string& ifaceId) {
21903ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
219145ca1b86SEd Tanous         {
219245ca1b86SEd Tanous             return;
219345ca1b86SEd Tanous         }
2194bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2195ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2196d577665bSRatan Gupta         std::optional<std::string> macAddress;
21979a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
2198*3dfed536SEd Tanous         std::optional<
2199*3dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
2200*3dfed536SEd Tanous             ipv4StaticAddresses;
2201*3dfed536SEd Tanous         std::optional<
2202*3dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
2203*3dfed536SEd Tanous             ipv6StaticAddresses;
2204*3dfed536SEd Tanous         std::optional<
2205*3dfed536SEd Tanous             std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>>
2206*3dfed536SEd Tanous             ipv6StaticDefaultGateways;
2207f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2208b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2209eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
221035fb5311STejas Patil         std::optional<size_t> mtuSize;
22111f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
22121f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2213b10d8db0SRavi Teja         // clang-format off
2214*3dfed536SEd Tanous         if (!json_util::readJsonPatch(req, asyncResp->res,
2215*3dfed536SEd Tanous                 "DHCPv4/DHCPEnabled",   v4dhcpParms.dhcpv4Enabled,
2216*3dfed536SEd Tanous                 "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers,
2217*3dfed536SEd Tanous                 "DHCPv4/UseDomainName", v4dhcpParms.useDomainName,
2218*3dfed536SEd Tanous                 "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers,
2219*3dfed536SEd Tanous                 "DHCPv6/OperatingMode", v6dhcpParms.dhcpv6OperatingMode,
2220*3dfed536SEd Tanous                 "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers,
2221*3dfed536SEd Tanous                 "DHCPv6/UseDomainName", v6dhcpParms.useDomainName,
2222*3dfed536SEd Tanous                 "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers,
2223b10d8db0SRavi Teja                 "FQDN", fqdn,
2224b10d8db0SRavi Teja                 "HostName", hostname,
2225b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2226b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2227b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2228ce73d5c8SSunitha Harish                 "IPv6StaticDefaultGateways", ipv6StaticDefaultGateways,
2229b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2230b10d8db0SRavi Teja                 "MACAddress", macAddress,
2231b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2232b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2233b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2234b10d8db0SRavi Teja                 )
2235b10d8db0SRavi Teja             )
22361abe55efSEd Tanous         {
2237588c3f0dSKowalski, Kamil             return;
2238588c3f0dSKowalski, Kamil         }
2239b10d8db0SRavi Teja         // clang-format on
2240da131a9aSJennifer Lee 
2241bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2242bf648f77SEd Tanous         // for JSON preparation
22434a0cb85cSEd Tanous         getEthernetIfaceData(
22442c70f800SEd Tanous             ifaceId,
2245bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2246ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2247d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
22489a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2249e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2250ce73d5c8SSunitha Harish              ipv6StaticDefaultGateway = std::move(ipv6StaticDefaultGateways),
2251*3dfed536SEd Tanous              staticNameServers = std::move(staticNameServers), mtuSize,
2252b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2253f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2254*3dfed536SEd Tanous                 const bool success, const EthernetInterfaceData& ethData,
225577179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
2256ce73d5c8SSunitha Harish                 const std::vector<IPv6AddressData>& ipv6Data,
2257*3dfed536SEd Tanous                 const std::vector<StaticGatewayData>& ipv6GatewayData) mutable {
22581abe55efSEd Tanous             if (!success)
22591abe55efSEd Tanous             {
2260588c3f0dSKowalski, Kamil                 // ... otherwise return error
2261bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2262bf648f77SEd Tanous                 // existing object, and other errors
2263002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2264002d39b4SEd Tanous                                            ifaceId);
2265588c3f0dSKowalski, Kamil                 return;
2266588c3f0dSKowalski, Kamil             }
2267588c3f0dSKowalski, Kamil 
2268002d39b4SEd Tanous             handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2269002d39b4SEd Tanous                             asyncResp);
22701f8c7b5dSJohnathan Mantey 
22710627a2c7SEd Tanous             if (hostname)
22721abe55efSEd Tanous             {
22730627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
22741abe55efSEd Tanous             }
22750627a2c7SEd Tanous 
2276b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2277b10d8db0SRavi Teja             {
2278b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2279b10d8db0SRavi Teja                                            asyncResp);
2280b10d8db0SRavi Teja             }
2281b10d8db0SRavi Teja 
2282ab6554f1SJoshi-Mansi             if (fqdn)
2283ab6554f1SJoshi-Mansi             {
22842c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2285ab6554f1SJoshi-Mansi             }
2286ab6554f1SJoshi-Mansi 
2287d577665bSRatan Gupta             if (macAddress)
2288d577665bSRatan Gupta             {
2289002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2290d577665bSRatan Gupta             }
2291d577665bSRatan Gupta 
2292d1d50814SRavi Teja             if (ipv4StaticAddresses)
2293d1d50814SRavi Teja             {
2294*3dfed536SEd Tanous                 handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses, ipv4Data,
2295*3dfed536SEd Tanous                                       asyncResp);
22961abe55efSEd Tanous             }
22970627a2c7SEd Tanous 
2298f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2299f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2300002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2301002d39b4SEd Tanous                                              asyncResp);
2302f85837bfSRAJESWARAN THILLAIGOVINDAN             }
23039a6fc6feSRavi Teja 
23049a6fc6feSRavi Teja             if (ipv6DefaultGateway)
23059a6fc6feSRavi Teja             {
23069a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
23079a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
23089a6fc6feSRavi Teja             }
2309e48c0fc5SRavi Teja 
2310e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2311e48c0fc5SRavi Teja             {
2312ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2313ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2314e48c0fc5SRavi Teja             }
2315eeedda23SJohnathan Mantey 
2316ce73d5c8SSunitha Harish             if (ipv6StaticDefaultGateway)
2317ce73d5c8SSunitha Harish             {
2318ce73d5c8SSunitha Harish                 handleIPv6DefaultGateway(ifaceId, *ipv6StaticDefaultGateway,
2319ce73d5c8SSunitha Harish                                          ipv6GatewayData, asyncResp);
2320ce73d5c8SSunitha Harish             }
2321ce73d5c8SSunitha Harish 
2322eeedda23SJohnathan Mantey             if (interfaceEnabled)
2323eeedda23SJohnathan Mantey             {
2324d02aad39SEd Tanous                 setDbusProperty(asyncResp, "xyz.openbmc_project.Network",
2325d02aad39SEd Tanous                                 sdbusplus::message::object_path(
2326d02aad39SEd Tanous                                     "/xyz/openbmc_project/network") /
2327d02aad39SEd Tanous                                     ifaceId,
2328d02aad39SEd Tanous                                 "xyz.openbmc_project.Network.EthernetInterface",
2329d02aad39SEd Tanous                                 "NICEnabled", "InterfaceEnabled",
2330d02aad39SEd Tanous                                 *interfaceEnabled);
2331eeedda23SJohnathan Mantey             }
233235fb5311STejas Patil 
233335fb5311STejas Patil             if (mtuSize)
233435fb5311STejas Patil             {
233535fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
233635fb5311STejas Patil             }
2337588c3f0dSKowalski, Kamil         });
2338bf648f77SEd Tanous     });
2339e7caf250SJiaqing Zhao 
2340e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2341e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2342e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2343e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2344e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2345e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2346e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2347e7caf250SJiaqing Zhao         {
2348e7caf250SJiaqing Zhao             return;
2349e7caf250SJiaqing Zhao         }
2350e7caf250SJiaqing Zhao 
2351e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2352e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2353e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2354e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2355e7caf250SJiaqing Zhao         },
2356e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2357e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2358e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2359e7caf250SJiaqing Zhao     });
23604a0cb85cSEd Tanous }
2361bf648f77SEd Tanous 
23629391bb9cSRapkiewicz, Pawel } // namespace redfish
2363