xref: /openbmc/bmcweb/redfish-core/lib/ethernet.hpp (revision 504af5a0568171b72caf13234cc81380b261fa21)
140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0
240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors
340e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright 2018 Intel Corporation
49391bb9cSRapkiewicz, Pawel #pragma once
59391bb9cSRapkiewicz, Pawel 
6d7857201SEd Tanous #include "bmcweb_config.h"
7d7857201SEd Tanous 
83ccb3adbSEd Tanous #include "app.hpp"
9d7857201SEd Tanous #include "async_resp.hpp"
103ccb3adbSEd Tanous #include "dbus_singleton.hpp"
117a1dbc48SGeorge Liu #include "dbus_utility.hpp"
123ccb3adbSEd Tanous #include "error_messages.hpp"
13539d8c6bSEd Tanous #include "generated/enums/ethernet_interface.hpp"
14539d8c6bSEd Tanous #include "generated/enums/resource.hpp"
15d7857201SEd Tanous #include "http_request.hpp"
16d7857201SEd Tanous #include "http_response.hpp"
172c5875a2SEd Tanous #include "human_sort.hpp"
18d7857201SEd Tanous #include "logging.hpp"
193ccb3adbSEd Tanous #include "query.hpp"
203ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
21d7857201SEd Tanous #include "utility.hpp"
22d7857201SEd Tanous #include "utils/dbus_utils.hpp"
23033f1e4dSEd Tanous #include "utils/ip_utils.hpp"
243ccb3adbSEd Tanous #include "utils/json_utils.hpp"
25033f1e4dSEd Tanous 
26d7857201SEd Tanous #include <systemd/sd-bus.h>
271214b7e7SGunnar Mills 
28d7857201SEd Tanous #include <boost/beast/http/verb.hpp>
29d7857201SEd Tanous #include <boost/system/error_code.hpp>
30d7857201SEd Tanous #include <boost/system/result.hpp>
31d7857201SEd Tanous #include <boost/url/format.hpp>
32d7857201SEd Tanous #include <boost/url/parse.hpp>
33d7857201SEd Tanous #include <boost/url/url.hpp>
34d7857201SEd Tanous #include <boost/url/url_view.hpp>
35d7857201SEd Tanous #include <sdbusplus/message.hpp>
36d7857201SEd Tanous #include <sdbusplus/message/native_types.hpp>
37d7857201SEd Tanous #include <sdbusplus/unpack_properties.hpp>
38d7857201SEd Tanous 
39d7857201SEd Tanous #include <algorithm>
40d7857201SEd Tanous #include <cctype>
413dfed536SEd Tanous #include <cstddef>
42d7857201SEd Tanous #include <cstdint>
43d7857201SEd Tanous #include <format>
44d7857201SEd Tanous #include <functional>
45ce73d5c8SSunitha Harish #include <memory>
46a24526dcSEd Tanous #include <optional>
473544d2a7SEd Tanous #include <ranges>
48ab6554f1SJoshi-Mansi #include <regex>
49d7857201SEd Tanous #include <string>
507a1dbc48SGeorge Liu #include <string_view>
51d7857201SEd Tanous #include <utility>
523dfed536SEd Tanous #include <variant>
5377179532SEd Tanous #include <vector>
549391bb9cSRapkiewicz, Pawel 
551abe55efSEd Tanous namespace redfish
561abe55efSEd Tanous {
579391bb9cSRapkiewicz, Pawel 
584a0cb85cSEd Tanous enum class LinkType
594a0cb85cSEd Tanous {
604a0cb85cSEd Tanous     Local,
614a0cb85cSEd Tanous     Global
624a0cb85cSEd Tanous };
639391bb9cSRapkiewicz, Pawel 
64743eb1c0SJohnathan Mantey enum class IpVersion
65743eb1c0SJohnathan Mantey {
66743eb1c0SJohnathan Mantey     IpV4,
67743eb1c0SJohnathan Mantey     IpV6
68743eb1c0SJohnathan Mantey };
69743eb1c0SJohnathan Mantey 
709391bb9cSRapkiewicz, Pawel /**
719391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
729391bb9cSRapkiewicz, Pawel  */
731abe55efSEd Tanous struct IPv4AddressData
741abe55efSEd Tanous {
75179db1d7SKowalski, Kamil     std::string id;
764a0cb85cSEd Tanous     std::string address;
774a0cb85cSEd Tanous     std::string domain;
784a0cb85cSEd Tanous     std::string gateway;
799391bb9cSRapkiewicz, Pawel     std::string netmask;
809391bb9cSRapkiewicz, Pawel     std::string origin;
8177179532SEd Tanous     LinkType linktype{};
8277179532SEd Tanous     bool isActive{};
839391bb9cSRapkiewicz, Pawel };
849391bb9cSRapkiewicz, Pawel 
859391bb9cSRapkiewicz, Pawel /**
86e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
87e48c0fc5SRavi Teja  */
88e48c0fc5SRavi Teja struct IPv6AddressData
89e48c0fc5SRavi Teja {
90e48c0fc5SRavi Teja     std::string id;
91e48c0fc5SRavi Teja     std::string address;
92e48c0fc5SRavi Teja     std::string origin;
9377179532SEd Tanous     uint8_t prefixLength = 0;
94e48c0fc5SRavi Teja };
95ce73d5c8SSunitha Harish 
96ce73d5c8SSunitha Harish /**
97ce73d5c8SSunitha Harish  * Structure for keeping static route data required by Redfish
98ce73d5c8SSunitha Harish  */
99ce73d5c8SSunitha Harish struct StaticGatewayData
100ce73d5c8SSunitha Harish {
101ce73d5c8SSunitha Harish     std::string id;
102ce73d5c8SSunitha Harish     std::string gateway;
103ce73d5c8SSunitha Harish     size_t prefixLength = 0;
104ce73d5c8SSunitha Harish     std::string protocol;
105ce73d5c8SSunitha Harish };
106ce73d5c8SSunitha Harish 
107e48c0fc5SRavi Teja /**
1089391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
1099391bb9cSRapkiewicz, Pawel  * available from DBus
1109391bb9cSRapkiewicz, Pawel  */
1111abe55efSEd Tanous struct EthernetInterfaceData
1121abe55efSEd Tanous {
1134a0cb85cSEd Tanous     uint32_t speed;
11435fb5311STejas Patil     size_t mtuSize;
11582695a5bSJiaqing Zhao     bool autoNeg;
116e4588158SJishnu CM     bool dnsv4Enabled;
117e4588158SJishnu CM     bool dnsv6Enabled;
11891c441ecSRavi Teja     bool domainv4Enabled;
11991c441ecSRavi Teja     bool domainv6Enabled;
120e4588158SJishnu CM     bool ntpv4Enabled;
121e4588158SJishnu CM     bool ntpv6Enabled;
122e4588158SJishnu CM     bool hostNamev4Enabled;
123e4588158SJishnu CM     bool hostNamev6Enabled;
124aa05fb27SJohnathan Mantey     bool linkUp;
125eeedda23SJohnathan Mantey     bool nicEnabled;
126b10d8db0SRavi Teja     bool ipv6AcceptRa;
12782695a5bSJiaqing Zhao     std::string dhcpEnabled;
1281f8c7b5dSJohnathan Mantey     std::string operatingMode;
12982695a5bSJiaqing Zhao     std::string hostName;
13082695a5bSJiaqing Zhao     std::string defaultGateway;
13182695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
132ce73d5c8SSunitha Harish     std::string ipv6StaticDefaultGateway;
1334652c640SAsmitha Karunanithi     std::optional<std::string> macAddress;
13417e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
1350f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1360f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
137d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1389391bb9cSRapkiewicz, Pawel };
1399391bb9cSRapkiewicz, Pawel 
1401f8c7b5dSJohnathan Mantey struct DHCPParameters
1411f8c7b5dSJohnathan Mantey {
1421f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
14382695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
14482695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
14582695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1461f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1471f8c7b5dSJohnathan Mantey };
1481f8c7b5dSJohnathan Mantey 
1499391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1509391bb9cSRapkiewicz, Pawel // into full dot notation
getNetmask(unsigned int bits)1511abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1521abe55efSEd Tanous {
1539391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1549391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1559391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1569391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1579391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1589391bb9cSRapkiewicz, Pawel     return netmask;
1599391bb9cSRapkiewicz, Pawel }
1609391bb9cSRapkiewicz, Pawel 
translateDhcpEnabledToBool(const std::string & inputDHCP,bool isIPv4)16182695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1621f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1631f8c7b5dSJohnathan Mantey {
1641f8c7b5dSJohnathan Mantey     if (isIPv4)
1651f8c7b5dSJohnathan Mantey     {
1661f8c7b5dSJohnathan Mantey         return (
1671f8c7b5dSJohnathan Mantey             (inputDHCP ==
1681f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1691f8c7b5dSJohnathan Mantey             (inputDHCP ==
1706e78b680SAsmitha Karunanithi              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both") ||
1716e78b680SAsmitha Karunanithi             (inputDHCP ==
1726e78b680SAsmitha Karunanithi              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4v6stateless"));
1731f8c7b5dSJohnathan Mantey     }
1741f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1751f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1761f8c7b5dSJohnathan Mantey             (inputDHCP ==
1771f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1781f8c7b5dSJohnathan Mantey }
1791f8c7b5dSJohnathan Mantey 
getDhcpEnabledEnumeration(bool isIPv4,bool isIPv6)1802c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1811f8c7b5dSJohnathan Mantey {
1821f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1831f8c7b5dSJohnathan Mantey     {
1841f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1851f8c7b5dSJohnathan Mantey     }
1863174e4dfSEd Tanous     if (isIPv4)
1871f8c7b5dSJohnathan Mantey     {
1881f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1891f8c7b5dSJohnathan Mantey     }
1903174e4dfSEd Tanous     if (isIPv6)
1911f8c7b5dSJohnathan Mantey     {
1921f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1931f8c7b5dSJohnathan Mantey     }
1941f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1951f8c7b5dSJohnathan Mantey }
1961f8c7b5dSJohnathan Mantey 
translateAddressOriginDbusToRedfish(const std::string & inputOrigin,bool isIPv4)197bd79bce8SPatrick Williams inline std::string translateAddressOriginDbusToRedfish(
198bd79bce8SPatrick Williams     const std::string& inputOrigin, bool isIPv4)
1991abe55efSEd Tanous {
2004a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
2011abe55efSEd Tanous     {
2024a0cb85cSEd Tanous         return "Static";
2039391bb9cSRapkiewicz, Pawel     }
2044a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
2051abe55efSEd Tanous     {
2064a0cb85cSEd Tanous         if (isIPv4)
2071abe55efSEd Tanous         {
2084a0cb85cSEd Tanous             return "IPv4LinkLocal";
2091abe55efSEd Tanous         }
2104a0cb85cSEd Tanous         return "LinkLocal";
2119391bb9cSRapkiewicz, Pawel     }
2124a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
2131abe55efSEd Tanous     {
2144a0cb85cSEd Tanous         if (isIPv4)
2154a0cb85cSEd Tanous         {
2164a0cb85cSEd Tanous             return "DHCP";
2174a0cb85cSEd Tanous         }
2184a0cb85cSEd Tanous         return "DHCPv6";
2194a0cb85cSEd Tanous     }
2204a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
2214a0cb85cSEd Tanous     {
2224a0cb85cSEd Tanous         return "SLAAC";
2234a0cb85cSEd Tanous     }
2244a0cb85cSEd Tanous     return "";
2254a0cb85cSEd Tanous }
2264a0cb85cSEd Tanous 
extractEthernetInterfaceData(const std::string & ethifaceId,const dbus::utility::ManagedObjectType & dbusData,EthernetInterfaceData & ethData)22702cad96eSEd Tanous inline bool extractEthernetInterfaceData(
22802cad96eSEd Tanous     const std::string& ethifaceId,
22902cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
2304a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
2314a0cb85cSEd Tanous {
2324c9afe43SEd Tanous     bool idFound = false;
23302cad96eSEd Tanous     for (const auto& objpath : dbusData)
2344a0cb85cSEd Tanous     {
23502cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
2364a0cb85cSEd Tanous         {
23781ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
238029573d4SEd Tanous             {
2394c9afe43SEd Tanous                 idFound = true;
2404a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2414a0cb85cSEd Tanous                 {
2424a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2434a0cb85cSEd Tanous                     {
2444a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2454a0cb85cSEd Tanous                         {
2464a0cb85cSEd Tanous                             const std::string* mac =
247abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2484a0cb85cSEd Tanous                             if (mac != nullptr)
2494a0cb85cSEd Tanous                             {
25082695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2514a0cb85cSEd Tanous                             }
2524a0cb85cSEd Tanous                         }
2534a0cb85cSEd Tanous                     }
2544a0cb85cSEd Tanous                 }
2554a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2564a0cb85cSEd Tanous                 {
2574a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2584a0cb85cSEd Tanous                     {
2594a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2604a0cb85cSEd Tanous                         {
2611b6b96c5SEd Tanous                             const uint32_t* id =
262abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2634a0cb85cSEd Tanous                             if (id != nullptr)
2644a0cb85cSEd Tanous                             {
26517e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2664a0cb85cSEd Tanous                             }
2674a0cb85cSEd Tanous                         }
2684a0cb85cSEd Tanous                     }
2694a0cb85cSEd Tanous                 }
2704a0cb85cSEd Tanous                 else if (ifacePair.first ==
2714a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2724a0cb85cSEd Tanous                 {
2734a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2744a0cb85cSEd Tanous                     {
2754a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2764a0cb85cSEd Tanous                         {
2772c70f800SEd Tanous                             const bool* autoNeg =
278abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2792c70f800SEd Tanous                             if (autoNeg != nullptr)
2804a0cb85cSEd Tanous                             {
28182695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2824a0cb85cSEd Tanous                             }
2834a0cb85cSEd Tanous                         }
2844a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2854a0cb85cSEd Tanous                         {
2864a0cb85cSEd Tanous                             const uint32_t* speed =
287abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2884a0cb85cSEd Tanous                             if (speed != nullptr)
2894a0cb85cSEd Tanous                             {
2904a0cb85cSEd Tanous                                 ethData.speed = *speed;
2914a0cb85cSEd Tanous                             }
2924a0cb85cSEd Tanous                         }
29335fb5311STejas Patil                         else if (propertyPair.first == "MTU")
29435fb5311STejas Patil                         {
2953e7a8da6SAnthony                             const size_t* mtuSize =
2963e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
29735fb5311STejas Patil                             if (mtuSize != nullptr)
29835fb5311STejas Patil                             {
29935fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
30035fb5311STejas Patil                             }
30135fb5311STejas Patil                         }
302aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
303aa05fb27SJohnathan Mantey                         {
304aa05fb27SJohnathan Mantey                             const bool* linkUp =
305aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
306aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
307aa05fb27SJohnathan Mantey                             {
308aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
309aa05fb27SJohnathan Mantey                             }
310aa05fb27SJohnathan Mantey                         }
311eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
312eeedda23SJohnathan Mantey                         {
313eeedda23SJohnathan Mantey                             const bool* nicEnabled =
314eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
315eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
316eeedda23SJohnathan Mantey                             {
317eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
318eeedda23SJohnathan Mantey                             }
319eeedda23SJohnathan Mantey                         }
320b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
321b10d8db0SRavi Teja                         {
322b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
323b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
324b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
325b10d8db0SRavi Teja                             {
326b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
327b10d8db0SRavi Teja                             }
328b10d8db0SRavi Teja                         }
329f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
330029573d4SEd Tanous                         {
331029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
3328d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
333029573d4SEd Tanous                                     &propertyPair.second);
334029573d4SEd Tanous                             if (nameservers != nullptr)
335029573d4SEd Tanous                             {
336f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3370f6efdc1Smanojkiran.eda@gmail.com                             }
3380f6efdc1Smanojkiran.eda@gmail.com                         }
3390f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3400f6efdc1Smanojkiran.eda@gmail.com                         {
3410f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3428d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3430f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3440f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3450f6efdc1Smanojkiran.eda@gmail.com                             {
346f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3474a0cb85cSEd Tanous                             }
3484a0cb85cSEd Tanous                         }
3492a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3502a133282Smanojkiraneda                         {
3512c70f800SEd Tanous                             const std::string* dhcpEnabled =
3521f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3532c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3542a133282Smanojkiraneda                             {
35582695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3562a133282Smanojkiraneda                             }
3572a133282Smanojkiraneda                         }
358d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
359d24bfc7aSJennifer Lee                         {
360d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3618d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
362d24bfc7aSJennifer Lee                                     &propertyPair.second);
363d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
364d24bfc7aSJennifer Lee                             {
365f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
366d24bfc7aSJennifer Lee                             }
367d24bfc7aSJennifer Lee                         }
3689010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3699010ec2eSRavi Teja                         {
3709010ec2eSRavi Teja                             const std::string* defaultGateway =
3719010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3729010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3739010ec2eSRavi Teja                             {
3749010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3759010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3769010ec2eSRavi Teja                                 {
37782695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3789010ec2eSRavi Teja                                 }
3799010ec2eSRavi Teja                                 else
3809010ec2eSRavi Teja                                 {
38182695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3829010ec2eSRavi Teja                                 }
3839010ec2eSRavi Teja                             }
3849010ec2eSRavi Teja                         }
3859010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3869010ec2eSRavi Teja                         {
3879010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3889010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3899010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3909010ec2eSRavi Teja                             {
3919010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3929010ec2eSRavi Teja                                     *defaultGateway6;
3939010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3949010ec2eSRavi Teja                                 {
39582695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3969010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3979010ec2eSRavi Teja                                 }
3989010ec2eSRavi Teja                                 else
3999010ec2eSRavi Teja                                 {
40082695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
4019010ec2eSRavi Teja                                         defaultGateway6Str;
4029010ec2eSRavi Teja                                 }
4039010ec2eSRavi Teja                             }
4049010ec2eSRavi Teja                         }
405029573d4SEd Tanous                     }
406029573d4SEd Tanous                 }
407029573d4SEd Tanous             }
4081f8c7b5dSJohnathan Mantey 
409e4588158SJishnu CM             sdbusplus::message::object_path path(
410e4588158SJishnu CM                 "/xyz/openbmc_project/network");
411bd79bce8SPatrick Williams             sdbusplus::message::object_path dhcp4Path =
412bd79bce8SPatrick Williams                 path / ethifaceId / "dhcp4";
413e4588158SJishnu CM 
414e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
4151f8c7b5dSJohnathan Mantey             {
4161f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
4171f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
4181f8c7b5dSJohnathan Mantey                 {
4191f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
4201f8c7b5dSJohnathan Mantey                     {
4211f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
4221f8c7b5dSJohnathan Mantey                         {
4232c70f800SEd Tanous                             const bool* dnsEnabled =
4241f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4252c70f800SEd Tanous                             if (dnsEnabled != nullptr)
4261f8c7b5dSJohnathan Mantey                             {
427e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
4281f8c7b5dSJohnathan Mantey                             }
4291f8c7b5dSJohnathan Mantey                         }
43091c441ecSRavi Teja                         else if (propertyPair.first == "DomainEnabled")
43191c441ecSRavi Teja                         {
43291c441ecSRavi Teja                             const bool* domainEnabled =
43391c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
43491c441ecSRavi Teja                             if (domainEnabled != nullptr)
43591c441ecSRavi Teja                             {
43691c441ecSRavi Teja                                 ethData.domainv4Enabled = *domainEnabled;
43791c441ecSRavi Teja                             }
43891c441ecSRavi Teja                         }
4391f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
4401f8c7b5dSJohnathan Mantey                         {
4412c70f800SEd Tanous                             const bool* ntpEnabled =
4421f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4432c70f800SEd Tanous                             if (ntpEnabled != nullptr)
4441f8c7b5dSJohnathan Mantey                             {
445e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4461f8c7b5dSJohnathan Mantey                             }
4471f8c7b5dSJohnathan Mantey                         }
4481f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4491f8c7b5dSJohnathan Mantey                         {
4502c70f800SEd Tanous                             const bool* hostNameEnabled =
4511f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4522c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4531f8c7b5dSJohnathan Mantey                             {
454e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
455e4588158SJishnu CM                             }
456e4588158SJishnu CM                         }
457e4588158SJishnu CM                     }
458e4588158SJishnu CM                 }
459e4588158SJishnu CM             }
460e4588158SJishnu CM 
461bd79bce8SPatrick Williams             sdbusplus::message::object_path dhcp6Path =
462bd79bce8SPatrick Williams                 path / ethifaceId / "dhcp6";
463e4588158SJishnu CM 
464e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
465e4588158SJishnu CM             {
466e4588158SJishnu CM                 if (ifacePair.first ==
467e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
468e4588158SJishnu CM                 {
469e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
470e4588158SJishnu CM                     {
471e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
472e4588158SJishnu CM                         {
473e4588158SJishnu CM                             const bool* dnsEnabled =
474e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
475e4588158SJishnu CM                             if (dnsEnabled != nullptr)
476e4588158SJishnu CM                             {
477e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
478e4588158SJishnu CM                             }
479e4588158SJishnu CM                         }
48091c441ecSRavi Teja                         if (propertyPair.first == "DomainEnabled")
48191c441ecSRavi Teja                         {
48291c441ecSRavi Teja                             const bool* domainEnabled =
48391c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
48491c441ecSRavi Teja                             if (domainEnabled != nullptr)
48591c441ecSRavi Teja                             {
48691c441ecSRavi Teja                                 ethData.domainv6Enabled = *domainEnabled;
48791c441ecSRavi Teja                             }
48891c441ecSRavi Teja                         }
489e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
490e4588158SJishnu CM                         {
491e4588158SJishnu CM                             const bool* ntpEnabled =
492e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
493e4588158SJishnu CM                             if (ntpEnabled != nullptr)
494e4588158SJishnu CM                             {
495e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
496e4588158SJishnu CM                             }
497e4588158SJishnu CM                         }
498e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
499e4588158SJishnu CM                         {
500e4588158SJishnu CM                             const bool* hostNameEnabled =
501e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
502e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
503e4588158SJishnu CM                             {
504e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
5051f8c7b5dSJohnathan Mantey                             }
5061f8c7b5dSJohnathan Mantey                         }
5071f8c7b5dSJohnathan Mantey                     }
5081f8c7b5dSJohnathan Mantey                 }
5091f8c7b5dSJohnathan Mantey             }
510029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
511029573d4SEd Tanous             // to check eth number
512029573d4SEd Tanous             if (ifacePair.first ==
5134a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
5144a0cb85cSEd Tanous             {
5154a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
5164a0cb85cSEd Tanous                 {
5174a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
5184a0cb85cSEd Tanous                     {
5194a0cb85cSEd Tanous                         const std::string* hostname =
5208d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
5214a0cb85cSEd Tanous                         if (hostname != nullptr)
5224a0cb85cSEd Tanous                         {
52382695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
5244a0cb85cSEd Tanous                         }
5254a0cb85cSEd Tanous                     }
5264a0cb85cSEd Tanous                 }
5274a0cb85cSEd Tanous             }
5284a0cb85cSEd Tanous         }
5294a0cb85cSEd Tanous     }
5304c9afe43SEd Tanous     return idFound;
5314a0cb85cSEd Tanous }
5324a0cb85cSEd Tanous 
533e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
extractIPV6Data(const std::string & ethifaceId,const dbus::utility::ManagedObjectType & dbusData,std::vector<IPv6AddressData> & ipv6Config)53477179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
535711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
53677179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
537e48c0fc5SRavi Teja {
538bd79bce8SPatrick Williams     const std::string ipPathStart =
539bd79bce8SPatrick Williams         "/xyz/openbmc_project/network/" + ethifaceId;
540e48c0fc5SRavi Teja 
541e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
542e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
54381ce609eSEd Tanous     for (const auto& objpath : dbusData)
544e48c0fc5SRavi Teja     {
545e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
546353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
547e48c0fc5SRavi Teja         {
5489eb808c1SEd Tanous             for (const auto& interface : objpath.second)
549e48c0fc5SRavi Teja             {
550e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
551e48c0fc5SRavi Teja                 {
552bd79bce8SPatrick Williams                     auto type = std::ranges::find_if(
553bd79bce8SPatrick Williams                         interface.second, [](const auto& property) {
554353163e9STony Lee                             return property.first == "Type";
555353163e9STony Lee                         });
556353163e9STony Lee                     if (type == interface.second.end())
557353163e9STony Lee                     {
558353163e9STony Lee                         continue;
559353163e9STony Lee                     }
560353163e9STony Lee 
561353163e9STony Lee                     const std::string* typeStr =
562353163e9STony Lee                         std::get_if<std::string>(&type->second);
563353163e9STony Lee 
564353163e9STony Lee                     if (typeStr == nullptr ||
565353163e9STony Lee                         (*typeStr !=
566353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
567353163e9STony Lee                     {
568353163e9STony Lee                         continue;
569353163e9STony Lee                     }
570353163e9STony Lee 
571e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
572e48c0fc5SRavi Teja                     // appropriate
57377179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5742c70f800SEd Tanous                     ipv6Address.id =
575353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5769eb808c1SEd Tanous                     for (const auto& property : interface.second)
577e48c0fc5SRavi Teja                     {
578e48c0fc5SRavi Teja                         if (property.first == "Address")
579e48c0fc5SRavi Teja                         {
580e48c0fc5SRavi Teja                             const std::string* address =
581e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
582e48c0fc5SRavi Teja                             if (address != nullptr)
583e48c0fc5SRavi Teja                             {
5842c70f800SEd Tanous                                 ipv6Address.address = *address;
585e48c0fc5SRavi Teja                             }
586e48c0fc5SRavi Teja                         }
587e48c0fc5SRavi Teja                         else if (property.first == "Origin")
588e48c0fc5SRavi Teja                         {
589e48c0fc5SRavi Teja                             const std::string* origin =
590e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
591e48c0fc5SRavi Teja                             if (origin != nullptr)
592e48c0fc5SRavi Teja                             {
5932c70f800SEd Tanous                                 ipv6Address.origin =
594e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
595e48c0fc5SRavi Teja                                                                         false);
596e48c0fc5SRavi Teja                             }
597e48c0fc5SRavi Teja                         }
598e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
599e48c0fc5SRavi Teja                         {
600e48c0fc5SRavi Teja                             const uint8_t* prefix =
601e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
602e48c0fc5SRavi Teja                             if (prefix != nullptr)
603e48c0fc5SRavi Teja                             {
6042c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
605e48c0fc5SRavi Teja                             }
606e48c0fc5SRavi Teja                         }
607889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
608889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
609889ff694SAsmitha Karunanithi                         {
610889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
611889ff694SAsmitha Karunanithi                         }
612e48c0fc5SRavi Teja                         else
613e48c0fc5SRavi Teja                         {
61462598e31SEd Tanous                             BMCWEB_LOG_ERROR(
61562598e31SEd Tanous                                 "Got extra property: {} on the {} object",
61662598e31SEd Tanous                                 property.first, objpath.first.str);
617e48c0fc5SRavi Teja                         }
618e48c0fc5SRavi Teja                     }
619e48c0fc5SRavi Teja                 }
620e48c0fc5SRavi Teja             }
621e48c0fc5SRavi Teja         }
622e48c0fc5SRavi Teja     }
623e48c0fc5SRavi Teja }
624e48c0fc5SRavi Teja 
6254a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
extractIPData(const std::string & ethifaceId,const dbus::utility::ManagedObjectType & dbusData,std::vector<IPv4AddressData> & ipv4Config)62677179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
627711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
62877179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
6294a0cb85cSEd Tanous {
630bd79bce8SPatrick Williams     const std::string ipPathStart =
631bd79bce8SPatrick Williams         "/xyz/openbmc_project/network/" + ethifaceId;
6324a0cb85cSEd Tanous 
6334a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
6344a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
63581ce609eSEd Tanous     for (const auto& objpath : dbusData)
6364a0cb85cSEd Tanous     {
6374a0cb85cSEd Tanous         // Check if proper pattern for object path appears
638353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
6394a0cb85cSEd Tanous         {
6409eb808c1SEd Tanous             for (const auto& interface : objpath.second)
6414a0cb85cSEd Tanous             {
6424a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
6434a0cb85cSEd Tanous                 {
644bd79bce8SPatrick Williams                     auto type = std::ranges::find_if(
645bd79bce8SPatrick Williams                         interface.second, [](const auto& property) {
646353163e9STony Lee                             return property.first == "Type";
647353163e9STony Lee                         });
648353163e9STony Lee                     if (type == interface.second.end())
649353163e9STony Lee                     {
650353163e9STony Lee                         continue;
651353163e9STony Lee                     }
652353163e9STony Lee 
653353163e9STony Lee                     const std::string* typeStr =
654353163e9STony Lee                         std::get_if<std::string>(&type->second);
655353163e9STony Lee 
656353163e9STony Lee                     if (typeStr == nullptr ||
657353163e9STony Lee                         (*typeStr !=
658353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
659353163e9STony Lee                     {
660353163e9STony Lee                         continue;
661353163e9STony Lee                     }
662353163e9STony Lee 
6634a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6644a0cb85cSEd Tanous                     // appropriate
66577179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6662c70f800SEd Tanous                     ipv4Address.id =
667353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6689eb808c1SEd Tanous                     for (const auto& property : interface.second)
6694a0cb85cSEd Tanous                     {
6704a0cb85cSEd Tanous                         if (property.first == "Address")
6714a0cb85cSEd Tanous                         {
6724a0cb85cSEd Tanous                             const std::string* address =
673abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6744a0cb85cSEd Tanous                             if (address != nullptr)
6754a0cb85cSEd Tanous                             {
6762c70f800SEd Tanous                                 ipv4Address.address = *address;
6774a0cb85cSEd Tanous                             }
6784a0cb85cSEd Tanous                         }
6794a0cb85cSEd Tanous                         else if (property.first == "Origin")
6804a0cb85cSEd Tanous                         {
6814a0cb85cSEd Tanous                             const std::string* origin =
682abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6834a0cb85cSEd Tanous                             if (origin != nullptr)
6844a0cb85cSEd Tanous                             {
6852c70f800SEd Tanous                                 ipv4Address.origin =
6864a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6874a0cb85cSEd Tanous                                                                         true);
6884a0cb85cSEd Tanous                             }
6894a0cb85cSEd Tanous                         }
6904a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6914a0cb85cSEd Tanous                         {
6924a0cb85cSEd Tanous                             const uint8_t* mask =
693abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6944a0cb85cSEd Tanous                             if (mask != nullptr)
6954a0cb85cSEd Tanous                             {
6964a0cb85cSEd Tanous                                 // convert it to the string
6972c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6984a0cb85cSEd Tanous                             }
6994a0cb85cSEd Tanous                         }
700889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
701889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
702889ff694SAsmitha Karunanithi                         {
703889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
704889ff694SAsmitha Karunanithi                         }
7054a0cb85cSEd Tanous                         else
7064a0cb85cSEd Tanous                         {
70762598e31SEd Tanous                             BMCWEB_LOG_ERROR(
70862598e31SEd Tanous                                 "Got extra property: {} on the {} object",
70962598e31SEd Tanous                                 property.first, objpath.first.str);
7104a0cb85cSEd Tanous                         }
7114a0cb85cSEd Tanous                     }
7124a0cb85cSEd Tanous                     // Check if given address is local, or global
7132c70f800SEd Tanous                     ipv4Address.linktype =
71411ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
71518659d10SJohnathan Mantey                             ? LinkType::Local
71618659d10SJohnathan Mantey                             : LinkType::Global;
7174a0cb85cSEd Tanous                 }
7184a0cb85cSEd Tanous             }
7194a0cb85cSEd Tanous         }
7204a0cb85cSEd Tanous     }
7214a0cb85cSEd Tanous }
722588c3f0dSKowalski, Kamil 
723588c3f0dSKowalski, Kamil /**
724743eb1c0SJohnathan Mantey  * @brief Modifies the default gateway assigned to the NIC
725743eb1c0SJohnathan Mantey  *
726743eb1c0SJohnathan Mantey  * @param[in] ifaceId     Id of network interface whose default gateway is to be
727743eb1c0SJohnathan Mantey  *                        changed
728743eb1c0SJohnathan Mantey  * @param[in] gateway     The new gateway value. Assigning an empty string
729743eb1c0SJohnathan Mantey  *                        causes the gateway to be deleted
730743eb1c0SJohnathan Mantey  * @param[io] asyncResp   Response object that will be returned to client
731743eb1c0SJohnathan Mantey  *
732743eb1c0SJohnathan Mantey  * @return None
733743eb1c0SJohnathan Mantey  */
updateIPv4DefaultGateway(const std::string & ifaceId,const std::string & gateway,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)734743eb1c0SJohnathan Mantey inline void updateIPv4DefaultGateway(
735743eb1c0SJohnathan Mantey     const std::string& ifaceId, const std::string& gateway,
736743eb1c0SJohnathan Mantey     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
737743eb1c0SJohnathan Mantey {
738743eb1c0SJohnathan Mantey     setDbusProperty(
739e93abac6SGinu George         asyncResp, "Gateway", "xyz.openbmc_project.Network",
740743eb1c0SJohnathan Mantey         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
741743eb1c0SJohnathan Mantey             ifaceId,
742743eb1c0SJohnathan Mantey         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
743e93abac6SGinu George         gateway);
744743eb1c0SJohnathan Mantey }
745743eb1c0SJohnathan Mantey 
746743eb1c0SJohnathan Mantey /**
747743eb1c0SJohnathan Mantey  * @brief Deletes given static IP address for the interface
748179db1d7SKowalski, Kamil  *
749179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
750179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
751179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
752179db1d7SKowalski, Kamil  *
753179db1d7SKowalski, Kamil  * @return None
754179db1d7SKowalski, Kamil  */
deleteIPAddress(const std::string & ifaceId,const std::string & ipHash,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)7559c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
7569c5e585cSRavi Teja                             const std::string& ipHash,
7578d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7581abe55efSEd Tanous {
75955c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7605e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
7611abe55efSEd Tanous             if (ec)
7621abe55efSEd Tanous             {
763a08b46ccSJason M. Bills                 messages::internalError(asyncResp->res);
7641abe55efSEd Tanous             }
765179db1d7SKowalski, Kamil         },
766179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
7679c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
768179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
769179db1d7SKowalski, Kamil }
770179db1d7SKowalski, Kamil 
771179db1d7SKowalski, Kamil /**
77201784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
773179db1d7SKowalski, Kamil  *
77401784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
77501784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
77601784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
77701784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
778179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
779179db1d7SKowalski, Kamil  *
780179db1d7SKowalski, Kamil  * @return None
781179db1d7SKowalski, Kamil  */
createIPv4(const std::string & ifaceId,uint8_t prefixLength,const std::string & gateway,const std::string & address,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)782cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
783cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7848d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7851abe55efSEd Tanous {
786bd79bce8SPatrick Williams     auto createIpHandler =
787bd79bce8SPatrick Williams         [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
7881abe55efSEd Tanous             if (ec)
7891abe55efSEd Tanous             {
790a08b46ccSJason M. Bills                 messages::internalError(asyncResp->res);
7919010ec2eSRavi Teja                 return;
792179db1d7SKowalski, Kamil             }
7939010ec2eSRavi Teja         };
7949010ec2eSRavi Teja 
7959010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7969010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
797179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
798179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
79901784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
800179db1d7SKowalski, Kamil         gateway);
801179db1d7SKowalski, Kamil }
802e48c0fc5SRavi Teja 
803e48c0fc5SRavi Teja /**
804743eb1c0SJohnathan Mantey  * @brief Deletes the IP entry for this interface and creates a replacement
805743eb1c0SJohnathan Mantey  * static entry
80601784826SJohnathan Mantey  *
80701784826SJohnathan Mantey  * @param[in] ifaceId        Id of interface upon which to create the IPv6 entry
80801784826SJohnathan Mantey  * @param[in] id             The unique hash entry identifying the DBus entry
809743eb1c0SJohnathan Mantey  * @param[in] prefixLength   Prefix syntax for the subnet mask
810743eb1c0SJohnathan Mantey  * @param[in] address        Address to assign to this interface
811743eb1c0SJohnathan Mantey  * @param[in] numStaticAddrs Count of IPv4 static addresses
81201784826SJohnathan Mantey  * @param[io] asyncResp      Response object that will be returned to client
81301784826SJohnathan Mantey  *
81401784826SJohnathan Mantey  * @return None
81501784826SJohnathan Mantey  */
8169c5e585cSRavi Teja 
deleteAndCreateIPAddress(IpVersion version,const std::string & ifaceId,const std::string & id,uint8_t prefixLength,const std::string & address,const std::string & gateway,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)8179c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
8189c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
8198d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
8209c5e585cSRavi Teja     const std::string& gateway,
8218d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
82201784826SJohnathan Mantey {
82301784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
8249c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
8259c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
82601784826SJohnathan Mantey             if (ec)
82701784826SJohnathan Mantey             {
82801784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
82901784826SJohnathan Mantey             }
8309c5e585cSRavi Teja             std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
8319c5e585cSRavi Teja             protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
83201784826SJohnathan Mantey             crow::connections::systemBus->async_method_call(
8335e7e2dc5SEd Tanous                 [asyncResp](const boost::system::error_code& ec2) {
83423a21a1cSEd Tanous                     if (ec2)
83501784826SJohnathan Mantey                     {
83601784826SJohnathan Mantey                         messages::internalError(asyncResp->res);
83701784826SJohnathan Mantey                     }
83801784826SJohnathan Mantey                 },
83901784826SJohnathan Mantey                 "xyz.openbmc_project.Network",
84001784826SJohnathan Mantey                 "/xyz/openbmc_project/network/" + ifaceId,
841bd79bce8SPatrick Williams                 "xyz.openbmc_project.Network.IP.Create", "IP", protocol,
842bd79bce8SPatrick Williams                 address, prefixLength, gateway);
84301784826SJohnathan Mantey         },
84401784826SJohnathan Mantey         "xyz.openbmc_project.Network",
8459c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
84601784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
84701784826SJohnathan Mantey }
84801784826SJohnathan Mantey 
extractIPv6DefaultGatewayData(const std::string & ethifaceId,const dbus::utility::ManagedObjectType & dbusData,std::vector<StaticGatewayData> & staticGatewayConfig)849ce73d5c8SSunitha Harish inline bool extractIPv6DefaultGatewayData(
850ce73d5c8SSunitha Harish     const std::string& ethifaceId,
851ce73d5c8SSunitha Harish     const dbus::utility::ManagedObjectType& dbusData,
852ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>& staticGatewayConfig)
853ce73d5c8SSunitha Harish {
854ce73d5c8SSunitha Harish     std::string staticGatewayPathStart("/xyz/openbmc_project/network/");
855ce73d5c8SSunitha Harish     staticGatewayPathStart += ethifaceId;
856ce73d5c8SSunitha Harish 
857ce73d5c8SSunitha Harish     for (const auto& objpath : dbusData)
858ce73d5c8SSunitha Harish     {
859ce73d5c8SSunitha Harish         if (!std::string_view(objpath.first.str)
860ce73d5c8SSunitha Harish                  .starts_with(staticGatewayPathStart))
861ce73d5c8SSunitha Harish         {
862ce73d5c8SSunitha Harish             continue;
863ce73d5c8SSunitha Harish         }
864ce73d5c8SSunitha Harish         for (const auto& interface : objpath.second)
865ce73d5c8SSunitha Harish         {
866ce73d5c8SSunitha Harish             if (interface.first != "xyz.openbmc_project.Network.StaticGateway")
867ce73d5c8SSunitha Harish             {
868ce73d5c8SSunitha Harish                 continue;
869ce73d5c8SSunitha Harish             }
870ce73d5c8SSunitha Harish             StaticGatewayData& staticGateway =
871ce73d5c8SSunitha Harish                 staticGatewayConfig.emplace_back();
872ce73d5c8SSunitha Harish             staticGateway.id = objpath.first.filename();
873ce73d5c8SSunitha Harish 
874ce73d5c8SSunitha Harish             bool success = sdbusplus::unpackPropertiesNoThrow(
875ce73d5c8SSunitha Harish                 redfish::dbus_utils::UnpackErrorPrinter(), interface.second,
876ab0d4390SRavi Teja                 "Gateway", staticGateway.gateway, "ProtocolType",
877ce73d5c8SSunitha Harish                 staticGateway.protocol);
878ce73d5c8SSunitha Harish             if (!success)
879ce73d5c8SSunitha Harish             {
880ce73d5c8SSunitha Harish                 return false;
881ce73d5c8SSunitha Harish             }
882ce73d5c8SSunitha Harish         }
883ce73d5c8SSunitha Harish     }
884ce73d5c8SSunitha Harish     return true;
885ce73d5c8SSunitha Harish }
886ce73d5c8SSunitha Harish 
88701784826SJohnathan Mantey /**
888e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
889e48c0fc5SRavi Teja  *
890e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
891e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
892e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
893e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
894e48c0fc5SRavi Teja  *
895e48c0fc5SRavi Teja  * @return None
896e48c0fc5SRavi Teja  */
createIPv6(const std::string & ifaceId,uint8_t prefixLength,const std::string & address,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)89701784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
89801784826SJohnathan Mantey                        const std::string& address,
8998d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
900e48c0fc5SRavi Teja {
901ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
902ce73d5c8SSunitha Harish     path /= ifaceId;
903ce73d5c8SSunitha Harish 
904bd79bce8SPatrick Williams     auto createIpHandler =
905bd79bce8SPatrick Williams         [asyncResp, address](const boost::system::error_code& ec) {
906e48c0fc5SRavi Teja             if (ec)
907e48c0fc5SRavi Teja             {
908fc23ef8aSNitin Kumar Kotania                 if (ec == boost::system::errc::io_error)
909fc23ef8aSNitin Kumar Kotania                 {
910fc23ef8aSNitin Kumar Kotania                     messages::propertyValueFormatError(asyncResp->res, address,
911fc23ef8aSNitin Kumar Kotania                                                        "Address");
912fc23ef8aSNitin Kumar Kotania                 }
913fc23ef8aSNitin Kumar Kotania                 else
914fc23ef8aSNitin Kumar Kotania                 {
915e48c0fc5SRavi Teja                     messages::internalError(asyncResp->res);
916e48c0fc5SRavi Teja                 }
917fc23ef8aSNitin Kumar Kotania             }
918e48c0fc5SRavi Teja         };
919ce73d5c8SSunitha Harish     // Passing null for gateway, as per redfish spec IPv6StaticAddresses
920ce73d5c8SSunitha Harish     // object does not have associated gateway property
921e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
922ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
923e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
924e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
925e48c0fc5SRavi Teja         "");
926e48c0fc5SRavi Teja }
927e48c0fc5SRavi Teja 
928179db1d7SKowalski, Kamil /**
929ce73d5c8SSunitha Harish  * @brief Deletes given IPv6 Static Gateway
930ce73d5c8SSunitha Harish  *
931ce73d5c8SSunitha Harish  * @param[in] ifaceId     Id of interface whose IP should be deleted
932ce73d5c8SSunitha Harish  * @param[in] ipHash      DBus Hash id of IP that should be deleted
933ce73d5c8SSunitha Harish  * @param[io] asyncResp   Response object that will be returned to client
934ce73d5c8SSunitha Harish  *
935ce73d5c8SSunitha Harish  * @return None
936ce73d5c8SSunitha Harish  */
deleteIPv6Gateway(std::string_view ifaceId,std::string_view gatewayId,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)937*504af5a0SPatrick Williams inline void deleteIPv6Gateway(
938*504af5a0SPatrick Williams     std::string_view ifaceId, std::string_view gatewayId,
939ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
940ce73d5c8SSunitha Harish {
941ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
942739b27b2SRavi Teja     path /= ifaceId;
943ce73d5c8SSunitha Harish     path /= gatewayId;
944ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
945ce73d5c8SSunitha Harish         [asyncResp](const boost::system::error_code& ec) {
946ce73d5c8SSunitha Harish             if (ec)
947ce73d5c8SSunitha Harish             {
948ce73d5c8SSunitha Harish                 messages::internalError(asyncResp->res);
949ce73d5c8SSunitha Harish             }
950ce73d5c8SSunitha Harish         },
951ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
952ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
953ce73d5c8SSunitha Harish }
954ce73d5c8SSunitha Harish 
955ce73d5c8SSunitha Harish /**
956ce73d5c8SSunitha Harish  * @brief Creates IPv6 static default gateway with given data
957ce73d5c8SSunitha Harish  *
958ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose IP should be added
959ce73d5c8SSunitha Harish  * @param[in] gateway      Gateway address that needs to be added
960ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
961ce73d5c8SSunitha Harish  *
962ce73d5c8SSunitha Harish  * @return None
963ce73d5c8SSunitha Harish  */
createIPv6DefaultGateway(std::string_view ifaceId,const std::string & gateway,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)964ce73d5c8SSunitha Harish inline void createIPv6DefaultGateway(
965cf91c8c4SAsmitha Karunanithi     std::string_view ifaceId, const std::string& gateway,
966ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
967ce73d5c8SSunitha Harish {
968ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
969ce73d5c8SSunitha Harish     path /= ifaceId;
970ce73d5c8SSunitha Harish     auto createIpHandler = [asyncResp](const boost::system::error_code& ec) {
971ce73d5c8SSunitha Harish         if (ec)
972ce73d5c8SSunitha Harish         {
973ce73d5c8SSunitha Harish             messages::internalError(asyncResp->res);
974ce73d5c8SSunitha Harish         }
975ce73d5c8SSunitha Harish     };
976ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
977ce73d5c8SSunitha Harish         std::move(createIpHandler), "xyz.openbmc_project.Network", path,
978ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network.StaticGateway.Create", "StaticGateway",
979ab0d4390SRavi Teja         gateway, "xyz.openbmc_project.Network.IP.Protocol.IPv6");
980ce73d5c8SSunitha Harish }
981ce73d5c8SSunitha Harish 
982ce73d5c8SSunitha Harish /**
983ce73d5c8SSunitha Harish  * @brief Deletes the IPv6 default gateway entry for this interface and
984ce73d5c8SSunitha Harish  * creates a replacement IPv6 default gateway entry
985ce73d5c8SSunitha Harish  *
986ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface upon which to create the IPv6
987ce73d5c8SSunitha Harish  * entry
988ce73d5c8SSunitha Harish  * @param[in] gateway      IPv6 gateway to assign to this interface
989ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
990ce73d5c8SSunitha Harish  *
991ce73d5c8SSunitha Harish  * @return None
992ce73d5c8SSunitha Harish  */
deleteAndCreateIPv6DefaultGateway(std::string_view ifaceId,std::string_view gatewayId,const std::string & gateway,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)993ce73d5c8SSunitha Harish inline void deleteAndCreateIPv6DefaultGateway(
994ce73d5c8SSunitha Harish     std::string_view ifaceId, std::string_view gatewayId,
995cf91c8c4SAsmitha Karunanithi     const std::string& gateway,
996ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
997ce73d5c8SSunitha Harish {
998ce73d5c8SSunitha Harish     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
999739b27b2SRavi Teja     path /= ifaceId;
1000ce73d5c8SSunitha Harish     path /= gatewayId;
1001ce73d5c8SSunitha Harish     crow::connections::systemBus->async_method_call(
1002ab0d4390SRavi Teja         [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
1003ce73d5c8SSunitha Harish             if (ec)
1004ce73d5c8SSunitha Harish             {
1005ce73d5c8SSunitha Harish                 messages::internalError(asyncResp->res);
1006ce73d5c8SSunitha Harish                 return;
1007ce73d5c8SSunitha Harish             }
1008ab0d4390SRavi Teja             createIPv6DefaultGateway(ifaceId, gateway, asyncResp);
1009ce73d5c8SSunitha Harish         },
1010ce73d5c8SSunitha Harish         "xyz.openbmc_project.Network", path,
1011ce73d5c8SSunitha Harish         "xyz.openbmc_project.Object.Delete", "Delete");
1012ce73d5c8SSunitha Harish }
1013ce73d5c8SSunitha Harish 
1014ce73d5c8SSunitha Harish /**
1015ce73d5c8SSunitha Harish  * @brief Sets IPv6 default gateway with given data
1016ce73d5c8SSunitha Harish  *
1017ce73d5c8SSunitha Harish  * @param[in] ifaceId      Id of interface whose gateway should be added
1018ce73d5c8SSunitha Harish  * @param[in] input        Contains address that needs to be added
1019ce73d5c8SSunitha Harish  * @param[in] staticGatewayData  Current static gateways in the system
1020ce73d5c8SSunitha Harish  * @param[io] asyncResp    Response object that will be returned to client
1021ce73d5c8SSunitha Harish  *
1022ce73d5c8SSunitha Harish  * @return None
1023ce73d5c8SSunitha Harish  */
1024ce73d5c8SSunitha Harish 
handleIPv6DefaultGateway(const std::string & ifaceId,std::vector<std::variant<nlohmann::json::object_t,std::nullptr_t>> & input,const std::vector<StaticGatewayData> & staticGatewayData,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1025ce73d5c8SSunitha Harish inline void handleIPv6DefaultGateway(
10263dfed536SEd Tanous     const std::string& ifaceId,
10273dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
1028ce73d5c8SSunitha Harish     const std::vector<StaticGatewayData>& staticGatewayData,
1029ce73d5c8SSunitha Harish     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1030ce73d5c8SSunitha Harish {
1031ce73d5c8SSunitha Harish     size_t entryIdx = 1;
1032ce73d5c8SSunitha Harish     std::vector<StaticGatewayData>::const_iterator staticGatewayEntry =
1033ce73d5c8SSunitha Harish         staticGatewayData.begin();
1034ce73d5c8SSunitha Harish 
10353dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
10363dfed536SEd Tanous          input)
1037ce73d5c8SSunitha Harish     {
1038ce73d5c8SSunitha Harish         // find the next gateway entry
1039ce73d5c8SSunitha Harish         while (staticGatewayEntry != staticGatewayData.end())
1040ce73d5c8SSunitha Harish         {
1041ce73d5c8SSunitha Harish             if (staticGatewayEntry->protocol ==
1042ce73d5c8SSunitha Harish                 "xyz.openbmc_project.Network.IP.Protocol.IPv6")
1043ce73d5c8SSunitha Harish             {
1044ce73d5c8SSunitha Harish                 break;
1045ce73d5c8SSunitha Harish             }
1046ce73d5c8SSunitha Harish             staticGatewayEntry++;
1047ce73d5c8SSunitha Harish         }
1048bd79bce8SPatrick Williams         std::string pathString =
1049bd79bce8SPatrick Williams             "IPv6StaticDefaultGateways/" + std::to_string(entryIdx);
10503dfed536SEd Tanous         nlohmann::json::object_t* obj =
10513dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
10523dfed536SEd Tanous         if (obj == nullptr)
1053ce73d5c8SSunitha Harish         {
1054ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1055ce73d5c8SSunitha Harish             {
1056ce73d5c8SSunitha Harish                 messages::resourceCannotBeDeleted(asyncResp->res);
1057ce73d5c8SSunitha Harish                 return;
1058ce73d5c8SSunitha Harish             }
1059739b27b2SRavi Teja             deleteIPv6Gateway(ifaceId, staticGatewayEntry->id, asyncResp);
1060ce73d5c8SSunitha Harish             return;
1061ce73d5c8SSunitha Harish         }
10623dfed536SEd Tanous         if (obj->empty())
1063ce73d5c8SSunitha Harish         {
1064ce73d5c8SSunitha Harish             // Do nothing, but make sure the entry exists.
1065ce73d5c8SSunitha Harish             if (staticGatewayEntry == staticGatewayData.end())
1066ce73d5c8SSunitha Harish             {
10673dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
1068ce73d5c8SSunitha Harish                                                    pathString);
1069ce73d5c8SSunitha Harish                 return;
1070ce73d5c8SSunitha Harish             }
1071ce73d5c8SSunitha Harish         }
1072ce73d5c8SSunitha Harish         std::optional<std::string> address;
1073ce73d5c8SSunitha Harish 
1074ab0d4390SRavi Teja         if (!json_util::readJsonObject(*obj, asyncResp->res, "Address",
1075ab0d4390SRavi Teja                                        address))
1076ce73d5c8SSunitha Harish         {
1077ce73d5c8SSunitha Harish             return;
1078ce73d5c8SSunitha Harish         }
1079ce73d5c8SSunitha Harish         const std::string* addr = nullptr;
1080ce73d5c8SSunitha Harish         if (address)
1081ce73d5c8SSunitha Harish         {
1082ce73d5c8SSunitha Harish             addr = &(*address);
1083ce73d5c8SSunitha Harish         }
1084ce73d5c8SSunitha Harish         else if (staticGatewayEntry != staticGatewayData.end())
1085ce73d5c8SSunitha Harish         {
1086ce73d5c8SSunitha Harish             addr = &(staticGatewayEntry->gateway);
1087ce73d5c8SSunitha Harish         }
1088ce73d5c8SSunitha Harish         else
1089ce73d5c8SSunitha Harish         {
1090ce73d5c8SSunitha Harish             messages::propertyMissing(asyncResp->res, pathString + "/Address");
1091ce73d5c8SSunitha Harish             return;
1092ce73d5c8SSunitha Harish         }
1093ce73d5c8SSunitha Harish         if (staticGatewayEntry != staticGatewayData.end())
1094ce73d5c8SSunitha Harish         {
1095ce73d5c8SSunitha Harish             deleteAndCreateIPv6DefaultGateway(ifaceId, staticGatewayEntry->id,
1096ab0d4390SRavi Teja                                               *addr, asyncResp);
1097ce73d5c8SSunitha Harish             staticGatewayEntry++;
1098ce73d5c8SSunitha Harish         }
1099ce73d5c8SSunitha Harish         else
1100ce73d5c8SSunitha Harish         {
1101ab0d4390SRavi Teja             createIPv6DefaultGateway(ifaceId, *addr, asyncResp);
1102ce73d5c8SSunitha Harish         }
1103ce73d5c8SSunitha Harish         entryIdx++;
1104ce73d5c8SSunitha Harish     }
1105ce73d5c8SSunitha Harish }
1106ce73d5c8SSunitha Harish 
1107ce73d5c8SSunitha Harish /**
1108179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
1109179db1d7SKowalski, Kamil  * Object
1110179db1d7SKowalski, Kamil  * from EntityManager Network Manager
11114a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
1112179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
1113179db1d7SKowalski, Kamil  * into JSON
1114179db1d7SKowalski, Kamil  */
1115179db1d7SKowalski, Kamil template <typename CallbackFunc>
getEthernetIfaceData(const std::string & ethifaceId,CallbackFunc && callback)111681ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
11171abe55efSEd Tanous                           CallbackFunc&& callback)
11181abe55efSEd Tanous {
1119f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1120f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1121f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
1122f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
11238cb2c024SEd Tanous          callback = std::forward<CallbackFunc>(callback)](
11248b24275dSEd Tanous             const boost::system::error_code& ec,
11253dfed536SEd Tanous             const dbus::utility::ManagedObjectType& resp) mutable {
112655c7b7a2SEd Tanous             EthernetInterfaceData ethData{};
112777179532SEd Tanous             std::vector<IPv4AddressData> ipv4Data;
112877179532SEd Tanous             std::vector<IPv6AddressData> ipv6Data;
1129ce73d5c8SSunitha Harish             std::vector<StaticGatewayData> ipv6GatewayData;
1130179db1d7SKowalski, Kamil 
11318b24275dSEd Tanous             if (ec)
11321abe55efSEd Tanous             {
1133ce73d5c8SSunitha Harish                 callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1134179db1d7SKowalski, Kamil                 return;
1135179db1d7SKowalski, Kamil             }
1136179db1d7SKowalski, Kamil 
1137bd79bce8SPatrick Williams             bool found =
1138bd79bce8SPatrick Williams                 extractEthernetInterfaceData(ethifaceId, resp, ethData);
11394c9afe43SEd Tanous             if (!found)
11404c9afe43SEd Tanous             {
1141ce73d5c8SSunitha Harish                 callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
11424c9afe43SEd Tanous                 return;
11434c9afe43SEd Tanous             }
11444c9afe43SEd Tanous 
11452c70f800SEd Tanous             extractIPData(ethifaceId, resp, ipv4Data);
1146179db1d7SKowalski, Kamil             // Fix global GW
11471abe55efSEd Tanous             for (IPv4AddressData& ipv4 : ipv4Data)
11481abe55efSEd Tanous             {
1149c619141bSRavi Teja                 if (((ipv4.linktype == LinkType::Global) &&
1150c619141bSRavi Teja                      (ipv4.gateway == "0.0.0.0")) ||
11519010ec2eSRavi Teja                     (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
11521abe55efSEd Tanous                 {
115382695a5bSJiaqing Zhao                     ipv4.gateway = ethData.defaultGateway;
1154179db1d7SKowalski, Kamil                 }
1155179db1d7SKowalski, Kamil             }
1156179db1d7SKowalski, Kamil 
11572c70f800SEd Tanous             extractIPV6Data(ethifaceId, resp, ipv6Data);
1158bd79bce8SPatrick Williams             if (!extractIPv6DefaultGatewayData(ethifaceId, resp,
1159bd79bce8SPatrick Williams                                                ipv6GatewayData))
1160ce73d5c8SSunitha Harish             {
1161ce73d5c8SSunitha Harish                 callback(false, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1162ce73d5c8SSunitha Harish             }
11634e0453b1SGunnar Mills             // Finally make a callback with useful data
1164ce73d5c8SSunitha Harish             callback(true, ethData, ipv4Data, ipv6Data, ipv6GatewayData);
1165f5892d0dSGeorge Liu         });
1166271584abSEd Tanous }
1167179db1d7SKowalski, Kamil 
1168179db1d7SKowalski, Kamil /**
11699391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
11709391bb9cSRapkiewicz, Pawel  * Manager
11711abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
11721abe55efSEd Tanous  * into JSON.
11739391bb9cSRapkiewicz, Pawel  */
11749391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
getEthernetIfaceList(CallbackFunc && callback)11751abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
11761abe55efSEd Tanous {
1177f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1178f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
1179f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
11808cb2c024SEd Tanous         [callback = std::forward<CallbackFunc>(callback)](
11818b24275dSEd Tanous             const boost::system::error_code& ec,
1182f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
11831abe55efSEd Tanous             // Callback requires vector<string> to retrieve all available
11841abe55efSEd Tanous             // ethernet interfaces
118577179532SEd Tanous             std::vector<std::string> ifaceList;
11862c70f800SEd Tanous             ifaceList.reserve(resp.size());
11878b24275dSEd Tanous             if (ec)
11881abe55efSEd Tanous             {
11892c70f800SEd Tanous                 callback(false, ifaceList);
11909391bb9cSRapkiewicz, Pawel                 return;
11919391bb9cSRapkiewicz, Pawel             }
11929391bb9cSRapkiewicz, Pawel 
11939391bb9cSRapkiewicz, Pawel             // Iterate over all retrieved ObjectPaths.
11944a0cb85cSEd Tanous             for (const auto& objpath : resp)
11951abe55efSEd Tanous             {
11969391bb9cSRapkiewicz, Pawel                 // And all interfaces available for certain ObjectPath.
11974a0cb85cSEd Tanous                 for (const auto& interface : objpath.second)
11981abe55efSEd Tanous                 {
11991abe55efSEd Tanous                     // If interface is
12004a0cb85cSEd Tanous                     // xyz.openbmc_project.Network.EthernetInterface, this is
12014a0cb85cSEd Tanous                     // what we're looking for.
12029391bb9cSRapkiewicz, Pawel                     if (interface.first ==
12031abe55efSEd Tanous                         "xyz.openbmc_project.Network.EthernetInterface")
12041abe55efSEd Tanous                     {
12052dfd18efSEd Tanous                         std::string ifaceId = objpath.first.filename();
12062dfd18efSEd Tanous                         if (ifaceId.empty())
12071abe55efSEd Tanous                         {
12082dfd18efSEd Tanous                             continue;
12099391bb9cSRapkiewicz, Pawel                         }
12102dfd18efSEd Tanous                         // and put it into output vector.
121177179532SEd Tanous                         ifaceList.emplace_back(ifaceId);
12129391bb9cSRapkiewicz, Pawel                     }
12139391bb9cSRapkiewicz, Pawel                 }
12149391bb9cSRapkiewicz, Pawel             }
12152c5875a2SEd Tanous 
12163544d2a7SEd Tanous             std::ranges::sort(ifaceList, AlphanumLess<std::string>());
12172c5875a2SEd Tanous 
1218a434f2bdSEd Tanous             // Finally make a callback with useful data
12192c70f800SEd Tanous             callback(true, ifaceList);
1220f5892d0dSGeorge Liu         });
1221271584abSEd Tanous }
12229391bb9cSRapkiewicz, Pawel 
handleHostnamePatch(const std::string & hostname,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1223*504af5a0SPatrick Williams inline void handleHostnamePatch(
1224*504af5a0SPatrick Williams     const std::string& hostname,
12258d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12261abe55efSEd Tanous {
1227ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
1228ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
1229ab6554f1SJoshi-Mansi     {
1230ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
1231ab6554f1SJoshi-Mansi                                            "HostName");
1232ab6554f1SJoshi-Mansi         return;
1233ab6554f1SJoshi-Mansi     }
1234d02aad39SEd Tanous     setDbusProperty(
1235e93abac6SGinu George         asyncResp, "HostName", "xyz.openbmc_project.Network",
1236d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network/config"),
1237d02aad39SEd Tanous         "xyz.openbmc_project.Network.SystemConfiguration", "HostName",
1238e93abac6SGinu George         hostname);
1239588c3f0dSKowalski, Kamil }
1240588c3f0dSKowalski, Kamil 
handleMTUSizePatch(const std::string & ifaceId,const size_t mtuSize,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1241*504af5a0SPatrick Williams inline void handleMTUSizePatch(
1242*504af5a0SPatrick Williams     const std::string& ifaceId, const size_t mtuSize,
124335fb5311STejas Patil     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
124435fb5311STejas Patil {
1245d02aad39SEd Tanous     sdbusplus::message::object_path objPath("/xyz/openbmc_project/network");
1246d02aad39SEd Tanous     objPath /= ifaceId;
1247e93abac6SGinu George     setDbusProperty(asyncResp, "MTUSize", "xyz.openbmc_project.Network",
1248e93abac6SGinu George                     objPath, "xyz.openbmc_project.Network.EthernetInterface",
1249e93abac6SGinu George                     "MTU", mtuSize);
125035fb5311STejas Patil }
125135fb5311STejas Patil 
handleDomainnamePatch(const std::string & ifaceId,const std::string & domainname,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1252bd79bce8SPatrick Williams inline void handleDomainnamePatch(
1253bd79bce8SPatrick Williams     const std::string& ifaceId, const std::string& domainname,
12548d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1255ab6554f1SJoshi-Mansi {
1256ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
1257d02aad39SEd Tanous     setDbusProperty(
1258e93abac6SGinu George         asyncResp, "FQDN", "xyz.openbmc_project.Network",
1259d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1260d02aad39SEd Tanous             ifaceId,
1261e93abac6SGinu George         "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
1262d02aad39SEd Tanous         vectorDomainname);
1263ab6554f1SJoshi-Mansi }
1264ab6554f1SJoshi-Mansi 
isHostnameValid(const std::string & hostname)12654f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1266bf648f77SEd Tanous {
1267bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
12683544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1269bf648f77SEd Tanous     {
1270bf648f77SEd Tanous         return false;
1271bf648f77SEd Tanous     }
1272bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1273bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1274bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1275bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
12764b242749SEd Tanous     const static std::regex pattern(
1277bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1278bf648f77SEd Tanous 
1279bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1280bf648f77SEd Tanous }
1281bf648f77SEd Tanous 
isDomainnameValid(const std::string & domainname)12824f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1283bf648f77SEd Tanous {
1284bf648f77SEd Tanous     // Can have multiple subdomains
1285bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
12864b242749SEd Tanous     const static std::regex pattern(
12870fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1288bf648f77SEd Tanous 
1289bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1290bf648f77SEd Tanous }
1291bf648f77SEd Tanous 
handleFqdnPatch(const std::string & ifaceId,const std::string & fqdn,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)12924f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
12938d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1294ab6554f1SJoshi-Mansi {
1295ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1296ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1297ab6554f1SJoshi-Mansi     {
1298ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1299ab6554f1SJoshi-Mansi         return;
1300ab6554f1SJoshi-Mansi     }
1301ab6554f1SJoshi-Mansi 
1302ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1303ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1304ab6554f1SJoshi-Mansi     {
1305ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1306ab6554f1SJoshi-Mansi         return;
1307ab6554f1SJoshi-Mansi     }
1308ab6554f1SJoshi-Mansi 
1309ab6554f1SJoshi-Mansi     std::string hostname;
1310ab6554f1SJoshi-Mansi     std::string domainname;
1311ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1312ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1313ab6554f1SJoshi-Mansi 
1314ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1315ab6554f1SJoshi-Mansi     {
1316ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1317ab6554f1SJoshi-Mansi         return;
1318ab6554f1SJoshi-Mansi     }
1319ab6554f1SJoshi-Mansi 
1320ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1321ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1322ab6554f1SJoshi-Mansi }
1323ab6554f1SJoshi-Mansi 
handleMACAddressPatch(const std::string & ifaceId,const std::string & macAddress,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1324bd79bce8SPatrick Williams inline void handleMACAddressPatch(
1325bd79bce8SPatrick Williams     const std::string& ifaceId, const std::string& macAddress,
13268d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1327d577665bSRatan Gupta {
1328d02aad39SEd Tanous     setDbusProperty(
1329e93abac6SGinu George         asyncResp, "MACAddress", "xyz.openbmc_project.Network",
1330d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1331d02aad39SEd Tanous             ifaceId,
1332e93abac6SGinu George         "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress);
1333d577665bSRatan Gupta }
1334286b9118SJohnathan Mantey 
setDHCPEnabled(const std::string & ifaceId,const std::string & propertyName,const bool v4Value,const bool v6Value,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)13354f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
13364f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
13374f48d5f6SEd Tanous                            const bool v6Value,
13388d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1339da131a9aSJennifer Lee {
13402c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
1341d02aad39SEd Tanous     setDbusProperty(
1342e93abac6SGinu George         asyncResp, "DHCPv4", "xyz.openbmc_project.Network",
1343d02aad39SEd Tanous         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
1344d02aad39SEd Tanous             ifaceId,
1345e93abac6SGinu George         "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp);
1346eeedda23SJohnathan Mantey }
1347eeedda23SJohnathan Mantey 
1348e4588158SJishnu CM enum class NetworkType
1349e4588158SJishnu CM {
1350e4588158SJishnu CM     dhcp4,
1351e4588158SJishnu CM     dhcp6
1352e4588158SJishnu CM };
1353e4588158SJishnu CM 
setDHCPConfig(const std::string & propertyName,const bool & value,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & ethifaceId,NetworkType type)1354e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1355e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1356e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1357da131a9aSJennifer Lee {
135862598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
13591847f2a0SAsmitha Karunanithi     std::string redfishPropertyName;
1360e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1361e4588158SJishnu CM     path /= ethifaceId;
1362e4588158SJishnu CM 
1363e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1364e4588158SJishnu CM     {
1365e4588158SJishnu CM         path /= "dhcp4";
13661847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv4";
1367e4588158SJishnu CM     }
1368e4588158SJishnu CM     else
1369e4588158SJishnu CM     {
1370e4588158SJishnu CM         path /= "dhcp6";
13711847f2a0SAsmitha Karunanithi         redfishPropertyName = "DHCPv6";
1372e4588158SJishnu CM     }
1373e4588158SJishnu CM 
1374e93abac6SGinu George     setDbusProperty(
1375e93abac6SGinu George         asyncResp, redfishPropertyName, "xyz.openbmc_project.Network", path,
1376e93abac6SGinu George         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value);
1377da131a9aSJennifer Lee }
1378d577665bSRatan Gupta 
handleSLAACAutoConfigPatch(const std::string & ifaceId,bool ipv6AutoConfigEnabled,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1379b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1380b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1381b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1382b10d8db0SRavi Teja {
1383b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1384b10d8db0SRavi Teja     path /= ifaceId;
1385e93abac6SGinu George     setDbusProperty(asyncResp,
13861847f2a0SAsmitha Karunanithi                     "StatelessAddressAutoConfig/IPv6AutoConfigEnabled",
1387e93abac6SGinu George                     "xyz.openbmc_project.Network", path,
1388e93abac6SGinu George                     "xyz.openbmc_project.Network.EthernetInterface",
1389e93abac6SGinu George                     "IPv6AcceptRA", ipv6AutoConfigEnabled);
1390b10d8db0SRavi Teja }
1391b10d8db0SRavi Teja 
handleDHCPPatch(const std::string & ifaceId,const EthernetInterfaceData & ethData,const DHCPParameters & v4dhcpParms,const DHCPParameters & v6dhcpParms,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)1392bd79bce8SPatrick Williams inline void handleDHCPPatch(
1393bd79bce8SPatrick Williams     const std::string& ifaceId, const EthernetInterfaceData& ethData,
1394bd79bce8SPatrick Williams     const DHCPParameters& v4dhcpParms, const DHCPParameters& v6dhcpParms,
13958d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1396da131a9aSJennifer Lee {
139782695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
139882695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1399da131a9aSJennifer Lee 
1400743eb1c0SJohnathan Mantey     if (ipv4Active)
1401743eb1c0SJohnathan Mantey     {
1402743eb1c0SJohnathan Mantey         updateIPv4DefaultGateway(ifaceId, "", asyncResp);
1403743eb1c0SJohnathan Mantey     }
14041f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
14051f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
14061f8c7b5dSJohnathan Mantey 
14071f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
14081f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1409da131a9aSJennifer Lee     {
1410b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
14111f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
14121f8c7b5dSJohnathan Mantey         {
1413bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1414bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
14151f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1416da131a9aSJennifer Lee             return;
1417da131a9aSJennifer Lee         }
1418b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
14191f8c7b5dSJohnathan Mantey     }
14201f8c7b5dSJohnathan Mantey     else
1421da131a9aSJennifer Lee     {
14221f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
14231f8c7b5dSJohnathan Mantey     }
14241f8c7b5dSJohnathan Mantey 
1425e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1426e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1427e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
14281f8c7b5dSJohnathan Mantey     {
1429e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
14301f8c7b5dSJohnathan Mantey     }
1431e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
14321f8c7b5dSJohnathan Mantey     {
1433e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
14341f8c7b5dSJohnathan Mantey     }
14351f8c7b5dSJohnathan Mantey 
1436e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1437e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1438e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
14391f8c7b5dSJohnathan Mantey     {
1440e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
14411f8c7b5dSJohnathan Mantey     }
1442e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
14431f8c7b5dSJohnathan Mantey     {
1444e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
14451f8c7b5dSJohnathan Mantey     }
14461f8c7b5dSJohnathan Mantey 
144791c441ecSRavi Teja     bool nextUsev4Domain = ethData.domainv4Enabled;
144891c441ecSRavi Teja     bool nextUsev6Domain = ethData.domainv6Enabled;
1449e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
14501f8c7b5dSJohnathan Mantey     {
1451e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
14521f8c7b5dSJohnathan Mantey     }
1453e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
14541f8c7b5dSJohnathan Mantey     {
1455e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
14561f8c7b5dSJohnathan Mantey     }
14571f8c7b5dSJohnathan Mantey 
145862598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
14591f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
14601f8c7b5dSJohnathan Mantey                    asyncResp);
146162598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1462e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1463e4588158SJishnu CM                   NetworkType::dhcp4);
146462598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1465e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1466e4588158SJishnu CM                   NetworkType::dhcp4);
146791c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled...");
146891c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
1469e4588158SJishnu CM                   NetworkType::dhcp4);
1470e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1471e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1472e4588158SJishnu CM                   NetworkType::dhcp6);
1473e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1474e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1475e4588158SJishnu CM                   NetworkType::dhcp6);
147691c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
147791c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
1478e4588158SJishnu CM                   NetworkType::dhcp6);
1479da131a9aSJennifer Lee }
148001784826SJohnathan Mantey 
getNextStaticIpEntry(const std::vector<IPv4AddressData>::const_iterator & head,const std::vector<IPv4AddressData>::const_iterator & end)148177179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
148277179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
148377179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
148401784826SJohnathan Mantey {
148517a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
148617a897dfSManojkiran Eda         return value.origin == "Static";
148717a897dfSManojkiran Eda     });
148801784826SJohnathan Mantey }
148901784826SJohnathan Mantey 
getNextStaticIpEntry(const std::vector<IPv6AddressData>::const_iterator & head,const std::vector<IPv6AddressData>::const_iterator & end)149077179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
149177179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
149277179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
149301784826SJohnathan Mantey {
149417a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
149517a897dfSManojkiran Eda         return value.origin == "Static";
149617a897dfSManojkiran Eda     });
149701784826SJohnathan Mantey }
149801784826SJohnathan Mantey 
14996e1a52faSEd Tanous enum class AddrChange
15001abe55efSEd Tanous {
15016e1a52faSEd Tanous     Noop,
15026e1a52faSEd Tanous     Delete,
15036e1a52faSEd Tanous     Update,
15046e1a52faSEd Tanous };
15056e1a52faSEd Tanous 
15066e1a52faSEd Tanous // Struct representing a dbus change
15076e1a52faSEd Tanous struct AddressPatch
15086e1a52faSEd Tanous {
15096e1a52faSEd Tanous     std::string address;
15106e1a52faSEd Tanous     std::string gateway;
15116e1a52faSEd Tanous     uint8_t prefixLength = 0;
15126e1a52faSEd Tanous     std::string existingDbusId;
15136e1a52faSEd Tanous     AddrChange operation = AddrChange::Noop;
15146e1a52faSEd Tanous };
15156e1a52faSEd Tanous 
parseAddresses(std::vector<std::variant<nlohmann::json::object_t,std::nullptr_t>> & input,const std::vector<IPv4AddressData> & ipv4Data,crow::Response & res,std::vector<AddressPatch> & addressesOut,std::string & gatewayOut)15166e1a52faSEd Tanous inline bool parseAddresses(
15176e1a52faSEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
15186e1a52faSEd Tanous     const std::vector<IPv4AddressData>& ipv4Data, crow::Response& res,
15196e1a52faSEd Tanous     std::vector<AddressPatch>& addressesOut, std::string& gatewayOut)
15206e1a52faSEd Tanous {
152177179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
15222c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
152301784826SJohnathan Mantey 
15246e1a52faSEd Tanous     std::string lastGatewayPath;
15256e1a52faSEd Tanous     size_t entryIdx = 0;
15263dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
15273dfed536SEd Tanous          input)
15281abe55efSEd Tanous     {
1529bd79bce8SPatrick Williams         std::string pathString =
15306e1a52faSEd Tanous             std::format("IPv4StaticAddresses/{}", entryIdx);
15316e1a52faSEd Tanous         AddressPatch& thisAddress = addressesOut.emplace_back();
15323dfed536SEd Tanous         nlohmann::json::object_t* obj =
15333dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
1534743eb1c0SJohnathan Mantey         if (nicIpEntry != ipv4Data.cend())
1535743eb1c0SJohnathan Mantey         {
15366e1a52faSEd Tanous             thisAddress.existingDbusId = nicIpEntry->id;
1537743eb1c0SJohnathan Mantey         }
1538743eb1c0SJohnathan Mantey 
15396e1a52faSEd Tanous         if (obj == nullptr)
15406e1a52faSEd Tanous         {
15416e1a52faSEd Tanous             if (thisAddress.existingDbusId.empty())
15426e1a52faSEd Tanous             {
15436e1a52faSEd Tanous                 // Received a DELETE action on an entry not assigned to the NIC
15446e1a52faSEd Tanous                 messages::resourceCannotBeDeleted(res);
15456e1a52faSEd Tanous                 return false;
15466e1a52faSEd Tanous             }
15476e1a52faSEd Tanous             thisAddress.operation = AddrChange::Delete;
15486e1a52faSEd Tanous         }
15496e1a52faSEd Tanous         else
1550f476acbfSRatan Gupta         {
1551537174c4SEd Tanous             std::optional<std::string> address;
1552537174c4SEd Tanous             std::optional<std::string> gateway;
15536e1a52faSEd Tanous             std::optional<std::string> subnetMask;
15546e1a52faSEd Tanous             if (!obj->empty())
15556e1a52faSEd Tanous             {
1556afc474aeSMyung Bae                 if (!json_util::readJsonObject(  //
15576e1a52faSEd Tanous                         *obj, res,               //
1558afc474aeSMyung Bae                         "Address", address,      //
1559afc474aeSMyung Bae                         "Gateway", gateway,      //
1560afc474aeSMyung Bae                         "SubnetMask", subnetMask //
1561afc474aeSMyung Bae                         ))
1562537174c4SEd Tanous                 {
15636e1a52faSEd Tanous                     messages::propertyValueFormatError(res, *obj, pathString);
15646e1a52faSEd Tanous                     return false;
1565179db1d7SKowalski, Kamil                 }
15666e1a52faSEd Tanous             }
156701784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
156801784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
156901784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
157001784826SJohnathan Mantey             // current request.
1571537174c4SEd Tanous             if (address)
15721abe55efSEd Tanous             {
1573e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
157401784826SJohnathan Mantey                 {
15756e1a52faSEd Tanous                     messages::propertyValueFormatError(res, *address,
1576bf648f77SEd Tanous                                                        pathString + "/Address");
15776e1a52faSEd Tanous                     return false;
157801784826SJohnathan Mantey                 }
15796e1a52faSEd Tanous                 thisAddress.operation = AddrChange::Update;
15806e1a52faSEd Tanous                 thisAddress.address = *address;
158101784826SJohnathan Mantey             }
15826e1a52faSEd Tanous             else if (thisAddress.existingDbusId.empty())
158301784826SJohnathan Mantey             {
15846e1a52faSEd Tanous                 messages::propertyMissing(res, pathString + "/Address");
15856e1a52faSEd Tanous                 return false;
158601784826SJohnathan Mantey             }
158701784826SJohnathan Mantey             else
158801784826SJohnathan Mantey             {
15896e1a52faSEd Tanous                 thisAddress.address = nicIpEntry->address;
15904a0cb85cSEd Tanous             }
15914a0cb85cSEd Tanous 
1592537174c4SEd Tanous             if (subnetMask)
15934a0cb85cSEd Tanous             {
15946e1a52faSEd Tanous                 uint8_t prefixLength = 0;
1595033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1596033f1e4dSEd Tanous                                                          &prefixLength))
15974a0cb85cSEd Tanous                 {
1598f12894f8SJason M. Bills                     messages::propertyValueFormatError(
15996e1a52faSEd Tanous                         res, *subnetMask, pathString + "/SubnetMask");
16006e1a52faSEd Tanous                     return false;
16014a0cb85cSEd Tanous                 }
16026e1a52faSEd Tanous                 thisAddress.prefixLength = prefixLength;
16036e1a52faSEd Tanous                 thisAddress.operation = AddrChange::Update;
16044a0cb85cSEd Tanous             }
16056e1a52faSEd Tanous             else if (thisAddress.existingDbusId.empty())
16064a0cb85cSEd Tanous             {
16076e1a52faSEd Tanous                 messages::propertyMissing(res, pathString + "/SubnetMask");
16086e1a52faSEd Tanous                 return false;
16094a0cb85cSEd Tanous             }
16101abe55efSEd Tanous             else
16111abe55efSEd Tanous             {
16126e1a52faSEd Tanous                 uint8_t prefixLength = 0;
16136e1a52faSEd Tanous                 // Ignore return code.  It came from internal, it's it's invalid
16146e1a52faSEd Tanous                 // nothing we can do
16156e1a52faSEd Tanous                 ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
16166e1a52faSEd Tanous                                                     &prefixLength);
161701784826SJohnathan Mantey 
16186e1a52faSEd Tanous                 thisAddress.prefixLength = prefixLength;
16196e1a52faSEd Tanous             }
162001784826SJohnathan Mantey             if (gateway)
162101784826SJohnathan Mantey             {
1622e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
162301784826SJohnathan Mantey                 {
16246e1a52faSEd Tanous                     messages::propertyValueFormatError(res, *gateway,
1625bf648f77SEd Tanous                                                        pathString + "/Gateway");
16266e1a52faSEd Tanous                     return false;
162701784826SJohnathan Mantey                 }
16286e1a52faSEd Tanous                 thisAddress.operation = AddrChange::Update;
16296e1a52faSEd Tanous                 thisAddress.gateway = *gateway;
163001784826SJohnathan Mantey             }
16316e1a52faSEd Tanous             else if (thisAddress.existingDbusId.empty())
163201784826SJohnathan Mantey             {
16336e1a52faSEd Tanous                 // Default to null gateway
16346e1a52faSEd Tanous                 gateway = "";
163501784826SJohnathan Mantey             }
163601784826SJohnathan Mantey             else
16371abe55efSEd Tanous             {
16386e1a52faSEd Tanous                 thisAddress.gateway = nicIpEntry->gateway;
16394a0cb85cSEd Tanous             }
16404a0cb85cSEd Tanous 
16416e1a52faSEd Tanous             // Changing gateway from existing
16426e1a52faSEd Tanous             if (!thisAddress.gateway.empty() &&
16436e1a52faSEd Tanous                 thisAddress.gateway != "0.0.0.0")
1644743eb1c0SJohnathan Mantey             {
16456e1a52faSEd Tanous                 if (!gatewayOut.empty() && gatewayOut != thisAddress.gateway)
1646743eb1c0SJohnathan Mantey                 {
1647743eb1c0SJohnathan Mantey                     // A NIC can only have a single active gateway value.
1648743eb1c0SJohnathan Mantey                     // If any gateway in the array of static addresses
1649743eb1c0SJohnathan Mantey                     // mismatch the PATCH is in error.
1650743eb1c0SJohnathan Mantey                     std::string arg1 = pathString + "/Gateway";
16516e1a52faSEd Tanous                     std::string arg2 = lastGatewayPath + "/Gateway";
16526e1a52faSEd Tanous                     messages::propertyValueConflict(res, arg1, arg2);
16536e1a52faSEd Tanous                     return false;
16546e1a52faSEd Tanous                 }
16556e1a52faSEd Tanous                 gatewayOut = thisAddress.gateway;
16566e1a52faSEd Tanous                 lastGatewayPath = pathString;
1657743eb1c0SJohnathan Mantey             }
1658743eb1c0SJohnathan Mantey         }
16596e1a52faSEd Tanous         nicIpEntry++;
16606e1a52faSEd Tanous         nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend());
16616e1a52faSEd Tanous         entryIdx++;
1662743eb1c0SJohnathan Mantey     }
1663743eb1c0SJohnathan Mantey 
16646e1a52faSEd Tanous     // Delete the remaining IPs
16656e1a52faSEd Tanous     while (nicIpEntry != ipv4Data.cend())
16661abe55efSEd Tanous     {
16676e1a52faSEd Tanous         AddressPatch& thisAddress = addressesOut.emplace_back();
16686e1a52faSEd Tanous         thisAddress.operation = AddrChange::Delete;
16696e1a52faSEd Tanous         thisAddress.existingDbusId = nicIpEntry->id;
16706e1a52faSEd Tanous         nicIpEntry++;
16716e1a52faSEd Tanous         nicIpEntry = getNextStaticIpEntry(nicIpEntry, ipv4Data.cend());
1672588c3f0dSKowalski, Kamil     }
16736e1a52faSEd Tanous 
16746e1a52faSEd Tanous     return true;
16754a0cb85cSEd Tanous }
16766e1a52faSEd Tanous 
handleIPv4StaticPatch(const std::string & ifaceId,std::vector<std::variant<nlohmann::json::object_t,std::nullptr_t>> & input,const EthernetInterfaceData & ethData,const std::vector<IPv4AddressData> & ipv4Data,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)16776e1a52faSEd Tanous inline void handleIPv4StaticPatch(
16786e1a52faSEd Tanous     const std::string& ifaceId,
16796e1a52faSEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
16806e1a52faSEd Tanous     const EthernetInterfaceData& ethData,
16816e1a52faSEd Tanous     const std::vector<IPv4AddressData>& ipv4Data,
16826e1a52faSEd Tanous     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
168301784826SJohnathan Mantey {
16846e1a52faSEd Tanous     std::vector<AddressPatch> addresses;
16856e1a52faSEd Tanous     std::string gatewayOut;
16866e1a52faSEd Tanous     if (!parseAddresses(input, ipv4Data, asyncResp->res, addresses, gatewayOut))
168701784826SJohnathan Mantey     {
1688743eb1c0SJohnathan Mantey         return;
1689743eb1c0SJohnathan Mantey     }
16906e1a52faSEd Tanous 
16916e1a52faSEd Tanous     // If we're setting the gateway to something new, delete the
16926e1a52faSEd Tanous     // existing so we won't conflict
16936e1a52faSEd Tanous     if (!ethData.defaultGateway.empty() && ethData.defaultGateway != gatewayOut)
16946e1a52faSEd Tanous     {
16956e1a52faSEd Tanous         updateIPv4DefaultGateway(ifaceId, "", asyncResp);
1696743eb1c0SJohnathan Mantey     }
16976e1a52faSEd Tanous 
16986e1a52faSEd Tanous     for (const AddressPatch& address : addresses)
16996e1a52faSEd Tanous     {
17006e1a52faSEd Tanous         switch (address.operation)
17016e1a52faSEd Tanous         {
17026e1a52faSEd Tanous             case AddrChange::Delete:
17036e1a52faSEd Tanous             {
17046e1a52faSEd Tanous                 BMCWEB_LOG_ERROR("Deleting id {} on interface {}",
17056e1a52faSEd Tanous                                  address.existingDbusId, ifaceId);
17066e1a52faSEd Tanous                 deleteIPAddress(ifaceId, address.existingDbusId, asyncResp);
17076e1a52faSEd Tanous             }
17086e1a52faSEd Tanous             break;
17096e1a52faSEd Tanous             case AddrChange::Update:
17106e1a52faSEd Tanous             {
17116e1a52faSEd Tanous                 // Update is a delete then a recreate
17126e1a52faSEd Tanous                 // Only need to update if there is an existing ip at this index
17136e1a52faSEd Tanous                 if (!address.existingDbusId.empty())
17146e1a52faSEd Tanous                 {
17156e1a52faSEd Tanous                     BMCWEB_LOG_ERROR("Deleting id {} on interface {}",
17166e1a52faSEd Tanous                                      address.existingDbusId, ifaceId);
17176e1a52faSEd Tanous                     deleteAndCreateIPAddress(
17186e1a52faSEd Tanous                         IpVersion::IpV4, ifaceId, address.existingDbusId,
17196e1a52faSEd Tanous                         address.prefixLength, address.address, address.gateway,
17206e1a52faSEd Tanous                         asyncResp);
17216e1a52faSEd Tanous                 }
17226e1a52faSEd Tanous                 else
17236e1a52faSEd Tanous                 {
17246e1a52faSEd Tanous                     // Otherwise, just create a new one
17256e1a52faSEd Tanous                     BMCWEB_LOG_ERROR(
17266e1a52faSEd Tanous                         "creating ip {} prefix {} gateway {} on interface {}",
17276e1a52faSEd Tanous                         address.address, address.prefixLength, address.gateway,
17286e1a52faSEd Tanous                         ifaceId);
17296e1a52faSEd Tanous                     createIPv4(ifaceId, address.prefixLength, address.gateway,
17306e1a52faSEd Tanous                                address.address, asyncResp);
17316e1a52faSEd Tanous                 }
17326e1a52faSEd Tanous             }
17336e1a52faSEd Tanous             break;
17346e1a52faSEd Tanous             default:
17356e1a52faSEd Tanous             {
17366e1a52faSEd Tanous                 // Leave alone
17376e1a52faSEd Tanous             }
17386e1a52faSEd Tanous             break;
17396e1a52faSEd Tanous         }
17406e1a52faSEd Tanous     }
17416e1a52faSEd Tanous 
17426e1a52faSEd Tanous     // now update to the new gateway.
17436e1a52faSEd Tanous     // Default gateway is already empty, so no need to update if we're clearing
17446e1a52faSEd Tanous     if (!gatewayOut.empty() && ethData.defaultGateway != gatewayOut)
17456e1a52faSEd Tanous     {
17466e1a52faSEd Tanous         updateIPv4DefaultGateway(ifaceId, gatewayOut, asyncResp);
174701784826SJohnathan Mantey     }
17484a0cb85cSEd Tanous }
17494a0cb85cSEd Tanous 
handleStaticNameServersPatch(const std::string & ifaceId,const std::vector<std::string> & updatedStaticNameServers,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)17504f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1751f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1752f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
17538d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1754f85837bfSRAJESWARAN THILLAIGOVINDAN {
17551847f2a0SAsmitha Karunanithi     setDbusProperty(
1756e93abac6SGinu George         asyncResp, "StaticNameServers", "xyz.openbmc_project.Network",
17571847f2a0SAsmitha Karunanithi         sdbusplus::message::object_path("/xyz/openbmc_project/network") /
17581847f2a0SAsmitha Karunanithi             ifaceId,
17599ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
1760e93abac6SGinu George         updatedStaticNameServers);
1761f85837bfSRAJESWARAN THILLAIGOVINDAN }
1762f85837bfSRAJESWARAN THILLAIGOVINDAN 
handleIPv6StaticAddressesPatch(const std::string & ifaceId,std::vector<std::variant<nlohmann::json::object_t,std::nullptr_t>> & input,const std::vector<IPv6AddressData> & ipv6Data,const std::shared_ptr<bmcweb::AsyncResp> & asyncResp)17634f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
17643dfed536SEd Tanous     const std::string& ifaceId,
17653dfed536SEd Tanous     std::vector<std::variant<nlohmann::json::object_t, std::nullptr_t>>& input,
176677179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
17678d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1768e48c0fc5SRavi Teja {
1769271584abSEd Tanous     size_t entryIdx = 1;
177077179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
17712c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
17723dfed536SEd Tanous     for (std::variant<nlohmann::json::object_t, std::nullptr_t>& thisJson :
17733dfed536SEd Tanous          input)
1774e48c0fc5SRavi Teja     {
1775bd79bce8SPatrick Williams         std::string pathString =
1776bd79bce8SPatrick Williams             "IPv6StaticAddresses/" + std::to_string(entryIdx);
17773dfed536SEd Tanous         nlohmann::json::object_t* obj =
17783dfed536SEd Tanous             std::get_if<nlohmann::json::object_t>(&thisJson);
17793dfed536SEd Tanous         if (obj != nullptr && !obj->empty())
1780e48c0fc5SRavi Teja         {
1781e48c0fc5SRavi Teja             std::optional<std::string> address;
1782e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
17833dfed536SEd Tanous             nlohmann::json::object_t thisJsonCopy = *obj;
1784afc474aeSMyung Bae             if (!json_util::readJsonObject(       //
1785afc474aeSMyung Bae                     thisJsonCopy, asyncResp->res, //
1786afc474aeSMyung Bae                     "Address", address,           //
1787afc474aeSMyung Bae                     "PrefixLength", prefixLength  //
1788afc474aeSMyung Bae                     ))
1789e48c0fc5SRavi Teja             {
17903dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJsonCopy,
179171f52d96SEd Tanous                                                    pathString);
1792e48c0fc5SRavi Teja                 return;
1793e48c0fc5SRavi Teja             }
1794e48c0fc5SRavi Teja 
179501784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
179601784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
179701784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
179801784826SJohnathan Mantey             // current request.
1799d547d8d2SEd Tanous             if (!address)
1800e48c0fc5SRavi Teja             {
1801d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
180201784826SJohnathan Mantey                 {
180301784826SJohnathan Mantey                     messages::propertyMissing(asyncResp->res,
180401784826SJohnathan Mantey                                               pathString + "/Address");
180501784826SJohnathan Mantey                     return;
1806e48c0fc5SRavi Teja                 }
1807d547d8d2SEd Tanous                 address = nicIpEntry->address;
1808d547d8d2SEd Tanous             }
1809e48c0fc5SRavi Teja 
1810d547d8d2SEd Tanous             if (!prefixLength)
1811e48c0fc5SRavi Teja             {
1812d547d8d2SEd Tanous                 if (nicIpEntry == ipv6Data.end())
1813e48c0fc5SRavi Teja                 {
1814e48c0fc5SRavi Teja                     messages::propertyMissing(asyncResp->res,
1815e48c0fc5SRavi Teja                                               pathString + "/PrefixLength");
181601784826SJohnathan Mantey                     return;
1817e48c0fc5SRavi Teja                 }
1818d547d8d2SEd Tanous                 prefixLength = nicIpEntry->prefixLength;
1819d547d8d2SEd Tanous             }
1820e48c0fc5SRavi Teja 
182185ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1822e48c0fc5SRavi Teja             {
18239c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
1824d547d8d2SEd Tanous                                          nicIpEntry->id, *prefixLength,
1825d547d8d2SEd Tanous                                          *address, "", asyncResp);
1826bd79bce8SPatrick Williams                 nicIpEntry =
1827bd79bce8SPatrick Williams                     getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend());
182801784826SJohnathan Mantey             }
182901784826SJohnathan Mantey             else
183001784826SJohnathan Mantey             {
1831d547d8d2SEd Tanous                 createIPv6(ifaceId, *prefixLength, *address, asyncResp);
1832e48c0fc5SRavi Teja             }
1833e48c0fc5SRavi Teja             entryIdx++;
1834e48c0fc5SRavi Teja         }
183501784826SJohnathan Mantey         else
183601784826SJohnathan Mantey         {
183785ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
183801784826SJohnathan Mantey             {
183901784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
184001784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
184101784826SJohnathan Mantey                 // in error, so bail out.
18423dfed536SEd Tanous                 if (obj == nullptr)
184301784826SJohnathan Mantey                 {
184401784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
184501784826SJohnathan Mantey                     return;
184601784826SJohnathan Mantey                 }
18473dfed536SEd Tanous                 messages::propertyValueFormatError(asyncResp->res, *obj,
184871f52d96SEd Tanous                                                    pathString);
184901784826SJohnathan Mantey                 return;
185001784826SJohnathan Mantey             }
185101784826SJohnathan Mantey 
18523dfed536SEd Tanous             if (obj == nullptr)
185301784826SJohnathan Mantey             {
18549c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
185501784826SJohnathan Mantey             }
185685ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
185701784826SJohnathan Mantey             {
1858bd79bce8SPatrick Williams                 nicIpEntry =
1859bd79bce8SPatrick Williams                     getNextStaticIpEntry(++nicIpEntry, ipv6Data.cend());
186001784826SJohnathan Mantey             }
186101784826SJohnathan Mantey             entryIdx++;
186201784826SJohnathan Mantey         }
186301784826SJohnathan Mantey     }
1864e48c0fc5SRavi Teja }
1865e48c0fc5SRavi Teja 
extractParentInterfaceName(const std::string & ifaceId)18667857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
18677857cb8dSJiaqing Zhao {
18687857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
18697857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
18707857cb8dSJiaqing Zhao }
18717857cb8dSJiaqing Zhao 
parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & ifaceId,const EthernetInterfaceData & ethData,const std::vector<IPv4AddressData> & ipv4Data,const std::vector<IPv6AddressData> & ipv6Data,const std::vector<StaticGatewayData> & ipv6GatewayData)1872bd79bce8SPatrick Williams inline void parseInterfaceData(
1873bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1874bd79bce8SPatrick Williams     const std::string& ifaceId, const EthernetInterfaceData& ethData,
187577179532SEd Tanous     const std::vector<IPv4AddressData>& ipv4Data,
1876ce73d5c8SSunitha Harish     const std::vector<IPv6AddressData>& ipv6Data,
1877ce73d5c8SSunitha Harish     const std::vector<StaticGatewayData>& ipv6GatewayData)
18784a0cb85cSEd Tanous {
18792c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
188081ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1881253f11b8SEd Tanous     jsonResponse["@odata.id"] =
1882253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}",
1883253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceId);
18842c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1885eeedda23SJohnathan Mantey 
1886eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1887eeedda23SJohnathan Mantey     {
1888539d8c6bSEd Tanous         jsonResponse["LinkStatus"] =
1889539d8c6bSEd Tanous             ethData.linkUp ? ethernet_interface::LinkStatus::LinkUp
1890539d8c6bSEd Tanous                            : ethernet_interface::LinkStatus::LinkDown;
1891539d8c6bSEd Tanous         jsonResponse["Status"]["State"] = resource::State::Enabled;
1892029573d4SEd Tanous     }
1893029573d4SEd Tanous     else
1894029573d4SEd Tanous     {
1895539d8c6bSEd Tanous         jsonResponse["LinkStatus"] = ethernet_interface::LinkStatus::NoLink;
1896539d8c6bSEd Tanous         jsonResponse["Status"]["State"] = resource::State::Disabled;
1897029573d4SEd Tanous     }
1898aa05fb27SJohnathan Mantey 
18992c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
190035fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
19014652c640SAsmitha Karunanithi     if (ethData.macAddress)
19024652c640SAsmitha Karunanithi     {
19034652c640SAsmitha Karunanithi         jsonResponse["MACAddress"] = *ethData.macAddress;
19044652c640SAsmitha Karunanithi     }
19052c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
190682695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1907e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1908e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1909de9ad764SRavi Teja     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.domainv4Enabled;
19102c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1911bd79bce8SPatrick Williams         translateDhcpEnabledToBool(ethData.dhcpEnabled, false)
1912bd79bce8SPatrick Williams             ? "Enabled"
19131f8c7b5dSJohnathan Mantey             : "Disabled";
1914e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1915e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1916de9ad764SRavi Teja     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.domainv6Enabled;
1917b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1918b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
19192a133282Smanojkiraneda 
192082695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
19214a0cb85cSEd Tanous     {
192282695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1923ab6554f1SJoshi-Mansi 
1924ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1925ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1926ab6554f1SJoshi-Mansi         // FQDN
192782695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1928d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1929d24bfc7aSJennifer Lee         {
19302c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1931d24bfc7aSJennifer Lee         }
19322c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
19334a0cb85cSEd Tanous     }
19344a0cb85cSEd Tanous 
19357857cb8dSJiaqing Zhao     if (ethData.vlanId)
19367857cb8dSJiaqing Zhao     {
1937539d8c6bSEd Tanous         jsonResponse["EthernetInterfaceType"] =
1938539d8c6bSEd Tanous             ethernet_interface::EthernetDeviceType::Virtual;
19397857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
19407857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
19417857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
19427857cb8dSJiaqing Zhao 
19437857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
19447857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
19457857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
1946253f11b8SEd Tanous             boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces",
1947253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME,
19487857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
19497857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
19507857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
19517857cb8dSJiaqing Zhao     }
19527857cb8dSJiaqing Zhao     else
19537857cb8dSJiaqing Zhao     {
1954539d8c6bSEd Tanous         jsonResponse["EthernetInterfaceType"] =
1955539d8c6bSEd Tanous             ethernet_interface::EthernetDeviceType::Physical;
19567857cb8dSJiaqing Zhao     }
19577857cb8dSJiaqing Zhao 
19582c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
19592c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
19604a0cb85cSEd Tanous 
19612c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
19622c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
19632c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
19642c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
19659eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
19664a0cb85cSEd Tanous     {
19672c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1968fa5053a6SGunnar Mills         if (gatewayStr.empty())
1969fa5053a6SGunnar Mills         {
1970fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1971fa5053a6SGunnar Mills         }
19721476687dSEd Tanous         nlohmann::json::object_t ipv4;
19731476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
19741476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
19751476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
19761476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1977fa5053a6SGunnar Mills 
19782c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1979d1d50814SRavi Teja         {
19801476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1981d1d50814SRavi Teja         }
19821476687dSEd Tanous 
1983b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
198401784826SJohnathan Mantey     }
1985d1d50814SRavi Teja 
198682695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
19877ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
19887ea79e5eSRavi Teja     {
19897ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
19907ea79e5eSRavi Teja     }
19917ea79e5eSRavi Teja 
19927ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1993e48c0fc5SRavi Teja 
1994ce73d5c8SSunitha Harish     nlohmann::json::array_t ipv6StaticGatewayArray;
1995ce73d5c8SSunitha Harish     for (const auto& ipv6GatewayConfig : ipv6GatewayData)
1996ce73d5c8SSunitha Harish     {
1997ce73d5c8SSunitha Harish         nlohmann::json::object_t ipv6Gateway;
1998ce73d5c8SSunitha Harish         ipv6Gateway["Address"] = ipv6GatewayConfig.gateway;
1999ce73d5c8SSunitha Harish         ipv6StaticGatewayArray.emplace_back(std::move(ipv6Gateway));
2000ce73d5c8SSunitha Harish     }
2001ce73d5c8SSunitha Harish     jsonResponse["IPv6StaticDefaultGateways"] =
2002ce73d5c8SSunitha Harish         std::move(ipv6StaticGatewayArray);
2003ce73d5c8SSunitha Harish 
20042c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
20052c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
20062c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
20072c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
20087f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
20092c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
20107f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
20119eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
2012e48c0fc5SRavi Teja     {
20131476687dSEd Tanous         nlohmann::json::object_t ipv6;
20141476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
20151476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
20161476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
2017f8361275SSunitha Harish 
2018b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
20192c70f800SEd Tanous         if (ipv6Config.origin == "Static")
2020e48c0fc5SRavi Teja         {
20211476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
20221476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
20231476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
2024b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
202501784826SJohnathan Mantey         }
2026e48c0fc5SRavi Teja     }
2027588c3f0dSKowalski, Kamil }
2028588c3f0dSKowalski, Kamil 
afterDelete(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & ifaceId,const boost::system::error_code & ec,const sdbusplus::message_t & m)2029e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2030e7caf250SJiaqing Zhao                         const std::string& ifaceId,
2031e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
2032e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
2033e7caf250SJiaqing Zhao {
2034e7caf250SJiaqing Zhao     if (!ec)
2035e7caf250SJiaqing Zhao     {
2036e7caf250SJiaqing Zhao         return;
2037e7caf250SJiaqing Zhao     }
2038e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
2039e7caf250SJiaqing Zhao     if (dbusError == nullptr)
2040e7caf250SJiaqing Zhao     {
2041e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
2042e7caf250SJiaqing Zhao         return;
2043e7caf250SJiaqing Zhao     }
204462598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2045e7caf250SJiaqing Zhao 
2046e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
2047e7caf250SJiaqing Zhao         dbusError->name)
2048e7caf250SJiaqing Zhao     {
2049e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2050e7caf250SJiaqing Zhao                                    ifaceId);
2051e7caf250SJiaqing Zhao         return;
2052e7caf250SJiaqing Zhao     }
2053e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
2054e7caf250SJiaqing Zhao         dbusError->name)
2055e7caf250SJiaqing Zhao     {
2056e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
2057e7caf250SJiaqing Zhao         return;
2058e7caf250SJiaqing Zhao     }
2059e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
2060e7caf250SJiaqing Zhao }
2061e7caf250SJiaqing Zhao 
afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp> & asyncResp,const std::string & parentInterfaceUri,const std::string & vlanInterface,const boost::system::error_code & ec,const sdbusplus::message_t & m)2062bd79bce8SPatrick Williams inline void afterVlanCreate(
2063bd79bce8SPatrick Williams     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2064bd79bce8SPatrick Williams     const std::string& parentInterfaceUri, const std::string& vlanInterface,
2065bd79bce8SPatrick Williams     const boost::system::error_code& ec, const sdbusplus::message_t& m
2066b5ca3fdcSJiaqing Zhao 
2067b5ca3fdcSJiaqing Zhao )
2068b5ca3fdcSJiaqing Zhao {
2069b5ca3fdcSJiaqing Zhao     if (ec)
2070b5ca3fdcSJiaqing Zhao     {
2071b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
2072b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
2073b5ca3fdcSJiaqing Zhao         {
2074b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
2075b5ca3fdcSJiaqing Zhao             return;
2076b5ca3fdcSJiaqing Zhao         }
207762598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
2078b5ca3fdcSJiaqing Zhao 
2079b5ca3fdcSJiaqing Zhao         if (std::string_view(
2080b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
2081b5ca3fdcSJiaqing Zhao             dbusError->name)
2082b5ca3fdcSJiaqing Zhao         {
2083b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
2084b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
2085b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
2086b5ca3fdcSJiaqing Zhao             return;
2087b5ca3fdcSJiaqing Zhao         }
2088b5ca3fdcSJiaqing Zhao         if (std::string_view(
2089b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
2090b5ca3fdcSJiaqing Zhao             dbusError->name)
2091b5ca3fdcSJiaqing Zhao         {
2092b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
2093b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
2094b5ca3fdcSJiaqing Zhao             return;
2095b5ca3fdcSJiaqing Zhao         }
2096b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
2097b5ca3fdcSJiaqing Zhao         return;
2098b5ca3fdcSJiaqing Zhao     }
2099b5ca3fdcSJiaqing Zhao 
2100253f11b8SEd Tanous     const boost::urls::url vlanInterfaceUri =
2101253f11b8SEd Tanous         boost::urls::format("/redfish/v1/Managers/{}/EthernetInterfaces/{}",
2102253f11b8SEd Tanous                             BMCWEB_REDFISH_MANAGER_URI_NAME, vlanInterface);
2103b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
2104b5ca3fdcSJiaqing Zhao }
2105b5ca3fdcSJiaqing Zhao 
requestEthernetInterfacesRoutes(App & app)2106bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
2107bf648f77SEd Tanous {
2108253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
2109ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
21101476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
21111476687dSEd Tanous             [&app](const crow::Request& req,
2112253f11b8SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2113253f11b8SEd Tanous                    const std::string& managerId) {
21143ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
211545ca1b86SEd Tanous                 {
211645ca1b86SEd Tanous                     return;
211745ca1b86SEd Tanous                 }
211845ca1b86SEd Tanous 
2119253f11b8SEd Tanous                 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2120253f11b8SEd Tanous                 {
2121bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "Manager",
2122bd79bce8SPatrick Williams                                                managerId);
2123253f11b8SEd Tanous                     return;
2124253f11b8SEd Tanous                 }
2125253f11b8SEd Tanous 
2126bf648f77SEd Tanous                 asyncResp->res.jsonValue["@odata.type"] =
2127bf648f77SEd Tanous                     "#EthernetInterfaceCollection.EthernetInterfaceCollection";
2128bd79bce8SPatrick Williams                 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
2129bd79bce8SPatrick Williams                     "/redfish/v1/Managers/{}/EthernetInterfaces",
2130253f11b8SEd Tanous                     BMCWEB_REDFISH_MANAGER_URI_NAME);
2131bf648f77SEd Tanous                 asyncResp->res.jsonValue["Name"] =
2132bf648f77SEd Tanous                     "Ethernet Network Interface Collection";
2133bf648f77SEd Tanous                 asyncResp->res.jsonValue["Description"] =
2134bf648f77SEd Tanous                     "Collection of EthernetInterfaces for this Manager";
2135bf648f77SEd Tanous 
2136bf648f77SEd Tanous                 // Get eth interface list, and call the below callback for JSON
2137bf648f77SEd Tanous                 // preparation
2138002d39b4SEd Tanous                 getEthernetIfaceList(
213977179532SEd Tanous                     [asyncResp](const bool& success,
214077179532SEd Tanous                                 const std::vector<std::string>& ifaceList) {
2141bf648f77SEd Tanous                         if (!success)
21421abe55efSEd Tanous                         {
2143f12894f8SJason M. Bills                             messages::internalError(asyncResp->res);
21449391bb9cSRapkiewicz, Pawel                             return;
21459391bb9cSRapkiewicz, Pawel                         }
21469391bb9cSRapkiewicz, Pawel 
2147bd79bce8SPatrick Williams                         nlohmann::json& ifaceArray =
2148bd79bce8SPatrick Williams                             asyncResp->res.jsonValue["Members"];
2149bf648f77SEd Tanous                         ifaceArray = nlohmann::json::array();
2150bf648f77SEd Tanous                         for (const std::string& ifaceItem : ifaceList)
2151bf648f77SEd Tanous                         {
21521476687dSEd Tanous                             nlohmann::json::object_t iface;
2153ef4c65b7SEd Tanous                             iface["@odata.id"] = boost::urls::format(
2154253f11b8SEd Tanous                                 "/redfish/v1/Managers/{}/EthernetInterfaces/{}",
2155253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME, ifaceItem);
21567857cb8dSJiaqing Zhao                             ifaceArray.push_back(std::move(iface));
2157bf648f77SEd Tanous                         }
2158bf648f77SEd Tanous 
2159bd79bce8SPatrick Williams                         asyncResp->res.jsonValue["Members@odata.count"] =
2160bd79bce8SPatrick Williams                             ifaceArray.size();
2161bd79bce8SPatrick Williams                         asyncResp->res.jsonValue["@odata.id"] =
2162bd79bce8SPatrick Williams                             boost::urls::format(
2163253f11b8SEd Tanous                                 "/redfish/v1/Managers/{}/EthernetInterfaces",
2164253f11b8SEd Tanous                                 BMCWEB_REDFISH_MANAGER_URI_NAME);
2165bf648f77SEd Tanous                     });
2166bf648f77SEd Tanous             });
2167bf648f77SEd Tanous 
2168253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/")
2169b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
2170b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
2171b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
2172253f11b8SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2173253f11b8SEd Tanous                    const std::string& managerId) {
2174b5ca3fdcSJiaqing Zhao                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2175b5ca3fdcSJiaqing Zhao                 {
2176b5ca3fdcSJiaqing Zhao                     return;
2177b5ca3fdcSJiaqing Zhao                 }
2178b5ca3fdcSJiaqing Zhao 
2179253f11b8SEd Tanous                 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2180253f11b8SEd Tanous                 {
2181bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "Manager",
2182bd79bce8SPatrick Williams                                                managerId);
2183253f11b8SEd Tanous                     return;
2184253f11b8SEd Tanous                 }
2185253f11b8SEd Tanous 
2186b5ca3fdcSJiaqing Zhao                 bool vlanEnable = false;
2187b5ca3fdcSJiaqing Zhao                 uint32_t vlanId = 0;
21883dfed536SEd Tanous                 std::vector<nlohmann::json::object_t> relatedInterfaces;
2189b5ca3fdcSJiaqing Zhao 
2190afc474aeSMyung Bae                 if (!json_util::readJsonPatch(                        //
2191afc474aeSMyung Bae                         req, asyncResp->res,                          //
2192afc474aeSMyung Bae                         "Links/RelatedInterfaces", relatedInterfaces, //
2193afc474aeSMyung Bae                         "VLAN/VLANEnable", vlanEnable,                //
2194afc474aeSMyung Bae                         "VLAN/VLANId", vlanId                         //
2195afc474aeSMyung Bae                         ))
2196b5ca3fdcSJiaqing Zhao                 {
2197b5ca3fdcSJiaqing Zhao                     return;
2198b5ca3fdcSJiaqing Zhao                 }
2199b5ca3fdcSJiaqing Zhao 
2200b5ca3fdcSJiaqing Zhao                 if (relatedInterfaces.size() != 1)
2201b5ca3fdcSJiaqing Zhao                 {
2202b5ca3fdcSJiaqing Zhao                     messages::arraySizeTooLong(asyncResp->res,
2203b5ca3fdcSJiaqing Zhao                                                "Links/RelatedInterfaces",
2204b5ca3fdcSJiaqing Zhao                                                relatedInterfaces.size());
2205b5ca3fdcSJiaqing Zhao                     return;
2206b5ca3fdcSJiaqing Zhao                 }
2207b5ca3fdcSJiaqing Zhao 
2208b5ca3fdcSJiaqing Zhao                 std::string parentInterfaceUri;
2209bd79bce8SPatrick Williams                 if (!json_util::readJsonObject(relatedInterfaces[0],
2210bd79bce8SPatrick Williams                                                asyncResp->res, "@odata.id",
2211bd79bce8SPatrick Williams                                                parentInterfaceUri))
2212b5ca3fdcSJiaqing Zhao                 {
2213bd79bce8SPatrick Williams                     messages::propertyMissing(
2214bd79bce8SPatrick Williams                         asyncResp->res, "Links/RelatedInterfaces/0/@odata.id");
2215b5ca3fdcSJiaqing Zhao                     return;
2216b5ca3fdcSJiaqing Zhao                 }
221762598e31SEd Tanous                 BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
2218b5ca3fdcSJiaqing Zhao 
22196fd29553SEd Tanous                 boost::system::result<boost::urls::url_view> parsedUri =
2220b5ca3fdcSJiaqing Zhao                     boost::urls::parse_relative_ref(parentInterfaceUri);
2221b5ca3fdcSJiaqing Zhao                 if (!parsedUri)
2222b5ca3fdcSJiaqing Zhao                 {
2223b5ca3fdcSJiaqing Zhao                     messages::propertyValueFormatError(
2224b5ca3fdcSJiaqing Zhao                         asyncResp->res, parentInterfaceUri,
2225b5ca3fdcSJiaqing Zhao                         "Links/RelatedInterfaces/0/@odata.id");
2226b5ca3fdcSJiaqing Zhao                     return;
2227b5ca3fdcSJiaqing Zhao                 }
2228b5ca3fdcSJiaqing Zhao 
2229b5ca3fdcSJiaqing Zhao                 std::string parentInterface;
2230b5ca3fdcSJiaqing Zhao                 if (!crow::utility::readUrlSegments(
2231b5ca3fdcSJiaqing Zhao                         *parsedUri, "redfish", "v1", "Managers", "bmc",
2232b5ca3fdcSJiaqing Zhao                         "EthernetInterfaces", std::ref(parentInterface)))
2233b5ca3fdcSJiaqing Zhao                 {
2234b5ca3fdcSJiaqing Zhao                     messages::propertyValueNotInList(
2235b5ca3fdcSJiaqing Zhao                         asyncResp->res, parentInterfaceUri,
2236b5ca3fdcSJiaqing Zhao                         "Links/RelatedInterfaces/0/@odata.id");
2237b5ca3fdcSJiaqing Zhao                     return;
2238b5ca3fdcSJiaqing Zhao                 }
2239b5ca3fdcSJiaqing Zhao 
2240b5ca3fdcSJiaqing Zhao                 if (!vlanEnable)
2241b5ca3fdcSJiaqing Zhao                 {
2242b5ca3fdcSJiaqing Zhao                     // In OpenBMC implementation, VLANEnable cannot be false on
2243b5ca3fdcSJiaqing Zhao                     // create
2244bd79bce8SPatrick Williams                     messages::propertyValueIncorrect(
2245bd79bce8SPatrick Williams                         asyncResp->res, "VLAN/VLANEnable", "false");
2246b5ca3fdcSJiaqing Zhao                     return;
2247b5ca3fdcSJiaqing Zhao                 }
2248b5ca3fdcSJiaqing Zhao 
2249bd79bce8SPatrick Williams                 std::string vlanInterface =
2250bd79bce8SPatrick Williams                     parentInterface + "_" + std::to_string(vlanId);
2251b5ca3fdcSJiaqing Zhao                 crow::connections::systemBus->async_method_call(
2252b5ca3fdcSJiaqing Zhao                     [asyncResp, parentInterfaceUri,
2253b5ca3fdcSJiaqing Zhao                      vlanInterface](const boost::system::error_code& ec,
2254b5ca3fdcSJiaqing Zhao                                     const sdbusplus::message_t& m) {
2255bd79bce8SPatrick Williams                         afterVlanCreate(asyncResp, parentInterfaceUri,
2256bd79bce8SPatrick Williams                                         vlanInterface, ec, m);
2257b5ca3fdcSJiaqing Zhao                     },
2258bd79bce8SPatrick Williams                     "xyz.openbmc_project.Network",
2259bd79bce8SPatrick Williams                     "/xyz/openbmc_project/network",
2260bd79bce8SPatrick Williams                     "xyz.openbmc_project.Network.VLAN.Create", "VLAN",
2261bd79bce8SPatrick Williams                     parentInterface, vlanId);
2262b5ca3fdcSJiaqing Zhao             });
2263b5ca3fdcSJiaqing Zhao 
2264253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2265ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
2266bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
226745ca1b86SEd Tanous             [&app](const crow::Request& req,
2268bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2269253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
22703ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
227145ca1b86SEd Tanous                 {
227245ca1b86SEd Tanous                     return;
227345ca1b86SEd Tanous                 }
2274253f11b8SEd Tanous 
2275253f11b8SEd Tanous                 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2276253f11b8SEd Tanous                 {
2277bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "Manager",
2278bd79bce8SPatrick Williams                                                managerId);
2279253f11b8SEd Tanous                     return;
2280253f11b8SEd Tanous                 }
2281253f11b8SEd Tanous 
22824a0cb85cSEd Tanous                 getEthernetIfaceData(
2283bf648f77SEd Tanous                     ifaceId,
2284bd79bce8SPatrick Williams                     [asyncResp, ifaceId](
2285bd79bce8SPatrick Williams                         const bool& success,
2286bd79bce8SPatrick Williams                         const EthernetInterfaceData& ethData,
228777179532SEd Tanous                         const std::vector<IPv4AddressData>& ipv4Data,
2288ce73d5c8SSunitha Harish                         const std::vector<IPv6AddressData>& ipv6Data,
2289ce73d5c8SSunitha Harish                         const std::vector<StaticGatewayData>& ipv6GatewayData) {
22904a0cb85cSEd Tanous                         if (!success)
22911abe55efSEd Tanous                         {
2292bf648f77SEd Tanous                             // TODO(Pawel)consider distinguish between non
2293bf648f77SEd Tanous                             // existing object, and other errors
2294bd79bce8SPatrick Williams                             messages::resourceNotFound(
2295bd79bce8SPatrick Williams                                 asyncResp->res, "EthernetInterface", ifaceId);
22964a0cb85cSEd Tanous                             return;
22979391bb9cSRapkiewicz, Pawel                         }
22984c9afe43SEd Tanous 
22990f74e643SEd Tanous                         asyncResp->res.jsonValue["@odata.type"] =
230093bbc953SJiaqing Zhao                             "#EthernetInterface.v1_9_0.EthernetInterface";
2301bd79bce8SPatrick Williams                         asyncResp->res.jsonValue["Name"] =
2302bd79bce8SPatrick Williams                             "Manager Ethernet Interface";
23030f74e643SEd Tanous                         asyncResp->res.jsonValue["Description"] =
23040f74e643SEd Tanous                             "Management Network Interface";
23050f74e643SEd Tanous 
2306bd79bce8SPatrick Williams                         parseInterfaceData(asyncResp, ifaceId, ethData,
2307bd79bce8SPatrick Williams                                            ipv4Data, ipv6Data, ipv6GatewayData);
23089391bb9cSRapkiewicz, Pawel                     });
2309bf648f77SEd Tanous             });
23109391bb9cSRapkiewicz, Pawel 
2311253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2312ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2313bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
231445ca1b86SEd Tanous             [&app](const crow::Request& req,
2315bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2316253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
23173ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
231845ca1b86SEd Tanous                 {
231945ca1b86SEd Tanous                     return;
232045ca1b86SEd Tanous                 }
2321253f11b8SEd Tanous 
2322253f11b8SEd Tanous                 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2323253f11b8SEd Tanous                 {
2324bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "Manager",
2325bd79bce8SPatrick Williams                                                managerId);
2326253f11b8SEd Tanous                     return;
2327253f11b8SEd Tanous                 }
2328253f11b8SEd Tanous 
2329bc0bd6e0SEd Tanous                 std::optional<std::string> hostname;
2330ab6554f1SJoshi-Mansi                 std::optional<std::string> fqdn;
2331d577665bSRatan Gupta                 std::optional<std::string> macAddress;
23329a6fc6feSRavi Teja                 std::optional<std::string> ipv6DefaultGateway;
2333bd79bce8SPatrick Williams                 std::optional<std::vector<
2334bd79bce8SPatrick Williams                     std::variant<nlohmann::json::object_t, std::nullptr_t>>>
23353dfed536SEd Tanous                     ipv4StaticAddresses;
2336bd79bce8SPatrick Williams                 std::optional<std::vector<
2337bd79bce8SPatrick Williams                     std::variant<nlohmann::json::object_t, std::nullptr_t>>>
23383dfed536SEd Tanous                     ipv6StaticAddresses;
2339bd79bce8SPatrick Williams                 std::optional<std::vector<
2340bd79bce8SPatrick Williams                     std::variant<nlohmann::json::object_t, std::nullptr_t>>>
23413dfed536SEd Tanous                     ipv6StaticDefaultGateways;
2342f85837bfSRAJESWARAN THILLAIGOVINDAN                 std::optional<std::vector<std::string>> staticNameServers;
2343b10d8db0SRavi Teja                 std::optional<bool> ipv6AutoConfigEnabled;
2344eeedda23SJohnathan Mantey                 std::optional<bool> interfaceEnabled;
234535fb5311STejas Patil                 std::optional<size_t> mtuSize;
23461f8c7b5dSJohnathan Mantey                 DHCPParameters v4dhcpParms;
23471f8c7b5dSJohnathan Mantey                 DHCPParameters v6dhcpParms;
2348afc474aeSMyung Bae 
2349afc474aeSMyung Bae                 if (!json_util::readJsonPatch(                             //
2350afc474aeSMyung Bae                         req, asyncResp->res,                               //
2351afc474aeSMyung Bae                         "DHCPv4/DHCPEnabled", v4dhcpParms.dhcpv4Enabled,   //
2352afc474aeSMyung Bae                         "DHCPv4/UseDNSServers", v4dhcpParms.useDnsServers, //
2353afc474aeSMyung Bae                         "DHCPv4/UseDomainName", v4dhcpParms.useDomainName, //
2354afc474aeSMyung Bae                         "DHCPv4/UseNTPServers", v4dhcpParms.useNtpServers, //
2355afc474aeSMyung Bae                         "DHCPv6/OperatingMode",
2356afc474aeSMyung Bae                         v6dhcpParms.dhcpv6OperatingMode,                   //
2357afc474aeSMyung Bae                         "DHCPv6/UseDNSServers", v6dhcpParms.useDnsServers, //
2358afc474aeSMyung Bae                         "DHCPv6/UseDomainName", v6dhcpParms.useDomainName, //
2359afc474aeSMyung Bae                         "DHCPv6/UseNTPServers", v6dhcpParms.useNtpServers, //
2360afc474aeSMyung Bae                         "FQDN", fqdn,                                      //
2361afc474aeSMyung Bae                         "HostName", hostname,                              //
2362afc474aeSMyung Bae                         "InterfaceEnabled", interfaceEnabled,              //
2363afc474aeSMyung Bae                         "IPv4StaticAddresses", ipv4StaticAddresses,        //
2364afc474aeSMyung Bae                         "IPv6DefaultGateway", ipv6DefaultGateway,          //
2365afc474aeSMyung Bae                         "IPv6StaticAddresses", ipv6StaticAddresses,        //
2366afc474aeSMyung Bae                         "IPv6StaticDefaultGateways",
2367afc474aeSMyung Bae                         ipv6StaticDefaultGateways,                         //
2368afc474aeSMyung Bae                         "InterfaceEnabled", interfaceEnabled,              //
2369afc474aeSMyung Bae                         "MACAddress", macAddress,                          //
2370afc474aeSMyung Bae                         "MTUSize", mtuSize,                                //
2371afc474aeSMyung Bae                         "StatelessAddressAutoConfig/IPv6AutoConfigEnabled",
2372afc474aeSMyung Bae                         ipv6AutoConfigEnabled,                             //
2373afc474aeSMyung Bae                         "StaticNameServers", staticNameServers             //
2374afc474aeSMyung Bae                         ))
23751abe55efSEd Tanous                 {
2376588c3f0dSKowalski, Kamil                     return;
2377588c3f0dSKowalski, Kamil                 }
2378da131a9aSJennifer Lee 
2379bf648f77SEd Tanous                 // Get single eth interface data, and call the below callback
2380bf648f77SEd Tanous                 // for JSON preparation
23814a0cb85cSEd Tanous                 getEthernetIfaceData(
23822c70f800SEd Tanous                     ifaceId,
2383bf648f77SEd Tanous                     [asyncResp, ifaceId, hostname = std::move(hostname),
2384ab6554f1SJoshi-Mansi                      fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2385d1d50814SRavi Teja                      ipv4StaticAddresses = std::move(ipv4StaticAddresses),
23869a6fc6feSRavi Teja                      ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2387e48c0fc5SRavi Teja                      ipv6StaticAddresses = std::move(ipv6StaticAddresses),
2388bd79bce8SPatrick Williams                      ipv6StaticDefaultGateway =
2389bd79bce8SPatrick Williams                          std::move(ipv6StaticDefaultGateways),
23903dfed536SEd Tanous                      staticNameServers = std::move(staticNameServers), mtuSize,
2391bd79bce8SPatrick Williams                      ipv6AutoConfigEnabled,
2392bd79bce8SPatrick Williams                      v4dhcpParms = std::move(v4dhcpParms),
2393f23b7296SEd Tanous                      v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2394bd79bce8SPatrick Williams                         const bool success,
2395bd79bce8SPatrick Williams                         const EthernetInterfaceData& ethData,
239677179532SEd Tanous                         const std::vector<IPv4AddressData>& ipv4Data,
2397ce73d5c8SSunitha Harish                         const std::vector<IPv6AddressData>& ipv6Data,
2398bd79bce8SPatrick Williams                         const std::vector<StaticGatewayData>&
2399bd79bce8SPatrick Williams                             ipv6GatewayData) mutable {
24001abe55efSEd Tanous                         if (!success)
24011abe55efSEd Tanous                         {
2402588c3f0dSKowalski, Kamil                             // ... otherwise return error
2403bf648f77SEd Tanous                             // TODO(Pawel)consider distinguish between non
2404bf648f77SEd Tanous                             // existing object, and other errors
2405bd79bce8SPatrick Williams                             messages::resourceNotFound(
2406bd79bce8SPatrick Williams                                 asyncResp->res, "EthernetInterface", ifaceId);
2407588c3f0dSKowalski, Kamil                             return;
2408588c3f0dSKowalski, Kamil                         }
2409588c3f0dSKowalski, Kamil 
2410bd79bce8SPatrick Williams                         handleDHCPPatch(ifaceId, ethData, v4dhcpParms,
2411bd79bce8SPatrick Williams                                         v6dhcpParms, asyncResp);
24121f8c7b5dSJohnathan Mantey 
24130627a2c7SEd Tanous                         if (hostname)
24141abe55efSEd Tanous                         {
24150627a2c7SEd Tanous                             handleHostnamePatch(*hostname, asyncResp);
24161abe55efSEd Tanous                         }
24170627a2c7SEd Tanous 
2418b10d8db0SRavi Teja                         if (ipv6AutoConfigEnabled)
2419b10d8db0SRavi Teja                         {
2420bd79bce8SPatrick Williams                             handleSLAACAutoConfigPatch(
2421bd79bce8SPatrick Williams                                 ifaceId, *ipv6AutoConfigEnabled, asyncResp);
2422b10d8db0SRavi Teja                         }
2423b10d8db0SRavi Teja 
2424ab6554f1SJoshi-Mansi                         if (fqdn)
2425ab6554f1SJoshi-Mansi                         {
24262c70f800SEd Tanous                             handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2427ab6554f1SJoshi-Mansi                         }
2428ab6554f1SJoshi-Mansi 
2429d577665bSRatan Gupta                         if (macAddress)
2430d577665bSRatan Gupta                         {
2431bd79bce8SPatrick Williams                             handleMACAddressPatch(ifaceId, *macAddress,
2432bd79bce8SPatrick Williams                                                   asyncResp);
2433d577665bSRatan Gupta                         }
2434d577665bSRatan Gupta 
2435d1d50814SRavi Teja                         if (ipv4StaticAddresses)
2436d1d50814SRavi Teja                         {
2437bd79bce8SPatrick Williams                             handleIPv4StaticPatch(ifaceId, *ipv4StaticAddresses,
2438bd79bce8SPatrick Williams                                                   ethData, ipv4Data, asyncResp);
24391abe55efSEd Tanous                         }
24400627a2c7SEd Tanous 
2441f85837bfSRAJESWARAN THILLAIGOVINDAN                         if (staticNameServers)
2442f85837bfSRAJESWARAN THILLAIGOVINDAN                         {
2443bd79bce8SPatrick Williams                             handleStaticNameServersPatch(
2444bd79bce8SPatrick Williams                                 ifaceId, *staticNameServers, asyncResp);
2445f85837bfSRAJESWARAN THILLAIGOVINDAN                         }
24469a6fc6feSRavi Teja 
24479a6fc6feSRavi Teja                         if (ipv6DefaultGateway)
24489a6fc6feSRavi Teja                         {
24499a6fc6feSRavi Teja                             messages::propertyNotWritable(asyncResp->res,
24509a6fc6feSRavi Teja                                                           "IPv6DefaultGateway");
24519a6fc6feSRavi Teja                         }
2452e48c0fc5SRavi Teja 
2453e48c0fc5SRavi Teja                         if (ipv6StaticAddresses)
2454e48c0fc5SRavi Teja                         {
2455bd79bce8SPatrick Williams                             handleIPv6StaticAddressesPatch(ifaceId,
2456bd79bce8SPatrick Williams                                                            *ipv6StaticAddresses,
2457ddd70dcaSEd Tanous                                                            ipv6Data, asyncResp);
2458e48c0fc5SRavi Teja                         }
2459eeedda23SJohnathan Mantey 
2460ce73d5c8SSunitha Harish                         if (ipv6StaticDefaultGateway)
2461ce73d5c8SSunitha Harish                         {
2462bd79bce8SPatrick Williams                             handleIPv6DefaultGateway(
2463bd79bce8SPatrick Williams                                 ifaceId, *ipv6StaticDefaultGateway,
2464ce73d5c8SSunitha Harish                                 ipv6GatewayData, asyncResp);
2465ce73d5c8SSunitha Harish                         }
2466ce73d5c8SSunitha Harish 
2467eeedda23SJohnathan Mantey                         if (interfaceEnabled)
2468eeedda23SJohnathan Mantey                         {
2469bd79bce8SPatrick Williams                             setDbusProperty(
2470bd79bce8SPatrick Williams                                 asyncResp, "InterfaceEnabled",
2471e93abac6SGinu George                                 "xyz.openbmc_project.Network",
2472d02aad39SEd Tanous                                 sdbusplus::message::object_path(
2473d02aad39SEd Tanous                                     "/xyz/openbmc_project/network") /
2474d02aad39SEd Tanous                                     ifaceId,
2475d02aad39SEd Tanous                                 "xyz.openbmc_project.Network.EthernetInterface",
2476e93abac6SGinu George                                 "NICEnabled", *interfaceEnabled);
2477eeedda23SJohnathan Mantey                         }
247835fb5311STejas Patil 
247935fb5311STejas Patil                         if (mtuSize)
248035fb5311STejas Patil                         {
248135fb5311STejas Patil                             handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
248235fb5311STejas Patil                         }
2483588c3f0dSKowalski, Kamil                     });
2484bf648f77SEd Tanous             });
2485e7caf250SJiaqing Zhao 
2486253f11b8SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/<str>/EthernetInterfaces/<str>/")
2487e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2488e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2489e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2490e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2491253f11b8SEd Tanous                    const std::string& managerId, const std::string& ifaceId) {
2492e7caf250SJiaqing Zhao                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2493e7caf250SJiaqing Zhao                 {
2494e7caf250SJiaqing Zhao                     return;
2495e7caf250SJiaqing Zhao                 }
2496e7caf250SJiaqing Zhao 
2497253f11b8SEd Tanous                 if (managerId != BMCWEB_REDFISH_MANAGER_URI_NAME)
2498253f11b8SEd Tanous                 {
2499bd79bce8SPatrick Williams                     messages::resourceNotFound(asyncResp->res, "Manager",
2500bd79bce8SPatrick Williams                                                managerId);
2501253f11b8SEd Tanous                     return;
2502253f11b8SEd Tanous                 }
2503253f11b8SEd Tanous 
2504e7caf250SJiaqing Zhao                 crow::connections::systemBus->async_method_call(
2505e7caf250SJiaqing Zhao                     [asyncResp, ifaceId](const boost::system::error_code& ec,
2506e7caf250SJiaqing Zhao                                          const sdbusplus::message_t& m) {
2507e7caf250SJiaqing Zhao                         afterDelete(asyncResp, ifaceId, ec, m);
2508e7caf250SJiaqing Zhao                     },
2509e7caf250SJiaqing Zhao                     "xyz.openbmc_project.Network",
2510e7caf250SJiaqing Zhao                     std::string("/xyz/openbmc_project/network/") + ifaceId,
2511e7caf250SJiaqing Zhao                     "xyz.openbmc_project.Object.Delete", "Delete");
2512e7caf250SJiaqing Zhao             });
25134a0cb85cSEd Tanous }
2514bf648f77SEd Tanous 
25159391bb9cSRapkiewicz, Pawel } // namespace redfish
2516