xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision e01d0c36af115ed46d54b5dbbacfe3ad92226bd3)
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 
3111ba3979SEd Tanous #include <boost/algorithm/string/classification.hpp>
3211ba3979SEd Tanous #include <boost/algorithm/string/split.hpp>
33ef4c65b7SEd Tanous #include <boost/url/format.hpp>
341214b7e7SGunnar Mills 
357a1dbc48SGeorge Liu #include <array>
36a24526dcSEd Tanous #include <optional>
37ab6554f1SJoshi-Mansi #include <regex>
387a1dbc48SGeorge Liu #include <string_view>
3977179532SEd Tanous #include <vector>
409391bb9cSRapkiewicz, Pawel 
411abe55efSEd Tanous namespace redfish
421abe55efSEd Tanous {
439391bb9cSRapkiewicz, Pawel 
444a0cb85cSEd Tanous enum class LinkType
454a0cb85cSEd Tanous {
464a0cb85cSEd Tanous     Local,
474a0cb85cSEd Tanous     Global
484a0cb85cSEd Tanous };
499391bb9cSRapkiewicz, Pawel 
509391bb9cSRapkiewicz, Pawel /**
519391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
529391bb9cSRapkiewicz, Pawel  */
531abe55efSEd Tanous struct IPv4AddressData
541abe55efSEd Tanous {
55179db1d7SKowalski, Kamil     std::string id;
564a0cb85cSEd Tanous     std::string address;
574a0cb85cSEd Tanous     std::string domain;
584a0cb85cSEd Tanous     std::string gateway;
599391bb9cSRapkiewicz, Pawel     std::string netmask;
609391bb9cSRapkiewicz, Pawel     std::string origin;
6177179532SEd Tanous     LinkType linktype{};
6277179532SEd Tanous     bool isActive{};
639391bb9cSRapkiewicz, Pawel };
649391bb9cSRapkiewicz, Pawel 
659391bb9cSRapkiewicz, Pawel /**
66e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
67e48c0fc5SRavi Teja  */
68e48c0fc5SRavi Teja struct IPv6AddressData
69e48c0fc5SRavi Teja {
70e48c0fc5SRavi Teja     std::string id;
71e48c0fc5SRavi Teja     std::string address;
72e48c0fc5SRavi Teja     std::string origin;
7377179532SEd Tanous     uint8_t prefixLength = 0;
74e48c0fc5SRavi Teja };
75e48c0fc5SRavi Teja /**
769391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
779391bb9cSRapkiewicz, Pawel  * available from DBus
789391bb9cSRapkiewicz, Pawel  */
791abe55efSEd Tanous struct EthernetInterfaceData
801abe55efSEd Tanous {
814a0cb85cSEd Tanous     uint32_t speed;
8235fb5311STejas Patil     size_t mtuSize;
8382695a5bSJiaqing Zhao     bool autoNeg;
8482695a5bSJiaqing Zhao     bool dnsEnabled;
8582695a5bSJiaqing Zhao     bool ntpEnabled;
8682695a5bSJiaqing Zhao     bool hostNameEnabled;
87aa05fb27SJohnathan Mantey     bool linkUp;
88eeedda23SJohnathan Mantey     bool nicEnabled;
89b10d8db0SRavi Teja     bool ipv6AcceptRa;
9082695a5bSJiaqing Zhao     std::string dhcpEnabled;
911f8c7b5dSJohnathan Mantey     std::string operatingMode;
9282695a5bSJiaqing Zhao     std::string hostName;
9382695a5bSJiaqing Zhao     std::string defaultGateway;
9482695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
9582695a5bSJiaqing Zhao     std::string macAddress;
9617e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
970f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
980f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
99d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1009391bb9cSRapkiewicz, Pawel };
1019391bb9cSRapkiewicz, Pawel 
1021f8c7b5dSJohnathan Mantey struct DHCPParameters
1031f8c7b5dSJohnathan Mantey {
1041f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
10582695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
10682695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
10782695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1081f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1091f8c7b5dSJohnathan Mantey };
1101f8c7b5dSJohnathan Mantey 
1119391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1129391bb9cSRapkiewicz, Pawel // into full dot notation
1131abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1141abe55efSEd Tanous {
1159391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1169391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1179391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1189391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1199391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1209391bb9cSRapkiewicz, Pawel     return netmask;
1219391bb9cSRapkiewicz, Pawel }
1229391bb9cSRapkiewicz, Pawel 
12382695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1241f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1251f8c7b5dSJohnathan Mantey {
1261f8c7b5dSJohnathan Mantey     if (isIPv4)
1271f8c7b5dSJohnathan Mantey     {
1281f8c7b5dSJohnathan Mantey         return (
1291f8c7b5dSJohnathan Mantey             (inputDHCP ==
1301f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1311f8c7b5dSJohnathan Mantey             (inputDHCP ==
1321f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1331f8c7b5dSJohnathan Mantey     }
1341f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1351f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1361f8c7b5dSJohnathan Mantey             (inputDHCP ==
1371f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1381f8c7b5dSJohnathan Mantey }
1391f8c7b5dSJohnathan Mantey 
1402c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1411f8c7b5dSJohnathan Mantey {
1421f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1431f8c7b5dSJohnathan Mantey     {
1441f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1451f8c7b5dSJohnathan Mantey     }
1463174e4dfSEd Tanous     if (isIPv4)
1471f8c7b5dSJohnathan Mantey     {
1481f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1491f8c7b5dSJohnathan Mantey     }
1503174e4dfSEd Tanous     if (isIPv6)
1511f8c7b5dSJohnathan Mantey     {
1521f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1531f8c7b5dSJohnathan Mantey     }
1541f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1551f8c7b5dSJohnathan Mantey }
1561f8c7b5dSJohnathan Mantey 
1574a0cb85cSEd Tanous inline std::string
1584a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1594a0cb85cSEd Tanous                                         bool isIPv4)
1601abe55efSEd Tanous {
1614a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1621abe55efSEd Tanous     {
1634a0cb85cSEd Tanous         return "Static";
1649391bb9cSRapkiewicz, Pawel     }
1654a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1661abe55efSEd Tanous     {
1674a0cb85cSEd Tanous         if (isIPv4)
1681abe55efSEd Tanous         {
1694a0cb85cSEd Tanous             return "IPv4LinkLocal";
1701abe55efSEd Tanous         }
1714a0cb85cSEd Tanous         return "LinkLocal";
1729391bb9cSRapkiewicz, Pawel     }
1734a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1741abe55efSEd Tanous     {
1754a0cb85cSEd Tanous         if (isIPv4)
1764a0cb85cSEd Tanous         {
1774a0cb85cSEd Tanous             return "DHCP";
1784a0cb85cSEd Tanous         }
1794a0cb85cSEd Tanous         return "DHCPv6";
1804a0cb85cSEd Tanous     }
1814a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
1824a0cb85cSEd Tanous     {
1834a0cb85cSEd Tanous         return "SLAAC";
1844a0cb85cSEd Tanous     }
1854a0cb85cSEd Tanous     return "";
1864a0cb85cSEd Tanous }
1874a0cb85cSEd Tanous 
18802cad96eSEd Tanous inline bool extractEthernetInterfaceData(
18902cad96eSEd Tanous     const std::string& ethifaceId,
19002cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
1914a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
1924a0cb85cSEd Tanous {
1934c9afe43SEd Tanous     bool idFound = false;
19402cad96eSEd Tanous     for (const auto& objpath : dbusData)
1954a0cb85cSEd Tanous     {
19602cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
1974a0cb85cSEd Tanous         {
19881ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
199029573d4SEd Tanous             {
2004c9afe43SEd Tanous                 idFound = true;
2014a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2024a0cb85cSEd Tanous                 {
2034a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2044a0cb85cSEd Tanous                     {
2054a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2064a0cb85cSEd Tanous                         {
2074a0cb85cSEd Tanous                             const std::string* mac =
208abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2094a0cb85cSEd Tanous                             if (mac != nullptr)
2104a0cb85cSEd Tanous                             {
21182695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2124a0cb85cSEd Tanous                             }
2134a0cb85cSEd Tanous                         }
2144a0cb85cSEd Tanous                     }
2154a0cb85cSEd Tanous                 }
2164a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2174a0cb85cSEd Tanous                 {
2184a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2194a0cb85cSEd Tanous                     {
2204a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2214a0cb85cSEd Tanous                         {
2221b6b96c5SEd Tanous                             const uint32_t* id =
223abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2244a0cb85cSEd Tanous                             if (id != nullptr)
2254a0cb85cSEd Tanous                             {
22617e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2274a0cb85cSEd Tanous                             }
2284a0cb85cSEd Tanous                         }
2294a0cb85cSEd Tanous                     }
2304a0cb85cSEd Tanous                 }
2314a0cb85cSEd Tanous                 else if (ifacePair.first ==
2324a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2334a0cb85cSEd Tanous                 {
2344a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2354a0cb85cSEd Tanous                     {
2364a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2374a0cb85cSEd Tanous                         {
2382c70f800SEd Tanous                             const bool* autoNeg =
239abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2402c70f800SEd Tanous                             if (autoNeg != nullptr)
2414a0cb85cSEd Tanous                             {
24282695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2434a0cb85cSEd Tanous                             }
2444a0cb85cSEd Tanous                         }
2454a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2464a0cb85cSEd Tanous                         {
2474a0cb85cSEd Tanous                             const uint32_t* speed =
248abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2494a0cb85cSEd Tanous                             if (speed != nullptr)
2504a0cb85cSEd Tanous                             {
2514a0cb85cSEd Tanous                                 ethData.speed = *speed;
2524a0cb85cSEd Tanous                             }
2534a0cb85cSEd Tanous                         }
25435fb5311STejas Patil                         else if (propertyPair.first == "MTU")
25535fb5311STejas Patil                         {
25635fb5311STejas Patil                             const uint32_t* mtuSize =
25735fb5311STejas Patil                                 std::get_if<uint32_t>(&propertyPair.second);
25835fb5311STejas Patil                             if (mtuSize != nullptr)
25935fb5311STejas Patil                             {
26035fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
26135fb5311STejas Patil                             }
26235fb5311STejas Patil                         }
263aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
264aa05fb27SJohnathan Mantey                         {
265aa05fb27SJohnathan Mantey                             const bool* linkUp =
266aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
267aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
268aa05fb27SJohnathan Mantey                             {
269aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
270aa05fb27SJohnathan Mantey                             }
271aa05fb27SJohnathan Mantey                         }
272eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
273eeedda23SJohnathan Mantey                         {
274eeedda23SJohnathan Mantey                             const bool* nicEnabled =
275eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
276eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
277eeedda23SJohnathan Mantey                             {
278eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
279eeedda23SJohnathan Mantey                             }
280eeedda23SJohnathan Mantey                         }
281b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
282b10d8db0SRavi Teja                         {
283b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
284b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
285b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
286b10d8db0SRavi Teja                             {
287b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
288b10d8db0SRavi Teja                             }
289b10d8db0SRavi Teja                         }
290f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
291029573d4SEd Tanous                         {
292029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
2938d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
294029573d4SEd Tanous                                     &propertyPair.second);
295029573d4SEd Tanous                             if (nameservers != nullptr)
296029573d4SEd Tanous                             {
297f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
2980f6efdc1Smanojkiran.eda@gmail.com                             }
2990f6efdc1Smanojkiran.eda@gmail.com                         }
3000f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3010f6efdc1Smanojkiran.eda@gmail.com                         {
3020f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3038d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3040f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3050f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3060f6efdc1Smanojkiran.eda@gmail.com                             {
307f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3084a0cb85cSEd Tanous                             }
3094a0cb85cSEd Tanous                         }
3102a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3112a133282Smanojkiraneda                         {
3122c70f800SEd Tanous                             const std::string* dhcpEnabled =
3131f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3142c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3152a133282Smanojkiraneda                             {
31682695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3172a133282Smanojkiraneda                             }
3182a133282Smanojkiraneda                         }
319d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
320d24bfc7aSJennifer Lee                         {
321d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3228d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
323d24bfc7aSJennifer Lee                                     &propertyPair.second);
324d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
325d24bfc7aSJennifer Lee                             {
326f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
327d24bfc7aSJennifer Lee                             }
328d24bfc7aSJennifer Lee                         }
3299010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3309010ec2eSRavi Teja                         {
3319010ec2eSRavi Teja                             const std::string* defaultGateway =
3329010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3339010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3349010ec2eSRavi Teja                             {
3359010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3369010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3379010ec2eSRavi Teja                                 {
33882695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3399010ec2eSRavi Teja                                 }
3409010ec2eSRavi Teja                                 else
3419010ec2eSRavi Teja                                 {
34282695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3439010ec2eSRavi Teja                                 }
3449010ec2eSRavi Teja                             }
3459010ec2eSRavi Teja                         }
3469010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3479010ec2eSRavi Teja                         {
3489010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3499010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3509010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3519010ec2eSRavi Teja                             {
3529010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3539010ec2eSRavi Teja                                     *defaultGateway6;
3549010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3559010ec2eSRavi Teja                                 {
35682695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3579010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3589010ec2eSRavi Teja                                 }
3599010ec2eSRavi Teja                                 else
3609010ec2eSRavi Teja                                 {
36182695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3629010ec2eSRavi Teja                                         defaultGateway6Str;
3639010ec2eSRavi Teja                                 }
3649010ec2eSRavi Teja                             }
3659010ec2eSRavi Teja                         }
366029573d4SEd Tanous                     }
367029573d4SEd Tanous                 }
368029573d4SEd Tanous             }
3691f8c7b5dSJohnathan Mantey 
3701e3f85e6SJian Zhang             if (objpath.first == "/xyz/openbmc_project/network/dhcp")
3711f8c7b5dSJohnathan Mantey             {
3721f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
3731f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
3741f8c7b5dSJohnathan Mantey                 {
3751f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
3761f8c7b5dSJohnathan Mantey                     {
3771f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
3781f8c7b5dSJohnathan Mantey                         {
3792c70f800SEd Tanous                             const bool* dnsEnabled =
3801f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
3812c70f800SEd Tanous                             if (dnsEnabled != nullptr)
3821f8c7b5dSJohnathan Mantey                             {
38382695a5bSJiaqing Zhao                                 ethData.dnsEnabled = *dnsEnabled;
3841f8c7b5dSJohnathan Mantey                             }
3851f8c7b5dSJohnathan Mantey                         }
3861f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
3871f8c7b5dSJohnathan Mantey                         {
3882c70f800SEd Tanous                             const bool* ntpEnabled =
3891f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
3902c70f800SEd Tanous                             if (ntpEnabled != nullptr)
3911f8c7b5dSJohnathan Mantey                             {
39282695a5bSJiaqing Zhao                                 ethData.ntpEnabled = *ntpEnabled;
3931f8c7b5dSJohnathan Mantey                             }
3941f8c7b5dSJohnathan Mantey                         }
3951f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
3961f8c7b5dSJohnathan Mantey                         {
3972c70f800SEd Tanous                             const bool* hostNameEnabled =
3981f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
3992c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4001f8c7b5dSJohnathan Mantey                             {
40182695a5bSJiaqing Zhao                                 ethData.hostNameEnabled = *hostNameEnabled;
4021f8c7b5dSJohnathan Mantey                             }
4031f8c7b5dSJohnathan Mantey                         }
4041f8c7b5dSJohnathan Mantey                     }
4051f8c7b5dSJohnathan Mantey                 }
4061f8c7b5dSJohnathan Mantey             }
407029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
408029573d4SEd Tanous             // to check eth number
409029573d4SEd Tanous             if (ifacePair.first ==
4104a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4114a0cb85cSEd Tanous             {
4124a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
4134a0cb85cSEd Tanous                 {
4144a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
4154a0cb85cSEd Tanous                     {
4164a0cb85cSEd Tanous                         const std::string* hostname =
4178d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
4184a0cb85cSEd Tanous                         if (hostname != nullptr)
4194a0cb85cSEd Tanous                         {
42082695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
4214a0cb85cSEd Tanous                         }
4224a0cb85cSEd Tanous                     }
4234a0cb85cSEd Tanous                 }
4244a0cb85cSEd Tanous             }
4254a0cb85cSEd Tanous         }
4264a0cb85cSEd Tanous     }
4274c9afe43SEd Tanous     return idFound;
4284a0cb85cSEd Tanous }
4294a0cb85cSEd Tanous 
430e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
43177179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
432711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
43377179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
434e48c0fc5SRavi Teja {
43589492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
43689492a15SPatrick Williams                                     ethifaceId;
437e48c0fc5SRavi Teja 
438e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
439e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
44081ce609eSEd Tanous     for (const auto& objpath : dbusData)
441e48c0fc5SRavi Teja     {
442e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
443353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
444e48c0fc5SRavi Teja         {
4459eb808c1SEd Tanous             for (const auto& interface : objpath.second)
446e48c0fc5SRavi Teja             {
447e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
448e48c0fc5SRavi Teja                 {
449353163e9STony Lee                     auto type = std::find_if(interface.second.begin(),
450353163e9STony Lee                                              interface.second.end(),
451353163e9STony Lee                                              [](const auto& property) {
452353163e9STony Lee                         return property.first == "Type";
453353163e9STony Lee                     });
454353163e9STony Lee                     if (type == interface.second.end())
455353163e9STony Lee                     {
456353163e9STony Lee                         continue;
457353163e9STony Lee                     }
458353163e9STony Lee 
459353163e9STony Lee                     const std::string* typeStr =
460353163e9STony Lee                         std::get_if<std::string>(&type->second);
461353163e9STony Lee 
462353163e9STony Lee                     if (typeStr == nullptr ||
463353163e9STony Lee                         (*typeStr !=
464353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
465353163e9STony Lee                     {
466353163e9STony Lee                         continue;
467353163e9STony Lee                     }
468353163e9STony Lee 
469e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
470e48c0fc5SRavi Teja                     // appropriate
47177179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
4722c70f800SEd Tanous                     ipv6Address.id =
473353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
4749eb808c1SEd Tanous                     for (const auto& property : interface.second)
475e48c0fc5SRavi Teja                     {
476e48c0fc5SRavi Teja                         if (property.first == "Address")
477e48c0fc5SRavi Teja                         {
478e48c0fc5SRavi Teja                             const std::string* address =
479e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
480e48c0fc5SRavi Teja                             if (address != nullptr)
481e48c0fc5SRavi Teja                             {
4822c70f800SEd Tanous                                 ipv6Address.address = *address;
483e48c0fc5SRavi Teja                             }
484e48c0fc5SRavi Teja                         }
485e48c0fc5SRavi Teja                         else if (property.first == "Origin")
486e48c0fc5SRavi Teja                         {
487e48c0fc5SRavi Teja                             const std::string* origin =
488e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
489e48c0fc5SRavi Teja                             if (origin != nullptr)
490e48c0fc5SRavi Teja                             {
4912c70f800SEd Tanous                                 ipv6Address.origin =
492e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
493e48c0fc5SRavi Teja                                                                         false);
494e48c0fc5SRavi Teja                             }
495e48c0fc5SRavi Teja                         }
496e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
497e48c0fc5SRavi Teja                         {
498e48c0fc5SRavi Teja                             const uint8_t* prefix =
499e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
500e48c0fc5SRavi Teja                             if (prefix != nullptr)
501e48c0fc5SRavi Teja                             {
5022c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
503e48c0fc5SRavi Teja                             }
504e48c0fc5SRavi Teja                         }
505889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
506889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
507889ff694SAsmitha Karunanithi                         {
508889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
509889ff694SAsmitha Karunanithi                         }
510e48c0fc5SRavi Teja                         else
511e48c0fc5SRavi Teja                         {
51262598e31SEd Tanous                             BMCWEB_LOG_ERROR(
51362598e31SEd Tanous                                 "Got extra property: {} on the {} object",
51462598e31SEd Tanous                                 property.first, objpath.first.str);
515e48c0fc5SRavi Teja                         }
516e48c0fc5SRavi Teja                     }
517e48c0fc5SRavi Teja                 }
518e48c0fc5SRavi Teja             }
519e48c0fc5SRavi Teja         }
520e48c0fc5SRavi Teja     }
521e48c0fc5SRavi Teja }
522e48c0fc5SRavi Teja 
5234a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
52477179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
525711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
52677179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
5274a0cb85cSEd Tanous {
52889492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
52989492a15SPatrick Williams                                     ethifaceId;
5304a0cb85cSEd Tanous 
5314a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
5324a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
53381ce609eSEd Tanous     for (const auto& objpath : dbusData)
5344a0cb85cSEd Tanous     {
5354a0cb85cSEd Tanous         // Check if proper pattern for object path appears
536353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
5374a0cb85cSEd Tanous         {
5389eb808c1SEd Tanous             for (const auto& interface : objpath.second)
5394a0cb85cSEd Tanous             {
5404a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
5414a0cb85cSEd Tanous                 {
542353163e9STony Lee                     auto type = std::find_if(interface.second.begin(),
543353163e9STony Lee                                              interface.second.end(),
544353163e9STony Lee                                              [](const auto& property) {
545353163e9STony Lee                         return property.first == "Type";
546353163e9STony Lee                     });
547353163e9STony Lee                     if (type == interface.second.end())
548353163e9STony Lee                     {
549353163e9STony Lee                         continue;
550353163e9STony Lee                     }
551353163e9STony Lee 
552353163e9STony Lee                     const std::string* typeStr =
553353163e9STony Lee                         std::get_if<std::string>(&type->second);
554353163e9STony Lee 
555353163e9STony Lee                     if (typeStr == nullptr ||
556353163e9STony Lee                         (*typeStr !=
557353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
558353163e9STony Lee                     {
559353163e9STony Lee                         continue;
560353163e9STony Lee                     }
561353163e9STony Lee 
5624a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
5634a0cb85cSEd Tanous                     // appropriate
56477179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
5652c70f800SEd Tanous                     ipv4Address.id =
566353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5679eb808c1SEd Tanous                     for (const auto& property : interface.second)
5684a0cb85cSEd Tanous                     {
5694a0cb85cSEd Tanous                         if (property.first == "Address")
5704a0cb85cSEd Tanous                         {
5714a0cb85cSEd Tanous                             const std::string* address =
572abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
5734a0cb85cSEd Tanous                             if (address != nullptr)
5744a0cb85cSEd Tanous                             {
5752c70f800SEd Tanous                                 ipv4Address.address = *address;
5764a0cb85cSEd Tanous                             }
5774a0cb85cSEd Tanous                         }
5784a0cb85cSEd Tanous                         else if (property.first == "Origin")
5794a0cb85cSEd Tanous                         {
5804a0cb85cSEd Tanous                             const std::string* origin =
581abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
5824a0cb85cSEd Tanous                             if (origin != nullptr)
5834a0cb85cSEd Tanous                             {
5842c70f800SEd Tanous                                 ipv4Address.origin =
5854a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
5864a0cb85cSEd Tanous                                                                         true);
5874a0cb85cSEd Tanous                             }
5884a0cb85cSEd Tanous                         }
5894a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
5904a0cb85cSEd Tanous                         {
5914a0cb85cSEd Tanous                             const uint8_t* mask =
592abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
5934a0cb85cSEd Tanous                             if (mask != nullptr)
5944a0cb85cSEd Tanous                             {
5954a0cb85cSEd Tanous                                 // convert it to the string
5962c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
5974a0cb85cSEd Tanous                             }
5984a0cb85cSEd Tanous                         }
599889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
600889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
601889ff694SAsmitha Karunanithi                         {
602889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
603889ff694SAsmitha Karunanithi                         }
6044a0cb85cSEd Tanous                         else
6054a0cb85cSEd Tanous                         {
60662598e31SEd Tanous                             BMCWEB_LOG_ERROR(
60762598e31SEd Tanous                                 "Got extra property: {} on the {} object",
60862598e31SEd Tanous                                 property.first, objpath.first.str);
6094a0cb85cSEd Tanous                         }
6104a0cb85cSEd Tanous                     }
6114a0cb85cSEd Tanous                     // Check if given address is local, or global
6122c70f800SEd Tanous                     ipv4Address.linktype =
61311ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
61418659d10SJohnathan Mantey                             ? LinkType::Local
61518659d10SJohnathan Mantey                             : LinkType::Global;
6164a0cb85cSEd Tanous                 }
6174a0cb85cSEd Tanous             }
6184a0cb85cSEd Tanous         }
6194a0cb85cSEd Tanous     }
6204a0cb85cSEd Tanous }
621588c3f0dSKowalski, Kamil 
622588c3f0dSKowalski, Kamil /**
62301784826SJohnathan Mantey  * @brief Deletes given IPv4 interface
624179db1d7SKowalski, Kamil  *
625179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
626179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
627179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
628179db1d7SKowalski, Kamil  *
629179db1d7SKowalski, Kamil  * @return None
630179db1d7SKowalski, Kamil  */
6319c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
6329c5e585cSRavi Teja                             const std::string& ipHash,
6338d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
6341abe55efSEd Tanous {
63555c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
6365e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
6371abe55efSEd Tanous         if (ec)
6381abe55efSEd Tanous         {
639a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
6401abe55efSEd Tanous         }
641179db1d7SKowalski, Kamil         },
642179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
6439c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
644179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
645179db1d7SKowalski, Kamil }
646179db1d7SKowalski, Kamil 
647244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway(
648244b6d5bSGunnar Mills     const std::string& ifaceId, const std::string& gateway,
649244b6d5bSGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
6509010ec2eSRavi Teja {
6519ae226faSGeorge Liu     sdbusplus::asio::setProperty(
6529ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
6539ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
6549ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
6559ae226faSGeorge Liu         gateway, [asyncResp](const boost::system::error_code& ec) {
6569010ec2eSRavi Teja             if (ec)
6579010ec2eSRavi Teja             {
6589010ec2eSRavi Teja                 messages::internalError(asyncResp->res);
6599010ec2eSRavi Teja                 return;
6609010ec2eSRavi Teja             }
6619010ec2eSRavi Teja             asyncResp->res.result(boost::beast::http::status::no_content);
6629ae226faSGeorge Liu         });
6639010ec2eSRavi Teja }
664179db1d7SKowalski, Kamil /**
66501784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
666179db1d7SKowalski, Kamil  *
66701784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
66801784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
66901784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
67001784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
671179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
672179db1d7SKowalski, Kamil  *
673179db1d7SKowalski, Kamil  * @return None
674179db1d7SKowalski, Kamil  */
675cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
676cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
6778d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
6781abe55efSEd Tanous {
679002d39b4SEd Tanous     auto createIpHandler =
6805e7e2dc5SEd Tanous         [asyncResp, ifaceId, gateway](const boost::system::error_code& ec) {
6811abe55efSEd Tanous         if (ec)
6821abe55efSEd Tanous         {
683a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
6849010ec2eSRavi Teja             return;
685179db1d7SKowalski, Kamil         }
6869010ec2eSRavi Teja         updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
6879010ec2eSRavi Teja     };
6889010ec2eSRavi Teja 
6899010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
6909010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
691179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
692179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
69301784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
694179db1d7SKowalski, Kamil         gateway);
695179db1d7SKowalski, Kamil }
696e48c0fc5SRavi Teja 
697e48c0fc5SRavi Teja /**
69801784826SJohnathan Mantey  * @brief Deletes the IPv6 entry for this interface and creates a replacement
69901784826SJohnathan Mantey  * static IPv6 entry
70001784826SJohnathan Mantey  *
70101784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv6 entry
70201784826SJohnathan Mantey  * @param[in] id           The unique hash entry identifying the DBus entry
70301784826SJohnathan Mantey  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
70401784826SJohnathan Mantey  * @param[in] address      IPv6 address to assign to this interface
70501784826SJohnathan Mantey  * @param[io] asyncResp    Response object that will be returned to client
70601784826SJohnathan Mantey  *
70701784826SJohnathan Mantey  * @return None
70801784826SJohnathan Mantey  */
7099c5e585cSRavi Teja 
7109c5e585cSRavi Teja enum class IpVersion
7119c5e585cSRavi Teja {
7129c5e585cSRavi Teja     IpV4,
7139c5e585cSRavi Teja     IpV6
7149c5e585cSRavi Teja };
7159c5e585cSRavi Teja 
7169c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
7179c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
7188d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
7199c5e585cSRavi Teja     const std::string& gateway,
7208d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
72101784826SJohnathan Mantey {
72201784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
7239c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
7249c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
72501784826SJohnathan Mantey         if (ec)
72601784826SJohnathan Mantey         {
72701784826SJohnathan Mantey             messages::internalError(asyncResp->res);
72801784826SJohnathan Mantey         }
7299c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
7309c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
73101784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
7325e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
73323a21a1cSEd Tanous             if (ec2)
73401784826SJohnathan Mantey             {
73501784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
73601784826SJohnathan Mantey             }
73701784826SJohnathan Mantey             },
73801784826SJohnathan Mantey             "xyz.openbmc_project.Network",
73901784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
7409c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
7419c5e585cSRavi Teja             prefixLength, gateway);
74201784826SJohnathan Mantey         },
74301784826SJohnathan Mantey         "xyz.openbmc_project.Network",
7449c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
74501784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
74601784826SJohnathan Mantey }
74701784826SJohnathan Mantey 
74801784826SJohnathan Mantey /**
749e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
750e48c0fc5SRavi Teja  *
751e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
752e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
753e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
754e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
755e48c0fc5SRavi Teja  *
756e48c0fc5SRavi Teja  * @return None
757e48c0fc5SRavi Teja  */
75801784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
75901784826SJohnathan Mantey                        const std::string& address,
7608d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
761e48c0fc5SRavi Teja {
762fc23ef8aSNitin Kumar Kotania     auto createIpHandler =
763fc23ef8aSNitin Kumar Kotania         [asyncResp, address](const boost::system::error_code& ec) {
764e48c0fc5SRavi Teja         if (ec)
765e48c0fc5SRavi Teja         {
766fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
767fc23ef8aSNitin Kumar Kotania             {
768fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
769fc23ef8aSNitin Kumar Kotania                                                    "Address");
770fc23ef8aSNitin Kumar Kotania             }
771fc23ef8aSNitin Kumar Kotania             else
772fc23ef8aSNitin Kumar Kotania             {
773e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
774e48c0fc5SRavi Teja             }
775fc23ef8aSNitin Kumar Kotania         }
776e48c0fc5SRavi Teja     };
777e48c0fc5SRavi Teja     // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
7784e0453b1SGunnar Mills     // does not have associated gateway property
779e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
780e48c0fc5SRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
781e48c0fc5SRavi Teja         "/xyz/openbmc_project/network/" + ifaceId,
782e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
783e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
784e48c0fc5SRavi Teja         "");
785e48c0fc5SRavi Teja }
786e48c0fc5SRavi Teja 
787179db1d7SKowalski, Kamil /**
788179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
789179db1d7SKowalski, Kamil  * Object
790179db1d7SKowalski, Kamil  * from EntityManager Network Manager
7914a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
792179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
793179db1d7SKowalski, Kamil  * into JSON
794179db1d7SKowalski, Kamil  */
795179db1d7SKowalski, Kamil template <typename CallbackFunc>
79681ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
7971abe55efSEd Tanous                           CallbackFunc&& callback)
7981abe55efSEd Tanous {
799f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
800f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
801f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
802f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
803f94c4ecfSEd Tanous          callback{std::forward<CallbackFunc>(callback)}](
8048b24275dSEd Tanous             const boost::system::error_code& ec,
80502cad96eSEd Tanous             const dbus::utility::ManagedObjectType& resp) {
80655c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
80777179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
80877179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
809179db1d7SKowalski, Kamil 
8108b24275dSEd Tanous         if (ec)
8111abe55efSEd Tanous         {
81201784826SJohnathan Mantey             callback(false, ethData, ipv4Data, ipv6Data);
813179db1d7SKowalski, Kamil             return;
814179db1d7SKowalski, Kamil         }
815179db1d7SKowalski, Kamil 
816002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
8174c9afe43SEd Tanous         if (!found)
8184c9afe43SEd Tanous         {
81901784826SJohnathan Mantey             callback(false, ethData, ipv4Data, ipv6Data);
8204c9afe43SEd Tanous             return;
8214c9afe43SEd Tanous         }
8224c9afe43SEd Tanous 
8232c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
824179db1d7SKowalski, Kamil         // Fix global GW
8251abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
8261abe55efSEd Tanous         {
827c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
828c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
8299010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
8301abe55efSEd Tanous             {
83182695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
832179db1d7SKowalski, Kamil             }
833179db1d7SKowalski, Kamil         }
834179db1d7SKowalski, Kamil 
8352c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
8364e0453b1SGunnar Mills         // Finally make a callback with useful data
83701784826SJohnathan Mantey         callback(true, ethData, ipv4Data, ipv6Data);
838f5892d0dSGeorge Liu         });
839271584abSEd Tanous }
840179db1d7SKowalski, Kamil 
841179db1d7SKowalski, Kamil /**
8429391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
8439391bb9cSRapkiewicz, Pawel  * Manager
8441abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
8451abe55efSEd Tanous  * into JSON.
8469391bb9cSRapkiewicz, Pawel  */
8479391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
8481abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
8491abe55efSEd Tanous {
850f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
851f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
852f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
853f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
8548b24275dSEd Tanous             const boost::system::error_code& ec,
855f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
8561abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
8571abe55efSEd Tanous         // ethernet interfaces
85877179532SEd Tanous         std::vector<std::string> ifaceList;
8592c70f800SEd Tanous         ifaceList.reserve(resp.size());
8608b24275dSEd Tanous         if (ec)
8611abe55efSEd Tanous         {
8622c70f800SEd Tanous             callback(false, ifaceList);
8639391bb9cSRapkiewicz, Pawel             return;
8649391bb9cSRapkiewicz, Pawel         }
8659391bb9cSRapkiewicz, Pawel 
8669391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
8674a0cb85cSEd Tanous         for (const auto& objpath : resp)
8681abe55efSEd Tanous         {
8699391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
8704a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
8711abe55efSEd Tanous             {
8721abe55efSEd Tanous                 // If interface is
8734a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
8744a0cb85cSEd Tanous                 // what we're looking for.
8759391bb9cSRapkiewicz, Pawel                 if (interface.first ==
8761abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
8771abe55efSEd Tanous                 {
8782dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
8792dfd18efSEd Tanous                     if (ifaceId.empty())
8801abe55efSEd Tanous                     {
8812dfd18efSEd Tanous                         continue;
8829391bb9cSRapkiewicz, Pawel                     }
8832dfd18efSEd Tanous                     // and put it into output vector.
88477179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
8859391bb9cSRapkiewicz, Pawel                 }
8869391bb9cSRapkiewicz, Pawel             }
8879391bb9cSRapkiewicz, Pawel         }
8882c5875a2SEd Tanous 
8892c5875a2SEd Tanous         std::sort(ifaceList.begin(), ifaceList.end(),
8902c5875a2SEd Tanous                   AlphanumLess<std::string>());
8912c5875a2SEd Tanous 
892a434f2bdSEd Tanous         // Finally make a callback with useful data
8932c70f800SEd Tanous         callback(true, ifaceList);
894f5892d0dSGeorge Liu         });
895271584abSEd Tanous }
8969391bb9cSRapkiewicz, Pawel 
8974f48d5f6SEd Tanous inline void
8984f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
8998d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
9001abe55efSEd Tanous {
901ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
902ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
903ab6554f1SJoshi-Mansi     {
904ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
905ab6554f1SJoshi-Mansi                                            "HostName");
906ab6554f1SJoshi-Mansi         return;
907ab6554f1SJoshi-Mansi     }
9089ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9099ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
9109ae226faSGeorge Liu         "/xyz/openbmc_project/network/config",
9119ae226faSGeorge Liu         "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
9125e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
9134a0cb85cSEd Tanous         if (ec)
9144a0cb85cSEd Tanous         {
915a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
9161abe55efSEd Tanous         }
9179ae226faSGeorge Liu         });
918588c3f0dSKowalski, Kamil }
919588c3f0dSKowalski, Kamil 
9204f48d5f6SEd Tanous inline void
92135fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
92235fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
92335fb5311STejas Patil {
92489492a15SPatrick Williams     sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
92589492a15SPatrick Williams                                               ifaceId;
9269ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9279ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
9289ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
9295e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
93035fb5311STejas Patil         if (ec)
93135fb5311STejas Patil         {
93235fb5311STejas Patil             messages::internalError(asyncResp->res);
93335fb5311STejas Patil         }
9349ae226faSGeorge Liu         });
93535fb5311STejas Patil }
93635fb5311STejas Patil 
93735fb5311STejas Patil inline void
9384f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
939bf648f77SEd Tanous                           const std::string& domainname,
9408d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
941ab6554f1SJoshi-Mansi {
942ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
9439ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9449ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
9459ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
9469ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
9479ae226faSGeorge Liu         vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
948ab6554f1SJoshi-Mansi             if (ec)
949ab6554f1SJoshi-Mansi             {
950ab6554f1SJoshi-Mansi                 messages::internalError(asyncResp->res);
951ab6554f1SJoshi-Mansi             }
9529ae226faSGeorge Liu         });
953ab6554f1SJoshi-Mansi }
954ab6554f1SJoshi-Mansi 
9554f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
956bf648f77SEd Tanous {
957bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
958bf648f77SEd Tanous     if (std::all_of(hostname.begin(), hostname.end(), ::isdigit))
959bf648f77SEd Tanous     {
960bf648f77SEd Tanous         return false;
961bf648f77SEd Tanous     }
962bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
963bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
964bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
965bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
9664b242749SEd Tanous     const static std::regex pattern(
967bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
968bf648f77SEd Tanous 
969bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
970bf648f77SEd Tanous }
971bf648f77SEd Tanous 
9724f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
973bf648f77SEd Tanous {
974bf648f77SEd Tanous     // Can have multiple subdomains
975bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
9764b242749SEd Tanous     const static std::regex pattern(
9770fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
978bf648f77SEd Tanous 
979bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
980bf648f77SEd Tanous }
981bf648f77SEd Tanous 
9824f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
9838d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
984ab6554f1SJoshi-Mansi {
985ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
986ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
987ab6554f1SJoshi-Mansi     {
988ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
989ab6554f1SJoshi-Mansi         return;
990ab6554f1SJoshi-Mansi     }
991ab6554f1SJoshi-Mansi 
992ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
993ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
994ab6554f1SJoshi-Mansi     {
995ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
996ab6554f1SJoshi-Mansi         return;
997ab6554f1SJoshi-Mansi     }
998ab6554f1SJoshi-Mansi 
999ab6554f1SJoshi-Mansi     std::string hostname;
1000ab6554f1SJoshi-Mansi     std::string domainname;
1001ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1002ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1003ab6554f1SJoshi-Mansi 
1004ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1005ab6554f1SJoshi-Mansi     {
1006ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1007ab6554f1SJoshi-Mansi         return;
1008ab6554f1SJoshi-Mansi     }
1009ab6554f1SJoshi-Mansi 
1010ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1011ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1012ab6554f1SJoshi-Mansi }
1013ab6554f1SJoshi-Mansi 
10144f48d5f6SEd Tanous inline void
10154f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1016bf648f77SEd Tanous                           const std::string& macAddress,
10178d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1018d577665bSRatan Gupta {
101958283f41SJohnathan Mantey     static constexpr std::string_view dbusNotAllowedError =
102058283f41SJohnathan Mantey         "xyz.openbmc_project.Common.Error.NotAllowed";
102158283f41SJohnathan Mantey 
10229ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10239ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10249ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10259ae226faSGeorge Liu         "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
10269ae226faSGeorge Liu         [asyncResp](const boost::system::error_code& ec,
10275b378546SPatrick Williams                     const sdbusplus::message_t& msg) {
1028d577665bSRatan Gupta         if (ec)
1029d577665bSRatan Gupta         {
103058283f41SJohnathan Mantey             const sd_bus_error* err = msg.get_error();
103158283f41SJohnathan Mantey             if (err == nullptr)
103258283f41SJohnathan Mantey             {
103358283f41SJohnathan Mantey                 messages::internalError(asyncResp->res);
103458283f41SJohnathan Mantey                 return;
103558283f41SJohnathan Mantey             }
103658283f41SJohnathan Mantey             if (err->name == dbusNotAllowedError)
103758283f41SJohnathan Mantey             {
103858283f41SJohnathan Mantey                 messages::propertyNotWritable(asyncResp->res, "MACAddress");
103958283f41SJohnathan Mantey                 return;
104058283f41SJohnathan Mantey             }
1041d577665bSRatan Gupta             messages::internalError(asyncResp->res);
1042d577665bSRatan Gupta             return;
1043d577665bSRatan Gupta         }
10449ae226faSGeorge Liu         });
1045d577665bSRatan Gupta }
1046286b9118SJohnathan Mantey 
10474f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
10484f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
10494f48d5f6SEd Tanous                            const bool v6Value,
10508d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1051da131a9aSJennifer Lee {
10522c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
10539ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10549ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10559ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10569ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
10575e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1058da131a9aSJennifer Lee         if (ec)
1059da131a9aSJennifer Lee         {
106062598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1061da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1062da131a9aSJennifer Lee             return;
1063da131a9aSJennifer Lee         }
10648f7e9c19SJayaprakash Mutyala         messages::success(asyncResp->res);
10659ae226faSGeorge Liu         });
1066da131a9aSJennifer Lee }
10671f8c7b5dSJohnathan Mantey 
10684f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty(
1069eeedda23SJohnathan Mantey     const std::string& ifaceId, const std::string& propertyName,
10708d1b46d7Szhanghch05     const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1071eeedda23SJohnathan Mantey {
10729ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10739ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10749ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10759ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
10765e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1077eeedda23SJohnathan Mantey         if (ec)
1078eeedda23SJohnathan Mantey         {
107962598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1080eeedda23SJohnathan Mantey             messages::internalError(asyncResp->res);
1081eeedda23SJohnathan Mantey             return;
1082eeedda23SJohnathan Mantey         }
10839ae226faSGeorge Liu         });
1084eeedda23SJohnathan Mantey }
1085eeedda23SJohnathan Mantey 
10864f48d5f6SEd Tanous inline void setDHCPv4Config(const std::string& propertyName, const bool& value,
10878d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1088da131a9aSJennifer Lee {
108962598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
10909ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10919ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10929ae226faSGeorge Liu         "/xyz/openbmc_project/network/dhcp",
10939ae226faSGeorge Liu         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
10945e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1095da131a9aSJennifer Lee         if (ec)
1096da131a9aSJennifer Lee         {
109762598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1098da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1099da131a9aSJennifer Lee             return;
1100da131a9aSJennifer Lee         }
11019ae226faSGeorge Liu         });
1102da131a9aSJennifer Lee }
1103d577665bSRatan Gupta 
1104b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1105b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1106b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1107b10d8db0SRavi Teja {
1108b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1109b10d8db0SRavi Teja     path /= ifaceId;
1110b10d8db0SRavi Teja     sdbusplus::asio::setProperty(
1111b10d8db0SRavi Teja         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1112b10d8db0SRavi Teja         "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1113b10d8db0SRavi Teja         ipv6AutoConfigEnabled,
1114b10d8db0SRavi Teja         [asyncResp](const boost::system::error_code& ec) {
1115b10d8db0SRavi Teja         if (ec)
1116b10d8db0SRavi Teja         {
1117b10d8db0SRavi Teja             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1118b10d8db0SRavi Teja             messages::internalError(asyncResp->res);
1119b10d8db0SRavi Teja             return;
1120b10d8db0SRavi Teja         }
1121b10d8db0SRavi Teja         messages::success(asyncResp->res);
1122b10d8db0SRavi Teja         });
1123b10d8db0SRavi Teja }
1124b10d8db0SRavi Teja 
11254f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
11261f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1127f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1128f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
11298d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1130da131a9aSJennifer Lee {
113182695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
113282695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1133da131a9aSJennifer Lee 
11341f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
11351f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
11361f8c7b5dSJohnathan Mantey 
11371f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
11381f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1139da131a9aSJennifer Lee     {
1140b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
11411f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
11421f8c7b5dSJohnathan Mantey         {
1143bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1144bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
11451f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1146da131a9aSJennifer Lee             return;
1147da131a9aSJennifer Lee         }
1148b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
11491f8c7b5dSJohnathan Mantey     }
11501f8c7b5dSJohnathan Mantey     else
1151da131a9aSJennifer Lee     {
11521f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
11531f8c7b5dSJohnathan Mantey     }
11541f8c7b5dSJohnathan Mantey 
11551f8c7b5dSJohnathan Mantey     bool nextDNS{};
115682695a5bSJiaqing Zhao     if (v4dhcpParms.useDnsServers && v6dhcpParms.useDnsServers)
11571f8c7b5dSJohnathan Mantey     {
115882695a5bSJiaqing Zhao         if (*v4dhcpParms.useDnsServers != *v6dhcpParms.useDnsServers)
11591f8c7b5dSJohnathan Mantey         {
11601f8c7b5dSJohnathan Mantey             messages::generalError(asyncResp->res);
11611f8c7b5dSJohnathan Mantey             return;
11621f8c7b5dSJohnathan Mantey         }
116382695a5bSJiaqing Zhao         nextDNS = *v4dhcpParms.useDnsServers;
11641f8c7b5dSJohnathan Mantey     }
116582695a5bSJiaqing Zhao     else if (v4dhcpParms.useDnsServers)
11661f8c7b5dSJohnathan Mantey     {
116782695a5bSJiaqing Zhao         nextDNS = *v4dhcpParms.useDnsServers;
11681f8c7b5dSJohnathan Mantey     }
116982695a5bSJiaqing Zhao     else if (v6dhcpParms.useDnsServers)
11701f8c7b5dSJohnathan Mantey     {
117182695a5bSJiaqing Zhao         nextDNS = *v6dhcpParms.useDnsServers;
11721f8c7b5dSJohnathan Mantey     }
11731f8c7b5dSJohnathan Mantey     else
11741f8c7b5dSJohnathan Mantey     {
117582695a5bSJiaqing Zhao         nextDNS = ethData.dnsEnabled;
11761f8c7b5dSJohnathan Mantey     }
11771f8c7b5dSJohnathan Mantey 
11781f8c7b5dSJohnathan Mantey     bool nextNTP{};
117982695a5bSJiaqing Zhao     if (v4dhcpParms.useNtpServers && v6dhcpParms.useNtpServers)
11801f8c7b5dSJohnathan Mantey     {
118182695a5bSJiaqing Zhao         if (*v4dhcpParms.useNtpServers != *v6dhcpParms.useNtpServers)
11821f8c7b5dSJohnathan Mantey         {
11831f8c7b5dSJohnathan Mantey             messages::generalError(asyncResp->res);
11841f8c7b5dSJohnathan Mantey             return;
11851f8c7b5dSJohnathan Mantey         }
118682695a5bSJiaqing Zhao         nextNTP = *v4dhcpParms.useNtpServers;
11871f8c7b5dSJohnathan Mantey     }
118882695a5bSJiaqing Zhao     else if (v4dhcpParms.useNtpServers)
11891f8c7b5dSJohnathan Mantey     {
119082695a5bSJiaqing Zhao         nextNTP = *v4dhcpParms.useNtpServers;
11911f8c7b5dSJohnathan Mantey     }
119282695a5bSJiaqing Zhao     else if (v6dhcpParms.useNtpServers)
11931f8c7b5dSJohnathan Mantey     {
119482695a5bSJiaqing Zhao         nextNTP = *v6dhcpParms.useNtpServers;
11951f8c7b5dSJohnathan Mantey     }
11961f8c7b5dSJohnathan Mantey     else
11971f8c7b5dSJohnathan Mantey     {
119882695a5bSJiaqing Zhao         nextNTP = ethData.ntpEnabled;
11991f8c7b5dSJohnathan Mantey     }
12001f8c7b5dSJohnathan Mantey 
12011f8c7b5dSJohnathan Mantey     bool nextUseDomain{};
120282695a5bSJiaqing Zhao     if (v4dhcpParms.useDomainName && v6dhcpParms.useDomainName)
12031f8c7b5dSJohnathan Mantey     {
120482695a5bSJiaqing Zhao         if (*v4dhcpParms.useDomainName != *v6dhcpParms.useDomainName)
12051f8c7b5dSJohnathan Mantey         {
12061f8c7b5dSJohnathan Mantey             messages::generalError(asyncResp->res);
12071f8c7b5dSJohnathan Mantey             return;
12081f8c7b5dSJohnathan Mantey         }
120982695a5bSJiaqing Zhao         nextUseDomain = *v4dhcpParms.useDomainName;
12101f8c7b5dSJohnathan Mantey     }
121182695a5bSJiaqing Zhao     else if (v4dhcpParms.useDomainName)
12121f8c7b5dSJohnathan Mantey     {
121382695a5bSJiaqing Zhao         nextUseDomain = *v4dhcpParms.useDomainName;
12141f8c7b5dSJohnathan Mantey     }
121582695a5bSJiaqing Zhao     else if (v6dhcpParms.useDomainName)
12161f8c7b5dSJohnathan Mantey     {
121782695a5bSJiaqing Zhao         nextUseDomain = *v6dhcpParms.useDomainName;
12181f8c7b5dSJohnathan Mantey     }
12191f8c7b5dSJohnathan Mantey     else
12201f8c7b5dSJohnathan Mantey     {
122182695a5bSJiaqing Zhao         nextUseDomain = ethData.hostNameEnabled;
12221f8c7b5dSJohnathan Mantey     }
12231f8c7b5dSJohnathan Mantey 
122462598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
12251f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
12261f8c7b5dSJohnathan Mantey                    asyncResp);
122762598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
12281f8c7b5dSJohnathan Mantey     setDHCPv4Config("DNSEnabled", nextDNS, asyncResp);
122962598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
12301f8c7b5dSJohnathan Mantey     setDHCPv4Config("NTPEnabled", nextNTP, asyncResp);
123162598e31SEd Tanous     BMCWEB_LOG_DEBUG("set HostNameEnabled...");
12321f8c7b5dSJohnathan Mantey     setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp);
1233da131a9aSJennifer Lee }
123401784826SJohnathan Mantey 
123577179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
123677179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
123777179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
123801784826SJohnathan Mantey {
123917a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
124017a897dfSManojkiran Eda         return value.origin == "Static";
124117a897dfSManojkiran Eda     });
124201784826SJohnathan Mantey }
124301784826SJohnathan Mantey 
124477179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
124577179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
124677179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
124701784826SJohnathan Mantey {
124817a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
124917a897dfSManojkiran Eda         return value.origin == "Static";
125017a897dfSManojkiran Eda     });
125101784826SJohnathan Mantey }
125201784826SJohnathan Mantey 
125377179532SEd Tanous inline void
1254ddd70dcaSEd Tanous     handleIPv4StaticPatch(const std::string& ifaceId,
1255ddd70dcaSEd Tanous                           nlohmann::json::array_t& input,
125677179532SEd Tanous                           const std::vector<IPv4AddressData>& ipv4Data,
12578d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12581abe55efSEd Tanous {
1259ddd70dcaSEd Tanous     if (input.empty())
1260f476acbfSRatan Gupta     {
12612e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1262d1d50814SRavi Teja                                          "IPv4StaticAddresses");
1263f476acbfSRatan Gupta         return;
1264f476acbfSRatan Gupta     }
1265f476acbfSRatan Gupta 
1266271584abSEd Tanous     unsigned entryIdx = 1;
126701784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
126801784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
126901784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
127001784826SJohnathan Mantey     // into the NIC.
127177179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
12722c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
127301784826SJohnathan Mantey 
1274537174c4SEd Tanous     for (nlohmann::json& thisJson : input)
12751abe55efSEd Tanous     {
127689492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
127789492a15SPatrick Williams                                  std::to_string(entryIdx);
1278179db1d7SKowalski, Kamil 
127901784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1280f476acbfSRatan Gupta         {
1281537174c4SEd Tanous             std::optional<std::string> address;
1282537174c4SEd Tanous             std::optional<std::string> subnetMask;
1283537174c4SEd Tanous             std::optional<std::string> gateway;
1284537174c4SEd Tanous 
1285537174c4SEd Tanous             if (!json_util::readJson(thisJson, asyncResp->res, "Address",
12867e27d832SJohnathan Mantey                                      address, "SubnetMask", subnetMask,
12877e27d832SJohnathan Mantey                                      "Gateway", gateway))
1288537174c4SEd Tanous             {
1289f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
129071f52d96SEd Tanous                                                    pathString);
1291537174c4SEd Tanous                 return;
1292179db1d7SKowalski, Kamil             }
1293179db1d7SKowalski, Kamil 
129401784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
129501784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
129601784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
129701784826SJohnathan Mantey             // current request.
1298537174c4SEd Tanous             if (address)
12991abe55efSEd Tanous             {
1300*e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
130101784826SJohnathan Mantey                 {
1302bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1303bf648f77SEd Tanous                                                        pathString + "/Address");
1304*e01d0c36SEd Tanous                     return;
130501784826SJohnathan Mantey                 }
130601784826SJohnathan Mantey             }
130785ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
130801784826SJohnathan Mantey             {
1309*e01d0c36SEd Tanous                 address = (nicIpEntry->address);
131001784826SJohnathan Mantey             }
131101784826SJohnathan Mantey             else
131201784826SJohnathan Mantey             {
131301784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
131401784826SJohnathan Mantey                                           pathString + "/Address");
1315*e01d0c36SEd Tanous                 return;
13164a0cb85cSEd Tanous             }
13174a0cb85cSEd Tanous 
1318*e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1319537174c4SEd Tanous             if (subnetMask)
13204a0cb85cSEd Tanous             {
1321033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1322033f1e4dSEd Tanous                                                          &prefixLength))
13234a0cb85cSEd Tanous                 {
1324f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1325537174c4SEd Tanous                         asyncResp->res, *subnetMask,
13264a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1327*e01d0c36SEd Tanous                     return;
13284a0cb85cSEd Tanous                 }
13294a0cb85cSEd Tanous             }
133085ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
13314a0cb85cSEd Tanous             {
1332033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
133301784826SJohnathan Mantey                                                          &prefixLength))
13344a0cb85cSEd Tanous                 {
133501784826SJohnathan Mantey                     messages::propertyValueFormatError(
133685ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
133701784826SJohnathan Mantey                         pathString + "/SubnetMask");
1338*e01d0c36SEd Tanous                     return;
13394a0cb85cSEd Tanous                 }
13404a0cb85cSEd Tanous             }
13411abe55efSEd Tanous             else
13421abe55efSEd Tanous             {
134301784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
134401784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1345*e01d0c36SEd Tanous                 return;
134601784826SJohnathan Mantey             }
134701784826SJohnathan Mantey 
134801784826SJohnathan Mantey             if (gateway)
134901784826SJohnathan Mantey             {
1350*e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
135101784826SJohnathan Mantey                 {
1352bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1353bf648f77SEd Tanous                                                        pathString + "/Gateway");
1354*e01d0c36SEd Tanous                     return;
135501784826SJohnathan Mantey                 }
135601784826SJohnathan Mantey             }
135785ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
135801784826SJohnathan Mantey             {
1359*e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
136001784826SJohnathan Mantey             }
136101784826SJohnathan Mantey             else
13621abe55efSEd Tanous             {
1363a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
13644a0cb85cSEd Tanous                                           pathString + "/Gateway");
136501784826SJohnathan Mantey                 return;
13664a0cb85cSEd Tanous             }
13674a0cb85cSEd Tanous 
136885ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
13691abe55efSEd Tanous             {
13709c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
1371*e01d0c36SEd Tanous                                          nicIpEntry->id, prefixLength, *gateway,
1372*e01d0c36SEd Tanous                                          *address, asyncResp);
137389492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
137489492a15SPatrick Williams                                                   ipv4Data.cend());
1375588c3f0dSKowalski, Kamil             }
137601784826SJohnathan Mantey             else
137701784826SJohnathan Mantey             {
1378cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1379cb13a392SEd Tanous                            asyncResp);
13804a0cb85cSEd Tanous             }
13814a0cb85cSEd Tanous             entryIdx++;
13824a0cb85cSEd Tanous         }
138301784826SJohnathan Mantey         else
138401784826SJohnathan Mantey         {
138585ffe86aSJiaqing Zhao             if (nicIpEntry == ipv4Data.cend())
138601784826SJohnathan Mantey             {
138701784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
138801784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
138901784826SJohnathan Mantey                 // in error, so bail out.
139001784826SJohnathan Mantey                 if (thisJson.is_null())
139101784826SJohnathan Mantey                 {
139201784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
139301784826SJohnathan Mantey                     return;
139401784826SJohnathan Mantey                 }
1395f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
139671f52d96SEd Tanous                                                    pathString);
139701784826SJohnathan Mantey                 return;
139801784826SJohnathan Mantey             }
139901784826SJohnathan Mantey 
140001784826SJohnathan Mantey             if (thisJson.is_null())
140101784826SJohnathan Mantey             {
14029c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
140301784826SJohnathan Mantey             }
140485ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
140501784826SJohnathan Mantey             {
140689492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
140789492a15SPatrick Williams                                                   ipv4Data.cend());
140801784826SJohnathan Mantey             }
140901784826SJohnathan Mantey             entryIdx++;
141001784826SJohnathan Mantey         }
141101784826SJohnathan Mantey     }
14124a0cb85cSEd Tanous }
14134a0cb85cSEd Tanous 
14144f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1415f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1416f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
14178d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1418f85837bfSRAJESWARAN THILLAIGOVINDAN {
14199ae226faSGeorge Liu     sdbusplus::asio::setProperty(
14209ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
14219ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
14229ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
14239ae226faSGeorge Liu         updatedStaticNameServers,
14245e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1425f85837bfSRAJESWARAN THILLAIGOVINDAN         if (ec)
1426f85837bfSRAJESWARAN THILLAIGOVINDAN         {
1427f85837bfSRAJESWARAN THILLAIGOVINDAN             messages::internalError(asyncResp->res);
1428f85837bfSRAJESWARAN THILLAIGOVINDAN             return;
1429f85837bfSRAJESWARAN THILLAIGOVINDAN         }
14309ae226faSGeorge Liu         });
1431f85837bfSRAJESWARAN THILLAIGOVINDAN }
1432f85837bfSRAJESWARAN THILLAIGOVINDAN 
14334f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
1434ddd70dcaSEd Tanous     const std::string& ifaceId, const nlohmann::json::array_t& input,
143577179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
14368d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1437e48c0fc5SRavi Teja {
1438ddd70dcaSEd Tanous     if (input.empty())
1439e48c0fc5SRavi Teja     {
14402e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1441e48c0fc5SRavi Teja                                          "IPv6StaticAddresses");
1442e48c0fc5SRavi Teja         return;
1443e48c0fc5SRavi Teja     }
1444271584abSEd Tanous     size_t entryIdx = 1;
144577179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
14462c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1447f23b7296SEd Tanous     for (const nlohmann::json& thisJson : input)
1448e48c0fc5SRavi Teja     {
144989492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
145089492a15SPatrick Williams                                  std::to_string(entryIdx);
1451e48c0fc5SRavi Teja 
145201784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1453e48c0fc5SRavi Teja         {
1454e48c0fc5SRavi Teja             std::optional<std::string> address;
1455e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
1456f23b7296SEd Tanous             nlohmann::json thisJsonCopy = thisJson;
1457bf648f77SEd Tanous             if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1458bf648f77SEd Tanous                                      address, "PrefixLength", prefixLength))
1459e48c0fc5SRavi Teja             {
1460f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
146171f52d96SEd Tanous                                                    pathString);
1462e48c0fc5SRavi Teja                 return;
1463e48c0fc5SRavi Teja             }
1464e48c0fc5SRavi Teja 
1465543f4400SEd Tanous             const std::string* addr = nullptr;
1466543f4400SEd Tanous             uint8_t prefix = 0;
146701784826SJohnathan Mantey 
146801784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
146901784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
147001784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
147101784826SJohnathan Mantey             // current request.
1472e48c0fc5SRavi Teja             if (address)
1473e48c0fc5SRavi Teja             {
147401784826SJohnathan Mantey                 addr = &(*address);
1475e48c0fc5SRavi Teja             }
147685ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
147701784826SJohnathan Mantey             {
147885ffe86aSJiaqing Zhao                 addr = &(nicIpEntry->address);
147901784826SJohnathan Mantey             }
148001784826SJohnathan Mantey             else
148101784826SJohnathan Mantey             {
148201784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
148301784826SJohnathan Mantey                                           pathString + "/Address");
148401784826SJohnathan Mantey                 return;
1485e48c0fc5SRavi Teja             }
1486e48c0fc5SRavi Teja 
1487e48c0fc5SRavi Teja             if (prefixLength)
1488e48c0fc5SRavi Teja             {
148901784826SJohnathan Mantey                 prefix = *prefixLength;
149001784826SJohnathan Mantey             }
149185ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
1492e48c0fc5SRavi Teja             {
149385ffe86aSJiaqing Zhao                 prefix = nicIpEntry->prefixLength;
1494e48c0fc5SRavi Teja             }
1495e48c0fc5SRavi Teja             else
1496e48c0fc5SRavi Teja             {
1497e48c0fc5SRavi Teja                 messages::propertyMissing(asyncResp->res,
1498e48c0fc5SRavi Teja                                           pathString + "/PrefixLength");
149901784826SJohnathan Mantey                 return;
1500e48c0fc5SRavi Teja             }
1501e48c0fc5SRavi Teja 
150285ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1503e48c0fc5SRavi Teja             {
15049c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
15059c5e585cSRavi Teja                                          nicIpEntry->id, prefix, "", *addr,
1506e48c0fc5SRavi Teja                                          asyncResp);
150789492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
150889492a15SPatrick Williams                                                   ipv6Data.cend());
150901784826SJohnathan Mantey             }
151001784826SJohnathan Mantey             else
151101784826SJohnathan Mantey             {
151201784826SJohnathan Mantey                 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1513e48c0fc5SRavi Teja             }
1514e48c0fc5SRavi Teja             entryIdx++;
1515e48c0fc5SRavi Teja         }
151601784826SJohnathan Mantey         else
151701784826SJohnathan Mantey         {
151885ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
151901784826SJohnathan Mantey             {
152001784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
152101784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
152201784826SJohnathan Mantey                 // in error, so bail out.
152301784826SJohnathan Mantey                 if (thisJson.is_null())
152401784826SJohnathan Mantey                 {
152501784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
152601784826SJohnathan Mantey                     return;
152701784826SJohnathan Mantey                 }
1528f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
152971f52d96SEd Tanous                                                    pathString);
153001784826SJohnathan Mantey                 return;
153101784826SJohnathan Mantey             }
153201784826SJohnathan Mantey 
153301784826SJohnathan Mantey             if (thisJson.is_null())
153401784826SJohnathan Mantey             {
15359c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
153601784826SJohnathan Mantey             }
153785ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
153801784826SJohnathan Mantey             {
153989492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
154089492a15SPatrick Williams                                                   ipv6Data.cend());
154101784826SJohnathan Mantey             }
154201784826SJohnathan Mantey             entryIdx++;
154301784826SJohnathan Mantey         }
154401784826SJohnathan Mantey     }
1545e48c0fc5SRavi Teja }
1546e48c0fc5SRavi Teja 
15477857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
15487857cb8dSJiaqing Zhao {
15497857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
15507857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
15517857cb8dSJiaqing Zhao }
15527857cb8dSJiaqing Zhao 
155377179532SEd Tanous inline void
155477179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
155577179532SEd Tanous                        const std::string& ifaceId,
155677179532SEd Tanous                        const EthernetInterfaceData& ethData,
155777179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
155877179532SEd Tanous                        const std::vector<IPv6AddressData>& ipv6Data)
15594a0cb85cSEd Tanous {
15602c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
156181ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1562ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1563ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
15642c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1565eeedda23SJohnathan Mantey 
156613451e39SWilly Tu     if constexpr (bmcwebEnableHealthPopulate)
156713451e39SWilly Tu     {
156813451e39SWilly Tu         constexpr std::array<std::string_view, 1> inventoryForEthernet = {
156913451e39SWilly Tu             "xyz.openbmc_project.Inventory.Item.Ethernet"};
1570eeedda23SJohnathan Mantey         auto health = std::make_shared<HealthPopulate>(asyncResp);
15717a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
15727a1dbc48SGeorge Liu             "/", 0, inventoryForEthernet,
15737a1dbc48SGeorge Liu             [health](const boost::system::error_code& ec,
1574b9d36b47SEd Tanous                      const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1575eeedda23SJohnathan Mantey             if (ec)
1576029573d4SEd Tanous             {
1577eeedda23SJohnathan Mantey                 return;
1578eeedda23SJohnathan Mantey             }
1579eeedda23SJohnathan Mantey 
1580914e2d5dSEd Tanous             health->inventory = resp;
15817a1dbc48SGeorge Liu             });
1582eeedda23SJohnathan Mantey 
1583eeedda23SJohnathan Mantey         health->populate();
158413451e39SWilly Tu     }
1585eeedda23SJohnathan Mantey 
1586eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1587eeedda23SJohnathan Mantey     {
15880ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
15892c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1590029573d4SEd Tanous     }
1591029573d4SEd Tanous     else
1592029573d4SEd Tanous     {
15932c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
15942c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1595029573d4SEd Tanous     }
1596aa05fb27SJohnathan Mantey 
15972c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
159835fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
159982695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
16002c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
160182695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
160282695a5bSJiaqing Zhao     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpEnabled;
160382695a5bSJiaqing Zhao     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsEnabled;
160482695a5bSJiaqing Zhao     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNameEnabled;
16051f8c7b5dSJohnathan Mantey 
16062c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1607b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
16081f8c7b5dSJohnathan Mantey                                                                : "Disabled";
160982695a5bSJiaqing Zhao     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpEnabled;
161082695a5bSJiaqing Zhao     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsEnabled;
161182695a5bSJiaqing Zhao     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNameEnabled;
1612b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1613b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
16142a133282Smanojkiraneda 
161582695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
16164a0cb85cSEd Tanous     {
161782695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1618ab6554f1SJoshi-Mansi 
1619ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1620ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1621ab6554f1SJoshi-Mansi         // FQDN
162282695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1623d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1624d24bfc7aSJennifer Lee         {
16252c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1626d24bfc7aSJennifer Lee         }
16272c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
16284a0cb85cSEd Tanous     }
16294a0cb85cSEd Tanous 
16307857cb8dSJiaqing Zhao     if (ethData.vlanId)
16317857cb8dSJiaqing Zhao     {
16327857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
16337857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
16347857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
16357857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
16367857cb8dSJiaqing Zhao 
16377857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
16387857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
16397857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
16407857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
16417857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
16427857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
16437857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
16447857cb8dSJiaqing Zhao     }
16457857cb8dSJiaqing Zhao     else
16467857cb8dSJiaqing Zhao     {
16477857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
16487857cb8dSJiaqing Zhao     }
16497857cb8dSJiaqing Zhao 
16502c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
16512c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
16524a0cb85cSEd Tanous 
16532c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
16542c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
16552c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
16562c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
16579eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
16584a0cb85cSEd Tanous     {
16592c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1660fa5053a6SGunnar Mills         if (gatewayStr.empty())
1661fa5053a6SGunnar Mills         {
1662fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1663fa5053a6SGunnar Mills         }
16641476687dSEd Tanous         nlohmann::json::object_t ipv4;
16651476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
16661476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
16671476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
16681476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1669fa5053a6SGunnar Mills 
16702c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1671d1d50814SRavi Teja         {
16721476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1673d1d50814SRavi Teja         }
16741476687dSEd Tanous 
1675b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
167601784826SJohnathan Mantey     }
1677d1d50814SRavi Teja 
167882695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
16797ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
16807ea79e5eSRavi Teja     {
16817ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
16827ea79e5eSRavi Teja     }
16837ea79e5eSRavi Teja 
16847ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1685e48c0fc5SRavi Teja 
16862c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
16872c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
16882c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
16892c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
16907f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
16912c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
16927f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
16939eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1694e48c0fc5SRavi Teja     {
16951476687dSEd Tanous         nlohmann::json::object_t ipv6;
16961476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
16971476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
16981476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1699f8361275SSunitha Harish 
1700b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
17012c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1702e48c0fc5SRavi Teja         {
17031476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
17041476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
17051476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1706b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
170701784826SJohnathan Mantey         }
1708e48c0fc5SRavi Teja     }
1709588c3f0dSKowalski, Kamil }
1710588c3f0dSKowalski, Kamil 
1711e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1712e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1713e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1714e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1715e7caf250SJiaqing Zhao {
1716e7caf250SJiaqing Zhao     if (!ec)
1717e7caf250SJiaqing Zhao     {
1718e7caf250SJiaqing Zhao         return;
1719e7caf250SJiaqing Zhao     }
1720e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
1721e7caf250SJiaqing Zhao     if (dbusError == nullptr)
1722e7caf250SJiaqing Zhao     {
1723e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
1724e7caf250SJiaqing Zhao         return;
1725e7caf250SJiaqing Zhao     }
172662598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1727e7caf250SJiaqing Zhao 
1728e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1729e7caf250SJiaqing Zhao         dbusError->name)
1730e7caf250SJiaqing Zhao     {
1731e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1732e7caf250SJiaqing Zhao                                    ifaceId);
1733e7caf250SJiaqing Zhao         return;
1734e7caf250SJiaqing Zhao     }
1735e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1736e7caf250SJiaqing Zhao         dbusError->name)
1737e7caf250SJiaqing Zhao     {
1738e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
1739e7caf250SJiaqing Zhao         return;
1740e7caf250SJiaqing Zhao     }
1741e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
1742e7caf250SJiaqing Zhao }
1743e7caf250SJiaqing Zhao 
1744b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1745b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
1746b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
1747b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
1748b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
1749b5ca3fdcSJiaqing Zhao 
1750b5ca3fdcSJiaqing Zhao )
1751b5ca3fdcSJiaqing Zhao {
1752b5ca3fdcSJiaqing Zhao     if (ec)
1753b5ca3fdcSJiaqing Zhao     {
1754b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
1755b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
1756b5ca3fdcSJiaqing Zhao         {
1757b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
1758b5ca3fdcSJiaqing Zhao             return;
1759b5ca3fdcSJiaqing Zhao         }
176062598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1761b5ca3fdcSJiaqing Zhao 
1762b5ca3fdcSJiaqing Zhao         if (std::string_view(
1763b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1764b5ca3fdcSJiaqing Zhao             dbusError->name)
1765b5ca3fdcSJiaqing Zhao         {
1766b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1767b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1768b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1769b5ca3fdcSJiaqing Zhao             return;
1770b5ca3fdcSJiaqing Zhao         }
1771b5ca3fdcSJiaqing Zhao         if (std::string_view(
1772b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1773b5ca3fdcSJiaqing Zhao             dbusError->name)
1774b5ca3fdcSJiaqing Zhao         {
1775b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1776b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
1777b5ca3fdcSJiaqing Zhao             return;
1778b5ca3fdcSJiaqing Zhao         }
1779b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
1780b5ca3fdcSJiaqing Zhao         return;
1781b5ca3fdcSJiaqing Zhao     }
1782b5ca3fdcSJiaqing Zhao 
1783b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
1784b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1785b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1786b5ca3fdcSJiaqing Zhao }
1787b5ca3fdcSJiaqing Zhao 
1788bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
1789bf648f77SEd Tanous {
1790bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1791ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
17921476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
17931476687dSEd Tanous             [&app](const crow::Request& req,
17941476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
17953ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
179645ca1b86SEd Tanous         {
179745ca1b86SEd Tanous             return;
179845ca1b86SEd Tanous         }
179945ca1b86SEd Tanous 
1800bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
1801bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1802bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
1803bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
1804bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
1805bf648f77SEd Tanous             "Ethernet Network Interface Collection";
1806bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
1807bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
1808bf648f77SEd Tanous 
1809bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
1810bf648f77SEd Tanous         // preparation
1811002d39b4SEd Tanous         getEthernetIfaceList(
181277179532SEd Tanous             [asyncResp](const bool& success,
181377179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
1814bf648f77SEd Tanous             if (!success)
18151abe55efSEd Tanous             {
1816f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
18179391bb9cSRapkiewicz, Pawel                 return;
18189391bb9cSRapkiewicz, Pawel             }
18199391bb9cSRapkiewicz, Pawel 
1820002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1821bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
1822bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
1823bf648f77SEd Tanous             {
18241476687dSEd Tanous                 nlohmann::json::object_t iface;
1825ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
1826ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1827ef4c65b7SEd Tanous                     ifaceItem);
18287857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
1829bf648f77SEd Tanous             }
1830bf648f77SEd Tanous 
1831002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1832bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
1833bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1834bf648f77SEd Tanous         });
1835bf648f77SEd Tanous         });
1836bf648f77SEd Tanous 
1837b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1838b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
1839b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
1840b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
1841b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1842b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1843b5ca3fdcSJiaqing Zhao         {
1844b5ca3fdcSJiaqing Zhao             return;
1845b5ca3fdcSJiaqing Zhao         }
1846b5ca3fdcSJiaqing Zhao 
1847b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
1848b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
1849b5ca3fdcSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
1850b5ca3fdcSJiaqing Zhao 
1851b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1852b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
1853b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
1854b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
1855b5ca3fdcSJiaqing Zhao         {
1856b5ca3fdcSJiaqing Zhao             return;
1857b5ca3fdcSJiaqing Zhao         }
1858b5ca3fdcSJiaqing Zhao 
1859b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
1860b5ca3fdcSJiaqing Zhao         {
1861b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
1862b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
1863b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
1864b5ca3fdcSJiaqing Zhao             return;
1865b5ca3fdcSJiaqing Zhao         }
1866b5ca3fdcSJiaqing Zhao 
1867b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
1868b5ca3fdcSJiaqing Zhao         if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1869b5ca3fdcSJiaqing Zhao                                  "@odata.id", parentInterfaceUri))
1870b5ca3fdcSJiaqing Zhao         {
1871b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
1872b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
1873b5ca3fdcSJiaqing Zhao             return;
1874b5ca3fdcSJiaqing Zhao         }
187562598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
1876b5ca3fdcSJiaqing Zhao 
1877b5ca3fdcSJiaqing Zhao         boost::urls::result<boost::urls::url_view> parsedUri =
1878b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
1879b5ca3fdcSJiaqing Zhao         if (!parsedUri)
1880b5ca3fdcSJiaqing Zhao         {
1881b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
1882b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1883b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1884b5ca3fdcSJiaqing Zhao             return;
1885b5ca3fdcSJiaqing Zhao         }
1886b5ca3fdcSJiaqing Zhao 
1887b5ca3fdcSJiaqing Zhao         std::string parentInterface;
1888b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
1889b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
1890b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
1891b5ca3fdcSJiaqing Zhao         {
1892b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1893b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1894b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1895b5ca3fdcSJiaqing Zhao             return;
1896b5ca3fdcSJiaqing Zhao         }
1897b5ca3fdcSJiaqing Zhao 
1898b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
1899b5ca3fdcSJiaqing Zhao         {
1900b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
1901b5ca3fdcSJiaqing Zhao             // create
1902b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1903b5ca3fdcSJiaqing Zhao                                              "false");
1904b5ca3fdcSJiaqing Zhao             return;
1905b5ca3fdcSJiaqing Zhao         }
1906b5ca3fdcSJiaqing Zhao 
1907b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
1908b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
1909b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
1910b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
1911b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
1912b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
1913b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1914b5ca3fdcSJiaqing Zhao                             m);
1915b5ca3fdcSJiaqing Zhao             },
1916b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1917b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1918b5ca3fdcSJiaqing Zhao             vlanId);
1919b5ca3fdcSJiaqing Zhao         });
1920b5ca3fdcSJiaqing Zhao 
1921bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
1922ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
1923bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
192445ca1b86SEd Tanous             [&app](const crow::Request& req,
1925bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1926bf648f77SEd Tanous                    const std::string& ifaceId) {
19273ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
192845ca1b86SEd Tanous         {
192945ca1b86SEd Tanous             return;
193045ca1b86SEd Tanous         }
19314a0cb85cSEd Tanous         getEthernetIfaceData(
1932bf648f77SEd Tanous             ifaceId,
193377179532SEd Tanous             [asyncResp, ifaceId](const bool& success,
193477179532SEd Tanous                                  const EthernetInterfaceData& ethData,
193577179532SEd Tanous                                  const std::vector<IPv4AddressData>& ipv4Data,
193677179532SEd Tanous                                  const std::vector<IPv6AddressData>& ipv6Data) {
19374a0cb85cSEd Tanous             if (!success)
19381abe55efSEd Tanous             {
1939bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
1940bf648f77SEd Tanous                 // existing object, and other errors
1941002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1942002d39b4SEd Tanous                                            ifaceId);
19434a0cb85cSEd Tanous                 return;
19449391bb9cSRapkiewicz, Pawel             }
19454c9afe43SEd Tanous 
19460f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
194793bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
1948002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
19490f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
19500f74e643SEd Tanous                 "Management Network Interface";
19510f74e643SEd Tanous 
1952002d39b4SEd Tanous             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
19539391bb9cSRapkiewicz, Pawel             });
1954bf648f77SEd Tanous         });
19559391bb9cSRapkiewicz, Pawel 
1956bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
1957ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
1958bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
195945ca1b86SEd Tanous             [&app](const crow::Request& req,
1960bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1961bf648f77SEd Tanous                    const std::string& ifaceId) {
19623ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
196345ca1b86SEd Tanous         {
196445ca1b86SEd Tanous             return;
196545ca1b86SEd Tanous         }
1966bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
1967ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
1968d577665bSRatan Gupta         std::optional<std::string> macAddress;
19699a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
1970ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
1971ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
1972f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
1973da131a9aSJennifer Lee         std::optional<nlohmann::json> dhcpv4;
19741f8c7b5dSJohnathan Mantey         std::optional<nlohmann::json> dhcpv6;
1975b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
1976eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
197735fb5311STejas Patil         std::optional<size_t> mtuSize;
19781f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
19791f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
1980b10d8db0SRavi Teja         // clang-format off
198115ed6780SWilly Tu         if (!json_util::readJsonPatch(
1982b10d8db0SRavi Teja                 req, asyncResp->res,
1983b10d8db0SRavi Teja                 "DHCPv4", dhcpv4,
1984b10d8db0SRavi Teja                 "DHCPv6", dhcpv6,
1985b10d8db0SRavi Teja                 "FQDN", fqdn,
1986b10d8db0SRavi Teja                 "HostName", hostname,
1987b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
1988b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
1989b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
1990b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
1991b10d8db0SRavi Teja                 "MACAddress", macAddress,
1992b10d8db0SRavi Teja                 "MTUSize", mtuSize,
1993b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
1994b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
1995b10d8db0SRavi Teja                 )
1996b10d8db0SRavi Teja             )
19971abe55efSEd Tanous         {
1998588c3f0dSKowalski, Kamil             return;
1999588c3f0dSKowalski, Kamil         }
2000b10d8db0SRavi Teja         //clang-format on
2001da131a9aSJennifer Lee         if (dhcpv4)
2002da131a9aSJennifer Lee         {
2003002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
20041f8c7b5dSJohnathan Mantey                                      v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
200582695a5bSJiaqing Zhao                                      v4dhcpParms.useDnsServers, "UseNTPServers",
200682695a5bSJiaqing Zhao                                      v4dhcpParms.useNtpServers, "UseDomainName",
200782695a5bSJiaqing Zhao                                      v4dhcpParms.useDomainName))
20081f8c7b5dSJohnathan Mantey             {
20091f8c7b5dSJohnathan Mantey                 return;
20101f8c7b5dSJohnathan Mantey             }
20111f8c7b5dSJohnathan Mantey         }
20121f8c7b5dSJohnathan Mantey 
20131f8c7b5dSJohnathan Mantey         if (dhcpv6)
20141f8c7b5dSJohnathan Mantey         {
2015002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2016002d39b4SEd Tanous                                      v6dhcpParms.dhcpv6OperatingMode,
2017002d39b4SEd Tanous                                      "UseDNSServers", v6dhcpParms.useDnsServers,
2018002d39b4SEd Tanous                                      "UseNTPServers", v6dhcpParms.useNtpServers,
2019002d39b4SEd Tanous                                      "UseDomainName",
202082695a5bSJiaqing Zhao                                      v6dhcpParms.useDomainName))
20211f8c7b5dSJohnathan Mantey             {
20221f8c7b5dSJohnathan Mantey                 return;
20231f8c7b5dSJohnathan Mantey             }
2024da131a9aSJennifer Lee         }
2025da131a9aSJennifer Lee 
2026bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2027bf648f77SEd Tanous         // for JSON preparation
20284a0cb85cSEd Tanous         getEthernetIfaceData(
20292c70f800SEd Tanous             ifaceId,
2030bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2031ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2032d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
20339a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2034e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
20351f8c7b5dSJohnathan Mantey              staticNameServers = std::move(staticNameServers),
2036bc20089aSEd Tanous              dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
2037b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2038f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2039002d39b4SEd Tanous                 const bool& success, const EthernetInterfaceData& ethData,
204077179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
204177179532SEd Tanous                 const std::vector<IPv6AddressData>& ipv6Data) {
20421abe55efSEd Tanous             if (!success)
20431abe55efSEd Tanous             {
2044588c3f0dSKowalski, Kamil                 // ... otherwise return error
2045bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2046bf648f77SEd Tanous                 // existing object, and other errors
2047002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2048002d39b4SEd Tanous                                            ifaceId);
2049588c3f0dSKowalski, Kamil                 return;
2050588c3f0dSKowalski, Kamil             }
2051588c3f0dSKowalski, Kamil 
20521f8c7b5dSJohnathan Mantey             if (dhcpv4 || dhcpv6)
20531f8c7b5dSJohnathan Mantey             {
2054002d39b4SEd Tanous                 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2055002d39b4SEd Tanous                                 asyncResp);
20561f8c7b5dSJohnathan Mantey             }
20571f8c7b5dSJohnathan Mantey 
20580627a2c7SEd Tanous             if (hostname)
20591abe55efSEd Tanous             {
20600627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
20611abe55efSEd Tanous             }
20620627a2c7SEd Tanous 
2063b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2064b10d8db0SRavi Teja             {
2065b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2066b10d8db0SRavi Teja                                            asyncResp);
2067b10d8db0SRavi Teja             }
2068b10d8db0SRavi Teja 
2069ab6554f1SJoshi-Mansi             if (fqdn)
2070ab6554f1SJoshi-Mansi             {
20712c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2072ab6554f1SJoshi-Mansi             }
2073ab6554f1SJoshi-Mansi 
2074d577665bSRatan Gupta             if (macAddress)
2075d577665bSRatan Gupta             {
2076002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2077d577665bSRatan Gupta             }
2078d577665bSRatan Gupta 
2079d1d50814SRavi Teja             if (ipv4StaticAddresses)
2080d1d50814SRavi Teja             {
2081bf648f77SEd Tanous                 // TODO(ed) for some reason the capture of
2082bf648f77SEd Tanous                 // ipv4Addresses above is returning a const value,
2083bf648f77SEd Tanous                 // not a non-const value. This doesn't really work
2084bf648f77SEd Tanous                 // for us, as we need to be able to efficiently move
2085bf648f77SEd Tanous                 // out the intermedia nlohmann::json objects. This
2086bf648f77SEd Tanous                 // makes a copy of the structure, and operates on
2087bf648f77SEd Tanous                 // that, but could be done more efficiently
2088ddd70dcaSEd Tanous                 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
2089002d39b4SEd Tanous                 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
20901abe55efSEd Tanous             }
20910627a2c7SEd Tanous 
2092f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2093f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2094002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2095002d39b4SEd Tanous                                              asyncResp);
2096f85837bfSRAJESWARAN THILLAIGOVINDAN             }
20979a6fc6feSRavi Teja 
20989a6fc6feSRavi Teja             if (ipv6DefaultGateway)
20999a6fc6feSRavi Teja             {
21009a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
21019a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
21029a6fc6feSRavi Teja             }
2103e48c0fc5SRavi Teja 
2104e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2105e48c0fc5SRavi Teja             {
2106ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2107ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2108e48c0fc5SRavi Teja             }
2109eeedda23SJohnathan Mantey 
2110eeedda23SJohnathan Mantey             if (interfaceEnabled)
2111eeedda23SJohnathan Mantey             {
2112002d39b4SEd Tanous                 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2113002d39b4SEd Tanous                                                  *interfaceEnabled, asyncResp);
2114eeedda23SJohnathan Mantey             }
211535fb5311STejas Patil 
211635fb5311STejas Patil             if (mtuSize)
211735fb5311STejas Patil             {
211835fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
211935fb5311STejas Patil             }
2120588c3f0dSKowalski, Kamil             });
2121bf648f77SEd Tanous         });
2122e7caf250SJiaqing Zhao 
2123e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2124e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2125e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2126e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2127e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2128e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2129e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2130e7caf250SJiaqing Zhao         {
2131e7caf250SJiaqing Zhao             return;
2132e7caf250SJiaqing Zhao         }
2133e7caf250SJiaqing Zhao 
2134e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2135e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2136e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2137e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2138e7caf250SJiaqing Zhao             },
2139e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2140e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2141e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2142e7caf250SJiaqing Zhao         });
21434a0cb85cSEd Tanous }
2144bf648f77SEd Tanous 
21459391bb9cSRapkiewicz, Pawel } // namespace redfish
2146