xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision 5a39f77a17fa28911c87caea1e2903c059e7ec41)
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>
373544d2a7SEd Tanous #include <ranges>
38ab6554f1SJoshi-Mansi #include <regex>
397a1dbc48SGeorge Liu #include <string_view>
4077179532SEd Tanous #include <vector>
419391bb9cSRapkiewicz, Pawel 
421abe55efSEd Tanous namespace redfish
431abe55efSEd Tanous {
449391bb9cSRapkiewicz, Pawel 
454a0cb85cSEd Tanous enum class LinkType
464a0cb85cSEd Tanous {
474a0cb85cSEd Tanous     Local,
484a0cb85cSEd Tanous     Global
494a0cb85cSEd Tanous };
509391bb9cSRapkiewicz, Pawel 
519391bb9cSRapkiewicz, Pawel /**
529391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
539391bb9cSRapkiewicz, Pawel  */
541abe55efSEd Tanous struct IPv4AddressData
551abe55efSEd Tanous {
56179db1d7SKowalski, Kamil     std::string id;
574a0cb85cSEd Tanous     std::string address;
584a0cb85cSEd Tanous     std::string domain;
594a0cb85cSEd Tanous     std::string gateway;
609391bb9cSRapkiewicz, Pawel     std::string netmask;
619391bb9cSRapkiewicz, Pawel     std::string origin;
6277179532SEd Tanous     LinkType linktype{};
6377179532SEd Tanous     bool isActive{};
649391bb9cSRapkiewicz, Pawel };
659391bb9cSRapkiewicz, Pawel 
669391bb9cSRapkiewicz, Pawel /**
67e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
68e48c0fc5SRavi Teja  */
69e48c0fc5SRavi Teja struct IPv6AddressData
70e48c0fc5SRavi Teja {
71e48c0fc5SRavi Teja     std::string id;
72e48c0fc5SRavi Teja     std::string address;
73e48c0fc5SRavi Teja     std::string origin;
7477179532SEd Tanous     uint8_t prefixLength = 0;
75e48c0fc5SRavi Teja };
76e48c0fc5SRavi Teja /**
779391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
789391bb9cSRapkiewicz, Pawel  * available from DBus
799391bb9cSRapkiewicz, Pawel  */
801abe55efSEd Tanous struct EthernetInterfaceData
811abe55efSEd Tanous {
824a0cb85cSEd Tanous     uint32_t speed;
8335fb5311STejas Patil     size_t mtuSize;
8482695a5bSJiaqing Zhao     bool autoNeg;
8582695a5bSJiaqing Zhao     bool dnsEnabled;
8682695a5bSJiaqing Zhao     bool ntpEnabled;
8782695a5bSJiaqing Zhao     bool hostNameEnabled;
88aa05fb27SJohnathan Mantey     bool linkUp;
89eeedda23SJohnathan Mantey     bool nicEnabled;
90b10d8db0SRavi Teja     bool ipv6AcceptRa;
9182695a5bSJiaqing Zhao     std::string dhcpEnabled;
921f8c7b5dSJohnathan Mantey     std::string operatingMode;
9382695a5bSJiaqing Zhao     std::string hostName;
9482695a5bSJiaqing Zhao     std::string defaultGateway;
9582695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
9682695a5bSJiaqing Zhao     std::string macAddress;
9717e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
980f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
990f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
100d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1019391bb9cSRapkiewicz, Pawel };
1029391bb9cSRapkiewicz, Pawel 
1031f8c7b5dSJohnathan Mantey struct DHCPParameters
1041f8c7b5dSJohnathan Mantey {
1051f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
10682695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
10782695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
10882695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1091f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1101f8c7b5dSJohnathan Mantey };
1111f8c7b5dSJohnathan Mantey 
1129391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1139391bb9cSRapkiewicz, Pawel // into full dot notation
1141abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1151abe55efSEd Tanous {
1169391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1179391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1189391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1199391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1209391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1219391bb9cSRapkiewicz, Pawel     return netmask;
1229391bb9cSRapkiewicz, Pawel }
1239391bb9cSRapkiewicz, Pawel 
12482695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1251f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1261f8c7b5dSJohnathan Mantey {
1271f8c7b5dSJohnathan Mantey     if (isIPv4)
1281f8c7b5dSJohnathan Mantey     {
1291f8c7b5dSJohnathan Mantey         return (
1301f8c7b5dSJohnathan Mantey             (inputDHCP ==
1311f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1321f8c7b5dSJohnathan Mantey             (inputDHCP ==
1331f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1341f8c7b5dSJohnathan Mantey     }
1351f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1361f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1371f8c7b5dSJohnathan Mantey             (inputDHCP ==
1381f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1391f8c7b5dSJohnathan Mantey }
1401f8c7b5dSJohnathan Mantey 
1412c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1421f8c7b5dSJohnathan Mantey {
1431f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1441f8c7b5dSJohnathan Mantey     {
1451f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1461f8c7b5dSJohnathan Mantey     }
1473174e4dfSEd Tanous     if (isIPv4)
1481f8c7b5dSJohnathan Mantey     {
1491f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1501f8c7b5dSJohnathan Mantey     }
1513174e4dfSEd Tanous     if (isIPv6)
1521f8c7b5dSJohnathan Mantey     {
1531f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1541f8c7b5dSJohnathan Mantey     }
1551f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1561f8c7b5dSJohnathan Mantey }
1571f8c7b5dSJohnathan Mantey 
1584a0cb85cSEd Tanous inline std::string
1594a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1604a0cb85cSEd Tanous                                         bool isIPv4)
1611abe55efSEd Tanous {
1624a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1631abe55efSEd Tanous     {
1644a0cb85cSEd Tanous         return "Static";
1659391bb9cSRapkiewicz, Pawel     }
1664a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1671abe55efSEd Tanous     {
1684a0cb85cSEd Tanous         if (isIPv4)
1691abe55efSEd Tanous         {
1704a0cb85cSEd Tanous             return "IPv4LinkLocal";
1711abe55efSEd Tanous         }
1724a0cb85cSEd Tanous         return "LinkLocal";
1739391bb9cSRapkiewicz, Pawel     }
1744a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1751abe55efSEd Tanous     {
1764a0cb85cSEd Tanous         if (isIPv4)
1774a0cb85cSEd Tanous         {
1784a0cb85cSEd Tanous             return "DHCP";
1794a0cb85cSEd Tanous         }
1804a0cb85cSEd Tanous         return "DHCPv6";
1814a0cb85cSEd Tanous     }
1824a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
1834a0cb85cSEd Tanous     {
1844a0cb85cSEd Tanous         return "SLAAC";
1854a0cb85cSEd Tanous     }
1864a0cb85cSEd Tanous     return "";
1874a0cb85cSEd Tanous }
1884a0cb85cSEd Tanous 
18902cad96eSEd Tanous inline bool extractEthernetInterfaceData(
19002cad96eSEd Tanous     const std::string& ethifaceId,
19102cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
1924a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
1934a0cb85cSEd Tanous {
1944c9afe43SEd Tanous     bool idFound = false;
19502cad96eSEd Tanous     for (const auto& objpath : dbusData)
1964a0cb85cSEd Tanous     {
19702cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
1984a0cb85cSEd Tanous         {
19981ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
200029573d4SEd Tanous             {
2014c9afe43SEd Tanous                 idFound = true;
2024a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2034a0cb85cSEd Tanous                 {
2044a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2054a0cb85cSEd Tanous                     {
2064a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2074a0cb85cSEd Tanous                         {
2084a0cb85cSEd Tanous                             const std::string* mac =
209abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2104a0cb85cSEd Tanous                             if (mac != nullptr)
2114a0cb85cSEd Tanous                             {
21282695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2134a0cb85cSEd Tanous                             }
2144a0cb85cSEd Tanous                         }
2154a0cb85cSEd Tanous                     }
2164a0cb85cSEd Tanous                 }
2174a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2184a0cb85cSEd Tanous                 {
2194a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2204a0cb85cSEd Tanous                     {
2214a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2224a0cb85cSEd Tanous                         {
2231b6b96c5SEd Tanous                             const uint32_t* id =
224abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2254a0cb85cSEd Tanous                             if (id != nullptr)
2264a0cb85cSEd Tanous                             {
22717e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2284a0cb85cSEd Tanous                             }
2294a0cb85cSEd Tanous                         }
2304a0cb85cSEd Tanous                     }
2314a0cb85cSEd Tanous                 }
2324a0cb85cSEd Tanous                 else if (ifacePair.first ==
2334a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2344a0cb85cSEd Tanous                 {
2354a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2364a0cb85cSEd Tanous                     {
2374a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2384a0cb85cSEd Tanous                         {
2392c70f800SEd Tanous                             const bool* autoNeg =
240abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2412c70f800SEd Tanous                             if (autoNeg != nullptr)
2424a0cb85cSEd Tanous                             {
24382695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2444a0cb85cSEd Tanous                             }
2454a0cb85cSEd Tanous                         }
2464a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2474a0cb85cSEd Tanous                         {
2484a0cb85cSEd Tanous                             const uint32_t* speed =
249abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2504a0cb85cSEd Tanous                             if (speed != nullptr)
2514a0cb85cSEd Tanous                             {
2524a0cb85cSEd Tanous                                 ethData.speed = *speed;
2534a0cb85cSEd Tanous                             }
2544a0cb85cSEd Tanous                         }
25535fb5311STejas Patil                         else if (propertyPair.first == "MTU")
25635fb5311STejas Patil                         {
25735fb5311STejas Patil                             const uint32_t* mtuSize =
25835fb5311STejas Patil                                 std::get_if<uint32_t>(&propertyPair.second);
25935fb5311STejas Patil                             if (mtuSize != nullptr)
26035fb5311STejas Patil                             {
26135fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
26235fb5311STejas Patil                             }
26335fb5311STejas Patil                         }
264aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
265aa05fb27SJohnathan Mantey                         {
266aa05fb27SJohnathan Mantey                             const bool* linkUp =
267aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
268aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
269aa05fb27SJohnathan Mantey                             {
270aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
271aa05fb27SJohnathan Mantey                             }
272aa05fb27SJohnathan Mantey                         }
273eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
274eeedda23SJohnathan Mantey                         {
275eeedda23SJohnathan Mantey                             const bool* nicEnabled =
276eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
277eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
278eeedda23SJohnathan Mantey                             {
279eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
280eeedda23SJohnathan Mantey                             }
281eeedda23SJohnathan Mantey                         }
282b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
283b10d8db0SRavi Teja                         {
284b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
285b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
286b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
287b10d8db0SRavi Teja                             {
288b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
289b10d8db0SRavi Teja                             }
290b10d8db0SRavi Teja                         }
291f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
292029573d4SEd Tanous                         {
293029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
2948d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
295029573d4SEd Tanous                                     &propertyPair.second);
296029573d4SEd Tanous                             if (nameservers != nullptr)
297029573d4SEd Tanous                             {
298f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
2990f6efdc1Smanojkiran.eda@gmail.com                             }
3000f6efdc1Smanojkiran.eda@gmail.com                         }
3010f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3020f6efdc1Smanojkiran.eda@gmail.com                         {
3030f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3048d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3050f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3060f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3070f6efdc1Smanojkiran.eda@gmail.com                             {
308f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3094a0cb85cSEd Tanous                             }
3104a0cb85cSEd Tanous                         }
3112a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3122a133282Smanojkiraneda                         {
3132c70f800SEd Tanous                             const std::string* dhcpEnabled =
3141f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3152c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3162a133282Smanojkiraneda                             {
31782695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3182a133282Smanojkiraneda                             }
3192a133282Smanojkiraneda                         }
320d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
321d24bfc7aSJennifer Lee                         {
322d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3238d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
324d24bfc7aSJennifer Lee                                     &propertyPair.second);
325d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
326d24bfc7aSJennifer Lee                             {
327f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
328d24bfc7aSJennifer Lee                             }
329d24bfc7aSJennifer Lee                         }
3309010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3319010ec2eSRavi Teja                         {
3329010ec2eSRavi Teja                             const std::string* defaultGateway =
3339010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3349010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3359010ec2eSRavi Teja                             {
3369010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3379010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3389010ec2eSRavi Teja                                 {
33982695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3409010ec2eSRavi Teja                                 }
3419010ec2eSRavi Teja                                 else
3429010ec2eSRavi Teja                                 {
34382695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3449010ec2eSRavi Teja                                 }
3459010ec2eSRavi Teja                             }
3469010ec2eSRavi Teja                         }
3479010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3489010ec2eSRavi Teja                         {
3499010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3509010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3519010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3529010ec2eSRavi Teja                             {
3539010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3549010ec2eSRavi Teja                                     *defaultGateway6;
3559010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3569010ec2eSRavi Teja                                 {
35782695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3589010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3599010ec2eSRavi Teja                                 }
3609010ec2eSRavi Teja                                 else
3619010ec2eSRavi Teja                                 {
36282695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3639010ec2eSRavi Teja                                         defaultGateway6Str;
3649010ec2eSRavi Teja                                 }
3659010ec2eSRavi Teja                             }
3669010ec2eSRavi Teja                         }
367029573d4SEd Tanous                     }
368029573d4SEd Tanous                 }
369029573d4SEd Tanous             }
3701f8c7b5dSJohnathan Mantey 
3711e3f85e6SJian Zhang             if (objpath.first == "/xyz/openbmc_project/network/dhcp")
3721f8c7b5dSJohnathan Mantey             {
3731f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
3741f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
3751f8c7b5dSJohnathan Mantey                 {
3761f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
3771f8c7b5dSJohnathan Mantey                     {
3781f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
3791f8c7b5dSJohnathan Mantey                         {
3802c70f800SEd Tanous                             const bool* dnsEnabled =
3811f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
3822c70f800SEd Tanous                             if (dnsEnabled != nullptr)
3831f8c7b5dSJohnathan Mantey                             {
38482695a5bSJiaqing Zhao                                 ethData.dnsEnabled = *dnsEnabled;
3851f8c7b5dSJohnathan Mantey                             }
3861f8c7b5dSJohnathan Mantey                         }
3871f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
3881f8c7b5dSJohnathan Mantey                         {
3892c70f800SEd Tanous                             const bool* ntpEnabled =
3901f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
3912c70f800SEd Tanous                             if (ntpEnabled != nullptr)
3921f8c7b5dSJohnathan Mantey                             {
39382695a5bSJiaqing Zhao                                 ethData.ntpEnabled = *ntpEnabled;
3941f8c7b5dSJohnathan Mantey                             }
3951f8c7b5dSJohnathan Mantey                         }
3961f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
3971f8c7b5dSJohnathan Mantey                         {
3982c70f800SEd Tanous                             const bool* hostNameEnabled =
3991f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4002c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4011f8c7b5dSJohnathan Mantey                             {
40282695a5bSJiaqing Zhao                                 ethData.hostNameEnabled = *hostNameEnabled;
4031f8c7b5dSJohnathan Mantey                             }
4041f8c7b5dSJohnathan Mantey                         }
4051f8c7b5dSJohnathan Mantey                     }
4061f8c7b5dSJohnathan Mantey                 }
4071f8c7b5dSJohnathan Mantey             }
408029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
409029573d4SEd Tanous             // to check eth number
410029573d4SEd Tanous             if (ifacePair.first ==
4114a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4124a0cb85cSEd Tanous             {
4134a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
4144a0cb85cSEd Tanous                 {
4154a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
4164a0cb85cSEd Tanous                     {
4174a0cb85cSEd Tanous                         const std::string* hostname =
4188d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
4194a0cb85cSEd Tanous                         if (hostname != nullptr)
4204a0cb85cSEd Tanous                         {
42182695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
4224a0cb85cSEd Tanous                         }
4234a0cb85cSEd Tanous                     }
4244a0cb85cSEd Tanous                 }
4254a0cb85cSEd Tanous             }
4264a0cb85cSEd Tanous         }
4274a0cb85cSEd Tanous     }
4284c9afe43SEd Tanous     return idFound;
4294a0cb85cSEd Tanous }
4304a0cb85cSEd Tanous 
431e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
43277179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
433711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
43477179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
435e48c0fc5SRavi Teja {
43689492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
43789492a15SPatrick Williams                                     ethifaceId;
438e48c0fc5SRavi Teja 
439e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
440e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
44181ce609eSEd Tanous     for (const auto& objpath : dbusData)
442e48c0fc5SRavi Teja     {
443e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
444353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
445e48c0fc5SRavi Teja         {
4469eb808c1SEd Tanous             for (const auto& interface : objpath.second)
447e48c0fc5SRavi Teja             {
448e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
449e48c0fc5SRavi Teja                 {
4503544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
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                 {
5423544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
543353163e9STony Lee                                                      [](const auto& property) {
544353163e9STony Lee                         return property.first == "Type";
545353163e9STony Lee                     });
546353163e9STony Lee                     if (type == interface.second.end())
547353163e9STony Lee                     {
548353163e9STony Lee                         continue;
549353163e9STony Lee                     }
550353163e9STony Lee 
551353163e9STony Lee                     const std::string* typeStr =
552353163e9STony Lee                         std::get_if<std::string>(&type->second);
553353163e9STony Lee 
554353163e9STony Lee                     if (typeStr == nullptr ||
555353163e9STony Lee                         (*typeStr !=
556353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
557353163e9STony Lee                     {
558353163e9STony Lee                         continue;
559353163e9STony Lee                     }
560353163e9STony Lee 
5614a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
5624a0cb85cSEd Tanous                     // appropriate
56377179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
5642c70f800SEd Tanous                     ipv4Address.id =
565353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5669eb808c1SEd Tanous                     for (const auto& property : interface.second)
5674a0cb85cSEd Tanous                     {
5684a0cb85cSEd Tanous                         if (property.first == "Address")
5694a0cb85cSEd Tanous                         {
5704a0cb85cSEd Tanous                             const std::string* address =
571abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
5724a0cb85cSEd Tanous                             if (address != nullptr)
5734a0cb85cSEd Tanous                             {
5742c70f800SEd Tanous                                 ipv4Address.address = *address;
5754a0cb85cSEd Tanous                             }
5764a0cb85cSEd Tanous                         }
5774a0cb85cSEd Tanous                         else if (property.first == "Origin")
5784a0cb85cSEd Tanous                         {
5794a0cb85cSEd Tanous                             const std::string* origin =
580abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
5814a0cb85cSEd Tanous                             if (origin != nullptr)
5824a0cb85cSEd Tanous                             {
5832c70f800SEd Tanous                                 ipv4Address.origin =
5844a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
5854a0cb85cSEd Tanous                                                                         true);
5864a0cb85cSEd Tanous                             }
5874a0cb85cSEd Tanous                         }
5884a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
5894a0cb85cSEd Tanous                         {
5904a0cb85cSEd Tanous                             const uint8_t* mask =
591abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
5924a0cb85cSEd Tanous                             if (mask != nullptr)
5934a0cb85cSEd Tanous                             {
5944a0cb85cSEd Tanous                                 // convert it to the string
5952c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
5964a0cb85cSEd Tanous                             }
5974a0cb85cSEd Tanous                         }
598889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
599889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
600889ff694SAsmitha Karunanithi                         {
601889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
602889ff694SAsmitha Karunanithi                         }
6034a0cb85cSEd Tanous                         else
6044a0cb85cSEd Tanous                         {
60562598e31SEd Tanous                             BMCWEB_LOG_ERROR(
60662598e31SEd Tanous                                 "Got extra property: {} on the {} object",
60762598e31SEd Tanous                                 property.first, objpath.first.str);
6084a0cb85cSEd Tanous                         }
6094a0cb85cSEd Tanous                     }
6104a0cb85cSEd Tanous                     // Check if given address is local, or global
6112c70f800SEd Tanous                     ipv4Address.linktype =
61211ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
61318659d10SJohnathan Mantey                             ? LinkType::Local
61418659d10SJohnathan Mantey                             : LinkType::Global;
6154a0cb85cSEd Tanous                 }
6164a0cb85cSEd Tanous             }
6174a0cb85cSEd Tanous         }
6184a0cb85cSEd Tanous     }
6194a0cb85cSEd Tanous }
620588c3f0dSKowalski, Kamil 
621588c3f0dSKowalski, Kamil /**
62201784826SJohnathan Mantey  * @brief Deletes given IPv4 interface
623179db1d7SKowalski, Kamil  *
624179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
625179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
626179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
627179db1d7SKowalski, Kamil  *
628179db1d7SKowalski, Kamil  * @return None
629179db1d7SKowalski, Kamil  */
6309c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
6319c5e585cSRavi Teja                             const std::string& ipHash,
6328d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
6331abe55efSEd Tanous {
63455c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
6355e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
6361abe55efSEd Tanous         if (ec)
6371abe55efSEd Tanous         {
638a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
6391abe55efSEd Tanous         }
640179db1d7SKowalski, Kamil     },
641179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
6429c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
643179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
644179db1d7SKowalski, Kamil }
645179db1d7SKowalski, Kamil 
646244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway(
647244b6d5bSGunnar Mills     const std::string& ifaceId, const std::string& gateway,
648244b6d5bSGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
6499010ec2eSRavi Teja {
6509ae226faSGeorge Liu     sdbusplus::asio::setProperty(
6519ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
6529ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
6539ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
6549ae226faSGeorge Liu         gateway, [asyncResp](const boost::system::error_code& ec) {
6559010ec2eSRavi Teja         if (ec)
6569010ec2eSRavi Teja         {
6579010ec2eSRavi Teja             messages::internalError(asyncResp->res);
6589010ec2eSRavi Teja             return;
6599010ec2eSRavi Teja         }
6609010ec2eSRavi Teja         asyncResp->res.result(boost::beast::http::status::no_content);
6619ae226faSGeorge Liu     });
6629010ec2eSRavi Teja }
663179db1d7SKowalski, Kamil /**
66401784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
665179db1d7SKowalski, Kamil  *
66601784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
66701784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
66801784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
66901784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
670179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
671179db1d7SKowalski, Kamil  *
672179db1d7SKowalski, Kamil  * @return None
673179db1d7SKowalski, Kamil  */
674cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
675cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
6768d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
6771abe55efSEd Tanous {
678*5a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
679*5a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
6801abe55efSEd Tanous         if (ec)
6811abe55efSEd Tanous         {
682a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
6839010ec2eSRavi Teja             return;
684179db1d7SKowalski, Kamil         }
6859010ec2eSRavi Teja         updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
6869010ec2eSRavi Teja     };
6879010ec2eSRavi Teja 
6889010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
6899010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
690179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
691179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
69201784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
693179db1d7SKowalski, Kamil         gateway);
694179db1d7SKowalski, Kamil }
695e48c0fc5SRavi Teja 
696e48c0fc5SRavi Teja /**
69701784826SJohnathan Mantey  * @brief Deletes the IPv6 entry for this interface and creates a replacement
69801784826SJohnathan Mantey  * static IPv6 entry
69901784826SJohnathan Mantey  *
70001784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv6 entry
70101784826SJohnathan Mantey  * @param[in] id           The unique hash entry identifying the DBus entry
70201784826SJohnathan Mantey  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
70301784826SJohnathan Mantey  * @param[in] address      IPv6 address to assign to this interface
70401784826SJohnathan Mantey  * @param[io] asyncResp    Response object that will be returned to client
70501784826SJohnathan Mantey  *
70601784826SJohnathan Mantey  * @return None
70701784826SJohnathan Mantey  */
7089c5e585cSRavi Teja 
7099c5e585cSRavi Teja enum class IpVersion
7109c5e585cSRavi Teja {
7119c5e585cSRavi Teja     IpV4,
7129c5e585cSRavi Teja     IpV6
7139c5e585cSRavi Teja };
7149c5e585cSRavi Teja 
7159c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
7169c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
7178d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
7189c5e585cSRavi Teja     const std::string& gateway,
7198d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
72001784826SJohnathan Mantey {
72101784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
7229c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
7239c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
72401784826SJohnathan Mantey         if (ec)
72501784826SJohnathan Mantey         {
72601784826SJohnathan Mantey             messages::internalError(asyncResp->res);
72701784826SJohnathan Mantey         }
7289c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
7299c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
73001784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
7315e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
73223a21a1cSEd Tanous             if (ec2)
73301784826SJohnathan Mantey             {
73401784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
73501784826SJohnathan Mantey             }
73601784826SJohnathan Mantey         },
73701784826SJohnathan Mantey             "xyz.openbmc_project.Network",
73801784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
7399c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
7409c5e585cSRavi Teja             prefixLength, gateway);
74101784826SJohnathan Mantey     },
74201784826SJohnathan Mantey         "xyz.openbmc_project.Network",
7439c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
74401784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
74501784826SJohnathan Mantey }
74601784826SJohnathan Mantey 
74701784826SJohnathan Mantey /**
748e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
749e48c0fc5SRavi Teja  *
750e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
751e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
752e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
753e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
754e48c0fc5SRavi Teja  *
755e48c0fc5SRavi Teja  * @return None
756e48c0fc5SRavi Teja  */
75701784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
75801784826SJohnathan Mantey                        const std::string& address,
7598d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
760e48c0fc5SRavi Teja {
761*5a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
762*5a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
763e48c0fc5SRavi Teja         if (ec)
764e48c0fc5SRavi Teja         {
765fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
766fc23ef8aSNitin Kumar Kotania             {
767fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
768fc23ef8aSNitin Kumar Kotania                                                    "Address");
769fc23ef8aSNitin Kumar Kotania             }
770fc23ef8aSNitin Kumar Kotania             else
771fc23ef8aSNitin Kumar Kotania             {
772e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
773e48c0fc5SRavi Teja             }
774fc23ef8aSNitin Kumar Kotania         }
775e48c0fc5SRavi Teja     };
776e48c0fc5SRavi Teja     // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
7774e0453b1SGunnar Mills     // does not have associated gateway property
778e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
779e48c0fc5SRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
780e48c0fc5SRavi Teja         "/xyz/openbmc_project/network/" + ifaceId,
781e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
782e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
783e48c0fc5SRavi Teja         "");
784e48c0fc5SRavi Teja }
785e48c0fc5SRavi Teja 
786179db1d7SKowalski, Kamil /**
787179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
788179db1d7SKowalski, Kamil  * Object
789179db1d7SKowalski, Kamil  * from EntityManager Network Manager
7904a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
791179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
792179db1d7SKowalski, Kamil  * into JSON
793179db1d7SKowalski, Kamil  */
794179db1d7SKowalski, Kamil template <typename CallbackFunc>
79581ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
7961abe55efSEd Tanous                           CallbackFunc&& callback)
7971abe55efSEd Tanous {
798f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
799f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
800f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
801f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
802f94c4ecfSEd Tanous          callback{std::forward<CallbackFunc>(callback)}](
8038b24275dSEd Tanous             const boost::system::error_code& ec,
80402cad96eSEd Tanous             const dbus::utility::ManagedObjectType& resp) {
80555c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
80677179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
80777179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
808179db1d7SKowalski, Kamil 
8098b24275dSEd Tanous         if (ec)
8101abe55efSEd Tanous         {
81101784826SJohnathan Mantey             callback(false, ethData, ipv4Data, ipv6Data);
812179db1d7SKowalski, Kamil             return;
813179db1d7SKowalski, Kamil         }
814179db1d7SKowalski, Kamil 
815002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
8164c9afe43SEd Tanous         if (!found)
8174c9afe43SEd Tanous         {
81801784826SJohnathan Mantey             callback(false, ethData, ipv4Data, ipv6Data);
8194c9afe43SEd Tanous             return;
8204c9afe43SEd Tanous         }
8214c9afe43SEd Tanous 
8222c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
823179db1d7SKowalski, Kamil         // Fix global GW
8241abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
8251abe55efSEd Tanous         {
826c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
827c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
8289010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
8291abe55efSEd Tanous             {
83082695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
831179db1d7SKowalski, Kamil             }
832179db1d7SKowalski, Kamil         }
833179db1d7SKowalski, Kamil 
8342c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
8354e0453b1SGunnar Mills         // Finally make a callback with useful data
83601784826SJohnathan Mantey         callback(true, ethData, ipv4Data, ipv6Data);
837f5892d0dSGeorge Liu     });
838271584abSEd Tanous }
839179db1d7SKowalski, Kamil 
840179db1d7SKowalski, Kamil /**
8419391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
8429391bb9cSRapkiewicz, Pawel  * Manager
8431abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
8441abe55efSEd Tanous  * into JSON.
8459391bb9cSRapkiewicz, Pawel  */
8469391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
8471abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
8481abe55efSEd Tanous {
849f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
850f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
851f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
852f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
8538b24275dSEd Tanous             const boost::system::error_code& ec,
854f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
8551abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
8561abe55efSEd Tanous         // ethernet interfaces
85777179532SEd Tanous         std::vector<std::string> ifaceList;
8582c70f800SEd Tanous         ifaceList.reserve(resp.size());
8598b24275dSEd Tanous         if (ec)
8601abe55efSEd Tanous         {
8612c70f800SEd Tanous             callback(false, ifaceList);
8629391bb9cSRapkiewicz, Pawel             return;
8639391bb9cSRapkiewicz, Pawel         }
8649391bb9cSRapkiewicz, Pawel 
8659391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
8664a0cb85cSEd Tanous         for (const auto& objpath : resp)
8671abe55efSEd Tanous         {
8689391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
8694a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
8701abe55efSEd Tanous             {
8711abe55efSEd Tanous                 // If interface is
8724a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
8734a0cb85cSEd Tanous                 // what we're looking for.
8749391bb9cSRapkiewicz, Pawel                 if (interface.first ==
8751abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
8761abe55efSEd Tanous                 {
8772dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
8782dfd18efSEd Tanous                     if (ifaceId.empty())
8791abe55efSEd Tanous                     {
8802dfd18efSEd Tanous                         continue;
8819391bb9cSRapkiewicz, Pawel                     }
8822dfd18efSEd Tanous                     // and put it into output vector.
88377179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
8849391bb9cSRapkiewicz, Pawel                 }
8859391bb9cSRapkiewicz, Pawel             }
8869391bb9cSRapkiewicz, Pawel         }
8872c5875a2SEd Tanous 
8883544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
8892c5875a2SEd Tanous 
890a434f2bdSEd Tanous         // Finally make a callback with useful data
8912c70f800SEd Tanous         callback(true, ifaceList);
892f5892d0dSGeorge Liu     });
893271584abSEd Tanous }
8949391bb9cSRapkiewicz, Pawel 
8954f48d5f6SEd Tanous inline void
8964f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
8978d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
8981abe55efSEd Tanous {
899ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
900ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
901ab6554f1SJoshi-Mansi     {
902ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
903ab6554f1SJoshi-Mansi                                            "HostName");
904ab6554f1SJoshi-Mansi         return;
905ab6554f1SJoshi-Mansi     }
9069ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9079ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
9089ae226faSGeorge Liu         "/xyz/openbmc_project/network/config",
9099ae226faSGeorge Liu         "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
9105e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
9114a0cb85cSEd Tanous         if (ec)
9124a0cb85cSEd Tanous         {
913a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
9141abe55efSEd Tanous         }
9159ae226faSGeorge Liu     });
916588c3f0dSKowalski, Kamil }
917588c3f0dSKowalski, Kamil 
9184f48d5f6SEd Tanous inline void
91935fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
92035fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
92135fb5311STejas Patil {
92289492a15SPatrick Williams     sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
92389492a15SPatrick Williams                                               ifaceId;
9249ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9259ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
9269ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
9275e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
92835fb5311STejas Patil         if (ec)
92935fb5311STejas Patil         {
93035fb5311STejas Patil             messages::internalError(asyncResp->res);
93135fb5311STejas Patil         }
9329ae226faSGeorge Liu     });
93335fb5311STejas Patil }
93435fb5311STejas Patil 
93535fb5311STejas Patil inline void
9364f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
937bf648f77SEd Tanous                           const std::string& domainname,
9388d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
939ab6554f1SJoshi-Mansi {
940ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
9419ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9429ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
9439ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
9449ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
9459ae226faSGeorge Liu         vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
946ab6554f1SJoshi-Mansi         if (ec)
947ab6554f1SJoshi-Mansi         {
948ab6554f1SJoshi-Mansi             messages::internalError(asyncResp->res);
949ab6554f1SJoshi-Mansi         }
9509ae226faSGeorge Liu     });
951ab6554f1SJoshi-Mansi }
952ab6554f1SJoshi-Mansi 
9534f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
954bf648f77SEd Tanous {
955bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
9563544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
957bf648f77SEd Tanous     {
958bf648f77SEd Tanous         return false;
959bf648f77SEd Tanous     }
960bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
961bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
962bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
963bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
9644b242749SEd Tanous     const static std::regex pattern(
965bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
966bf648f77SEd Tanous 
967bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
968bf648f77SEd Tanous }
969bf648f77SEd Tanous 
9704f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
971bf648f77SEd Tanous {
972bf648f77SEd Tanous     // Can have multiple subdomains
973bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
9744b242749SEd Tanous     const static std::regex pattern(
9750fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
976bf648f77SEd Tanous 
977bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
978bf648f77SEd Tanous }
979bf648f77SEd Tanous 
9804f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
9818d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
982ab6554f1SJoshi-Mansi {
983ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
984ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
985ab6554f1SJoshi-Mansi     {
986ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
987ab6554f1SJoshi-Mansi         return;
988ab6554f1SJoshi-Mansi     }
989ab6554f1SJoshi-Mansi 
990ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
991ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
992ab6554f1SJoshi-Mansi     {
993ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
994ab6554f1SJoshi-Mansi         return;
995ab6554f1SJoshi-Mansi     }
996ab6554f1SJoshi-Mansi 
997ab6554f1SJoshi-Mansi     std::string hostname;
998ab6554f1SJoshi-Mansi     std::string domainname;
999ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1000ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1001ab6554f1SJoshi-Mansi 
1002ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1003ab6554f1SJoshi-Mansi     {
1004ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1005ab6554f1SJoshi-Mansi         return;
1006ab6554f1SJoshi-Mansi     }
1007ab6554f1SJoshi-Mansi 
1008ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1009ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1010ab6554f1SJoshi-Mansi }
1011ab6554f1SJoshi-Mansi 
10124f48d5f6SEd Tanous inline void
10134f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1014bf648f77SEd Tanous                           const std::string& macAddress,
10158d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1016d577665bSRatan Gupta {
101758283f41SJohnathan Mantey     static constexpr std::string_view dbusNotAllowedError =
101858283f41SJohnathan Mantey         "xyz.openbmc_project.Common.Error.NotAllowed";
101958283f41SJohnathan Mantey 
10209ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10219ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10229ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10239ae226faSGeorge Liu         "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
10249ae226faSGeorge Liu         [asyncResp](const boost::system::error_code& ec,
10255b378546SPatrick Williams                     const sdbusplus::message_t& msg) {
1026d577665bSRatan Gupta         if (ec)
1027d577665bSRatan Gupta         {
102858283f41SJohnathan Mantey             const sd_bus_error* err = msg.get_error();
102958283f41SJohnathan Mantey             if (err == nullptr)
103058283f41SJohnathan Mantey             {
103158283f41SJohnathan Mantey                 messages::internalError(asyncResp->res);
103258283f41SJohnathan Mantey                 return;
103358283f41SJohnathan Mantey             }
103458283f41SJohnathan Mantey             if (err->name == dbusNotAllowedError)
103558283f41SJohnathan Mantey             {
103658283f41SJohnathan Mantey                 messages::propertyNotWritable(asyncResp->res, "MACAddress");
103758283f41SJohnathan Mantey                 return;
103858283f41SJohnathan Mantey             }
1039d577665bSRatan Gupta             messages::internalError(asyncResp->res);
1040d577665bSRatan Gupta             return;
1041d577665bSRatan Gupta         }
10429ae226faSGeorge Liu     });
1043d577665bSRatan Gupta }
1044286b9118SJohnathan Mantey 
10454f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
10464f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
10474f48d5f6SEd Tanous                            const bool v6Value,
10488d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1049da131a9aSJennifer Lee {
10502c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
10519ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10529ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10539ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10549ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
10555e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1056da131a9aSJennifer Lee         if (ec)
1057da131a9aSJennifer Lee         {
105862598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1059da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1060da131a9aSJennifer Lee             return;
1061da131a9aSJennifer Lee         }
10628f7e9c19SJayaprakash Mutyala         messages::success(asyncResp->res);
10639ae226faSGeorge Liu     });
1064da131a9aSJennifer Lee }
10651f8c7b5dSJohnathan Mantey 
10664f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty(
1067eeedda23SJohnathan Mantey     const std::string& ifaceId, const std::string& propertyName,
10688d1b46d7Szhanghch05     const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1069eeedda23SJohnathan Mantey {
10709ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10719ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10729ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10739ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
10745e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1075eeedda23SJohnathan Mantey         if (ec)
1076eeedda23SJohnathan Mantey         {
107762598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1078eeedda23SJohnathan Mantey             messages::internalError(asyncResp->res);
1079eeedda23SJohnathan Mantey             return;
1080eeedda23SJohnathan Mantey         }
10819ae226faSGeorge Liu     });
1082eeedda23SJohnathan Mantey }
1083eeedda23SJohnathan Mantey 
10844f48d5f6SEd Tanous inline void setDHCPv4Config(const std::string& propertyName, const bool& value,
10858d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1086da131a9aSJennifer Lee {
108762598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
10889ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10899ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10909ae226faSGeorge Liu         "/xyz/openbmc_project/network/dhcp",
10919ae226faSGeorge Liu         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
10925e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1093da131a9aSJennifer Lee         if (ec)
1094da131a9aSJennifer Lee         {
109562598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1096da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1097da131a9aSJennifer Lee             return;
1098da131a9aSJennifer Lee         }
10999ae226faSGeorge Liu     });
1100da131a9aSJennifer Lee }
1101d577665bSRatan Gupta 
1102b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1103b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1104b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1105b10d8db0SRavi Teja {
1106b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1107b10d8db0SRavi Teja     path /= ifaceId;
1108b10d8db0SRavi Teja     sdbusplus::asio::setProperty(
1109b10d8db0SRavi Teja         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1110b10d8db0SRavi Teja         "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1111b10d8db0SRavi Teja         ipv6AutoConfigEnabled,
1112b10d8db0SRavi Teja         [asyncResp](const boost::system::error_code& ec) {
1113b10d8db0SRavi Teja         if (ec)
1114b10d8db0SRavi Teja         {
1115b10d8db0SRavi Teja             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1116b10d8db0SRavi Teja             messages::internalError(asyncResp->res);
1117b10d8db0SRavi Teja             return;
1118b10d8db0SRavi Teja         }
1119b10d8db0SRavi Teja         messages::success(asyncResp->res);
1120b10d8db0SRavi Teja     });
1121b10d8db0SRavi Teja }
1122b10d8db0SRavi Teja 
11234f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
11241f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1125f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1126f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
11278d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1128da131a9aSJennifer Lee {
112982695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
113082695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1131da131a9aSJennifer Lee 
11321f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
11331f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
11341f8c7b5dSJohnathan Mantey 
11351f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
11361f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1137da131a9aSJennifer Lee     {
1138b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
11391f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
11401f8c7b5dSJohnathan Mantey         {
1141bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1142bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
11431f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1144da131a9aSJennifer Lee             return;
1145da131a9aSJennifer Lee         }
1146b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
11471f8c7b5dSJohnathan Mantey     }
11481f8c7b5dSJohnathan Mantey     else
1149da131a9aSJennifer Lee     {
11501f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
11511f8c7b5dSJohnathan Mantey     }
11521f8c7b5dSJohnathan Mantey 
11531f8c7b5dSJohnathan Mantey     bool nextDNS{};
115482695a5bSJiaqing Zhao     if (v4dhcpParms.useDnsServers && v6dhcpParms.useDnsServers)
11551f8c7b5dSJohnathan Mantey     {
115682695a5bSJiaqing Zhao         if (*v4dhcpParms.useDnsServers != *v6dhcpParms.useDnsServers)
11571f8c7b5dSJohnathan Mantey         {
11581f8c7b5dSJohnathan Mantey             messages::generalError(asyncResp->res);
11591f8c7b5dSJohnathan Mantey             return;
11601f8c7b5dSJohnathan Mantey         }
116182695a5bSJiaqing Zhao         nextDNS = *v4dhcpParms.useDnsServers;
11621f8c7b5dSJohnathan Mantey     }
116382695a5bSJiaqing Zhao     else if (v4dhcpParms.useDnsServers)
11641f8c7b5dSJohnathan Mantey     {
116582695a5bSJiaqing Zhao         nextDNS = *v4dhcpParms.useDnsServers;
11661f8c7b5dSJohnathan Mantey     }
116782695a5bSJiaqing Zhao     else if (v6dhcpParms.useDnsServers)
11681f8c7b5dSJohnathan Mantey     {
116982695a5bSJiaqing Zhao         nextDNS = *v6dhcpParms.useDnsServers;
11701f8c7b5dSJohnathan Mantey     }
11711f8c7b5dSJohnathan Mantey     else
11721f8c7b5dSJohnathan Mantey     {
117382695a5bSJiaqing Zhao         nextDNS = ethData.dnsEnabled;
11741f8c7b5dSJohnathan Mantey     }
11751f8c7b5dSJohnathan Mantey 
11761f8c7b5dSJohnathan Mantey     bool nextNTP{};
117782695a5bSJiaqing Zhao     if (v4dhcpParms.useNtpServers && v6dhcpParms.useNtpServers)
11781f8c7b5dSJohnathan Mantey     {
117982695a5bSJiaqing Zhao         if (*v4dhcpParms.useNtpServers != *v6dhcpParms.useNtpServers)
11801f8c7b5dSJohnathan Mantey         {
11811f8c7b5dSJohnathan Mantey             messages::generalError(asyncResp->res);
11821f8c7b5dSJohnathan Mantey             return;
11831f8c7b5dSJohnathan Mantey         }
118482695a5bSJiaqing Zhao         nextNTP = *v4dhcpParms.useNtpServers;
11851f8c7b5dSJohnathan Mantey     }
118682695a5bSJiaqing Zhao     else if (v4dhcpParms.useNtpServers)
11871f8c7b5dSJohnathan Mantey     {
118882695a5bSJiaqing Zhao         nextNTP = *v4dhcpParms.useNtpServers;
11891f8c7b5dSJohnathan Mantey     }
119082695a5bSJiaqing Zhao     else if (v6dhcpParms.useNtpServers)
11911f8c7b5dSJohnathan Mantey     {
119282695a5bSJiaqing Zhao         nextNTP = *v6dhcpParms.useNtpServers;
11931f8c7b5dSJohnathan Mantey     }
11941f8c7b5dSJohnathan Mantey     else
11951f8c7b5dSJohnathan Mantey     {
119682695a5bSJiaqing Zhao         nextNTP = ethData.ntpEnabled;
11971f8c7b5dSJohnathan Mantey     }
11981f8c7b5dSJohnathan Mantey 
11991f8c7b5dSJohnathan Mantey     bool nextUseDomain{};
120082695a5bSJiaqing Zhao     if (v4dhcpParms.useDomainName && v6dhcpParms.useDomainName)
12011f8c7b5dSJohnathan Mantey     {
120282695a5bSJiaqing Zhao         if (*v4dhcpParms.useDomainName != *v6dhcpParms.useDomainName)
12031f8c7b5dSJohnathan Mantey         {
12041f8c7b5dSJohnathan Mantey             messages::generalError(asyncResp->res);
12051f8c7b5dSJohnathan Mantey             return;
12061f8c7b5dSJohnathan Mantey         }
120782695a5bSJiaqing Zhao         nextUseDomain = *v4dhcpParms.useDomainName;
12081f8c7b5dSJohnathan Mantey     }
120982695a5bSJiaqing Zhao     else if (v4dhcpParms.useDomainName)
12101f8c7b5dSJohnathan Mantey     {
121182695a5bSJiaqing Zhao         nextUseDomain = *v4dhcpParms.useDomainName;
12121f8c7b5dSJohnathan Mantey     }
121382695a5bSJiaqing Zhao     else if (v6dhcpParms.useDomainName)
12141f8c7b5dSJohnathan Mantey     {
121582695a5bSJiaqing Zhao         nextUseDomain = *v6dhcpParms.useDomainName;
12161f8c7b5dSJohnathan Mantey     }
12171f8c7b5dSJohnathan Mantey     else
12181f8c7b5dSJohnathan Mantey     {
121982695a5bSJiaqing Zhao         nextUseDomain = ethData.hostNameEnabled;
12201f8c7b5dSJohnathan Mantey     }
12211f8c7b5dSJohnathan Mantey 
122262598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
12231f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
12241f8c7b5dSJohnathan Mantey                    asyncResp);
122562598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
12261f8c7b5dSJohnathan Mantey     setDHCPv4Config("DNSEnabled", nextDNS, asyncResp);
122762598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
12281f8c7b5dSJohnathan Mantey     setDHCPv4Config("NTPEnabled", nextNTP, asyncResp);
122962598e31SEd Tanous     BMCWEB_LOG_DEBUG("set HostNameEnabled...");
12301f8c7b5dSJohnathan Mantey     setDHCPv4Config("HostNameEnabled", nextUseDomain, asyncResp);
1231da131a9aSJennifer Lee }
123201784826SJohnathan Mantey 
123377179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
123477179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
123577179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
123601784826SJohnathan Mantey {
123717a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
123817a897dfSManojkiran Eda         return value.origin == "Static";
123917a897dfSManojkiran Eda     });
124001784826SJohnathan Mantey }
124101784826SJohnathan Mantey 
124277179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
124377179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
124477179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
124501784826SJohnathan Mantey {
124617a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
124717a897dfSManojkiran Eda         return value.origin == "Static";
124817a897dfSManojkiran Eda     });
124901784826SJohnathan Mantey }
125001784826SJohnathan Mantey 
125177179532SEd Tanous inline void
1252ddd70dcaSEd Tanous     handleIPv4StaticPatch(const std::string& ifaceId,
1253ddd70dcaSEd Tanous                           nlohmann::json::array_t& input,
125477179532SEd Tanous                           const std::vector<IPv4AddressData>& ipv4Data,
12558d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
12561abe55efSEd Tanous {
1257ddd70dcaSEd Tanous     if (input.empty())
1258f476acbfSRatan Gupta     {
12592e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1260d1d50814SRavi Teja                                          "IPv4StaticAddresses");
1261f476acbfSRatan Gupta         return;
1262f476acbfSRatan Gupta     }
1263f476acbfSRatan Gupta 
1264271584abSEd Tanous     unsigned entryIdx = 1;
126501784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
126601784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
126701784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
126801784826SJohnathan Mantey     // into the NIC.
126977179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
12702c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
127101784826SJohnathan Mantey 
1272537174c4SEd Tanous     for (nlohmann::json& thisJson : input)
12731abe55efSEd Tanous     {
127489492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
127589492a15SPatrick Williams                                  std::to_string(entryIdx);
1276179db1d7SKowalski, Kamil 
127701784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1278f476acbfSRatan Gupta         {
1279537174c4SEd Tanous             std::optional<std::string> address;
1280537174c4SEd Tanous             std::optional<std::string> subnetMask;
1281537174c4SEd Tanous             std::optional<std::string> gateway;
1282537174c4SEd Tanous 
1283537174c4SEd Tanous             if (!json_util::readJson(thisJson, asyncResp->res, "Address",
12847e27d832SJohnathan Mantey                                      address, "SubnetMask", subnetMask,
12857e27d832SJohnathan Mantey                                      "Gateway", gateway))
1286537174c4SEd Tanous             {
1287f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
128871f52d96SEd Tanous                                                    pathString);
1289537174c4SEd Tanous                 return;
1290179db1d7SKowalski, Kamil             }
1291179db1d7SKowalski, Kamil 
129201784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
129301784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
129401784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
129501784826SJohnathan Mantey             // current request.
1296537174c4SEd Tanous             if (address)
12971abe55efSEd Tanous             {
1298e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
129901784826SJohnathan Mantey                 {
1300bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1301bf648f77SEd Tanous                                                        pathString + "/Address");
1302e01d0c36SEd Tanous                     return;
130301784826SJohnathan Mantey                 }
130401784826SJohnathan Mantey             }
130585ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
130601784826SJohnathan Mantey             {
1307e01d0c36SEd Tanous                 address = (nicIpEntry->address);
130801784826SJohnathan Mantey             }
130901784826SJohnathan Mantey             else
131001784826SJohnathan Mantey             {
131101784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
131201784826SJohnathan Mantey                                           pathString + "/Address");
1313e01d0c36SEd Tanous                 return;
13144a0cb85cSEd Tanous             }
13154a0cb85cSEd Tanous 
1316e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1317537174c4SEd Tanous             if (subnetMask)
13184a0cb85cSEd Tanous             {
1319033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1320033f1e4dSEd Tanous                                                          &prefixLength))
13214a0cb85cSEd Tanous                 {
1322f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1323537174c4SEd Tanous                         asyncResp->res, *subnetMask,
13244a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1325e01d0c36SEd Tanous                     return;
13264a0cb85cSEd Tanous                 }
13274a0cb85cSEd Tanous             }
132885ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
13294a0cb85cSEd Tanous             {
1330033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
133101784826SJohnathan Mantey                                                          &prefixLength))
13324a0cb85cSEd Tanous                 {
133301784826SJohnathan Mantey                     messages::propertyValueFormatError(
133485ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
133501784826SJohnathan Mantey                         pathString + "/SubnetMask");
1336e01d0c36SEd Tanous                     return;
13374a0cb85cSEd Tanous                 }
13384a0cb85cSEd Tanous             }
13391abe55efSEd Tanous             else
13401abe55efSEd Tanous             {
134101784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
134201784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1343e01d0c36SEd Tanous                 return;
134401784826SJohnathan Mantey             }
134501784826SJohnathan Mantey 
134601784826SJohnathan Mantey             if (gateway)
134701784826SJohnathan Mantey             {
1348e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
134901784826SJohnathan Mantey                 {
1350bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1351bf648f77SEd Tanous                                                        pathString + "/Gateway");
1352e01d0c36SEd Tanous                     return;
135301784826SJohnathan Mantey                 }
135401784826SJohnathan Mantey             }
135585ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
135601784826SJohnathan Mantey             {
1357e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
135801784826SJohnathan Mantey             }
135901784826SJohnathan Mantey             else
13601abe55efSEd Tanous             {
1361a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
13624a0cb85cSEd Tanous                                           pathString + "/Gateway");
136301784826SJohnathan Mantey                 return;
13644a0cb85cSEd Tanous             }
13654a0cb85cSEd Tanous 
136685ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
13671abe55efSEd Tanous             {
13689c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
136977eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
137077eb0153SEd Tanous                                          *gateway, asyncResp);
137189492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
137289492a15SPatrick Williams                                                   ipv4Data.cend());
1373588c3f0dSKowalski, Kamil             }
137401784826SJohnathan Mantey             else
137501784826SJohnathan Mantey             {
1376cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1377cb13a392SEd Tanous                            asyncResp);
13784a0cb85cSEd Tanous             }
13794a0cb85cSEd Tanous             entryIdx++;
13804a0cb85cSEd Tanous         }
138101784826SJohnathan Mantey         else
138201784826SJohnathan Mantey         {
138385ffe86aSJiaqing Zhao             if (nicIpEntry == ipv4Data.cend())
138401784826SJohnathan Mantey             {
138501784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
138601784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
138701784826SJohnathan Mantey                 // in error, so bail out.
138801784826SJohnathan Mantey                 if (thisJson.is_null())
138901784826SJohnathan Mantey                 {
139001784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
139101784826SJohnathan Mantey                     return;
139201784826SJohnathan Mantey                 }
1393f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
139471f52d96SEd Tanous                                                    pathString);
139501784826SJohnathan Mantey                 return;
139601784826SJohnathan Mantey             }
139701784826SJohnathan Mantey 
139801784826SJohnathan Mantey             if (thisJson.is_null())
139901784826SJohnathan Mantey             {
14009c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
140101784826SJohnathan Mantey             }
140285ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
140301784826SJohnathan Mantey             {
140489492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
140589492a15SPatrick Williams                                                   ipv4Data.cend());
140601784826SJohnathan Mantey             }
140701784826SJohnathan Mantey             entryIdx++;
140801784826SJohnathan Mantey         }
140901784826SJohnathan Mantey     }
14104a0cb85cSEd Tanous }
14114a0cb85cSEd Tanous 
14124f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1413f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1414f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
14158d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1416f85837bfSRAJESWARAN THILLAIGOVINDAN {
14179ae226faSGeorge Liu     sdbusplus::asio::setProperty(
14189ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
14199ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
14209ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
14219ae226faSGeorge Liu         updatedStaticNameServers,
14225e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1423f85837bfSRAJESWARAN THILLAIGOVINDAN         if (ec)
1424f85837bfSRAJESWARAN THILLAIGOVINDAN         {
1425f85837bfSRAJESWARAN THILLAIGOVINDAN             messages::internalError(asyncResp->res);
1426f85837bfSRAJESWARAN THILLAIGOVINDAN             return;
1427f85837bfSRAJESWARAN THILLAIGOVINDAN         }
14289ae226faSGeorge Liu     });
1429f85837bfSRAJESWARAN THILLAIGOVINDAN }
1430f85837bfSRAJESWARAN THILLAIGOVINDAN 
14314f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
1432ddd70dcaSEd Tanous     const std::string& ifaceId, const nlohmann::json::array_t& input,
143377179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
14348d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1435e48c0fc5SRavi Teja {
1436ddd70dcaSEd Tanous     if (input.empty())
1437e48c0fc5SRavi Teja     {
14382e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1439e48c0fc5SRavi Teja                                          "IPv6StaticAddresses");
1440e48c0fc5SRavi Teja         return;
1441e48c0fc5SRavi Teja     }
1442271584abSEd Tanous     size_t entryIdx = 1;
144377179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
14442c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1445f23b7296SEd Tanous     for (const nlohmann::json& thisJson : input)
1446e48c0fc5SRavi Teja     {
144789492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
144889492a15SPatrick Williams                                  std::to_string(entryIdx);
1449e48c0fc5SRavi Teja 
145001784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1451e48c0fc5SRavi Teja         {
1452e48c0fc5SRavi Teja             std::optional<std::string> address;
1453e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
1454f23b7296SEd Tanous             nlohmann::json thisJsonCopy = thisJson;
1455bf648f77SEd Tanous             if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1456bf648f77SEd Tanous                                      address, "PrefixLength", prefixLength))
1457e48c0fc5SRavi Teja             {
1458f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
145971f52d96SEd Tanous                                                    pathString);
1460e48c0fc5SRavi Teja                 return;
1461e48c0fc5SRavi Teja             }
1462e48c0fc5SRavi Teja 
1463543f4400SEd Tanous             const std::string* addr = nullptr;
1464543f4400SEd Tanous             uint8_t prefix = 0;
146501784826SJohnathan Mantey 
146601784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
146701784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
146801784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
146901784826SJohnathan Mantey             // current request.
1470e48c0fc5SRavi Teja             if (address)
1471e48c0fc5SRavi Teja             {
147201784826SJohnathan Mantey                 addr = &(*address);
1473e48c0fc5SRavi Teja             }
147485ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
147501784826SJohnathan Mantey             {
147685ffe86aSJiaqing Zhao                 addr = &(nicIpEntry->address);
147701784826SJohnathan Mantey             }
147801784826SJohnathan Mantey             else
147901784826SJohnathan Mantey             {
148001784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
148101784826SJohnathan Mantey                                           pathString + "/Address");
148201784826SJohnathan Mantey                 return;
1483e48c0fc5SRavi Teja             }
1484e48c0fc5SRavi Teja 
1485e48c0fc5SRavi Teja             if (prefixLength)
1486e48c0fc5SRavi Teja             {
148701784826SJohnathan Mantey                 prefix = *prefixLength;
148801784826SJohnathan Mantey             }
148985ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
1490e48c0fc5SRavi Teja             {
149185ffe86aSJiaqing Zhao                 prefix = nicIpEntry->prefixLength;
1492e48c0fc5SRavi Teja             }
1493e48c0fc5SRavi Teja             else
1494e48c0fc5SRavi Teja             {
1495e48c0fc5SRavi Teja                 messages::propertyMissing(asyncResp->res,
1496e48c0fc5SRavi Teja                                           pathString + "/PrefixLength");
149701784826SJohnathan Mantey                 return;
1498e48c0fc5SRavi Teja             }
1499e48c0fc5SRavi Teja 
150085ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1501e48c0fc5SRavi Teja             {
15029c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
150377eb0153SEd Tanous                                          nicIpEntry->id, prefix, *addr, "",
1504e48c0fc5SRavi Teja                                          asyncResp);
150589492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
150689492a15SPatrick Williams                                                   ipv6Data.cend());
150701784826SJohnathan Mantey             }
150801784826SJohnathan Mantey             else
150901784826SJohnathan Mantey             {
151001784826SJohnathan Mantey                 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1511e48c0fc5SRavi Teja             }
1512e48c0fc5SRavi Teja             entryIdx++;
1513e48c0fc5SRavi Teja         }
151401784826SJohnathan Mantey         else
151501784826SJohnathan Mantey         {
151685ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
151701784826SJohnathan Mantey             {
151801784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
151901784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
152001784826SJohnathan Mantey                 // in error, so bail out.
152101784826SJohnathan Mantey                 if (thisJson.is_null())
152201784826SJohnathan Mantey                 {
152301784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
152401784826SJohnathan Mantey                     return;
152501784826SJohnathan Mantey                 }
1526f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
152771f52d96SEd Tanous                                                    pathString);
152801784826SJohnathan Mantey                 return;
152901784826SJohnathan Mantey             }
153001784826SJohnathan Mantey 
153101784826SJohnathan Mantey             if (thisJson.is_null())
153201784826SJohnathan Mantey             {
15339c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
153401784826SJohnathan Mantey             }
153585ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
153601784826SJohnathan Mantey             {
153789492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
153889492a15SPatrick Williams                                                   ipv6Data.cend());
153901784826SJohnathan Mantey             }
154001784826SJohnathan Mantey             entryIdx++;
154101784826SJohnathan Mantey         }
154201784826SJohnathan Mantey     }
1543e48c0fc5SRavi Teja }
1544e48c0fc5SRavi Teja 
15457857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
15467857cb8dSJiaqing Zhao {
15477857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
15487857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
15497857cb8dSJiaqing Zhao }
15507857cb8dSJiaqing Zhao 
155177179532SEd Tanous inline void
155277179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
155377179532SEd Tanous                        const std::string& ifaceId,
155477179532SEd Tanous                        const EthernetInterfaceData& ethData,
155577179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
155677179532SEd Tanous                        const std::vector<IPv6AddressData>& ipv6Data)
15574a0cb85cSEd Tanous {
15582c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
155981ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1560ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1561ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
15622c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1563eeedda23SJohnathan Mantey 
156413451e39SWilly Tu     if constexpr (bmcwebEnableHealthPopulate)
156513451e39SWilly Tu     {
156613451e39SWilly Tu         constexpr std::array<std::string_view, 1> inventoryForEthernet = {
156713451e39SWilly Tu             "xyz.openbmc_project.Inventory.Item.Ethernet"};
1568eeedda23SJohnathan Mantey         auto health = std::make_shared<HealthPopulate>(asyncResp);
15697a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
15707a1dbc48SGeorge Liu             "/", 0, inventoryForEthernet,
15717a1dbc48SGeorge Liu             [health](const boost::system::error_code& ec,
1572b9d36b47SEd Tanous                      const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1573eeedda23SJohnathan Mantey             if (ec)
1574029573d4SEd Tanous             {
1575eeedda23SJohnathan Mantey                 return;
1576eeedda23SJohnathan Mantey             }
1577eeedda23SJohnathan Mantey 
1578914e2d5dSEd Tanous             health->inventory = resp;
15797a1dbc48SGeorge Liu         });
1580eeedda23SJohnathan Mantey 
1581eeedda23SJohnathan Mantey         health->populate();
158213451e39SWilly Tu     }
1583eeedda23SJohnathan Mantey 
1584eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1585eeedda23SJohnathan Mantey     {
15860ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
15872c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1588029573d4SEd Tanous     }
1589029573d4SEd Tanous     else
1590029573d4SEd Tanous     {
15912c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
15922c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1593029573d4SEd Tanous     }
1594aa05fb27SJohnathan Mantey 
15952c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
159635fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
159782695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
15982c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
159982695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
160082695a5bSJiaqing Zhao     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpEnabled;
160182695a5bSJiaqing Zhao     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsEnabled;
160282695a5bSJiaqing Zhao     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNameEnabled;
16031f8c7b5dSJohnathan Mantey 
16042c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1605b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
16061f8c7b5dSJohnathan Mantey                                                                : "Disabled";
160782695a5bSJiaqing Zhao     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpEnabled;
160882695a5bSJiaqing Zhao     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsEnabled;
160982695a5bSJiaqing Zhao     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNameEnabled;
1610b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1611b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
16122a133282Smanojkiraneda 
161382695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
16144a0cb85cSEd Tanous     {
161582695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1616ab6554f1SJoshi-Mansi 
1617ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1618ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1619ab6554f1SJoshi-Mansi         // FQDN
162082695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1621d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1622d24bfc7aSJennifer Lee         {
16232c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1624d24bfc7aSJennifer Lee         }
16252c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
16264a0cb85cSEd Tanous     }
16274a0cb85cSEd Tanous 
16287857cb8dSJiaqing Zhao     if (ethData.vlanId)
16297857cb8dSJiaqing Zhao     {
16307857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
16317857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
16327857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
16337857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
16347857cb8dSJiaqing Zhao 
16357857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
16367857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
16377857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
16387857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
16397857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
16407857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
16417857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
16427857cb8dSJiaqing Zhao     }
16437857cb8dSJiaqing Zhao     else
16447857cb8dSJiaqing Zhao     {
16457857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
16467857cb8dSJiaqing Zhao     }
16477857cb8dSJiaqing Zhao 
16482c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
16492c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
16504a0cb85cSEd Tanous 
16512c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
16522c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
16532c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
16542c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
16559eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
16564a0cb85cSEd Tanous     {
16572c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1658fa5053a6SGunnar Mills         if (gatewayStr.empty())
1659fa5053a6SGunnar Mills         {
1660fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1661fa5053a6SGunnar Mills         }
16621476687dSEd Tanous         nlohmann::json::object_t ipv4;
16631476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
16641476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
16651476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
16661476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1667fa5053a6SGunnar Mills 
16682c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1669d1d50814SRavi Teja         {
16701476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1671d1d50814SRavi Teja         }
16721476687dSEd Tanous 
1673b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
167401784826SJohnathan Mantey     }
1675d1d50814SRavi Teja 
167682695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
16777ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
16787ea79e5eSRavi Teja     {
16797ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
16807ea79e5eSRavi Teja     }
16817ea79e5eSRavi Teja 
16827ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1683e48c0fc5SRavi Teja 
16842c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
16852c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
16862c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
16872c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
16887f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
16892c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
16907f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
16919eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1692e48c0fc5SRavi Teja     {
16931476687dSEd Tanous         nlohmann::json::object_t ipv6;
16941476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
16951476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
16961476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1697f8361275SSunitha Harish 
1698b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
16992c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1700e48c0fc5SRavi Teja         {
17011476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
17021476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
17031476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1704b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
170501784826SJohnathan Mantey         }
1706e48c0fc5SRavi Teja     }
1707588c3f0dSKowalski, Kamil }
1708588c3f0dSKowalski, Kamil 
1709e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1710e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1711e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1712e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1713e7caf250SJiaqing Zhao {
1714e7caf250SJiaqing Zhao     if (!ec)
1715e7caf250SJiaqing Zhao     {
1716e7caf250SJiaqing Zhao         return;
1717e7caf250SJiaqing Zhao     }
1718e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
1719e7caf250SJiaqing Zhao     if (dbusError == nullptr)
1720e7caf250SJiaqing Zhao     {
1721e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
1722e7caf250SJiaqing Zhao         return;
1723e7caf250SJiaqing Zhao     }
172462598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1725e7caf250SJiaqing Zhao 
1726e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1727e7caf250SJiaqing Zhao         dbusError->name)
1728e7caf250SJiaqing Zhao     {
1729e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1730e7caf250SJiaqing Zhao                                    ifaceId);
1731e7caf250SJiaqing Zhao         return;
1732e7caf250SJiaqing Zhao     }
1733e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1734e7caf250SJiaqing Zhao         dbusError->name)
1735e7caf250SJiaqing Zhao     {
1736e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
1737e7caf250SJiaqing Zhao         return;
1738e7caf250SJiaqing Zhao     }
1739e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
1740e7caf250SJiaqing Zhao }
1741e7caf250SJiaqing Zhao 
1742b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1743b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
1744b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
1745b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
1746b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
1747b5ca3fdcSJiaqing Zhao 
1748b5ca3fdcSJiaqing Zhao )
1749b5ca3fdcSJiaqing Zhao {
1750b5ca3fdcSJiaqing Zhao     if (ec)
1751b5ca3fdcSJiaqing Zhao     {
1752b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
1753b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
1754b5ca3fdcSJiaqing Zhao         {
1755b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
1756b5ca3fdcSJiaqing Zhao             return;
1757b5ca3fdcSJiaqing Zhao         }
175862598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1759b5ca3fdcSJiaqing Zhao 
1760b5ca3fdcSJiaqing Zhao         if (std::string_view(
1761b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1762b5ca3fdcSJiaqing Zhao             dbusError->name)
1763b5ca3fdcSJiaqing Zhao         {
1764b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1765b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1766b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1767b5ca3fdcSJiaqing Zhao             return;
1768b5ca3fdcSJiaqing Zhao         }
1769b5ca3fdcSJiaqing Zhao         if (std::string_view(
1770b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1771b5ca3fdcSJiaqing Zhao             dbusError->name)
1772b5ca3fdcSJiaqing Zhao         {
1773b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1774b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
1775b5ca3fdcSJiaqing Zhao             return;
1776b5ca3fdcSJiaqing Zhao         }
1777b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
1778b5ca3fdcSJiaqing Zhao         return;
1779b5ca3fdcSJiaqing Zhao     }
1780b5ca3fdcSJiaqing Zhao 
1781b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
1782b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1783b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1784b5ca3fdcSJiaqing Zhao }
1785b5ca3fdcSJiaqing Zhao 
1786bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
1787bf648f77SEd Tanous {
1788bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1789ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
17901476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
17911476687dSEd Tanous             [&app](const crow::Request& req,
17921476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
17933ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
179445ca1b86SEd Tanous         {
179545ca1b86SEd Tanous             return;
179645ca1b86SEd Tanous         }
179745ca1b86SEd Tanous 
1798bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
1799bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1800bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
1801bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
1802bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
1803bf648f77SEd Tanous             "Ethernet Network Interface Collection";
1804bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
1805bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
1806bf648f77SEd Tanous 
1807bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
1808bf648f77SEd Tanous         // preparation
1809002d39b4SEd Tanous         getEthernetIfaceList(
181077179532SEd Tanous             [asyncResp](const bool& success,
181177179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
1812bf648f77SEd Tanous             if (!success)
18131abe55efSEd Tanous             {
1814f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
18159391bb9cSRapkiewicz, Pawel                 return;
18169391bb9cSRapkiewicz, Pawel             }
18179391bb9cSRapkiewicz, Pawel 
1818002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1819bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
1820bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
1821bf648f77SEd Tanous             {
18221476687dSEd Tanous                 nlohmann::json::object_t iface;
1823ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
1824ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1825ef4c65b7SEd Tanous                     ifaceItem);
18267857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
1827bf648f77SEd Tanous             }
1828bf648f77SEd Tanous 
1829002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1830bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
1831bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1832bf648f77SEd Tanous         });
1833bf648f77SEd Tanous     });
1834bf648f77SEd Tanous 
1835b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1836b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
1837b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
1838b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
1839b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1840b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1841b5ca3fdcSJiaqing Zhao         {
1842b5ca3fdcSJiaqing Zhao             return;
1843b5ca3fdcSJiaqing Zhao         }
1844b5ca3fdcSJiaqing Zhao 
1845b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
1846b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
1847b5ca3fdcSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
1848b5ca3fdcSJiaqing Zhao 
1849b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1850b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
1851b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
1852b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
1853b5ca3fdcSJiaqing Zhao         {
1854b5ca3fdcSJiaqing Zhao             return;
1855b5ca3fdcSJiaqing Zhao         }
1856b5ca3fdcSJiaqing Zhao 
1857b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
1858b5ca3fdcSJiaqing Zhao         {
1859b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
1860b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
1861b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
1862b5ca3fdcSJiaqing Zhao             return;
1863b5ca3fdcSJiaqing Zhao         }
1864b5ca3fdcSJiaqing Zhao 
1865b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
1866b5ca3fdcSJiaqing Zhao         if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1867b5ca3fdcSJiaqing Zhao                                  "@odata.id", parentInterfaceUri))
1868b5ca3fdcSJiaqing Zhao         {
1869b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
1870b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
1871b5ca3fdcSJiaqing Zhao             return;
1872b5ca3fdcSJiaqing Zhao         }
187362598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
1874b5ca3fdcSJiaqing Zhao 
18756fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
1876b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
1877b5ca3fdcSJiaqing Zhao         if (!parsedUri)
1878b5ca3fdcSJiaqing Zhao         {
1879b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
1880b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1881b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1882b5ca3fdcSJiaqing Zhao             return;
1883b5ca3fdcSJiaqing Zhao         }
1884b5ca3fdcSJiaqing Zhao 
1885b5ca3fdcSJiaqing Zhao         std::string parentInterface;
1886b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
1887b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
1888b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
1889b5ca3fdcSJiaqing Zhao         {
1890b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1891b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1892b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1893b5ca3fdcSJiaqing Zhao             return;
1894b5ca3fdcSJiaqing Zhao         }
1895b5ca3fdcSJiaqing Zhao 
1896b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
1897b5ca3fdcSJiaqing Zhao         {
1898b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
1899b5ca3fdcSJiaqing Zhao             // create
1900b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1901b5ca3fdcSJiaqing Zhao                                              "false");
1902b5ca3fdcSJiaqing Zhao             return;
1903b5ca3fdcSJiaqing Zhao         }
1904b5ca3fdcSJiaqing Zhao 
1905b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
1906b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
1907b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
1908b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
1909b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
1910b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
1911b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1912b5ca3fdcSJiaqing Zhao                             m);
1913b5ca3fdcSJiaqing Zhao         },
1914b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1915b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1916b5ca3fdcSJiaqing Zhao             vlanId);
1917b5ca3fdcSJiaqing Zhao     });
1918b5ca3fdcSJiaqing Zhao 
1919bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
1920ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
1921bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
192245ca1b86SEd Tanous             [&app](const crow::Request& req,
1923bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1924bf648f77SEd Tanous                    const std::string& ifaceId) {
19253ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
192645ca1b86SEd Tanous         {
192745ca1b86SEd Tanous             return;
192845ca1b86SEd Tanous         }
19294a0cb85cSEd Tanous         getEthernetIfaceData(
1930bf648f77SEd Tanous             ifaceId,
193177179532SEd Tanous             [asyncResp, ifaceId](const bool& success,
193277179532SEd Tanous                                  const EthernetInterfaceData& ethData,
193377179532SEd Tanous                                  const std::vector<IPv4AddressData>& ipv4Data,
193477179532SEd Tanous                                  const std::vector<IPv6AddressData>& ipv6Data) {
19354a0cb85cSEd Tanous             if (!success)
19361abe55efSEd Tanous             {
1937bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
1938bf648f77SEd Tanous                 // existing object, and other errors
1939002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1940002d39b4SEd Tanous                                            ifaceId);
19414a0cb85cSEd Tanous                 return;
19429391bb9cSRapkiewicz, Pawel             }
19434c9afe43SEd Tanous 
19440f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
194593bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
1946002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
19470f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
19480f74e643SEd Tanous                 "Management Network Interface";
19490f74e643SEd Tanous 
1950002d39b4SEd Tanous             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
19519391bb9cSRapkiewicz, Pawel         });
1952bf648f77SEd Tanous     });
19539391bb9cSRapkiewicz, Pawel 
1954bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
1955ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
1956bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
195745ca1b86SEd Tanous             [&app](const crow::Request& req,
1958bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1959bf648f77SEd Tanous                    const std::string& ifaceId) {
19603ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
196145ca1b86SEd Tanous         {
196245ca1b86SEd Tanous             return;
196345ca1b86SEd Tanous         }
1964bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
1965ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
1966d577665bSRatan Gupta         std::optional<std::string> macAddress;
19679a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
1968ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
1969ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
1970f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
1971da131a9aSJennifer Lee         std::optional<nlohmann::json> dhcpv4;
19721f8c7b5dSJohnathan Mantey         std::optional<nlohmann::json> dhcpv6;
1973b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
1974eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
197535fb5311STejas Patil         std::optional<size_t> mtuSize;
19761f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
19771f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
1978b10d8db0SRavi Teja         // clang-format off
197915ed6780SWilly Tu         if (!json_util::readJsonPatch(
1980b10d8db0SRavi Teja                 req, asyncResp->res,
1981b10d8db0SRavi Teja                 "DHCPv4", dhcpv4,
1982b10d8db0SRavi Teja                 "DHCPv6", dhcpv6,
1983b10d8db0SRavi Teja                 "FQDN", fqdn,
1984b10d8db0SRavi Teja                 "HostName", hostname,
1985b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
1986b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
1987b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
1988b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
1989b10d8db0SRavi Teja                 "MACAddress", macAddress,
1990b10d8db0SRavi Teja                 "MTUSize", mtuSize,
1991b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
1992b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
1993b10d8db0SRavi Teja                 )
1994b10d8db0SRavi Teja             )
19951abe55efSEd Tanous         {
1996588c3f0dSKowalski, Kamil             return;
1997588c3f0dSKowalski, Kamil         }
1998b10d8db0SRavi Teja         //clang-format on
1999da131a9aSJennifer Lee         if (dhcpv4)
2000da131a9aSJennifer Lee         {
2001002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
20021f8c7b5dSJohnathan Mantey                                      v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
200382695a5bSJiaqing Zhao                                      v4dhcpParms.useDnsServers, "UseNTPServers",
200482695a5bSJiaqing Zhao                                      v4dhcpParms.useNtpServers, "UseDomainName",
200582695a5bSJiaqing Zhao                                      v4dhcpParms.useDomainName))
20061f8c7b5dSJohnathan Mantey             {
20071f8c7b5dSJohnathan Mantey                 return;
20081f8c7b5dSJohnathan Mantey             }
20091f8c7b5dSJohnathan Mantey         }
20101f8c7b5dSJohnathan Mantey 
20111f8c7b5dSJohnathan Mantey         if (dhcpv6)
20121f8c7b5dSJohnathan Mantey         {
2013002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2014002d39b4SEd Tanous                                      v6dhcpParms.dhcpv6OperatingMode,
2015002d39b4SEd Tanous                                      "UseDNSServers", v6dhcpParms.useDnsServers,
2016002d39b4SEd Tanous                                      "UseNTPServers", v6dhcpParms.useNtpServers,
2017002d39b4SEd Tanous                                      "UseDomainName",
201882695a5bSJiaqing Zhao                                      v6dhcpParms.useDomainName))
20191f8c7b5dSJohnathan Mantey             {
20201f8c7b5dSJohnathan Mantey                 return;
20211f8c7b5dSJohnathan Mantey             }
2022da131a9aSJennifer Lee         }
2023da131a9aSJennifer Lee 
2024bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2025bf648f77SEd Tanous         // for JSON preparation
20264a0cb85cSEd Tanous         getEthernetIfaceData(
20272c70f800SEd Tanous             ifaceId,
2028bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2029ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2030d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
20319a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2032e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
20331f8c7b5dSJohnathan Mantey              staticNameServers = std::move(staticNameServers),
2034bc20089aSEd Tanous              dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
2035b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2036f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2037002d39b4SEd Tanous                 const bool& success, const EthernetInterfaceData& ethData,
203877179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
203977179532SEd Tanous                 const std::vector<IPv6AddressData>& ipv6Data) {
20401abe55efSEd Tanous             if (!success)
20411abe55efSEd Tanous             {
2042588c3f0dSKowalski, Kamil                 // ... otherwise return error
2043bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2044bf648f77SEd Tanous                 // existing object, and other errors
2045002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2046002d39b4SEd Tanous                                            ifaceId);
2047588c3f0dSKowalski, Kamil                 return;
2048588c3f0dSKowalski, Kamil             }
2049588c3f0dSKowalski, Kamil 
20501f8c7b5dSJohnathan Mantey             if (dhcpv4 || dhcpv6)
20511f8c7b5dSJohnathan Mantey             {
2052002d39b4SEd Tanous                 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2053002d39b4SEd Tanous                                 asyncResp);
20541f8c7b5dSJohnathan Mantey             }
20551f8c7b5dSJohnathan Mantey 
20560627a2c7SEd Tanous             if (hostname)
20571abe55efSEd Tanous             {
20580627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
20591abe55efSEd Tanous             }
20600627a2c7SEd Tanous 
2061b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2062b10d8db0SRavi Teja             {
2063b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2064b10d8db0SRavi Teja                                            asyncResp);
2065b10d8db0SRavi Teja             }
2066b10d8db0SRavi Teja 
2067ab6554f1SJoshi-Mansi             if (fqdn)
2068ab6554f1SJoshi-Mansi             {
20692c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2070ab6554f1SJoshi-Mansi             }
2071ab6554f1SJoshi-Mansi 
2072d577665bSRatan Gupta             if (macAddress)
2073d577665bSRatan Gupta             {
2074002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2075d577665bSRatan Gupta             }
2076d577665bSRatan Gupta 
2077d1d50814SRavi Teja             if (ipv4StaticAddresses)
2078d1d50814SRavi Teja             {
2079bf648f77SEd Tanous                 // TODO(ed) for some reason the capture of
2080bf648f77SEd Tanous                 // ipv4Addresses above is returning a const value,
2081bf648f77SEd Tanous                 // not a non-const value. This doesn't really work
2082bf648f77SEd Tanous                 // for us, as we need to be able to efficiently move
2083bf648f77SEd Tanous                 // out the intermedia nlohmann::json objects. This
2084bf648f77SEd Tanous                 // makes a copy of the structure, and operates on
2085bf648f77SEd Tanous                 // that, but could be done more efficiently
2086ddd70dcaSEd Tanous                 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
2087002d39b4SEd Tanous                 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
20881abe55efSEd Tanous             }
20890627a2c7SEd Tanous 
2090f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2091f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2092002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2093002d39b4SEd Tanous                                              asyncResp);
2094f85837bfSRAJESWARAN THILLAIGOVINDAN             }
20959a6fc6feSRavi Teja 
20969a6fc6feSRavi Teja             if (ipv6DefaultGateway)
20979a6fc6feSRavi Teja             {
20989a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
20999a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
21009a6fc6feSRavi Teja             }
2101e48c0fc5SRavi Teja 
2102e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2103e48c0fc5SRavi Teja             {
2104ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2105ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2106e48c0fc5SRavi Teja             }
2107eeedda23SJohnathan Mantey 
2108eeedda23SJohnathan Mantey             if (interfaceEnabled)
2109eeedda23SJohnathan Mantey             {
2110002d39b4SEd Tanous                 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2111002d39b4SEd Tanous                                                  *interfaceEnabled, asyncResp);
2112eeedda23SJohnathan Mantey             }
211335fb5311STejas Patil 
211435fb5311STejas Patil             if (mtuSize)
211535fb5311STejas Patil             {
211635fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
211735fb5311STejas Patil             }
2118588c3f0dSKowalski, Kamil             });
2119bf648f77SEd Tanous         });
2120e7caf250SJiaqing Zhao 
2121e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2122e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2123e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2124e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2125e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2126e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2127e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2128e7caf250SJiaqing Zhao         {
2129e7caf250SJiaqing Zhao             return;
2130e7caf250SJiaqing Zhao         }
2131e7caf250SJiaqing Zhao 
2132e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2133e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2134e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2135e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2136e7caf250SJiaqing Zhao             },
2137e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2138e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2139e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2140e7caf250SJiaqing Zhao         });
21414a0cb85cSEd Tanous }
2142bf648f77SEd Tanous 
21439391bb9cSRapkiewicz, Pawel } // namespace redfish
2144