xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision e4588158c0ccc2b3b7af459b262e8eaefaf8f985)
19391bb9cSRapkiewicz, Pawel /*
29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation
39391bb9cSRapkiewicz, Pawel //
49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License");
59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License.
69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at
79391bb9cSRapkiewicz, Pawel //
89391bb9cSRapkiewicz, Pawel //      http://www.apache.org/licenses/LICENSE-2.0
99391bb9cSRapkiewicz, Pawel //
109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software
119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS,
129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and
149391bb9cSRapkiewicz, Pawel // limitations under the License.
159391bb9cSRapkiewicz, Pawel */
169391bb9cSRapkiewicz, Pawel #pragma once
179391bb9cSRapkiewicz, Pawel 
1813451e39SWilly Tu #include "bmcweb_config.h"
1913451e39SWilly Tu 
203ccb3adbSEd Tanous #include "app.hpp"
213ccb3adbSEd Tanous #include "dbus_singleton.hpp"
227a1dbc48SGeorge Liu #include "dbus_utility.hpp"
233ccb3adbSEd Tanous #include "error_messages.hpp"
243ccb3adbSEd Tanous #include "health.hpp"
252c5875a2SEd Tanous #include "human_sort.hpp"
263ccb3adbSEd Tanous #include "query.hpp"
273ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
28033f1e4dSEd Tanous #include "utils/ip_utils.hpp"
293ccb3adbSEd Tanous #include "utils/json_utils.hpp"
30033f1e4dSEd Tanous 
31ef4c65b7SEd Tanous #include <boost/url/format.hpp>
321214b7e7SGunnar Mills 
337a1dbc48SGeorge Liu #include <array>
34a24526dcSEd Tanous #include <optional>
353544d2a7SEd Tanous #include <ranges>
36ab6554f1SJoshi-Mansi #include <regex>
377a1dbc48SGeorge Liu #include <string_view>
3877179532SEd Tanous #include <vector>
399391bb9cSRapkiewicz, Pawel 
401abe55efSEd Tanous namespace redfish
411abe55efSEd Tanous {
429391bb9cSRapkiewicz, Pawel 
434a0cb85cSEd Tanous enum class LinkType
444a0cb85cSEd Tanous {
454a0cb85cSEd Tanous     Local,
464a0cb85cSEd Tanous     Global
474a0cb85cSEd Tanous };
489391bb9cSRapkiewicz, Pawel 
499391bb9cSRapkiewicz, Pawel /**
509391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
519391bb9cSRapkiewicz, Pawel  */
521abe55efSEd Tanous struct IPv4AddressData
531abe55efSEd Tanous {
54179db1d7SKowalski, Kamil     std::string id;
554a0cb85cSEd Tanous     std::string address;
564a0cb85cSEd Tanous     std::string domain;
574a0cb85cSEd Tanous     std::string gateway;
589391bb9cSRapkiewicz, Pawel     std::string netmask;
599391bb9cSRapkiewicz, Pawel     std::string origin;
6077179532SEd Tanous     LinkType linktype{};
6177179532SEd Tanous     bool isActive{};
629391bb9cSRapkiewicz, Pawel };
639391bb9cSRapkiewicz, Pawel 
649391bb9cSRapkiewicz, Pawel /**
65e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
66e48c0fc5SRavi Teja  */
67e48c0fc5SRavi Teja struct IPv6AddressData
68e48c0fc5SRavi Teja {
69e48c0fc5SRavi Teja     std::string id;
70e48c0fc5SRavi Teja     std::string address;
71e48c0fc5SRavi Teja     std::string origin;
7277179532SEd Tanous     uint8_t prefixLength = 0;
73e48c0fc5SRavi Teja };
74e48c0fc5SRavi Teja /**
759391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
769391bb9cSRapkiewicz, Pawel  * available from DBus
779391bb9cSRapkiewicz, Pawel  */
781abe55efSEd Tanous struct EthernetInterfaceData
791abe55efSEd Tanous {
804a0cb85cSEd Tanous     uint32_t speed;
8135fb5311STejas Patil     size_t mtuSize;
8282695a5bSJiaqing Zhao     bool autoNeg;
83*e4588158SJishnu CM     bool dnsv4Enabled;
84*e4588158SJishnu CM     bool dnsv6Enabled;
85*e4588158SJishnu CM     bool ntpv4Enabled;
86*e4588158SJishnu CM     bool ntpv6Enabled;
87*e4588158SJishnu CM     bool hostNamev4Enabled;
88*e4588158SJishnu CM     bool hostNamev6Enabled;
89aa05fb27SJohnathan Mantey     bool linkUp;
90eeedda23SJohnathan Mantey     bool nicEnabled;
91b10d8db0SRavi Teja     bool ipv6AcceptRa;
9282695a5bSJiaqing Zhao     std::string dhcpEnabled;
931f8c7b5dSJohnathan Mantey     std::string operatingMode;
9482695a5bSJiaqing Zhao     std::string hostName;
9582695a5bSJiaqing Zhao     std::string defaultGateway;
9682695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
9782695a5bSJiaqing Zhao     std::string macAddress;
9817e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
990f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1000f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
101d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1029391bb9cSRapkiewicz, Pawel };
1039391bb9cSRapkiewicz, Pawel 
1041f8c7b5dSJohnathan Mantey struct DHCPParameters
1051f8c7b5dSJohnathan Mantey {
1061f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
10782695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
10882695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
10982695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1101f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1111f8c7b5dSJohnathan Mantey };
1121f8c7b5dSJohnathan Mantey 
1139391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1149391bb9cSRapkiewicz, Pawel // into full dot notation
1151abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1161abe55efSEd Tanous {
1179391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1189391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1199391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1209391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1219391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1229391bb9cSRapkiewicz, Pawel     return netmask;
1239391bb9cSRapkiewicz, Pawel }
1249391bb9cSRapkiewicz, Pawel 
12582695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1261f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1271f8c7b5dSJohnathan Mantey {
1281f8c7b5dSJohnathan Mantey     if (isIPv4)
1291f8c7b5dSJohnathan Mantey     {
1301f8c7b5dSJohnathan Mantey         return (
1311f8c7b5dSJohnathan Mantey             (inputDHCP ==
1321f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1331f8c7b5dSJohnathan Mantey             (inputDHCP ==
1341f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1351f8c7b5dSJohnathan Mantey     }
1361f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1371f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1381f8c7b5dSJohnathan Mantey             (inputDHCP ==
1391f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1401f8c7b5dSJohnathan Mantey }
1411f8c7b5dSJohnathan Mantey 
1422c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1431f8c7b5dSJohnathan Mantey {
1441f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1451f8c7b5dSJohnathan Mantey     {
1461f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1471f8c7b5dSJohnathan Mantey     }
1483174e4dfSEd Tanous     if (isIPv4)
1491f8c7b5dSJohnathan Mantey     {
1501f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1511f8c7b5dSJohnathan Mantey     }
1523174e4dfSEd Tanous     if (isIPv6)
1531f8c7b5dSJohnathan Mantey     {
1541f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1551f8c7b5dSJohnathan Mantey     }
1561f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1571f8c7b5dSJohnathan Mantey }
1581f8c7b5dSJohnathan Mantey 
1594a0cb85cSEd Tanous inline std::string
1604a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1614a0cb85cSEd Tanous                                         bool isIPv4)
1621abe55efSEd Tanous {
1634a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1641abe55efSEd Tanous     {
1654a0cb85cSEd Tanous         return "Static";
1669391bb9cSRapkiewicz, Pawel     }
1674a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1681abe55efSEd Tanous     {
1694a0cb85cSEd Tanous         if (isIPv4)
1701abe55efSEd Tanous         {
1714a0cb85cSEd Tanous             return "IPv4LinkLocal";
1721abe55efSEd Tanous         }
1734a0cb85cSEd Tanous         return "LinkLocal";
1749391bb9cSRapkiewicz, Pawel     }
1754a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1761abe55efSEd Tanous     {
1774a0cb85cSEd Tanous         if (isIPv4)
1784a0cb85cSEd Tanous         {
1794a0cb85cSEd Tanous             return "DHCP";
1804a0cb85cSEd Tanous         }
1814a0cb85cSEd Tanous         return "DHCPv6";
1824a0cb85cSEd Tanous     }
1834a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
1844a0cb85cSEd Tanous     {
1854a0cb85cSEd Tanous         return "SLAAC";
1864a0cb85cSEd Tanous     }
1874a0cb85cSEd Tanous     return "";
1884a0cb85cSEd Tanous }
1894a0cb85cSEd Tanous 
19002cad96eSEd Tanous inline bool extractEthernetInterfaceData(
19102cad96eSEd Tanous     const std::string& ethifaceId,
19202cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
1934a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
1944a0cb85cSEd Tanous {
1954c9afe43SEd Tanous     bool idFound = false;
19602cad96eSEd Tanous     for (const auto& objpath : dbusData)
1974a0cb85cSEd Tanous     {
19802cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
1994a0cb85cSEd Tanous         {
20081ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
201029573d4SEd Tanous             {
2024c9afe43SEd Tanous                 idFound = true;
2034a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2044a0cb85cSEd Tanous                 {
2054a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2064a0cb85cSEd Tanous                     {
2074a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2084a0cb85cSEd Tanous                         {
2094a0cb85cSEd Tanous                             const std::string* mac =
210abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2114a0cb85cSEd Tanous                             if (mac != nullptr)
2124a0cb85cSEd Tanous                             {
21382695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2144a0cb85cSEd Tanous                             }
2154a0cb85cSEd Tanous                         }
2164a0cb85cSEd Tanous                     }
2174a0cb85cSEd Tanous                 }
2184a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2194a0cb85cSEd Tanous                 {
2204a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2214a0cb85cSEd Tanous                     {
2224a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2234a0cb85cSEd Tanous                         {
2241b6b96c5SEd Tanous                             const uint32_t* id =
225abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2264a0cb85cSEd Tanous                             if (id != nullptr)
2274a0cb85cSEd Tanous                             {
22817e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2294a0cb85cSEd Tanous                             }
2304a0cb85cSEd Tanous                         }
2314a0cb85cSEd Tanous                     }
2324a0cb85cSEd Tanous                 }
2334a0cb85cSEd Tanous                 else if (ifacePair.first ==
2344a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2354a0cb85cSEd Tanous                 {
2364a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2374a0cb85cSEd Tanous                     {
2384a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2394a0cb85cSEd Tanous                         {
2402c70f800SEd Tanous                             const bool* autoNeg =
241abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2422c70f800SEd Tanous                             if (autoNeg != nullptr)
2434a0cb85cSEd Tanous                             {
24482695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2454a0cb85cSEd Tanous                             }
2464a0cb85cSEd Tanous                         }
2474a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2484a0cb85cSEd Tanous                         {
2494a0cb85cSEd Tanous                             const uint32_t* speed =
250abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2514a0cb85cSEd Tanous                             if (speed != nullptr)
2524a0cb85cSEd Tanous                             {
2534a0cb85cSEd Tanous                                 ethData.speed = *speed;
2544a0cb85cSEd Tanous                             }
2554a0cb85cSEd Tanous                         }
25635fb5311STejas Patil                         else if (propertyPair.first == "MTU")
25735fb5311STejas Patil                         {
2583e7a8da6SAnthony                             const size_t* mtuSize =
2593e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
26035fb5311STejas Patil                             if (mtuSize != nullptr)
26135fb5311STejas Patil                             {
26235fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
26335fb5311STejas Patil                             }
26435fb5311STejas Patil                         }
265aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
266aa05fb27SJohnathan Mantey                         {
267aa05fb27SJohnathan Mantey                             const bool* linkUp =
268aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
269aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
270aa05fb27SJohnathan Mantey                             {
271aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
272aa05fb27SJohnathan Mantey                             }
273aa05fb27SJohnathan Mantey                         }
274eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
275eeedda23SJohnathan Mantey                         {
276eeedda23SJohnathan Mantey                             const bool* nicEnabled =
277eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
278eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
279eeedda23SJohnathan Mantey                             {
280eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
281eeedda23SJohnathan Mantey                             }
282eeedda23SJohnathan Mantey                         }
283b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
284b10d8db0SRavi Teja                         {
285b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
286b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
287b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
288b10d8db0SRavi Teja                             {
289b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
290b10d8db0SRavi Teja                             }
291b10d8db0SRavi Teja                         }
292f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
293029573d4SEd Tanous                         {
294029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
2958d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
296029573d4SEd Tanous                                     &propertyPair.second);
297029573d4SEd Tanous                             if (nameservers != nullptr)
298029573d4SEd Tanous                             {
299f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3000f6efdc1Smanojkiran.eda@gmail.com                             }
3010f6efdc1Smanojkiran.eda@gmail.com                         }
3020f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3030f6efdc1Smanojkiran.eda@gmail.com                         {
3040f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3058d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3060f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3070f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3080f6efdc1Smanojkiran.eda@gmail.com                             {
309f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3104a0cb85cSEd Tanous                             }
3114a0cb85cSEd Tanous                         }
3122a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3132a133282Smanojkiraneda                         {
3142c70f800SEd Tanous                             const std::string* dhcpEnabled =
3151f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3162c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3172a133282Smanojkiraneda                             {
31882695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3192a133282Smanojkiraneda                             }
3202a133282Smanojkiraneda                         }
321d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
322d24bfc7aSJennifer Lee                         {
323d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3248d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
325d24bfc7aSJennifer Lee                                     &propertyPair.second);
326d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
327d24bfc7aSJennifer Lee                             {
328f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
329d24bfc7aSJennifer Lee                             }
330d24bfc7aSJennifer Lee                         }
3319010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3329010ec2eSRavi Teja                         {
3339010ec2eSRavi Teja                             const std::string* defaultGateway =
3349010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3359010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3369010ec2eSRavi Teja                             {
3379010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3389010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3399010ec2eSRavi Teja                                 {
34082695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3419010ec2eSRavi Teja                                 }
3429010ec2eSRavi Teja                                 else
3439010ec2eSRavi Teja                                 {
34482695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3459010ec2eSRavi Teja                                 }
3469010ec2eSRavi Teja                             }
3479010ec2eSRavi Teja                         }
3489010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3499010ec2eSRavi Teja                         {
3509010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3519010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3529010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3539010ec2eSRavi Teja                             {
3549010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3559010ec2eSRavi Teja                                     *defaultGateway6;
3569010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3579010ec2eSRavi Teja                                 {
35882695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3599010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3609010ec2eSRavi Teja                                 }
3619010ec2eSRavi Teja                                 else
3629010ec2eSRavi Teja                                 {
36382695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3649010ec2eSRavi Teja                                         defaultGateway6Str;
3659010ec2eSRavi Teja                                 }
3669010ec2eSRavi Teja                             }
3679010ec2eSRavi Teja                         }
368029573d4SEd Tanous                     }
369029573d4SEd Tanous                 }
370029573d4SEd Tanous             }
3711f8c7b5dSJohnathan Mantey 
372*e4588158SJishnu CM             sdbusplus::message::object_path path(
373*e4588158SJishnu CM                 "/xyz/openbmc_project/network");
374*e4588158SJishnu CM             sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
375*e4588158SJishnu CM                                                         "dhcp4";
376*e4588158SJishnu CM 
377*e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
3781f8c7b5dSJohnathan Mantey             {
3791f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
3801f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
3811f8c7b5dSJohnathan Mantey                 {
3821f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
3831f8c7b5dSJohnathan Mantey                     {
3841f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
3851f8c7b5dSJohnathan Mantey                         {
3862c70f800SEd Tanous                             const bool* dnsEnabled =
3871f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
3882c70f800SEd Tanous                             if (dnsEnabled != nullptr)
3891f8c7b5dSJohnathan Mantey                             {
390*e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
3911f8c7b5dSJohnathan Mantey                             }
3921f8c7b5dSJohnathan Mantey                         }
3931f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
3941f8c7b5dSJohnathan Mantey                         {
3952c70f800SEd Tanous                             const bool* ntpEnabled =
3961f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
3972c70f800SEd Tanous                             if (ntpEnabled != nullptr)
3981f8c7b5dSJohnathan Mantey                             {
399*e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4001f8c7b5dSJohnathan Mantey                             }
4011f8c7b5dSJohnathan Mantey                         }
4021f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4031f8c7b5dSJohnathan Mantey                         {
4042c70f800SEd Tanous                             const bool* hostNameEnabled =
4051f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4062c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4071f8c7b5dSJohnathan Mantey                             {
408*e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
409*e4588158SJishnu CM                             }
410*e4588158SJishnu CM                         }
411*e4588158SJishnu CM                     }
412*e4588158SJishnu CM                 }
413*e4588158SJishnu CM             }
414*e4588158SJishnu CM 
415*e4588158SJishnu CM             sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
416*e4588158SJishnu CM                                                         "dhcp6";
417*e4588158SJishnu CM 
418*e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
419*e4588158SJishnu CM             {
420*e4588158SJishnu CM                 if (ifacePair.first ==
421*e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
422*e4588158SJishnu CM                 {
423*e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
424*e4588158SJishnu CM                     {
425*e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
426*e4588158SJishnu CM                         {
427*e4588158SJishnu CM                             const bool* dnsEnabled =
428*e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
429*e4588158SJishnu CM                             if (dnsEnabled != nullptr)
430*e4588158SJishnu CM                             {
431*e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
432*e4588158SJishnu CM                             }
433*e4588158SJishnu CM                         }
434*e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
435*e4588158SJishnu CM                         {
436*e4588158SJishnu CM                             const bool* ntpEnabled =
437*e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
438*e4588158SJishnu CM                             if (ntpEnabled != nullptr)
439*e4588158SJishnu CM                             {
440*e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
441*e4588158SJishnu CM                             }
442*e4588158SJishnu CM                         }
443*e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
444*e4588158SJishnu CM                         {
445*e4588158SJishnu CM                             const bool* hostNameEnabled =
446*e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
447*e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
448*e4588158SJishnu CM                             {
449*e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
4501f8c7b5dSJohnathan Mantey                             }
4511f8c7b5dSJohnathan Mantey                         }
4521f8c7b5dSJohnathan Mantey                     }
4531f8c7b5dSJohnathan Mantey                 }
4541f8c7b5dSJohnathan Mantey             }
455029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
456029573d4SEd Tanous             // to check eth number
457029573d4SEd Tanous             if (ifacePair.first ==
4584a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4594a0cb85cSEd Tanous             {
4604a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
4614a0cb85cSEd Tanous                 {
4624a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
4634a0cb85cSEd Tanous                     {
4644a0cb85cSEd Tanous                         const std::string* hostname =
4658d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
4664a0cb85cSEd Tanous                         if (hostname != nullptr)
4674a0cb85cSEd Tanous                         {
46882695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
4694a0cb85cSEd Tanous                         }
4704a0cb85cSEd Tanous                     }
4714a0cb85cSEd Tanous                 }
4724a0cb85cSEd Tanous             }
4734a0cb85cSEd Tanous         }
4744a0cb85cSEd Tanous     }
4754c9afe43SEd Tanous     return idFound;
4764a0cb85cSEd Tanous }
4774a0cb85cSEd Tanous 
478e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
47977179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
480711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
48177179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
482e48c0fc5SRavi Teja {
48389492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
48489492a15SPatrick Williams                                     ethifaceId;
485e48c0fc5SRavi Teja 
486e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
487e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
48881ce609eSEd Tanous     for (const auto& objpath : dbusData)
489e48c0fc5SRavi Teja     {
490e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
491353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
492e48c0fc5SRavi Teja         {
4939eb808c1SEd Tanous             for (const auto& interface : objpath.second)
494e48c0fc5SRavi Teja             {
495e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
496e48c0fc5SRavi Teja                 {
4973544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
498353163e9STony Lee                                                      [](const auto& property) {
499353163e9STony Lee                         return property.first == "Type";
500353163e9STony Lee                     });
501353163e9STony Lee                     if (type == interface.second.end())
502353163e9STony Lee                     {
503353163e9STony Lee                         continue;
504353163e9STony Lee                     }
505353163e9STony Lee 
506353163e9STony Lee                     const std::string* typeStr =
507353163e9STony Lee                         std::get_if<std::string>(&type->second);
508353163e9STony Lee 
509353163e9STony Lee                     if (typeStr == nullptr ||
510353163e9STony Lee                         (*typeStr !=
511353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
512353163e9STony Lee                     {
513353163e9STony Lee                         continue;
514353163e9STony Lee                     }
515353163e9STony Lee 
516e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
517e48c0fc5SRavi Teja                     // appropriate
51877179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5192c70f800SEd Tanous                     ipv6Address.id =
520353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5219eb808c1SEd Tanous                     for (const auto& property : interface.second)
522e48c0fc5SRavi Teja                     {
523e48c0fc5SRavi Teja                         if (property.first == "Address")
524e48c0fc5SRavi Teja                         {
525e48c0fc5SRavi Teja                             const std::string* address =
526e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
527e48c0fc5SRavi Teja                             if (address != nullptr)
528e48c0fc5SRavi Teja                             {
5292c70f800SEd Tanous                                 ipv6Address.address = *address;
530e48c0fc5SRavi Teja                             }
531e48c0fc5SRavi Teja                         }
532e48c0fc5SRavi Teja                         else if (property.first == "Origin")
533e48c0fc5SRavi Teja                         {
534e48c0fc5SRavi Teja                             const std::string* origin =
535e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
536e48c0fc5SRavi Teja                             if (origin != nullptr)
537e48c0fc5SRavi Teja                             {
5382c70f800SEd Tanous                                 ipv6Address.origin =
539e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
540e48c0fc5SRavi Teja                                                                         false);
541e48c0fc5SRavi Teja                             }
542e48c0fc5SRavi Teja                         }
543e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
544e48c0fc5SRavi Teja                         {
545e48c0fc5SRavi Teja                             const uint8_t* prefix =
546e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
547e48c0fc5SRavi Teja                             if (prefix != nullptr)
548e48c0fc5SRavi Teja                             {
5492c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
550e48c0fc5SRavi Teja                             }
551e48c0fc5SRavi Teja                         }
552889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
553889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
554889ff694SAsmitha Karunanithi                         {
555889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
556889ff694SAsmitha Karunanithi                         }
557e48c0fc5SRavi Teja                         else
558e48c0fc5SRavi Teja                         {
55962598e31SEd Tanous                             BMCWEB_LOG_ERROR(
56062598e31SEd Tanous                                 "Got extra property: {} on the {} object",
56162598e31SEd Tanous                                 property.first, objpath.first.str);
562e48c0fc5SRavi Teja                         }
563e48c0fc5SRavi Teja                     }
564e48c0fc5SRavi Teja                 }
565e48c0fc5SRavi Teja             }
566e48c0fc5SRavi Teja         }
567e48c0fc5SRavi Teja     }
568e48c0fc5SRavi Teja }
569e48c0fc5SRavi Teja 
5704a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
57177179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
572711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
57377179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
5744a0cb85cSEd Tanous {
57589492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
57689492a15SPatrick Williams                                     ethifaceId;
5774a0cb85cSEd Tanous 
5784a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
5794a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
58081ce609eSEd Tanous     for (const auto& objpath : dbusData)
5814a0cb85cSEd Tanous     {
5824a0cb85cSEd Tanous         // Check if proper pattern for object path appears
583353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
5844a0cb85cSEd Tanous         {
5859eb808c1SEd Tanous             for (const auto& interface : objpath.second)
5864a0cb85cSEd Tanous             {
5874a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
5884a0cb85cSEd Tanous                 {
5893544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
590353163e9STony Lee                                                      [](const auto& property) {
591353163e9STony Lee                         return property.first == "Type";
592353163e9STony Lee                     });
593353163e9STony Lee                     if (type == interface.second.end())
594353163e9STony Lee                     {
595353163e9STony Lee                         continue;
596353163e9STony Lee                     }
597353163e9STony Lee 
598353163e9STony Lee                     const std::string* typeStr =
599353163e9STony Lee                         std::get_if<std::string>(&type->second);
600353163e9STony Lee 
601353163e9STony Lee                     if (typeStr == nullptr ||
602353163e9STony Lee                         (*typeStr !=
603353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
604353163e9STony Lee                     {
605353163e9STony Lee                         continue;
606353163e9STony Lee                     }
607353163e9STony Lee 
6084a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6094a0cb85cSEd Tanous                     // appropriate
61077179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6112c70f800SEd Tanous                     ipv4Address.id =
612353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6139eb808c1SEd Tanous                     for (const auto& property : interface.second)
6144a0cb85cSEd Tanous                     {
6154a0cb85cSEd Tanous                         if (property.first == "Address")
6164a0cb85cSEd Tanous                         {
6174a0cb85cSEd Tanous                             const std::string* address =
618abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6194a0cb85cSEd Tanous                             if (address != nullptr)
6204a0cb85cSEd Tanous                             {
6212c70f800SEd Tanous                                 ipv4Address.address = *address;
6224a0cb85cSEd Tanous                             }
6234a0cb85cSEd Tanous                         }
6244a0cb85cSEd Tanous                         else if (property.first == "Origin")
6254a0cb85cSEd Tanous                         {
6264a0cb85cSEd Tanous                             const std::string* origin =
627abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6284a0cb85cSEd Tanous                             if (origin != nullptr)
6294a0cb85cSEd Tanous                             {
6302c70f800SEd Tanous                                 ipv4Address.origin =
6314a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6324a0cb85cSEd Tanous                                                                         true);
6334a0cb85cSEd Tanous                             }
6344a0cb85cSEd Tanous                         }
6354a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6364a0cb85cSEd Tanous                         {
6374a0cb85cSEd Tanous                             const uint8_t* mask =
638abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6394a0cb85cSEd Tanous                             if (mask != nullptr)
6404a0cb85cSEd Tanous                             {
6414a0cb85cSEd Tanous                                 // convert it to the string
6422c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6434a0cb85cSEd Tanous                             }
6444a0cb85cSEd Tanous                         }
645889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
646889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
647889ff694SAsmitha Karunanithi                         {
648889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
649889ff694SAsmitha Karunanithi                         }
6504a0cb85cSEd Tanous                         else
6514a0cb85cSEd Tanous                         {
65262598e31SEd Tanous                             BMCWEB_LOG_ERROR(
65362598e31SEd Tanous                                 "Got extra property: {} on the {} object",
65462598e31SEd Tanous                                 property.first, objpath.first.str);
6554a0cb85cSEd Tanous                         }
6564a0cb85cSEd Tanous                     }
6574a0cb85cSEd Tanous                     // Check if given address is local, or global
6582c70f800SEd Tanous                     ipv4Address.linktype =
65911ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
66018659d10SJohnathan Mantey                             ? LinkType::Local
66118659d10SJohnathan Mantey                             : LinkType::Global;
6624a0cb85cSEd Tanous                 }
6634a0cb85cSEd Tanous             }
6644a0cb85cSEd Tanous         }
6654a0cb85cSEd Tanous     }
6664a0cb85cSEd Tanous }
667588c3f0dSKowalski, Kamil 
668588c3f0dSKowalski, Kamil /**
66901784826SJohnathan Mantey  * @brief Deletes given IPv4 interface
670179db1d7SKowalski, Kamil  *
671179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
672179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
673179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
674179db1d7SKowalski, Kamil  *
675179db1d7SKowalski, Kamil  * @return None
676179db1d7SKowalski, Kamil  */
6779c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
6789c5e585cSRavi Teja                             const std::string& ipHash,
6798d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
6801abe55efSEd Tanous {
68155c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
6825e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
6831abe55efSEd Tanous         if (ec)
6841abe55efSEd Tanous         {
685a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
6861abe55efSEd Tanous         }
687179db1d7SKowalski, Kamil     },
688179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
6899c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
690179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
691179db1d7SKowalski, Kamil }
692179db1d7SKowalski, Kamil 
693244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway(
694244b6d5bSGunnar Mills     const std::string& ifaceId, const std::string& gateway,
695244b6d5bSGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
6969010ec2eSRavi Teja {
6979ae226faSGeorge Liu     sdbusplus::asio::setProperty(
6989ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
6999ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
7009ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
7019ae226faSGeorge Liu         gateway, [asyncResp](const boost::system::error_code& ec) {
7029010ec2eSRavi Teja         if (ec)
7039010ec2eSRavi Teja         {
7049010ec2eSRavi Teja             messages::internalError(asyncResp->res);
7059010ec2eSRavi Teja             return;
7069010ec2eSRavi Teja         }
7079010ec2eSRavi Teja         asyncResp->res.result(boost::beast::http::status::no_content);
7089ae226faSGeorge Liu     });
7099010ec2eSRavi Teja }
710179db1d7SKowalski, Kamil /**
71101784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
712179db1d7SKowalski, Kamil  *
71301784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
71401784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
71501784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
71601784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
717179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
718179db1d7SKowalski, Kamil  *
719179db1d7SKowalski, Kamil  * @return None
720179db1d7SKowalski, Kamil  */
721cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
722cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7238d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7241abe55efSEd Tanous {
7255a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
7265a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
7271abe55efSEd Tanous         if (ec)
7281abe55efSEd Tanous         {
729a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7309010ec2eSRavi Teja             return;
731179db1d7SKowalski, Kamil         }
7329010ec2eSRavi Teja         updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
7339010ec2eSRavi Teja     };
7349010ec2eSRavi Teja 
7359010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7369010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
737179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
738179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
73901784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
740179db1d7SKowalski, Kamil         gateway);
741179db1d7SKowalski, Kamil }
742e48c0fc5SRavi Teja 
743e48c0fc5SRavi Teja /**
74401784826SJohnathan Mantey  * @brief Deletes the IPv6 entry for this interface and creates a replacement
74501784826SJohnathan Mantey  * static IPv6 entry
74601784826SJohnathan Mantey  *
74701784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv6 entry
74801784826SJohnathan Mantey  * @param[in] id           The unique hash entry identifying the DBus entry
74901784826SJohnathan Mantey  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
75001784826SJohnathan Mantey  * @param[in] address      IPv6 address to assign to this interface
75101784826SJohnathan Mantey  * @param[io] asyncResp    Response object that will be returned to client
75201784826SJohnathan Mantey  *
75301784826SJohnathan Mantey  * @return None
75401784826SJohnathan Mantey  */
7559c5e585cSRavi Teja 
7569c5e585cSRavi Teja enum class IpVersion
7579c5e585cSRavi Teja {
7589c5e585cSRavi Teja     IpV4,
7599c5e585cSRavi Teja     IpV6
7609c5e585cSRavi Teja };
7619c5e585cSRavi Teja 
7629c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
7639c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
7648d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
7659c5e585cSRavi Teja     const std::string& gateway,
7668d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
76701784826SJohnathan Mantey {
76801784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
7699c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
7709c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
77101784826SJohnathan Mantey         if (ec)
77201784826SJohnathan Mantey         {
77301784826SJohnathan Mantey             messages::internalError(asyncResp->res);
77401784826SJohnathan Mantey         }
7759c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
7769c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
77701784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
7785e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
77923a21a1cSEd Tanous             if (ec2)
78001784826SJohnathan Mantey             {
78101784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
78201784826SJohnathan Mantey             }
78301784826SJohnathan Mantey         },
78401784826SJohnathan Mantey             "xyz.openbmc_project.Network",
78501784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
7869c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
7879c5e585cSRavi Teja             prefixLength, gateway);
78801784826SJohnathan Mantey     },
78901784826SJohnathan Mantey         "xyz.openbmc_project.Network",
7909c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
79101784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
79201784826SJohnathan Mantey }
79301784826SJohnathan Mantey 
79401784826SJohnathan Mantey /**
795e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
796e48c0fc5SRavi Teja  *
797e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
798e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
799e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
800e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
801e48c0fc5SRavi Teja  *
802e48c0fc5SRavi Teja  * @return None
803e48c0fc5SRavi Teja  */
80401784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
80501784826SJohnathan Mantey                        const std::string& address,
8068d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
807e48c0fc5SRavi Teja {
8085a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
8095a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
810e48c0fc5SRavi Teja         if (ec)
811e48c0fc5SRavi Teja         {
812fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
813fc23ef8aSNitin Kumar Kotania             {
814fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
815fc23ef8aSNitin Kumar Kotania                                                    "Address");
816fc23ef8aSNitin Kumar Kotania             }
817fc23ef8aSNitin Kumar Kotania             else
818fc23ef8aSNitin Kumar Kotania             {
819e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
820e48c0fc5SRavi Teja             }
821fc23ef8aSNitin Kumar Kotania         }
822e48c0fc5SRavi Teja     };
823e48c0fc5SRavi Teja     // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
8244e0453b1SGunnar Mills     // does not have associated gateway property
825e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
826e48c0fc5SRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
827e48c0fc5SRavi Teja         "/xyz/openbmc_project/network/" + ifaceId,
828e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
829e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
830e48c0fc5SRavi Teja         "");
831e48c0fc5SRavi Teja }
832e48c0fc5SRavi Teja 
833179db1d7SKowalski, Kamil /**
834179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
835179db1d7SKowalski, Kamil  * Object
836179db1d7SKowalski, Kamil  * from EntityManager Network Manager
8374a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
838179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
839179db1d7SKowalski, Kamil  * into JSON
840179db1d7SKowalski, Kamil  */
841179db1d7SKowalski, Kamil template <typename CallbackFunc>
84281ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
8431abe55efSEd Tanous                           CallbackFunc&& callback)
8441abe55efSEd Tanous {
845f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
846f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
847f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
848f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
849f94c4ecfSEd Tanous          callback{std::forward<CallbackFunc>(callback)}](
8508b24275dSEd Tanous             const boost::system::error_code& ec,
85102cad96eSEd Tanous             const dbus::utility::ManagedObjectType& resp) {
85255c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
85377179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
85477179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
855179db1d7SKowalski, Kamil 
8568b24275dSEd Tanous         if (ec)
8571abe55efSEd Tanous         {
85801784826SJohnathan Mantey             callback(false, ethData, ipv4Data, ipv6Data);
859179db1d7SKowalski, Kamil             return;
860179db1d7SKowalski, Kamil         }
861179db1d7SKowalski, Kamil 
862002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
8634c9afe43SEd Tanous         if (!found)
8644c9afe43SEd Tanous         {
86501784826SJohnathan Mantey             callback(false, ethData, ipv4Data, ipv6Data);
8664c9afe43SEd Tanous             return;
8674c9afe43SEd Tanous         }
8684c9afe43SEd Tanous 
8692c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
870179db1d7SKowalski, Kamil         // Fix global GW
8711abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
8721abe55efSEd Tanous         {
873c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
874c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
8759010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
8761abe55efSEd Tanous             {
87782695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
878179db1d7SKowalski, Kamil             }
879179db1d7SKowalski, Kamil         }
880179db1d7SKowalski, Kamil 
8812c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
8824e0453b1SGunnar Mills         // Finally make a callback with useful data
88301784826SJohnathan Mantey         callback(true, ethData, ipv4Data, ipv6Data);
884f5892d0dSGeorge Liu     });
885271584abSEd Tanous }
886179db1d7SKowalski, Kamil 
887179db1d7SKowalski, Kamil /**
8889391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
8899391bb9cSRapkiewicz, Pawel  * Manager
8901abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
8911abe55efSEd Tanous  * into JSON.
8929391bb9cSRapkiewicz, Pawel  */
8939391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
8941abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
8951abe55efSEd Tanous {
896f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
897f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
898f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
899f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
9008b24275dSEd Tanous             const boost::system::error_code& ec,
901f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
9021abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
9031abe55efSEd Tanous         // ethernet interfaces
90477179532SEd Tanous         std::vector<std::string> ifaceList;
9052c70f800SEd Tanous         ifaceList.reserve(resp.size());
9068b24275dSEd Tanous         if (ec)
9071abe55efSEd Tanous         {
9082c70f800SEd Tanous             callback(false, ifaceList);
9099391bb9cSRapkiewicz, Pawel             return;
9109391bb9cSRapkiewicz, Pawel         }
9119391bb9cSRapkiewicz, Pawel 
9129391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
9134a0cb85cSEd Tanous         for (const auto& objpath : resp)
9141abe55efSEd Tanous         {
9159391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
9164a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
9171abe55efSEd Tanous             {
9181abe55efSEd Tanous                 // If interface is
9194a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
9204a0cb85cSEd Tanous                 // what we're looking for.
9219391bb9cSRapkiewicz, Pawel                 if (interface.first ==
9221abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
9231abe55efSEd Tanous                 {
9242dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
9252dfd18efSEd Tanous                     if (ifaceId.empty())
9261abe55efSEd Tanous                     {
9272dfd18efSEd Tanous                         continue;
9289391bb9cSRapkiewicz, Pawel                     }
9292dfd18efSEd Tanous                     // and put it into output vector.
93077179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
9319391bb9cSRapkiewicz, Pawel                 }
9329391bb9cSRapkiewicz, Pawel             }
9339391bb9cSRapkiewicz, Pawel         }
9342c5875a2SEd Tanous 
9353544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
9362c5875a2SEd Tanous 
937a434f2bdSEd Tanous         // Finally make a callback with useful data
9382c70f800SEd Tanous         callback(true, ifaceList);
939f5892d0dSGeorge Liu     });
940271584abSEd Tanous }
9419391bb9cSRapkiewicz, Pawel 
9424f48d5f6SEd Tanous inline void
9434f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
9448d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
9451abe55efSEd Tanous {
946ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
947ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
948ab6554f1SJoshi-Mansi     {
949ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
950ab6554f1SJoshi-Mansi                                            "HostName");
951ab6554f1SJoshi-Mansi         return;
952ab6554f1SJoshi-Mansi     }
9539ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9549ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
9559ae226faSGeorge Liu         "/xyz/openbmc_project/network/config",
9569ae226faSGeorge Liu         "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
9575e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
9584a0cb85cSEd Tanous         if (ec)
9594a0cb85cSEd Tanous         {
960a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
9611abe55efSEd Tanous         }
9629ae226faSGeorge Liu     });
963588c3f0dSKowalski, Kamil }
964588c3f0dSKowalski, Kamil 
9654f48d5f6SEd Tanous inline void
96635fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
96735fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
96835fb5311STejas Patil {
96989492a15SPatrick Williams     sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
97089492a15SPatrick Williams                                               ifaceId;
9719ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9729ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
9739ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
9745e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
97535fb5311STejas Patil         if (ec)
97635fb5311STejas Patil         {
97735fb5311STejas Patil             messages::internalError(asyncResp->res);
97835fb5311STejas Patil         }
9799ae226faSGeorge Liu     });
98035fb5311STejas Patil }
98135fb5311STejas Patil 
98235fb5311STejas Patil inline void
9834f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
984bf648f77SEd Tanous                           const std::string& domainname,
9858d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
986ab6554f1SJoshi-Mansi {
987ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
9889ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9899ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
9909ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
9919ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
9929ae226faSGeorge Liu         vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
993ab6554f1SJoshi-Mansi         if (ec)
994ab6554f1SJoshi-Mansi         {
995ab6554f1SJoshi-Mansi             messages::internalError(asyncResp->res);
996ab6554f1SJoshi-Mansi         }
9979ae226faSGeorge Liu     });
998ab6554f1SJoshi-Mansi }
999ab6554f1SJoshi-Mansi 
10004f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1001bf648f77SEd Tanous {
1002bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
10033544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1004bf648f77SEd Tanous     {
1005bf648f77SEd Tanous         return false;
1006bf648f77SEd Tanous     }
1007bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1008bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1009bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1010bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
10114b242749SEd Tanous     const static std::regex pattern(
1012bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1013bf648f77SEd Tanous 
1014bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1015bf648f77SEd Tanous }
1016bf648f77SEd Tanous 
10174f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1018bf648f77SEd Tanous {
1019bf648f77SEd Tanous     // Can have multiple subdomains
1020bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
10214b242749SEd Tanous     const static std::regex pattern(
10220fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1023bf648f77SEd Tanous 
1024bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1025bf648f77SEd Tanous }
1026bf648f77SEd Tanous 
10274f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
10288d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1029ab6554f1SJoshi-Mansi {
1030ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1031ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1032ab6554f1SJoshi-Mansi     {
1033ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1034ab6554f1SJoshi-Mansi         return;
1035ab6554f1SJoshi-Mansi     }
1036ab6554f1SJoshi-Mansi 
1037ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1038ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1039ab6554f1SJoshi-Mansi     {
1040ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1041ab6554f1SJoshi-Mansi         return;
1042ab6554f1SJoshi-Mansi     }
1043ab6554f1SJoshi-Mansi 
1044ab6554f1SJoshi-Mansi     std::string hostname;
1045ab6554f1SJoshi-Mansi     std::string domainname;
1046ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1047ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1048ab6554f1SJoshi-Mansi 
1049ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1050ab6554f1SJoshi-Mansi     {
1051ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1052ab6554f1SJoshi-Mansi         return;
1053ab6554f1SJoshi-Mansi     }
1054ab6554f1SJoshi-Mansi 
1055ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1056ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1057ab6554f1SJoshi-Mansi }
1058ab6554f1SJoshi-Mansi 
10594f48d5f6SEd Tanous inline void
10604f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1061bf648f77SEd Tanous                           const std::string& macAddress,
10628d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1063d577665bSRatan Gupta {
106458283f41SJohnathan Mantey     static constexpr std::string_view dbusNotAllowedError =
106558283f41SJohnathan Mantey         "xyz.openbmc_project.Common.Error.NotAllowed";
106658283f41SJohnathan Mantey 
10679ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10689ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10699ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10709ae226faSGeorge Liu         "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
10719ae226faSGeorge Liu         [asyncResp](const boost::system::error_code& ec,
10725b378546SPatrick Williams                     const sdbusplus::message_t& msg) {
1073d577665bSRatan Gupta         if (ec)
1074d577665bSRatan Gupta         {
107558283f41SJohnathan Mantey             const sd_bus_error* err = msg.get_error();
107658283f41SJohnathan Mantey             if (err == nullptr)
107758283f41SJohnathan Mantey             {
107858283f41SJohnathan Mantey                 messages::internalError(asyncResp->res);
107958283f41SJohnathan Mantey                 return;
108058283f41SJohnathan Mantey             }
108158283f41SJohnathan Mantey             if (err->name == dbusNotAllowedError)
108258283f41SJohnathan Mantey             {
108358283f41SJohnathan Mantey                 messages::propertyNotWritable(asyncResp->res, "MACAddress");
108458283f41SJohnathan Mantey                 return;
108558283f41SJohnathan Mantey             }
1086d577665bSRatan Gupta             messages::internalError(asyncResp->res);
1087d577665bSRatan Gupta             return;
1088d577665bSRatan Gupta         }
10899ae226faSGeorge Liu     });
1090d577665bSRatan Gupta }
1091286b9118SJohnathan Mantey 
10924f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
10934f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
10944f48d5f6SEd Tanous                            const bool v6Value,
10958d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1096da131a9aSJennifer Lee {
10972c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
10989ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10999ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
11009ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
11019ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
11025e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1103da131a9aSJennifer Lee         if (ec)
1104da131a9aSJennifer Lee         {
110562598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1106da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1107da131a9aSJennifer Lee             return;
1108da131a9aSJennifer Lee         }
11098f7e9c19SJayaprakash Mutyala         messages::success(asyncResp->res);
11109ae226faSGeorge Liu     });
1111da131a9aSJennifer Lee }
11121f8c7b5dSJohnathan Mantey 
11134f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty(
1114eeedda23SJohnathan Mantey     const std::string& ifaceId, const std::string& propertyName,
11158d1b46d7Szhanghch05     const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1116eeedda23SJohnathan Mantey {
11179ae226faSGeorge Liu     sdbusplus::asio::setProperty(
11189ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
11199ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
11209ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
11215e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1122eeedda23SJohnathan Mantey         if (ec)
1123eeedda23SJohnathan Mantey         {
112462598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1125eeedda23SJohnathan Mantey             messages::internalError(asyncResp->res);
1126eeedda23SJohnathan Mantey             return;
1127eeedda23SJohnathan Mantey         }
11289ae226faSGeorge Liu     });
1129eeedda23SJohnathan Mantey }
1130eeedda23SJohnathan Mantey 
1131*e4588158SJishnu CM enum class NetworkType
1132*e4588158SJishnu CM {
1133*e4588158SJishnu CM     dhcp4,
1134*e4588158SJishnu CM     dhcp6
1135*e4588158SJishnu CM };
1136*e4588158SJishnu CM 
1137*e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1138*e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1139*e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1140da131a9aSJennifer Lee {
114162598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
1142*e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1143*e4588158SJishnu CM     path /= ethifaceId;
1144*e4588158SJishnu CM 
1145*e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1146*e4588158SJishnu CM     {
1147*e4588158SJishnu CM         path /= "dhcp4";
1148*e4588158SJishnu CM     }
1149*e4588158SJishnu CM     else
1150*e4588158SJishnu CM     {
1151*e4588158SJishnu CM         path /= "dhcp6";
1152*e4588158SJishnu CM     }
1153*e4588158SJishnu CM 
11549ae226faSGeorge Liu     sdbusplus::asio::setProperty(
1155*e4588158SJishnu CM         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
11569ae226faSGeorge Liu         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
11575e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1158da131a9aSJennifer Lee         if (ec)
1159da131a9aSJennifer Lee         {
116062598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1161da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1162da131a9aSJennifer Lee             return;
1163da131a9aSJennifer Lee         }
11649ae226faSGeorge Liu     });
1165da131a9aSJennifer Lee }
1166d577665bSRatan Gupta 
1167b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1168b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1169b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1170b10d8db0SRavi Teja {
1171b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1172b10d8db0SRavi Teja     path /= ifaceId;
1173b10d8db0SRavi Teja     sdbusplus::asio::setProperty(
1174b10d8db0SRavi Teja         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1175b10d8db0SRavi Teja         "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1176b10d8db0SRavi Teja         ipv6AutoConfigEnabled,
1177b10d8db0SRavi Teja         [asyncResp](const boost::system::error_code& ec) {
1178b10d8db0SRavi Teja         if (ec)
1179b10d8db0SRavi Teja         {
1180b10d8db0SRavi Teja             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1181b10d8db0SRavi Teja             messages::internalError(asyncResp->res);
1182b10d8db0SRavi Teja             return;
1183b10d8db0SRavi Teja         }
1184b10d8db0SRavi Teja         messages::success(asyncResp->res);
1185b10d8db0SRavi Teja     });
1186b10d8db0SRavi Teja }
1187b10d8db0SRavi Teja 
11884f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
11891f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1190f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1191f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
11928d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1193da131a9aSJennifer Lee {
119482695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
119582695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1196da131a9aSJennifer Lee 
11971f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
11981f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
11991f8c7b5dSJohnathan Mantey 
12001f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
12011f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1202da131a9aSJennifer Lee     {
1203b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
12041f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
12051f8c7b5dSJohnathan Mantey         {
1206bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1207bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
12081f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1209da131a9aSJennifer Lee             return;
1210da131a9aSJennifer Lee         }
1211b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
12121f8c7b5dSJohnathan Mantey     }
12131f8c7b5dSJohnathan Mantey     else
1214da131a9aSJennifer Lee     {
12151f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
12161f8c7b5dSJohnathan Mantey     }
12171f8c7b5dSJohnathan Mantey 
1218*e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1219*e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1220*e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
12211f8c7b5dSJohnathan Mantey     {
1222*e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
12231f8c7b5dSJohnathan Mantey     }
1224*e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
12251f8c7b5dSJohnathan Mantey     {
1226*e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
12271f8c7b5dSJohnathan Mantey     }
12281f8c7b5dSJohnathan Mantey 
1229*e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1230*e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1231*e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
12321f8c7b5dSJohnathan Mantey     {
1233*e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
12341f8c7b5dSJohnathan Mantey     }
1235*e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
12361f8c7b5dSJohnathan Mantey     {
1237*e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
12381f8c7b5dSJohnathan Mantey     }
12391f8c7b5dSJohnathan Mantey 
1240*e4588158SJishnu CM     bool nextUsev4Domain = ethData.hostNamev4Enabled;
1241*e4588158SJishnu CM     bool nextUsev6Domain = ethData.hostNamev6Enabled;
1242*e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
12431f8c7b5dSJohnathan Mantey     {
1244*e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
12451f8c7b5dSJohnathan Mantey     }
1246*e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
12471f8c7b5dSJohnathan Mantey     {
1248*e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
12491f8c7b5dSJohnathan Mantey     }
12501f8c7b5dSJohnathan Mantey 
125162598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
12521f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
12531f8c7b5dSJohnathan Mantey                    asyncResp);
125462598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1255*e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1256*e4588158SJishnu CM                   NetworkType::dhcp4);
125762598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1258*e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1259*e4588158SJishnu CM                   NetworkType::dhcp4);
126062598e31SEd Tanous     BMCWEB_LOG_DEBUG("set HostNameEnabled...");
1261*e4588158SJishnu CM     setDHCPConfig("HostNameEnabled", nextUsev4Domain, asyncResp, ifaceId,
1262*e4588158SJishnu CM                   NetworkType::dhcp4);
1263*e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1264*e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1265*e4588158SJishnu CM                   NetworkType::dhcp6);
1266*e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1267*e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1268*e4588158SJishnu CM                   NetworkType::dhcp6);
1269*e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set HostNameEnabled for dhcp6...");
1270*e4588158SJishnu CM     setDHCPConfig("HostNameEnabled", nextUsev6Domain, asyncResp, ifaceId,
1271*e4588158SJishnu CM                   NetworkType::dhcp6);
1272da131a9aSJennifer Lee }
127301784826SJohnathan Mantey 
127477179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
127577179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
127677179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
127701784826SJohnathan Mantey {
127817a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
127917a897dfSManojkiran Eda         return value.origin == "Static";
128017a897dfSManojkiran Eda     });
128101784826SJohnathan Mantey }
128201784826SJohnathan Mantey 
128377179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
128477179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
128577179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
128601784826SJohnathan Mantey {
128717a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
128817a897dfSManojkiran Eda         return value.origin == "Static";
128917a897dfSManojkiran Eda     });
129001784826SJohnathan Mantey }
129101784826SJohnathan Mantey 
129277179532SEd Tanous inline void
1293ddd70dcaSEd Tanous     handleIPv4StaticPatch(const std::string& ifaceId,
1294ddd70dcaSEd Tanous                           nlohmann::json::array_t& input,
129577179532SEd Tanous                           const std::vector<IPv4AddressData>& ipv4Data,
12968d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12971abe55efSEd Tanous {
1298ddd70dcaSEd Tanous     if (input.empty())
1299f476acbfSRatan Gupta     {
13002e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1301d1d50814SRavi Teja                                          "IPv4StaticAddresses");
1302f476acbfSRatan Gupta         return;
1303f476acbfSRatan Gupta     }
1304f476acbfSRatan Gupta 
1305271584abSEd Tanous     unsigned entryIdx = 1;
130601784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
130701784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
130801784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
130901784826SJohnathan Mantey     // into the NIC.
131077179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
13112c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
131201784826SJohnathan Mantey 
1313537174c4SEd Tanous     for (nlohmann::json& thisJson : input)
13141abe55efSEd Tanous     {
131589492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
131689492a15SPatrick Williams                                  std::to_string(entryIdx);
1317179db1d7SKowalski, Kamil 
131801784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1319f476acbfSRatan Gupta         {
1320537174c4SEd Tanous             std::optional<std::string> address;
1321537174c4SEd Tanous             std::optional<std::string> subnetMask;
1322537174c4SEd Tanous             std::optional<std::string> gateway;
1323537174c4SEd Tanous 
1324537174c4SEd Tanous             if (!json_util::readJson(thisJson, asyncResp->res, "Address",
13257e27d832SJohnathan Mantey                                      address, "SubnetMask", subnetMask,
13267e27d832SJohnathan Mantey                                      "Gateway", gateway))
1327537174c4SEd Tanous             {
1328f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
132971f52d96SEd Tanous                                                    pathString);
1330537174c4SEd Tanous                 return;
1331179db1d7SKowalski, Kamil             }
1332179db1d7SKowalski, Kamil 
133301784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
133401784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
133501784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
133601784826SJohnathan Mantey             // current request.
1337537174c4SEd Tanous             if (address)
13381abe55efSEd Tanous             {
1339e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
134001784826SJohnathan Mantey                 {
1341bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1342bf648f77SEd Tanous                                                        pathString + "/Address");
1343e01d0c36SEd Tanous                     return;
134401784826SJohnathan Mantey                 }
134501784826SJohnathan Mantey             }
134685ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
134701784826SJohnathan Mantey             {
1348e01d0c36SEd Tanous                 address = (nicIpEntry->address);
134901784826SJohnathan Mantey             }
135001784826SJohnathan Mantey             else
135101784826SJohnathan Mantey             {
135201784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
135301784826SJohnathan Mantey                                           pathString + "/Address");
1354e01d0c36SEd Tanous                 return;
13554a0cb85cSEd Tanous             }
13564a0cb85cSEd Tanous 
1357e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1358537174c4SEd Tanous             if (subnetMask)
13594a0cb85cSEd Tanous             {
1360033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1361033f1e4dSEd Tanous                                                          &prefixLength))
13624a0cb85cSEd Tanous                 {
1363f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1364537174c4SEd Tanous                         asyncResp->res, *subnetMask,
13654a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1366e01d0c36SEd Tanous                     return;
13674a0cb85cSEd Tanous                 }
13684a0cb85cSEd Tanous             }
136985ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
13704a0cb85cSEd Tanous             {
1371033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
137201784826SJohnathan Mantey                                                          &prefixLength))
13734a0cb85cSEd Tanous                 {
137401784826SJohnathan Mantey                     messages::propertyValueFormatError(
137585ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
137601784826SJohnathan Mantey                         pathString + "/SubnetMask");
1377e01d0c36SEd Tanous                     return;
13784a0cb85cSEd Tanous                 }
13794a0cb85cSEd Tanous             }
13801abe55efSEd Tanous             else
13811abe55efSEd Tanous             {
138201784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
138301784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1384e01d0c36SEd Tanous                 return;
138501784826SJohnathan Mantey             }
138601784826SJohnathan Mantey 
138701784826SJohnathan Mantey             if (gateway)
138801784826SJohnathan Mantey             {
1389e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
139001784826SJohnathan Mantey                 {
1391bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1392bf648f77SEd Tanous                                                        pathString + "/Gateway");
1393e01d0c36SEd Tanous                     return;
139401784826SJohnathan Mantey                 }
139501784826SJohnathan Mantey             }
139685ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
139701784826SJohnathan Mantey             {
1398e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
139901784826SJohnathan Mantey             }
140001784826SJohnathan Mantey             else
14011abe55efSEd Tanous             {
1402a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
14034a0cb85cSEd Tanous                                           pathString + "/Gateway");
140401784826SJohnathan Mantey                 return;
14054a0cb85cSEd Tanous             }
14064a0cb85cSEd Tanous 
140785ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
14081abe55efSEd Tanous             {
14099c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
141077eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
141177eb0153SEd Tanous                                          *gateway, asyncResp);
141289492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
141389492a15SPatrick Williams                                                   ipv4Data.cend());
1414588c3f0dSKowalski, Kamil             }
141501784826SJohnathan Mantey             else
141601784826SJohnathan Mantey             {
1417cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1418cb13a392SEd Tanous                            asyncResp);
14194a0cb85cSEd Tanous             }
14204a0cb85cSEd Tanous             entryIdx++;
14214a0cb85cSEd Tanous         }
142201784826SJohnathan Mantey         else
142301784826SJohnathan Mantey         {
142485ffe86aSJiaqing Zhao             if (nicIpEntry == ipv4Data.cend())
142501784826SJohnathan Mantey             {
142601784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
142701784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
142801784826SJohnathan Mantey                 // in error, so bail out.
142901784826SJohnathan Mantey                 if (thisJson.is_null())
143001784826SJohnathan Mantey                 {
143101784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
143201784826SJohnathan Mantey                     return;
143301784826SJohnathan Mantey                 }
1434f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
143571f52d96SEd Tanous                                                    pathString);
143601784826SJohnathan Mantey                 return;
143701784826SJohnathan Mantey             }
143801784826SJohnathan Mantey 
143901784826SJohnathan Mantey             if (thisJson.is_null())
144001784826SJohnathan Mantey             {
14419c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
144201784826SJohnathan Mantey             }
144385ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
144401784826SJohnathan Mantey             {
144589492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
144689492a15SPatrick Williams                                                   ipv4Data.cend());
144701784826SJohnathan Mantey             }
144801784826SJohnathan Mantey             entryIdx++;
144901784826SJohnathan Mantey         }
145001784826SJohnathan Mantey     }
14514a0cb85cSEd Tanous }
14524a0cb85cSEd Tanous 
14534f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1454f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1455f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
14568d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1457f85837bfSRAJESWARAN THILLAIGOVINDAN {
14589ae226faSGeorge Liu     sdbusplus::asio::setProperty(
14599ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
14609ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
14619ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
14629ae226faSGeorge Liu         updatedStaticNameServers,
14635e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1464f85837bfSRAJESWARAN THILLAIGOVINDAN         if (ec)
1465f85837bfSRAJESWARAN THILLAIGOVINDAN         {
1466f85837bfSRAJESWARAN THILLAIGOVINDAN             messages::internalError(asyncResp->res);
1467f85837bfSRAJESWARAN THILLAIGOVINDAN             return;
1468f85837bfSRAJESWARAN THILLAIGOVINDAN         }
14699ae226faSGeorge Liu     });
1470f85837bfSRAJESWARAN THILLAIGOVINDAN }
1471f85837bfSRAJESWARAN THILLAIGOVINDAN 
14724f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
1473ddd70dcaSEd Tanous     const std::string& ifaceId, const nlohmann::json::array_t& input,
147477179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
14758d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1476e48c0fc5SRavi Teja {
1477ddd70dcaSEd Tanous     if (input.empty())
1478e48c0fc5SRavi Teja     {
14792e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1480e48c0fc5SRavi Teja                                          "IPv6StaticAddresses");
1481e48c0fc5SRavi Teja         return;
1482e48c0fc5SRavi Teja     }
1483271584abSEd Tanous     size_t entryIdx = 1;
148477179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
14852c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1486f23b7296SEd Tanous     for (const nlohmann::json& thisJson : input)
1487e48c0fc5SRavi Teja     {
148889492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
148989492a15SPatrick Williams                                  std::to_string(entryIdx);
1490e48c0fc5SRavi Teja 
149101784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1492e48c0fc5SRavi Teja         {
1493e48c0fc5SRavi Teja             std::optional<std::string> address;
1494e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
1495f23b7296SEd Tanous             nlohmann::json thisJsonCopy = thisJson;
1496bf648f77SEd Tanous             if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1497bf648f77SEd Tanous                                      address, "PrefixLength", prefixLength))
1498e48c0fc5SRavi Teja             {
1499f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
150071f52d96SEd Tanous                                                    pathString);
1501e48c0fc5SRavi Teja                 return;
1502e48c0fc5SRavi Teja             }
1503e48c0fc5SRavi Teja 
1504543f4400SEd Tanous             const std::string* addr = nullptr;
1505543f4400SEd Tanous             uint8_t prefix = 0;
150601784826SJohnathan Mantey 
150701784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
150801784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
150901784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
151001784826SJohnathan Mantey             // current request.
1511e48c0fc5SRavi Teja             if (address)
1512e48c0fc5SRavi Teja             {
151301784826SJohnathan Mantey                 addr = &(*address);
1514e48c0fc5SRavi Teja             }
151585ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
151601784826SJohnathan Mantey             {
151785ffe86aSJiaqing Zhao                 addr = &(nicIpEntry->address);
151801784826SJohnathan Mantey             }
151901784826SJohnathan Mantey             else
152001784826SJohnathan Mantey             {
152101784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
152201784826SJohnathan Mantey                                           pathString + "/Address");
152301784826SJohnathan Mantey                 return;
1524e48c0fc5SRavi Teja             }
1525e48c0fc5SRavi Teja 
1526e48c0fc5SRavi Teja             if (prefixLength)
1527e48c0fc5SRavi Teja             {
152801784826SJohnathan Mantey                 prefix = *prefixLength;
152901784826SJohnathan Mantey             }
153085ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
1531e48c0fc5SRavi Teja             {
153285ffe86aSJiaqing Zhao                 prefix = nicIpEntry->prefixLength;
1533e48c0fc5SRavi Teja             }
1534e48c0fc5SRavi Teja             else
1535e48c0fc5SRavi Teja             {
1536e48c0fc5SRavi Teja                 messages::propertyMissing(asyncResp->res,
1537e48c0fc5SRavi Teja                                           pathString + "/PrefixLength");
153801784826SJohnathan Mantey                 return;
1539e48c0fc5SRavi Teja             }
1540e48c0fc5SRavi Teja 
154185ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1542e48c0fc5SRavi Teja             {
15439c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
154477eb0153SEd Tanous                                          nicIpEntry->id, prefix, *addr, "",
1545e48c0fc5SRavi Teja                                          asyncResp);
154689492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
154789492a15SPatrick Williams                                                   ipv6Data.cend());
154801784826SJohnathan Mantey             }
154901784826SJohnathan Mantey             else
155001784826SJohnathan Mantey             {
155101784826SJohnathan Mantey                 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1552e48c0fc5SRavi Teja             }
1553e48c0fc5SRavi Teja             entryIdx++;
1554e48c0fc5SRavi Teja         }
155501784826SJohnathan Mantey         else
155601784826SJohnathan Mantey         {
155785ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
155801784826SJohnathan Mantey             {
155901784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
156001784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
156101784826SJohnathan Mantey                 // in error, so bail out.
156201784826SJohnathan Mantey                 if (thisJson.is_null())
156301784826SJohnathan Mantey                 {
156401784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
156501784826SJohnathan Mantey                     return;
156601784826SJohnathan Mantey                 }
1567f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
156871f52d96SEd Tanous                                                    pathString);
156901784826SJohnathan Mantey                 return;
157001784826SJohnathan Mantey             }
157101784826SJohnathan Mantey 
157201784826SJohnathan Mantey             if (thisJson.is_null())
157301784826SJohnathan Mantey             {
15749c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
157501784826SJohnathan Mantey             }
157685ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
157701784826SJohnathan Mantey             {
157889492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
157989492a15SPatrick Williams                                                   ipv6Data.cend());
158001784826SJohnathan Mantey             }
158101784826SJohnathan Mantey             entryIdx++;
158201784826SJohnathan Mantey         }
158301784826SJohnathan Mantey     }
1584e48c0fc5SRavi Teja }
1585e48c0fc5SRavi Teja 
15867857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
15877857cb8dSJiaqing Zhao {
15887857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
15897857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
15907857cb8dSJiaqing Zhao }
15917857cb8dSJiaqing Zhao 
159277179532SEd Tanous inline void
159377179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
159477179532SEd Tanous                        const std::string& ifaceId,
159577179532SEd Tanous                        const EthernetInterfaceData& ethData,
159677179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
159777179532SEd Tanous                        const std::vector<IPv6AddressData>& ipv6Data)
15984a0cb85cSEd Tanous {
15992c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
160081ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1601ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1602ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
16032c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1604eeedda23SJohnathan Mantey 
160513451e39SWilly Tu     if constexpr (bmcwebEnableHealthPopulate)
160613451e39SWilly Tu     {
160713451e39SWilly Tu         constexpr std::array<std::string_view, 1> inventoryForEthernet = {
160813451e39SWilly Tu             "xyz.openbmc_project.Inventory.Item.Ethernet"};
1609eeedda23SJohnathan Mantey         auto health = std::make_shared<HealthPopulate>(asyncResp);
16107a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
16117a1dbc48SGeorge Liu             "/", 0, inventoryForEthernet,
16127a1dbc48SGeorge Liu             [health](const boost::system::error_code& ec,
1613b9d36b47SEd Tanous                      const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1614eeedda23SJohnathan Mantey             if (ec)
1615029573d4SEd Tanous             {
1616eeedda23SJohnathan Mantey                 return;
1617eeedda23SJohnathan Mantey             }
1618eeedda23SJohnathan Mantey 
1619914e2d5dSEd Tanous             health->inventory = resp;
16207a1dbc48SGeorge Liu         });
1621eeedda23SJohnathan Mantey 
1622eeedda23SJohnathan Mantey         health->populate();
162313451e39SWilly Tu     }
1624eeedda23SJohnathan Mantey 
1625eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1626eeedda23SJohnathan Mantey     {
16270ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
16282c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1629029573d4SEd Tanous     }
1630029573d4SEd Tanous     else
1631029573d4SEd Tanous     {
16322c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
16332c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1634029573d4SEd Tanous     }
1635aa05fb27SJohnathan Mantey 
16362c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
163735fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
163882695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
16392c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
164082695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1641*e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1642*e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1643*e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
16442c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1645b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
16461f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1647*e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1648*e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1649*e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
1650b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1651b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
16522a133282Smanojkiraneda 
165382695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
16544a0cb85cSEd Tanous     {
165582695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1656ab6554f1SJoshi-Mansi 
1657ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1658ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1659ab6554f1SJoshi-Mansi         // FQDN
166082695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1661d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1662d24bfc7aSJennifer Lee         {
16632c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1664d24bfc7aSJennifer Lee         }
16652c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
16664a0cb85cSEd Tanous     }
16674a0cb85cSEd Tanous 
16687857cb8dSJiaqing Zhao     if (ethData.vlanId)
16697857cb8dSJiaqing Zhao     {
16707857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
16717857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
16727857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
16737857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
16747857cb8dSJiaqing Zhao 
16757857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
16767857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
16777857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
16787857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
16797857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
16807857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
16817857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
16827857cb8dSJiaqing Zhao     }
16837857cb8dSJiaqing Zhao     else
16847857cb8dSJiaqing Zhao     {
16857857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
16867857cb8dSJiaqing Zhao     }
16877857cb8dSJiaqing Zhao 
16882c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
16892c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
16904a0cb85cSEd Tanous 
16912c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
16922c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
16932c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
16942c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
16959eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
16964a0cb85cSEd Tanous     {
16972c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1698fa5053a6SGunnar Mills         if (gatewayStr.empty())
1699fa5053a6SGunnar Mills         {
1700fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1701fa5053a6SGunnar Mills         }
17021476687dSEd Tanous         nlohmann::json::object_t ipv4;
17031476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
17041476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
17051476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
17061476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1707fa5053a6SGunnar Mills 
17082c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1709d1d50814SRavi Teja         {
17101476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1711d1d50814SRavi Teja         }
17121476687dSEd Tanous 
1713b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
171401784826SJohnathan Mantey     }
1715d1d50814SRavi Teja 
171682695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
17177ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
17187ea79e5eSRavi Teja     {
17197ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
17207ea79e5eSRavi Teja     }
17217ea79e5eSRavi Teja 
17227ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1723e48c0fc5SRavi Teja 
17242c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
17252c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
17262c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
17272c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
17287f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
17292c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
17307f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
17319eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1732e48c0fc5SRavi Teja     {
17331476687dSEd Tanous         nlohmann::json::object_t ipv6;
17341476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
17351476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
17361476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1737f8361275SSunitha Harish 
1738b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
17392c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1740e48c0fc5SRavi Teja         {
17411476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
17421476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
17431476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1744b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
174501784826SJohnathan Mantey         }
1746e48c0fc5SRavi Teja     }
1747588c3f0dSKowalski, Kamil }
1748588c3f0dSKowalski, Kamil 
1749e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1750e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1751e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1752e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1753e7caf250SJiaqing Zhao {
1754e7caf250SJiaqing Zhao     if (!ec)
1755e7caf250SJiaqing Zhao     {
1756e7caf250SJiaqing Zhao         return;
1757e7caf250SJiaqing Zhao     }
1758e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
1759e7caf250SJiaqing Zhao     if (dbusError == nullptr)
1760e7caf250SJiaqing Zhao     {
1761e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
1762e7caf250SJiaqing Zhao         return;
1763e7caf250SJiaqing Zhao     }
176462598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1765e7caf250SJiaqing Zhao 
1766e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1767e7caf250SJiaqing Zhao         dbusError->name)
1768e7caf250SJiaqing Zhao     {
1769e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1770e7caf250SJiaqing Zhao                                    ifaceId);
1771e7caf250SJiaqing Zhao         return;
1772e7caf250SJiaqing Zhao     }
1773e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1774e7caf250SJiaqing Zhao         dbusError->name)
1775e7caf250SJiaqing Zhao     {
1776e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
1777e7caf250SJiaqing Zhao         return;
1778e7caf250SJiaqing Zhao     }
1779e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
1780e7caf250SJiaqing Zhao }
1781e7caf250SJiaqing Zhao 
1782b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1783b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
1784b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
1785b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
1786b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
1787b5ca3fdcSJiaqing Zhao 
1788b5ca3fdcSJiaqing Zhao )
1789b5ca3fdcSJiaqing Zhao {
1790b5ca3fdcSJiaqing Zhao     if (ec)
1791b5ca3fdcSJiaqing Zhao     {
1792b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
1793b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
1794b5ca3fdcSJiaqing Zhao         {
1795b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
1796b5ca3fdcSJiaqing Zhao             return;
1797b5ca3fdcSJiaqing Zhao         }
179862598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1799b5ca3fdcSJiaqing Zhao 
1800b5ca3fdcSJiaqing Zhao         if (std::string_view(
1801b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1802b5ca3fdcSJiaqing Zhao             dbusError->name)
1803b5ca3fdcSJiaqing Zhao         {
1804b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1805b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1806b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1807b5ca3fdcSJiaqing Zhao             return;
1808b5ca3fdcSJiaqing Zhao         }
1809b5ca3fdcSJiaqing Zhao         if (std::string_view(
1810b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1811b5ca3fdcSJiaqing Zhao             dbusError->name)
1812b5ca3fdcSJiaqing Zhao         {
1813b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1814b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
1815b5ca3fdcSJiaqing Zhao             return;
1816b5ca3fdcSJiaqing Zhao         }
1817b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
1818b5ca3fdcSJiaqing Zhao         return;
1819b5ca3fdcSJiaqing Zhao     }
1820b5ca3fdcSJiaqing Zhao 
1821b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
1822b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1823b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1824b5ca3fdcSJiaqing Zhao }
1825b5ca3fdcSJiaqing Zhao 
1826bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
1827bf648f77SEd Tanous {
1828bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1829ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
18301476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
18311476687dSEd Tanous             [&app](const crow::Request& req,
18321476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
18333ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
183445ca1b86SEd Tanous         {
183545ca1b86SEd Tanous             return;
183645ca1b86SEd Tanous         }
183745ca1b86SEd Tanous 
1838bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
1839bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1840bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
1841bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
1842bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
1843bf648f77SEd Tanous             "Ethernet Network Interface Collection";
1844bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
1845bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
1846bf648f77SEd Tanous 
1847bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
1848bf648f77SEd Tanous         // preparation
1849002d39b4SEd Tanous         getEthernetIfaceList(
185077179532SEd Tanous             [asyncResp](const bool& success,
185177179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
1852bf648f77SEd Tanous             if (!success)
18531abe55efSEd Tanous             {
1854f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
18559391bb9cSRapkiewicz, Pawel                 return;
18569391bb9cSRapkiewicz, Pawel             }
18579391bb9cSRapkiewicz, Pawel 
1858002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1859bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
1860bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
1861bf648f77SEd Tanous             {
18621476687dSEd Tanous                 nlohmann::json::object_t iface;
1863ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
1864ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1865ef4c65b7SEd Tanous                     ifaceItem);
18667857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
1867bf648f77SEd Tanous             }
1868bf648f77SEd Tanous 
1869002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1870bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
1871bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1872bf648f77SEd Tanous         });
1873bf648f77SEd Tanous     });
1874bf648f77SEd Tanous 
1875b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1876b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
1877b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
1878b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
1879b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1880b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1881b5ca3fdcSJiaqing Zhao         {
1882b5ca3fdcSJiaqing Zhao             return;
1883b5ca3fdcSJiaqing Zhao         }
1884b5ca3fdcSJiaqing Zhao 
1885b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
1886b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
1887b5ca3fdcSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
1888b5ca3fdcSJiaqing Zhao 
1889b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1890b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
1891b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
1892b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
1893b5ca3fdcSJiaqing Zhao         {
1894b5ca3fdcSJiaqing Zhao             return;
1895b5ca3fdcSJiaqing Zhao         }
1896b5ca3fdcSJiaqing Zhao 
1897b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
1898b5ca3fdcSJiaqing Zhao         {
1899b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
1900b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
1901b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
1902b5ca3fdcSJiaqing Zhao             return;
1903b5ca3fdcSJiaqing Zhao         }
1904b5ca3fdcSJiaqing Zhao 
1905b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
1906b5ca3fdcSJiaqing Zhao         if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1907b5ca3fdcSJiaqing Zhao                                  "@odata.id", parentInterfaceUri))
1908b5ca3fdcSJiaqing Zhao         {
1909b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
1910b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
1911b5ca3fdcSJiaqing Zhao             return;
1912b5ca3fdcSJiaqing Zhao         }
191362598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
1914b5ca3fdcSJiaqing Zhao 
19156fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
1916b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
1917b5ca3fdcSJiaqing Zhao         if (!parsedUri)
1918b5ca3fdcSJiaqing Zhao         {
1919b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
1920b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1921b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1922b5ca3fdcSJiaqing Zhao             return;
1923b5ca3fdcSJiaqing Zhao         }
1924b5ca3fdcSJiaqing Zhao 
1925b5ca3fdcSJiaqing Zhao         std::string parentInterface;
1926b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
1927b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
1928b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
1929b5ca3fdcSJiaqing Zhao         {
1930b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1931b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1932b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1933b5ca3fdcSJiaqing Zhao             return;
1934b5ca3fdcSJiaqing Zhao         }
1935b5ca3fdcSJiaqing Zhao 
1936b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
1937b5ca3fdcSJiaqing Zhao         {
1938b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
1939b5ca3fdcSJiaqing Zhao             // create
1940b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1941b5ca3fdcSJiaqing Zhao                                              "false");
1942b5ca3fdcSJiaqing Zhao             return;
1943b5ca3fdcSJiaqing Zhao         }
1944b5ca3fdcSJiaqing Zhao 
1945b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
1946b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
1947b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
1948b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
1949b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
1950b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
1951b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1952b5ca3fdcSJiaqing Zhao                             m);
1953b5ca3fdcSJiaqing Zhao         },
1954b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1955b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1956b5ca3fdcSJiaqing Zhao             vlanId);
1957b5ca3fdcSJiaqing Zhao     });
1958b5ca3fdcSJiaqing Zhao 
1959bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
1960ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
1961bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
196245ca1b86SEd Tanous             [&app](const crow::Request& req,
1963bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1964bf648f77SEd Tanous                    const std::string& ifaceId) {
19653ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
196645ca1b86SEd Tanous         {
196745ca1b86SEd Tanous             return;
196845ca1b86SEd Tanous         }
19694a0cb85cSEd Tanous         getEthernetIfaceData(
1970bf648f77SEd Tanous             ifaceId,
197177179532SEd Tanous             [asyncResp, ifaceId](const bool& success,
197277179532SEd Tanous                                  const EthernetInterfaceData& ethData,
197377179532SEd Tanous                                  const std::vector<IPv4AddressData>& ipv4Data,
197477179532SEd Tanous                                  const std::vector<IPv6AddressData>& ipv6Data) {
19754a0cb85cSEd Tanous             if (!success)
19761abe55efSEd Tanous             {
1977bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
1978bf648f77SEd Tanous                 // existing object, and other errors
1979002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1980002d39b4SEd Tanous                                            ifaceId);
19814a0cb85cSEd Tanous                 return;
19829391bb9cSRapkiewicz, Pawel             }
19834c9afe43SEd Tanous 
19840f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
198593bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
1986002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
19870f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
19880f74e643SEd Tanous                 "Management Network Interface";
19890f74e643SEd Tanous 
1990002d39b4SEd Tanous             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
19919391bb9cSRapkiewicz, Pawel         });
1992bf648f77SEd Tanous     });
19939391bb9cSRapkiewicz, Pawel 
1994bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
1995ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
1996bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
199745ca1b86SEd Tanous             [&app](const crow::Request& req,
1998bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1999bf648f77SEd Tanous                    const std::string& ifaceId) {
20003ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
200145ca1b86SEd Tanous         {
200245ca1b86SEd Tanous             return;
200345ca1b86SEd Tanous         }
2004bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2005ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2006d577665bSRatan Gupta         std::optional<std::string> macAddress;
20079a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
2008ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
2009ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
2010f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2011da131a9aSJennifer Lee         std::optional<nlohmann::json> dhcpv4;
20121f8c7b5dSJohnathan Mantey         std::optional<nlohmann::json> dhcpv6;
2013b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2014eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
201535fb5311STejas Patil         std::optional<size_t> mtuSize;
20161f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
20171f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2018b10d8db0SRavi Teja         // clang-format off
201915ed6780SWilly Tu         if (!json_util::readJsonPatch(
2020b10d8db0SRavi Teja                 req, asyncResp->res,
2021b10d8db0SRavi Teja                 "DHCPv4", dhcpv4,
2022b10d8db0SRavi Teja                 "DHCPv6", dhcpv6,
2023b10d8db0SRavi Teja                 "FQDN", fqdn,
2024b10d8db0SRavi Teja                 "HostName", hostname,
2025b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2026b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2027b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2028b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2029b10d8db0SRavi Teja                 "MACAddress", macAddress,
2030b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2031b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2032b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2033b10d8db0SRavi Teja                 )
2034b10d8db0SRavi Teja             )
20351abe55efSEd Tanous         {
2036588c3f0dSKowalski, Kamil             return;
2037588c3f0dSKowalski, Kamil         }
2038b10d8db0SRavi Teja         //clang-format on
2039da131a9aSJennifer Lee         if (dhcpv4)
2040da131a9aSJennifer Lee         {
2041002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
20421f8c7b5dSJohnathan Mantey                                      v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
204382695a5bSJiaqing Zhao                                      v4dhcpParms.useDnsServers, "UseNTPServers",
204482695a5bSJiaqing Zhao                                      v4dhcpParms.useNtpServers, "UseDomainName",
204582695a5bSJiaqing Zhao                                      v4dhcpParms.useDomainName))
20461f8c7b5dSJohnathan Mantey             {
20471f8c7b5dSJohnathan Mantey                 return;
20481f8c7b5dSJohnathan Mantey             }
20491f8c7b5dSJohnathan Mantey         }
20501f8c7b5dSJohnathan Mantey 
20511f8c7b5dSJohnathan Mantey         if (dhcpv6)
20521f8c7b5dSJohnathan Mantey         {
2053002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2054002d39b4SEd Tanous                                      v6dhcpParms.dhcpv6OperatingMode,
2055002d39b4SEd Tanous                                      "UseDNSServers", v6dhcpParms.useDnsServers,
2056002d39b4SEd Tanous                                      "UseNTPServers", v6dhcpParms.useNtpServers,
2057002d39b4SEd Tanous                                      "UseDomainName",
205882695a5bSJiaqing Zhao                                      v6dhcpParms.useDomainName))
20591f8c7b5dSJohnathan Mantey             {
20601f8c7b5dSJohnathan Mantey                 return;
20611f8c7b5dSJohnathan Mantey             }
2062da131a9aSJennifer Lee         }
2063da131a9aSJennifer Lee 
2064bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2065bf648f77SEd Tanous         // for JSON preparation
20664a0cb85cSEd Tanous         getEthernetIfaceData(
20672c70f800SEd Tanous             ifaceId,
2068bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2069ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2070d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
20719a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2072e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
20731f8c7b5dSJohnathan Mantey              staticNameServers = std::move(staticNameServers),
2074bc20089aSEd Tanous              dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
2075b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2076f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2077002d39b4SEd Tanous                 const bool& success, const EthernetInterfaceData& ethData,
207877179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
207977179532SEd Tanous                 const std::vector<IPv6AddressData>& ipv6Data) {
20801abe55efSEd Tanous             if (!success)
20811abe55efSEd Tanous             {
2082588c3f0dSKowalski, Kamil                 // ... otherwise return error
2083bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2084bf648f77SEd Tanous                 // existing object, and other errors
2085002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2086002d39b4SEd Tanous                                            ifaceId);
2087588c3f0dSKowalski, Kamil                 return;
2088588c3f0dSKowalski, Kamil             }
2089588c3f0dSKowalski, Kamil 
20901f8c7b5dSJohnathan Mantey             if (dhcpv4 || dhcpv6)
20911f8c7b5dSJohnathan Mantey             {
2092002d39b4SEd Tanous                 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2093002d39b4SEd Tanous                                 asyncResp);
20941f8c7b5dSJohnathan Mantey             }
20951f8c7b5dSJohnathan Mantey 
20960627a2c7SEd Tanous             if (hostname)
20971abe55efSEd Tanous             {
20980627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
20991abe55efSEd Tanous             }
21000627a2c7SEd Tanous 
2101b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2102b10d8db0SRavi Teja             {
2103b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2104b10d8db0SRavi Teja                                            asyncResp);
2105b10d8db0SRavi Teja             }
2106b10d8db0SRavi Teja 
2107ab6554f1SJoshi-Mansi             if (fqdn)
2108ab6554f1SJoshi-Mansi             {
21092c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2110ab6554f1SJoshi-Mansi             }
2111ab6554f1SJoshi-Mansi 
2112d577665bSRatan Gupta             if (macAddress)
2113d577665bSRatan Gupta             {
2114002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2115d577665bSRatan Gupta             }
2116d577665bSRatan Gupta 
2117d1d50814SRavi Teja             if (ipv4StaticAddresses)
2118d1d50814SRavi Teja             {
2119bf648f77SEd Tanous                 // TODO(ed) for some reason the capture of
2120bf648f77SEd Tanous                 // ipv4Addresses above is returning a const value,
2121bf648f77SEd Tanous                 // not a non-const value. This doesn't really work
2122bf648f77SEd Tanous                 // for us, as we need to be able to efficiently move
2123bf648f77SEd Tanous                 // out the intermedia nlohmann::json objects. This
2124bf648f77SEd Tanous                 // makes a copy of the structure, and operates on
2125bf648f77SEd Tanous                 // that, but could be done more efficiently
2126ddd70dcaSEd Tanous                 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
2127002d39b4SEd Tanous                 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
21281abe55efSEd Tanous             }
21290627a2c7SEd Tanous 
2130f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2131f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2132002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2133002d39b4SEd Tanous                                              asyncResp);
2134f85837bfSRAJESWARAN THILLAIGOVINDAN             }
21359a6fc6feSRavi Teja 
21369a6fc6feSRavi Teja             if (ipv6DefaultGateway)
21379a6fc6feSRavi Teja             {
21389a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
21399a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
21409a6fc6feSRavi Teja             }
2141e48c0fc5SRavi Teja 
2142e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2143e48c0fc5SRavi Teja             {
2144ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2145ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2146e48c0fc5SRavi Teja             }
2147eeedda23SJohnathan Mantey 
2148eeedda23SJohnathan Mantey             if (interfaceEnabled)
2149eeedda23SJohnathan Mantey             {
2150002d39b4SEd Tanous                 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2151002d39b4SEd Tanous                                                  *interfaceEnabled, asyncResp);
2152eeedda23SJohnathan Mantey             }
215335fb5311STejas Patil 
215435fb5311STejas Patil             if (mtuSize)
215535fb5311STejas Patil             {
215635fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
215735fb5311STejas Patil             }
2158588c3f0dSKowalski, Kamil             });
2159bf648f77SEd Tanous         });
2160e7caf250SJiaqing Zhao 
2161e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2162e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2163e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2164e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2165e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2166e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2167e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2168e7caf250SJiaqing Zhao         {
2169e7caf250SJiaqing Zhao             return;
2170e7caf250SJiaqing Zhao         }
2171e7caf250SJiaqing Zhao 
2172e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2173e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2174e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2175e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2176e7caf250SJiaqing Zhao             },
2177e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2178e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2179e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2180e7caf250SJiaqing Zhao         });
21814a0cb85cSEd Tanous }
2182bf648f77SEd Tanous 
21839391bb9cSRapkiewicz, Pawel } // namespace redfish
2184