xref: /openbmc/bmcweb/features/redfish/lib/ethernet.hpp (revision 91c441ecd8603d6ba6c64e52dded5b300b2eec01)
19391bb9cSRapkiewicz, Pawel /*
29391bb9cSRapkiewicz, Pawel // Copyright (c) 2018 Intel Corporation
39391bb9cSRapkiewicz, Pawel //
49391bb9cSRapkiewicz, Pawel // Licensed under the Apache License, Version 2.0 (the "License");
59391bb9cSRapkiewicz, Pawel // you may not use this file except in compliance with the License.
69391bb9cSRapkiewicz, Pawel // You may obtain a copy of the License at
79391bb9cSRapkiewicz, Pawel //
89391bb9cSRapkiewicz, Pawel //      http://www.apache.org/licenses/LICENSE-2.0
99391bb9cSRapkiewicz, Pawel //
109391bb9cSRapkiewicz, Pawel // Unless required by applicable law or agreed to in writing, software
119391bb9cSRapkiewicz, Pawel // distributed under the License is distributed on an "AS IS" BASIS,
129391bb9cSRapkiewicz, Pawel // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139391bb9cSRapkiewicz, Pawel // See the License for the specific language governing permissions and
149391bb9cSRapkiewicz, Pawel // limitations under the License.
159391bb9cSRapkiewicz, Pawel */
169391bb9cSRapkiewicz, Pawel #pragma once
179391bb9cSRapkiewicz, Pawel 
1813451e39SWilly Tu #include "bmcweb_config.h"
1913451e39SWilly Tu 
203ccb3adbSEd Tanous #include "app.hpp"
213ccb3adbSEd Tanous #include "dbus_singleton.hpp"
227a1dbc48SGeorge Liu #include "dbus_utility.hpp"
233ccb3adbSEd Tanous #include "error_messages.hpp"
243ccb3adbSEd Tanous #include "health.hpp"
252c5875a2SEd Tanous #include "human_sort.hpp"
263ccb3adbSEd Tanous #include "query.hpp"
273ccb3adbSEd Tanous #include "registries/privilege_registry.hpp"
28033f1e4dSEd Tanous #include "utils/ip_utils.hpp"
293ccb3adbSEd Tanous #include "utils/json_utils.hpp"
30033f1e4dSEd Tanous 
31ef4c65b7SEd Tanous #include <boost/url/format.hpp>
321214b7e7SGunnar Mills 
337a1dbc48SGeorge Liu #include <array>
34a24526dcSEd Tanous #include <optional>
353544d2a7SEd Tanous #include <ranges>
36ab6554f1SJoshi-Mansi #include <regex>
377a1dbc48SGeorge Liu #include <string_view>
3877179532SEd Tanous #include <vector>
399391bb9cSRapkiewicz, Pawel 
401abe55efSEd Tanous namespace redfish
411abe55efSEd Tanous {
429391bb9cSRapkiewicz, Pawel 
434a0cb85cSEd Tanous enum class LinkType
444a0cb85cSEd Tanous {
454a0cb85cSEd Tanous     Local,
464a0cb85cSEd Tanous     Global
474a0cb85cSEd Tanous };
489391bb9cSRapkiewicz, Pawel 
499391bb9cSRapkiewicz, Pawel /**
509391bb9cSRapkiewicz, Pawel  * Structure for keeping IPv4 data required by Redfish
519391bb9cSRapkiewicz, Pawel  */
521abe55efSEd Tanous struct IPv4AddressData
531abe55efSEd Tanous {
54179db1d7SKowalski, Kamil     std::string id;
554a0cb85cSEd Tanous     std::string address;
564a0cb85cSEd Tanous     std::string domain;
574a0cb85cSEd Tanous     std::string gateway;
589391bb9cSRapkiewicz, Pawel     std::string netmask;
599391bb9cSRapkiewicz, Pawel     std::string origin;
6077179532SEd Tanous     LinkType linktype{};
6177179532SEd Tanous     bool isActive{};
629391bb9cSRapkiewicz, Pawel };
639391bb9cSRapkiewicz, Pawel 
649391bb9cSRapkiewicz, Pawel /**
65e48c0fc5SRavi Teja  * Structure for keeping IPv6 data required by Redfish
66e48c0fc5SRavi Teja  */
67e48c0fc5SRavi Teja struct IPv6AddressData
68e48c0fc5SRavi Teja {
69e48c0fc5SRavi Teja     std::string id;
70e48c0fc5SRavi Teja     std::string address;
71e48c0fc5SRavi Teja     std::string origin;
7277179532SEd Tanous     uint8_t prefixLength = 0;
73e48c0fc5SRavi Teja };
74e48c0fc5SRavi Teja /**
759391bb9cSRapkiewicz, Pawel  * Structure for keeping basic single Ethernet Interface information
769391bb9cSRapkiewicz, Pawel  * available from DBus
779391bb9cSRapkiewicz, Pawel  */
781abe55efSEd Tanous struct EthernetInterfaceData
791abe55efSEd Tanous {
804a0cb85cSEd Tanous     uint32_t speed;
8135fb5311STejas Patil     size_t mtuSize;
8282695a5bSJiaqing Zhao     bool autoNeg;
83e4588158SJishnu CM     bool dnsv4Enabled;
84e4588158SJishnu CM     bool dnsv6Enabled;
85*91c441ecSRavi Teja     bool domainv4Enabled;
86*91c441ecSRavi Teja     bool domainv6Enabled;
87e4588158SJishnu CM     bool ntpv4Enabled;
88e4588158SJishnu CM     bool ntpv6Enabled;
89e4588158SJishnu CM     bool hostNamev4Enabled;
90e4588158SJishnu CM     bool hostNamev6Enabled;
91aa05fb27SJohnathan Mantey     bool linkUp;
92eeedda23SJohnathan Mantey     bool nicEnabled;
93b10d8db0SRavi Teja     bool ipv6AcceptRa;
9482695a5bSJiaqing Zhao     std::string dhcpEnabled;
951f8c7b5dSJohnathan Mantey     std::string operatingMode;
9682695a5bSJiaqing Zhao     std::string hostName;
9782695a5bSJiaqing Zhao     std::string defaultGateway;
9882695a5bSJiaqing Zhao     std::string ipv6DefaultGateway;
9982695a5bSJiaqing Zhao     std::string macAddress;
10017e22024SJiaqing Zhao     std::optional<uint32_t> vlanId;
1010f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> nameServers;
1020f6efdc1Smanojkiran.eda@gmail.com     std::vector<std::string> staticNameServers;
103d24bfc7aSJennifer Lee     std::vector<std::string> domainnames;
1049391bb9cSRapkiewicz, Pawel };
1059391bb9cSRapkiewicz, Pawel 
1061f8c7b5dSJohnathan Mantey struct DHCPParameters
1071f8c7b5dSJohnathan Mantey {
1081f8c7b5dSJohnathan Mantey     std::optional<bool> dhcpv4Enabled;
10982695a5bSJiaqing Zhao     std::optional<bool> useDnsServers;
11082695a5bSJiaqing Zhao     std::optional<bool> useNtpServers;
11182695a5bSJiaqing Zhao     std::optional<bool> useDomainName;
1121f8c7b5dSJohnathan Mantey     std::optional<std::string> dhcpv6OperatingMode;
1131f8c7b5dSJohnathan Mantey };
1141f8c7b5dSJohnathan Mantey 
1159391bb9cSRapkiewicz, Pawel // Helper function that changes bits netmask notation (i.e. /24)
1169391bb9cSRapkiewicz, Pawel // into full dot notation
1171abe55efSEd Tanous inline std::string getNetmask(unsigned int bits)
1181abe55efSEd Tanous {
1199391bb9cSRapkiewicz, Pawel     uint32_t value = 0xffffffff << (32 - bits);
1209391bb9cSRapkiewicz, Pawel     std::string netmask = std::to_string((value >> 24) & 0xff) + "." +
1219391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 16) & 0xff) + "." +
1229391bb9cSRapkiewicz, Pawel                           std::to_string((value >> 8) & 0xff) + "." +
1239391bb9cSRapkiewicz, Pawel                           std::to_string(value & 0xff);
1249391bb9cSRapkiewicz, Pawel     return netmask;
1259391bb9cSRapkiewicz, Pawel }
1269391bb9cSRapkiewicz, Pawel 
12782695a5bSJiaqing Zhao inline bool translateDhcpEnabledToBool(const std::string& inputDHCP,
1281f8c7b5dSJohnathan Mantey                                        bool isIPv4)
1291f8c7b5dSJohnathan Mantey {
1301f8c7b5dSJohnathan Mantey     if (isIPv4)
1311f8c7b5dSJohnathan Mantey     {
1321f8c7b5dSJohnathan Mantey         return (
1331f8c7b5dSJohnathan Mantey             (inputDHCP ==
1341f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4") ||
1351f8c7b5dSJohnathan Mantey             (inputDHCP ==
1361f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1371f8c7b5dSJohnathan Mantey     }
1381f8c7b5dSJohnathan Mantey     return ((inputDHCP ==
1391f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6") ||
1401f8c7b5dSJohnathan Mantey             (inputDHCP ==
1411f8c7b5dSJohnathan Mantey              "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both"));
1421f8c7b5dSJohnathan Mantey }
1431f8c7b5dSJohnathan Mantey 
1442c70f800SEd Tanous inline std::string getDhcpEnabledEnumeration(bool isIPv4, bool isIPv6)
1451f8c7b5dSJohnathan Mantey {
1461f8c7b5dSJohnathan Mantey     if (isIPv4 && isIPv6)
1471f8c7b5dSJohnathan Mantey     {
1481f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.both";
1491f8c7b5dSJohnathan Mantey     }
1503174e4dfSEd Tanous     if (isIPv4)
1511f8c7b5dSJohnathan Mantey     {
1521f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v4";
1531f8c7b5dSJohnathan Mantey     }
1543174e4dfSEd Tanous     if (isIPv6)
1551f8c7b5dSJohnathan Mantey     {
1561f8c7b5dSJohnathan Mantey         return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.v6";
1571f8c7b5dSJohnathan Mantey     }
1581f8c7b5dSJohnathan Mantey     return "xyz.openbmc_project.Network.EthernetInterface.DHCPConf.none";
1591f8c7b5dSJohnathan Mantey }
1601f8c7b5dSJohnathan Mantey 
1614a0cb85cSEd Tanous inline std::string
1624a0cb85cSEd Tanous     translateAddressOriginDbusToRedfish(const std::string& inputOrigin,
1634a0cb85cSEd Tanous                                         bool isIPv4)
1641abe55efSEd Tanous {
1654a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
1661abe55efSEd Tanous     {
1674a0cb85cSEd Tanous         return "Static";
1689391bb9cSRapkiewicz, Pawel     }
1694a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.LinkLocal")
1701abe55efSEd Tanous     {
1714a0cb85cSEd Tanous         if (isIPv4)
1721abe55efSEd Tanous         {
1734a0cb85cSEd Tanous             return "IPv4LinkLocal";
1741abe55efSEd Tanous         }
1754a0cb85cSEd Tanous         return "LinkLocal";
1769391bb9cSRapkiewicz, Pawel     }
1774a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1781abe55efSEd Tanous     {
1794a0cb85cSEd Tanous         if (isIPv4)
1804a0cb85cSEd Tanous         {
1814a0cb85cSEd Tanous             return "DHCP";
1824a0cb85cSEd Tanous         }
1834a0cb85cSEd Tanous         return "DHCPv6";
1844a0cb85cSEd Tanous     }
1854a0cb85cSEd Tanous     if (inputOrigin == "xyz.openbmc_project.Network.IP.AddressOrigin.SLAAC")
1864a0cb85cSEd Tanous     {
1874a0cb85cSEd Tanous         return "SLAAC";
1884a0cb85cSEd Tanous     }
1894a0cb85cSEd Tanous     return "";
1904a0cb85cSEd Tanous }
1914a0cb85cSEd Tanous 
19202cad96eSEd Tanous inline bool extractEthernetInterfaceData(
19302cad96eSEd Tanous     const std::string& ethifaceId,
19402cad96eSEd Tanous     const dbus::utility::ManagedObjectType& dbusData,
1954a0cb85cSEd Tanous     EthernetInterfaceData& ethData)
1964a0cb85cSEd Tanous {
1974c9afe43SEd Tanous     bool idFound = false;
19802cad96eSEd Tanous     for (const auto& objpath : dbusData)
1994a0cb85cSEd Tanous     {
20002cad96eSEd Tanous         for (const auto& ifacePair : objpath.second)
2014a0cb85cSEd Tanous         {
20281ce609eSEd Tanous             if (objpath.first == "/xyz/openbmc_project/network/" + ethifaceId)
203029573d4SEd Tanous             {
2044c9afe43SEd Tanous                 idFound = true;
2054a0cb85cSEd Tanous                 if (ifacePair.first == "xyz.openbmc_project.Network.MACAddress")
2064a0cb85cSEd Tanous                 {
2074a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2084a0cb85cSEd Tanous                     {
2094a0cb85cSEd Tanous                         if (propertyPair.first == "MACAddress")
2104a0cb85cSEd Tanous                         {
2114a0cb85cSEd Tanous                             const std::string* mac =
212abf2add6SEd Tanous                                 std::get_if<std::string>(&propertyPair.second);
2134a0cb85cSEd Tanous                             if (mac != nullptr)
2144a0cb85cSEd Tanous                             {
21582695a5bSJiaqing Zhao                                 ethData.macAddress = *mac;
2164a0cb85cSEd Tanous                             }
2174a0cb85cSEd Tanous                         }
2184a0cb85cSEd Tanous                     }
2194a0cb85cSEd Tanous                 }
2204a0cb85cSEd Tanous                 else if (ifacePair.first == "xyz.openbmc_project.Network.VLAN")
2214a0cb85cSEd Tanous                 {
2224a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2234a0cb85cSEd Tanous                     {
2244a0cb85cSEd Tanous                         if (propertyPair.first == "Id")
2254a0cb85cSEd Tanous                         {
2261b6b96c5SEd Tanous                             const uint32_t* id =
227abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2284a0cb85cSEd Tanous                             if (id != nullptr)
2294a0cb85cSEd Tanous                             {
23017e22024SJiaqing Zhao                                 ethData.vlanId = *id;
2314a0cb85cSEd Tanous                             }
2324a0cb85cSEd Tanous                         }
2334a0cb85cSEd Tanous                     }
2344a0cb85cSEd Tanous                 }
2354a0cb85cSEd Tanous                 else if (ifacePair.first ==
2364a0cb85cSEd Tanous                          "xyz.openbmc_project.Network.EthernetInterface")
2374a0cb85cSEd Tanous                 {
2384a0cb85cSEd Tanous                     for (const auto& propertyPair : ifacePair.second)
2394a0cb85cSEd Tanous                     {
2404a0cb85cSEd Tanous                         if (propertyPair.first == "AutoNeg")
2414a0cb85cSEd Tanous                         {
2422c70f800SEd Tanous                             const bool* autoNeg =
243abf2add6SEd Tanous                                 std::get_if<bool>(&propertyPair.second);
2442c70f800SEd Tanous                             if (autoNeg != nullptr)
2454a0cb85cSEd Tanous                             {
24682695a5bSJiaqing Zhao                                 ethData.autoNeg = *autoNeg;
2474a0cb85cSEd Tanous                             }
2484a0cb85cSEd Tanous                         }
2494a0cb85cSEd Tanous                         else if (propertyPair.first == "Speed")
2504a0cb85cSEd Tanous                         {
2514a0cb85cSEd Tanous                             const uint32_t* speed =
252abf2add6SEd Tanous                                 std::get_if<uint32_t>(&propertyPair.second);
2534a0cb85cSEd Tanous                             if (speed != nullptr)
2544a0cb85cSEd Tanous                             {
2554a0cb85cSEd Tanous                                 ethData.speed = *speed;
2564a0cb85cSEd Tanous                             }
2574a0cb85cSEd Tanous                         }
25835fb5311STejas Patil                         else if (propertyPair.first == "MTU")
25935fb5311STejas Patil                         {
2603e7a8da6SAnthony                             const size_t* mtuSize =
2613e7a8da6SAnthony                                 std::get_if<size_t>(&propertyPair.second);
26235fb5311STejas Patil                             if (mtuSize != nullptr)
26335fb5311STejas Patil                             {
26435fb5311STejas Patil                                 ethData.mtuSize = *mtuSize;
26535fb5311STejas Patil                             }
26635fb5311STejas Patil                         }
267aa05fb27SJohnathan Mantey                         else if (propertyPair.first == "LinkUp")
268aa05fb27SJohnathan Mantey                         {
269aa05fb27SJohnathan Mantey                             const bool* linkUp =
270aa05fb27SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
271aa05fb27SJohnathan Mantey                             if (linkUp != nullptr)
272aa05fb27SJohnathan Mantey                             {
273aa05fb27SJohnathan Mantey                                 ethData.linkUp = *linkUp;
274aa05fb27SJohnathan Mantey                             }
275aa05fb27SJohnathan Mantey                         }
276eeedda23SJohnathan Mantey                         else if (propertyPair.first == "NICEnabled")
277eeedda23SJohnathan Mantey                         {
278eeedda23SJohnathan Mantey                             const bool* nicEnabled =
279eeedda23SJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
280eeedda23SJohnathan Mantey                             if (nicEnabled != nullptr)
281eeedda23SJohnathan Mantey                             {
282eeedda23SJohnathan Mantey                                 ethData.nicEnabled = *nicEnabled;
283eeedda23SJohnathan Mantey                             }
284eeedda23SJohnathan Mantey                         }
285b10d8db0SRavi Teja                         else if (propertyPair.first == "IPv6AcceptRA")
286b10d8db0SRavi Teja                         {
287b10d8db0SRavi Teja                             const bool* ipv6AcceptRa =
288b10d8db0SRavi Teja                                 std::get_if<bool>(&propertyPair.second);
289b10d8db0SRavi Teja                             if (ipv6AcceptRa != nullptr)
290b10d8db0SRavi Teja                             {
291b10d8db0SRavi Teja                                 ethData.ipv6AcceptRa = *ipv6AcceptRa;
292b10d8db0SRavi Teja                             }
293b10d8db0SRavi Teja                         }
294f85837bfSRAJESWARAN THILLAIGOVINDAN                         else if (propertyPair.first == "Nameservers")
295029573d4SEd Tanous                         {
296029573d4SEd Tanous                             const std::vector<std::string>* nameservers =
2978d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
298029573d4SEd Tanous                                     &propertyPair.second);
299029573d4SEd Tanous                             if (nameservers != nullptr)
300029573d4SEd Tanous                             {
301f23b7296SEd Tanous                                 ethData.nameServers = *nameservers;
3020f6efdc1Smanojkiran.eda@gmail.com                             }
3030f6efdc1Smanojkiran.eda@gmail.com                         }
3040f6efdc1Smanojkiran.eda@gmail.com                         else if (propertyPair.first == "StaticNameServers")
3050f6efdc1Smanojkiran.eda@gmail.com                         {
3060f6efdc1Smanojkiran.eda@gmail.com                             const std::vector<std::string>* staticNameServers =
3078d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
3080f6efdc1Smanojkiran.eda@gmail.com                                     &propertyPair.second);
3090f6efdc1Smanojkiran.eda@gmail.com                             if (staticNameServers != nullptr)
3100f6efdc1Smanojkiran.eda@gmail.com                             {
311f23b7296SEd Tanous                                 ethData.staticNameServers = *staticNameServers;
3124a0cb85cSEd Tanous                             }
3134a0cb85cSEd Tanous                         }
3142a133282Smanojkiraneda                         else if (propertyPair.first == "DHCPEnabled")
3152a133282Smanojkiraneda                         {
3162c70f800SEd Tanous                             const std::string* dhcpEnabled =
3171f8c7b5dSJohnathan Mantey                                 std::get_if<std::string>(&propertyPair.second);
3182c70f800SEd Tanous                             if (dhcpEnabled != nullptr)
3192a133282Smanojkiraneda                             {
32082695a5bSJiaqing Zhao                                 ethData.dhcpEnabled = *dhcpEnabled;
3212a133282Smanojkiraneda                             }
3222a133282Smanojkiraneda                         }
323d24bfc7aSJennifer Lee                         else if (propertyPair.first == "DomainName")
324d24bfc7aSJennifer Lee                         {
325d24bfc7aSJennifer Lee                             const std::vector<std::string>* domainNames =
3268d78b7a9SPatrick Williams                                 std::get_if<std::vector<std::string>>(
327d24bfc7aSJennifer Lee                                     &propertyPair.second);
328d24bfc7aSJennifer Lee                             if (domainNames != nullptr)
329d24bfc7aSJennifer Lee                             {
330f23b7296SEd Tanous                                 ethData.domainnames = *domainNames;
331d24bfc7aSJennifer Lee                             }
332d24bfc7aSJennifer Lee                         }
3339010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway")
3349010ec2eSRavi Teja                         {
3359010ec2eSRavi Teja                             const std::string* defaultGateway =
3369010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3379010ec2eSRavi Teja                             if (defaultGateway != nullptr)
3389010ec2eSRavi Teja                             {
3399010ec2eSRavi Teja                                 std::string defaultGatewayStr = *defaultGateway;
3409010ec2eSRavi Teja                                 if (defaultGatewayStr.empty())
3419010ec2eSRavi Teja                                 {
34282695a5bSJiaqing Zhao                                     ethData.defaultGateway = "0.0.0.0";
3439010ec2eSRavi Teja                                 }
3449010ec2eSRavi Teja                                 else
3459010ec2eSRavi Teja                                 {
34682695a5bSJiaqing Zhao                                     ethData.defaultGateway = defaultGatewayStr;
3479010ec2eSRavi Teja                                 }
3489010ec2eSRavi Teja                             }
3499010ec2eSRavi Teja                         }
3509010ec2eSRavi Teja                         else if (propertyPair.first == "DefaultGateway6")
3519010ec2eSRavi Teja                         {
3529010ec2eSRavi Teja                             const std::string* defaultGateway6 =
3539010ec2eSRavi Teja                                 std::get_if<std::string>(&propertyPair.second);
3549010ec2eSRavi Teja                             if (defaultGateway6 != nullptr)
3559010ec2eSRavi Teja                             {
3569010ec2eSRavi Teja                                 std::string defaultGateway6Str =
3579010ec2eSRavi Teja                                     *defaultGateway6;
3589010ec2eSRavi Teja                                 if (defaultGateway6Str.empty())
3599010ec2eSRavi Teja                                 {
36082695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3619010ec2eSRavi Teja                                         "0:0:0:0:0:0:0:0";
3629010ec2eSRavi Teja                                 }
3639010ec2eSRavi Teja                                 else
3649010ec2eSRavi Teja                                 {
36582695a5bSJiaqing Zhao                                     ethData.ipv6DefaultGateway =
3669010ec2eSRavi Teja                                         defaultGateway6Str;
3679010ec2eSRavi Teja                                 }
3689010ec2eSRavi Teja                             }
3699010ec2eSRavi Teja                         }
370029573d4SEd Tanous                     }
371029573d4SEd Tanous                 }
372029573d4SEd Tanous             }
3731f8c7b5dSJohnathan Mantey 
374e4588158SJishnu CM             sdbusplus::message::object_path path(
375e4588158SJishnu CM                 "/xyz/openbmc_project/network");
376e4588158SJishnu CM             sdbusplus::message::object_path dhcp4Path = path / ethifaceId /
377e4588158SJishnu CM                                                         "dhcp4";
378e4588158SJishnu CM 
379e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp4Path)
3801f8c7b5dSJohnathan Mantey             {
3811f8c7b5dSJohnathan Mantey                 if (ifacePair.first ==
3821f8c7b5dSJohnathan Mantey                     "xyz.openbmc_project.Network.DHCPConfiguration")
3831f8c7b5dSJohnathan Mantey                 {
3841f8c7b5dSJohnathan Mantey                     for (const auto& propertyPair : ifacePair.second)
3851f8c7b5dSJohnathan Mantey                     {
3861f8c7b5dSJohnathan Mantey                         if (propertyPair.first == "DNSEnabled")
3871f8c7b5dSJohnathan Mantey                         {
3882c70f800SEd Tanous                             const bool* dnsEnabled =
3891f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
3902c70f800SEd Tanous                             if (dnsEnabled != nullptr)
3911f8c7b5dSJohnathan Mantey                             {
392e4588158SJishnu CM                                 ethData.dnsv4Enabled = *dnsEnabled;
3931f8c7b5dSJohnathan Mantey                             }
3941f8c7b5dSJohnathan Mantey                         }
395*91c441ecSRavi Teja                         else if (propertyPair.first == "DomainEnabled")
396*91c441ecSRavi Teja                         {
397*91c441ecSRavi Teja                             const bool* domainEnabled =
398*91c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
399*91c441ecSRavi Teja                             if (domainEnabled != nullptr)
400*91c441ecSRavi Teja                             {
401*91c441ecSRavi Teja                                 ethData.domainv4Enabled = *domainEnabled;
402*91c441ecSRavi Teja                             }
403*91c441ecSRavi Teja                         }
4041f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "NTPEnabled")
4051f8c7b5dSJohnathan Mantey                         {
4062c70f800SEd Tanous                             const bool* ntpEnabled =
4071f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4082c70f800SEd Tanous                             if (ntpEnabled != nullptr)
4091f8c7b5dSJohnathan Mantey                             {
410e4588158SJishnu CM                                 ethData.ntpv4Enabled = *ntpEnabled;
4111f8c7b5dSJohnathan Mantey                             }
4121f8c7b5dSJohnathan Mantey                         }
4131f8c7b5dSJohnathan Mantey                         else if (propertyPair.first == "HostNameEnabled")
4141f8c7b5dSJohnathan Mantey                         {
4152c70f800SEd Tanous                             const bool* hostNameEnabled =
4161f8c7b5dSJohnathan Mantey                                 std::get_if<bool>(&propertyPair.second);
4172c70f800SEd Tanous                             if (hostNameEnabled != nullptr)
4181f8c7b5dSJohnathan Mantey                             {
419e4588158SJishnu CM                                 ethData.hostNamev4Enabled = *hostNameEnabled;
420e4588158SJishnu CM                             }
421e4588158SJishnu CM                         }
422e4588158SJishnu CM                     }
423e4588158SJishnu CM                 }
424e4588158SJishnu CM             }
425e4588158SJishnu CM 
426e4588158SJishnu CM             sdbusplus::message::object_path dhcp6Path = path / ethifaceId /
427e4588158SJishnu CM                                                         "dhcp6";
428e4588158SJishnu CM 
429e4588158SJishnu CM             if (sdbusplus::message::object_path(objpath.first) == dhcp6Path)
430e4588158SJishnu CM             {
431e4588158SJishnu CM                 if (ifacePair.first ==
432e4588158SJishnu CM                     "xyz.openbmc_project.Network.DHCPConfiguration")
433e4588158SJishnu CM                 {
434e4588158SJishnu CM                     for (const auto& propertyPair : ifacePair.second)
435e4588158SJishnu CM                     {
436e4588158SJishnu CM                         if (propertyPair.first == "DNSEnabled")
437e4588158SJishnu CM                         {
438e4588158SJishnu CM                             const bool* dnsEnabled =
439e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
440e4588158SJishnu CM                             if (dnsEnabled != nullptr)
441e4588158SJishnu CM                             {
442e4588158SJishnu CM                                 ethData.dnsv6Enabled = *dnsEnabled;
443e4588158SJishnu CM                             }
444e4588158SJishnu CM                         }
445*91c441ecSRavi Teja                         if (propertyPair.first == "DomainEnabled")
446*91c441ecSRavi Teja                         {
447*91c441ecSRavi Teja                             const bool* domainEnabled =
448*91c441ecSRavi Teja                                 std::get_if<bool>(&propertyPair.second);
449*91c441ecSRavi Teja                             if (domainEnabled != nullptr)
450*91c441ecSRavi Teja                             {
451*91c441ecSRavi Teja                                 ethData.domainv6Enabled = *domainEnabled;
452*91c441ecSRavi Teja                             }
453*91c441ecSRavi Teja                         }
454e4588158SJishnu CM                         else if (propertyPair.first == "NTPEnabled")
455e4588158SJishnu CM                         {
456e4588158SJishnu CM                             const bool* ntpEnabled =
457e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
458e4588158SJishnu CM                             if (ntpEnabled != nullptr)
459e4588158SJishnu CM                             {
460e4588158SJishnu CM                                 ethData.ntpv6Enabled = *ntpEnabled;
461e4588158SJishnu CM                             }
462e4588158SJishnu CM                         }
463e4588158SJishnu CM                         else if (propertyPair.first == "HostNameEnabled")
464e4588158SJishnu CM                         {
465e4588158SJishnu CM                             const bool* hostNameEnabled =
466e4588158SJishnu CM                                 std::get_if<bool>(&propertyPair.second);
467e4588158SJishnu CM                             if (hostNameEnabled != nullptr)
468e4588158SJishnu CM                             {
469e4588158SJishnu CM                                 ethData.hostNamev6Enabled = *hostNameEnabled;
4701f8c7b5dSJohnathan Mantey                             }
4711f8c7b5dSJohnathan Mantey                         }
4721f8c7b5dSJohnathan Mantey                     }
4731f8c7b5dSJohnathan Mantey                 }
4741f8c7b5dSJohnathan Mantey             }
475029573d4SEd Tanous             // System configuration shows up in the global namespace, so no need
476029573d4SEd Tanous             // to check eth number
477029573d4SEd Tanous             if (ifacePair.first ==
4784a0cb85cSEd Tanous                 "xyz.openbmc_project.Network.SystemConfiguration")
4794a0cb85cSEd Tanous             {
4804a0cb85cSEd Tanous                 for (const auto& propertyPair : ifacePair.second)
4814a0cb85cSEd Tanous                 {
4824a0cb85cSEd Tanous                     if (propertyPair.first == "HostName")
4834a0cb85cSEd Tanous                     {
4844a0cb85cSEd Tanous                         const std::string* hostname =
4858d78b7a9SPatrick Williams                             std::get_if<std::string>(&propertyPair.second);
4864a0cb85cSEd Tanous                         if (hostname != nullptr)
4874a0cb85cSEd Tanous                         {
48882695a5bSJiaqing Zhao                             ethData.hostName = *hostname;
4894a0cb85cSEd Tanous                         }
4904a0cb85cSEd Tanous                     }
4914a0cb85cSEd Tanous                 }
4924a0cb85cSEd Tanous             }
4934a0cb85cSEd Tanous         }
4944a0cb85cSEd Tanous     }
4954c9afe43SEd Tanous     return idFound;
4964a0cb85cSEd Tanous }
4974a0cb85cSEd Tanous 
498e48c0fc5SRavi Teja // Helper function that extracts data for single ethernet ipv6 address
49977179532SEd Tanous inline void extractIPV6Data(const std::string& ethifaceId,
500711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& dbusData,
50177179532SEd Tanous                             std::vector<IPv6AddressData>& ipv6Config)
502e48c0fc5SRavi Teja {
50389492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
50489492a15SPatrick Williams                                     ethifaceId;
505e48c0fc5SRavi Teja 
506e48c0fc5SRavi Teja     // Since there might be several IPv6 configurations aligned with
507e48c0fc5SRavi Teja     // single ethernet interface, loop over all of them
50881ce609eSEd Tanous     for (const auto& objpath : dbusData)
509e48c0fc5SRavi Teja     {
510e48c0fc5SRavi Teja         // Check if proper pattern for object path appears
511353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
512e48c0fc5SRavi Teja         {
5139eb808c1SEd Tanous             for (const auto& interface : objpath.second)
514e48c0fc5SRavi Teja             {
515e48c0fc5SRavi Teja                 if (interface.first == "xyz.openbmc_project.Network.IP")
516e48c0fc5SRavi Teja                 {
5173544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
518353163e9STony Lee                                                      [](const auto& property) {
519353163e9STony Lee                         return property.first == "Type";
520353163e9STony Lee                     });
521353163e9STony Lee                     if (type == interface.second.end())
522353163e9STony Lee                     {
523353163e9STony Lee                         continue;
524353163e9STony Lee                     }
525353163e9STony Lee 
526353163e9STony Lee                     const std::string* typeStr =
527353163e9STony Lee                         std::get_if<std::string>(&type->second);
528353163e9STony Lee 
529353163e9STony Lee                     if (typeStr == nullptr ||
530353163e9STony Lee                         (*typeStr !=
531353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv6"))
532353163e9STony Lee                     {
533353163e9STony Lee                         continue;
534353163e9STony Lee                     }
535353163e9STony Lee 
536e48c0fc5SRavi Teja                     // Instance IPv6AddressData structure, and set as
537e48c0fc5SRavi Teja                     // appropriate
53877179532SEd Tanous                     IPv6AddressData& ipv6Address = ipv6Config.emplace_back();
5392c70f800SEd Tanous                     ipv6Address.id =
540353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
5419eb808c1SEd Tanous                     for (const auto& property : interface.second)
542e48c0fc5SRavi Teja                     {
543e48c0fc5SRavi Teja                         if (property.first == "Address")
544e48c0fc5SRavi Teja                         {
545e48c0fc5SRavi Teja                             const std::string* address =
546e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
547e48c0fc5SRavi Teja                             if (address != nullptr)
548e48c0fc5SRavi Teja                             {
5492c70f800SEd Tanous                                 ipv6Address.address = *address;
550e48c0fc5SRavi Teja                             }
551e48c0fc5SRavi Teja                         }
552e48c0fc5SRavi Teja                         else if (property.first == "Origin")
553e48c0fc5SRavi Teja                         {
554e48c0fc5SRavi Teja                             const std::string* origin =
555e48c0fc5SRavi Teja                                 std::get_if<std::string>(&property.second);
556e48c0fc5SRavi Teja                             if (origin != nullptr)
557e48c0fc5SRavi Teja                             {
5582c70f800SEd Tanous                                 ipv6Address.origin =
559e48c0fc5SRavi Teja                                     translateAddressOriginDbusToRedfish(*origin,
560e48c0fc5SRavi Teja                                                                         false);
561e48c0fc5SRavi Teja                             }
562e48c0fc5SRavi Teja                         }
563e48c0fc5SRavi Teja                         else if (property.first == "PrefixLength")
564e48c0fc5SRavi Teja                         {
565e48c0fc5SRavi Teja                             const uint8_t* prefix =
566e48c0fc5SRavi Teja                                 std::get_if<uint8_t>(&property.second);
567e48c0fc5SRavi Teja                             if (prefix != nullptr)
568e48c0fc5SRavi Teja                             {
5692c70f800SEd Tanous                                 ipv6Address.prefixLength = *prefix;
570e48c0fc5SRavi Teja                             }
571e48c0fc5SRavi Teja                         }
572889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
573889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
574889ff694SAsmitha Karunanithi                         {
575889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
576889ff694SAsmitha Karunanithi                         }
577e48c0fc5SRavi Teja                         else
578e48c0fc5SRavi Teja                         {
57962598e31SEd Tanous                             BMCWEB_LOG_ERROR(
58062598e31SEd Tanous                                 "Got extra property: {} on the {} object",
58162598e31SEd Tanous                                 property.first, objpath.first.str);
582e48c0fc5SRavi Teja                         }
583e48c0fc5SRavi Teja                     }
584e48c0fc5SRavi Teja                 }
585e48c0fc5SRavi Teja             }
586e48c0fc5SRavi Teja         }
587e48c0fc5SRavi Teja     }
588e48c0fc5SRavi Teja }
589e48c0fc5SRavi Teja 
5904a0cb85cSEd Tanous // Helper function that extracts data for single ethernet ipv4 address
59177179532SEd Tanous inline void extractIPData(const std::string& ethifaceId,
592711ac7a9SEd Tanous                           const dbus::utility::ManagedObjectType& dbusData,
59377179532SEd Tanous                           std::vector<IPv4AddressData>& ipv4Config)
5944a0cb85cSEd Tanous {
59589492a15SPatrick Williams     const std::string ipPathStart = "/xyz/openbmc_project/network/" +
59689492a15SPatrick Williams                                     ethifaceId;
5974a0cb85cSEd Tanous 
5984a0cb85cSEd Tanous     // Since there might be several IPv4 configurations aligned with
5994a0cb85cSEd Tanous     // single ethernet interface, loop over all of them
60081ce609eSEd Tanous     for (const auto& objpath : dbusData)
6014a0cb85cSEd Tanous     {
6024a0cb85cSEd Tanous         // Check if proper pattern for object path appears
603353163e9STony Lee         if (objpath.first.str.starts_with(ipPathStart + "/"))
6044a0cb85cSEd Tanous         {
6059eb808c1SEd Tanous             for (const auto& interface : objpath.second)
6064a0cb85cSEd Tanous             {
6074a0cb85cSEd Tanous                 if (interface.first == "xyz.openbmc_project.Network.IP")
6084a0cb85cSEd Tanous                 {
6093544d2a7SEd Tanous                     auto type = std::ranges::find_if(interface.second,
610353163e9STony Lee                                                      [](const auto& property) {
611353163e9STony Lee                         return property.first == "Type";
612353163e9STony Lee                     });
613353163e9STony Lee                     if (type == interface.second.end())
614353163e9STony Lee                     {
615353163e9STony Lee                         continue;
616353163e9STony Lee                     }
617353163e9STony Lee 
618353163e9STony Lee                     const std::string* typeStr =
619353163e9STony Lee                         std::get_if<std::string>(&type->second);
620353163e9STony Lee 
621353163e9STony Lee                     if (typeStr == nullptr ||
622353163e9STony Lee                         (*typeStr !=
623353163e9STony Lee                          "xyz.openbmc_project.Network.IP.Protocol.IPv4"))
624353163e9STony Lee                     {
625353163e9STony Lee                         continue;
626353163e9STony Lee                     }
627353163e9STony Lee 
6284a0cb85cSEd Tanous                     // Instance IPv4AddressData structure, and set as
6294a0cb85cSEd Tanous                     // appropriate
63077179532SEd Tanous                     IPv4AddressData& ipv4Address = ipv4Config.emplace_back();
6312c70f800SEd Tanous                     ipv4Address.id =
632353163e9STony Lee                         objpath.first.str.substr(ipPathStart.size());
6339eb808c1SEd Tanous                     for (const auto& property : interface.second)
6344a0cb85cSEd Tanous                     {
6354a0cb85cSEd Tanous                         if (property.first == "Address")
6364a0cb85cSEd Tanous                         {
6374a0cb85cSEd Tanous                             const std::string* address =
638abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6394a0cb85cSEd Tanous                             if (address != nullptr)
6404a0cb85cSEd Tanous                             {
6412c70f800SEd Tanous                                 ipv4Address.address = *address;
6424a0cb85cSEd Tanous                             }
6434a0cb85cSEd Tanous                         }
6444a0cb85cSEd Tanous                         else if (property.first == "Origin")
6454a0cb85cSEd Tanous                         {
6464a0cb85cSEd Tanous                             const std::string* origin =
647abf2add6SEd Tanous                                 std::get_if<std::string>(&property.second);
6484a0cb85cSEd Tanous                             if (origin != nullptr)
6494a0cb85cSEd Tanous                             {
6502c70f800SEd Tanous                                 ipv4Address.origin =
6514a0cb85cSEd Tanous                                     translateAddressOriginDbusToRedfish(*origin,
6524a0cb85cSEd Tanous                                                                         true);
6534a0cb85cSEd Tanous                             }
6544a0cb85cSEd Tanous                         }
6554a0cb85cSEd Tanous                         else if (property.first == "PrefixLength")
6564a0cb85cSEd Tanous                         {
6574a0cb85cSEd Tanous                             const uint8_t* mask =
658abf2add6SEd Tanous                                 std::get_if<uint8_t>(&property.second);
6594a0cb85cSEd Tanous                             if (mask != nullptr)
6604a0cb85cSEd Tanous                             {
6614a0cb85cSEd Tanous                                 // convert it to the string
6622c70f800SEd Tanous                                 ipv4Address.netmask = getNetmask(*mask);
6634a0cb85cSEd Tanous                             }
6644a0cb85cSEd Tanous                         }
665889ff694SAsmitha Karunanithi                         else if (property.first == "Type" ||
666889ff694SAsmitha Karunanithi                                  property.first == "Gateway")
667889ff694SAsmitha Karunanithi                         {
668889ff694SAsmitha Karunanithi                             // Type & Gateway is not used
669889ff694SAsmitha Karunanithi                         }
6704a0cb85cSEd Tanous                         else
6714a0cb85cSEd Tanous                         {
67262598e31SEd Tanous                             BMCWEB_LOG_ERROR(
67362598e31SEd Tanous                                 "Got extra property: {} on the {} object",
67462598e31SEd Tanous                                 property.first, objpath.first.str);
6754a0cb85cSEd Tanous                         }
6764a0cb85cSEd Tanous                     }
6774a0cb85cSEd Tanous                     // Check if given address is local, or global
6782c70f800SEd Tanous                     ipv4Address.linktype =
67911ba3979SEd Tanous                         ipv4Address.address.starts_with("169.254.")
68018659d10SJohnathan Mantey                             ? LinkType::Local
68118659d10SJohnathan Mantey                             : LinkType::Global;
6824a0cb85cSEd Tanous                 }
6834a0cb85cSEd Tanous             }
6844a0cb85cSEd Tanous         }
6854a0cb85cSEd Tanous     }
6864a0cb85cSEd Tanous }
687588c3f0dSKowalski, Kamil 
688588c3f0dSKowalski, Kamil /**
68901784826SJohnathan Mantey  * @brief Deletes given IPv4 interface
690179db1d7SKowalski, Kamil  *
691179db1d7SKowalski, Kamil  * @param[in] ifaceId     Id of interface whose IP should be deleted
692179db1d7SKowalski, Kamil  * @param[in] ipHash      DBus Hash id of IP that should be deleted
693179db1d7SKowalski, Kamil  * @param[io] asyncResp   Response object that will be returned to client
694179db1d7SKowalski, Kamil  *
695179db1d7SKowalski, Kamil  * @return None
696179db1d7SKowalski, Kamil  */
6979c5e585cSRavi Teja inline void deleteIPAddress(const std::string& ifaceId,
6989c5e585cSRavi Teja                             const std::string& ipHash,
6998d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7001abe55efSEd Tanous {
70155c7b7a2SEd Tanous     crow::connections::systemBus->async_method_call(
7025e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
7031abe55efSEd Tanous         if (ec)
7041abe55efSEd Tanous         {
705a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7061abe55efSEd Tanous         }
707179db1d7SKowalski, Kamil     },
708179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network",
7099c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + ipHash,
710179db1d7SKowalski, Kamil         "xyz.openbmc_project.Object.Delete", "Delete");
711179db1d7SKowalski, Kamil }
712179db1d7SKowalski, Kamil 
713244b6d5bSGunnar Mills inline void updateIPv4DefaultGateway(
714244b6d5bSGunnar Mills     const std::string& ifaceId, const std::string& gateway,
715244b6d5bSGunnar Mills     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7169010ec2eSRavi Teja {
7179ae226faSGeorge Liu     sdbusplus::asio::setProperty(
7189ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
7199ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
7209ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DefaultGateway",
7219ae226faSGeorge Liu         gateway, [asyncResp](const boost::system::error_code& ec) {
7229010ec2eSRavi Teja         if (ec)
7239010ec2eSRavi Teja         {
7249010ec2eSRavi Teja             messages::internalError(asyncResp->res);
7259010ec2eSRavi Teja             return;
7269010ec2eSRavi Teja         }
7279010ec2eSRavi Teja         asyncResp->res.result(boost::beast::http::status::no_content);
7289ae226faSGeorge Liu     });
7299010ec2eSRavi Teja }
730179db1d7SKowalski, Kamil /**
73101784826SJohnathan Mantey  * @brief Creates a static IPv4 entry
732179db1d7SKowalski, Kamil  *
73301784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv4 entry
73401784826SJohnathan Mantey  * @param[in] prefixLength IPv4 prefix syntax for the subnet mask
73501784826SJohnathan Mantey  * @param[in] gateway      IPv4 address of this interfaces gateway
73601784826SJohnathan Mantey  * @param[in] address      IPv4 address to assign to this interface
737179db1d7SKowalski, Kamil  * @param[io] asyncResp    Response object that will be returned to client
738179db1d7SKowalski, Kamil  *
739179db1d7SKowalski, Kamil  * @return None
740179db1d7SKowalski, Kamil  */
741cb13a392SEd Tanous inline void createIPv4(const std::string& ifaceId, uint8_t prefixLength,
742cb13a392SEd Tanous                        const std::string& gateway, const std::string& address,
7438d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
7441abe55efSEd Tanous {
7455a39f77aSPatrick Williams     auto createIpHandler = [asyncResp, ifaceId,
7465a39f77aSPatrick Williams                             gateway](const boost::system::error_code& ec) {
7471abe55efSEd Tanous         if (ec)
7481abe55efSEd Tanous         {
749a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
7509010ec2eSRavi Teja             return;
751179db1d7SKowalski, Kamil         }
7529010ec2eSRavi Teja         updateIPv4DefaultGateway(ifaceId, gateway, asyncResp);
7539010ec2eSRavi Teja     };
7549010ec2eSRavi Teja 
7559010ec2eSRavi Teja     crow::connections::systemBus->async_method_call(
7569010ec2eSRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
757179db1d7SKowalski, Kamil         "/xyz/openbmc_project/network/" + ifaceId,
758179db1d7SKowalski, Kamil         "xyz.openbmc_project.Network.IP.Create", "IP",
75901784826SJohnathan Mantey         "xyz.openbmc_project.Network.IP.Protocol.IPv4", address, prefixLength,
760179db1d7SKowalski, Kamil         gateway);
761179db1d7SKowalski, Kamil }
762e48c0fc5SRavi Teja 
763e48c0fc5SRavi Teja /**
76401784826SJohnathan Mantey  * @brief Deletes the IPv6 entry for this interface and creates a replacement
76501784826SJohnathan Mantey  * static IPv6 entry
76601784826SJohnathan Mantey  *
76701784826SJohnathan Mantey  * @param[in] ifaceId      Id of interface upon which to create the IPv6 entry
76801784826SJohnathan Mantey  * @param[in] id           The unique hash entry identifying the DBus entry
76901784826SJohnathan Mantey  * @param[in] prefixLength IPv6 prefix syntax for the subnet mask
77001784826SJohnathan Mantey  * @param[in] address      IPv6 address to assign to this interface
77101784826SJohnathan Mantey  * @param[io] asyncResp    Response object that will be returned to client
77201784826SJohnathan Mantey  *
77301784826SJohnathan Mantey  * @return None
77401784826SJohnathan Mantey  */
7759c5e585cSRavi Teja 
7769c5e585cSRavi Teja enum class IpVersion
7779c5e585cSRavi Teja {
7789c5e585cSRavi Teja     IpV4,
7799c5e585cSRavi Teja     IpV6
7809c5e585cSRavi Teja };
7819c5e585cSRavi Teja 
7829c5e585cSRavi Teja inline void deleteAndCreateIPAddress(
7839c5e585cSRavi Teja     IpVersion version, const std::string& ifaceId, const std::string& id,
7848d1b46d7Szhanghch05     uint8_t prefixLength, const std::string& address,
7859c5e585cSRavi Teja     const std::string& gateway,
7868d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
78701784826SJohnathan Mantey {
78801784826SJohnathan Mantey     crow::connections::systemBus->async_method_call(
7899c5e585cSRavi Teja         [asyncResp, version, ifaceId, address, prefixLength,
7909c5e585cSRavi Teja          gateway](const boost::system::error_code& ec) {
79101784826SJohnathan Mantey         if (ec)
79201784826SJohnathan Mantey         {
79301784826SJohnathan Mantey             messages::internalError(asyncResp->res);
79401784826SJohnathan Mantey         }
7959c5e585cSRavi Teja         std::string protocol = "xyz.openbmc_project.Network.IP.Protocol.";
7969c5e585cSRavi Teja         protocol += version == IpVersion::IpV4 ? "IPv4" : "IPv6";
79701784826SJohnathan Mantey         crow::connections::systemBus->async_method_call(
7985e7e2dc5SEd Tanous             [asyncResp](const boost::system::error_code& ec2) {
79923a21a1cSEd Tanous             if (ec2)
80001784826SJohnathan Mantey             {
80101784826SJohnathan Mantey                 messages::internalError(asyncResp->res);
80201784826SJohnathan Mantey             }
80301784826SJohnathan Mantey         },
80401784826SJohnathan Mantey             "xyz.openbmc_project.Network",
80501784826SJohnathan Mantey             "/xyz/openbmc_project/network/" + ifaceId,
8069c5e585cSRavi Teja             "xyz.openbmc_project.Network.IP.Create", "IP", protocol, address,
8079c5e585cSRavi Teja             prefixLength, gateway);
80801784826SJohnathan Mantey     },
80901784826SJohnathan Mantey         "xyz.openbmc_project.Network",
8109c5e585cSRavi Teja         "/xyz/openbmc_project/network/" + ifaceId + id,
81101784826SJohnathan Mantey         "xyz.openbmc_project.Object.Delete", "Delete");
81201784826SJohnathan Mantey }
81301784826SJohnathan Mantey 
81401784826SJohnathan Mantey /**
815e48c0fc5SRavi Teja  * @brief Creates IPv6 with given data
816e48c0fc5SRavi Teja  *
817e48c0fc5SRavi Teja  * @param[in] ifaceId      Id of interface whose IP should be added
818e48c0fc5SRavi Teja  * @param[in] prefixLength Prefix length that needs to be added
819e48c0fc5SRavi Teja  * @param[in] address      IP address that needs to be added
820e48c0fc5SRavi Teja  * @param[io] asyncResp    Response object that will be returned to client
821e48c0fc5SRavi Teja  *
822e48c0fc5SRavi Teja  * @return None
823e48c0fc5SRavi Teja  */
82401784826SJohnathan Mantey inline void createIPv6(const std::string& ifaceId, uint8_t prefixLength,
82501784826SJohnathan Mantey                        const std::string& address,
8268d1b46d7Szhanghch05                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
827e48c0fc5SRavi Teja {
8285a39f77aSPatrick Williams     auto createIpHandler = [asyncResp,
8295a39f77aSPatrick Williams                             address](const boost::system::error_code& ec) {
830e48c0fc5SRavi Teja         if (ec)
831e48c0fc5SRavi Teja         {
832fc23ef8aSNitin Kumar Kotania             if (ec == boost::system::errc::io_error)
833fc23ef8aSNitin Kumar Kotania             {
834fc23ef8aSNitin Kumar Kotania                 messages::propertyValueFormatError(asyncResp->res, address,
835fc23ef8aSNitin Kumar Kotania                                                    "Address");
836fc23ef8aSNitin Kumar Kotania             }
837fc23ef8aSNitin Kumar Kotania             else
838fc23ef8aSNitin Kumar Kotania             {
839e48c0fc5SRavi Teja                 messages::internalError(asyncResp->res);
840e48c0fc5SRavi Teja             }
841fc23ef8aSNitin Kumar Kotania         }
842e48c0fc5SRavi Teja     };
843e48c0fc5SRavi Teja     // Passing null for gateway, as per redfish spec IPv6StaticAddresses object
8444e0453b1SGunnar Mills     // does not have associated gateway property
845e48c0fc5SRavi Teja     crow::connections::systemBus->async_method_call(
846e48c0fc5SRavi Teja         std::move(createIpHandler), "xyz.openbmc_project.Network",
847e48c0fc5SRavi Teja         "/xyz/openbmc_project/network/" + ifaceId,
848e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Create", "IP",
849e48c0fc5SRavi Teja         "xyz.openbmc_project.Network.IP.Protocol.IPv6", address, prefixLength,
850e48c0fc5SRavi Teja         "");
851e48c0fc5SRavi Teja }
852e48c0fc5SRavi Teja 
853179db1d7SKowalski, Kamil /**
854179db1d7SKowalski, Kamil  * Function that retrieves all properties for given Ethernet Interface
855179db1d7SKowalski, Kamil  * Object
856179db1d7SKowalski, Kamil  * from EntityManager Network Manager
8574a0cb85cSEd Tanous  * @param ethiface_id a eth interface id to query on DBus
858179db1d7SKowalski, Kamil  * @param callback a function that shall be called to convert Dbus output
859179db1d7SKowalski, Kamil  * into JSON
860179db1d7SKowalski, Kamil  */
861179db1d7SKowalski, Kamil template <typename CallbackFunc>
86281ce609eSEd Tanous void getEthernetIfaceData(const std::string& ethifaceId,
8631abe55efSEd Tanous                           CallbackFunc&& callback)
8641abe55efSEd Tanous {
865f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
866f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
867f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
868f94c4ecfSEd Tanous         [ethifaceId{std::string{ethifaceId}},
869f94c4ecfSEd Tanous          callback{std::forward<CallbackFunc>(callback)}](
8708b24275dSEd Tanous             const boost::system::error_code& ec,
87102cad96eSEd Tanous             const dbus::utility::ManagedObjectType& resp) {
87255c7b7a2SEd Tanous         EthernetInterfaceData ethData{};
87377179532SEd Tanous         std::vector<IPv4AddressData> ipv4Data;
87477179532SEd Tanous         std::vector<IPv6AddressData> ipv6Data;
875179db1d7SKowalski, Kamil 
8768b24275dSEd Tanous         if (ec)
8771abe55efSEd Tanous         {
87801784826SJohnathan Mantey             callback(false, ethData, ipv4Data, ipv6Data);
879179db1d7SKowalski, Kamil             return;
880179db1d7SKowalski, Kamil         }
881179db1d7SKowalski, Kamil 
882002d39b4SEd Tanous         bool found = extractEthernetInterfaceData(ethifaceId, resp, ethData);
8834c9afe43SEd Tanous         if (!found)
8844c9afe43SEd Tanous         {
88501784826SJohnathan Mantey             callback(false, ethData, ipv4Data, ipv6Data);
8864c9afe43SEd Tanous             return;
8874c9afe43SEd Tanous         }
8884c9afe43SEd Tanous 
8892c70f800SEd Tanous         extractIPData(ethifaceId, resp, ipv4Data);
890179db1d7SKowalski, Kamil         // Fix global GW
8911abe55efSEd Tanous         for (IPv4AddressData& ipv4 : ipv4Data)
8921abe55efSEd Tanous         {
893c619141bSRavi Teja             if (((ipv4.linktype == LinkType::Global) &&
894c619141bSRavi Teja                  (ipv4.gateway == "0.0.0.0")) ||
8959010ec2eSRavi Teja                 (ipv4.origin == "DHCP") || (ipv4.origin == "Static"))
8961abe55efSEd Tanous             {
89782695a5bSJiaqing Zhao                 ipv4.gateway = ethData.defaultGateway;
898179db1d7SKowalski, Kamil             }
899179db1d7SKowalski, Kamil         }
900179db1d7SKowalski, Kamil 
9012c70f800SEd Tanous         extractIPV6Data(ethifaceId, resp, ipv6Data);
9024e0453b1SGunnar Mills         // Finally make a callback with useful data
90301784826SJohnathan Mantey         callback(true, ethData, ipv4Data, ipv6Data);
904f5892d0dSGeorge Liu     });
905271584abSEd Tanous }
906179db1d7SKowalski, Kamil 
907179db1d7SKowalski, Kamil /**
9089391bb9cSRapkiewicz, Pawel  * Function that retrieves all Ethernet Interfaces available through Network
9099391bb9cSRapkiewicz, Pawel  * Manager
9101abe55efSEd Tanous  * @param callback a function that shall be called to convert Dbus output
9111abe55efSEd Tanous  * into JSON.
9129391bb9cSRapkiewicz, Pawel  */
9139391bb9cSRapkiewicz, Pawel template <typename CallbackFunc>
9141abe55efSEd Tanous void getEthernetIfaceList(CallbackFunc&& callback)
9151abe55efSEd Tanous {
916f5892d0dSGeorge Liu     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
917f5892d0dSGeorge Liu     dbus::utility::getManagedObjects(
918f5892d0dSGeorge Liu         "xyz.openbmc_project.Network", path,
919f94c4ecfSEd Tanous         [callback{std::forward<CallbackFunc>(callback)}](
9208b24275dSEd Tanous             const boost::system::error_code& ec,
921f5892d0dSGeorge Liu             const dbus::utility::ManagedObjectType& resp) {
9221abe55efSEd Tanous         // Callback requires vector<string> to retrieve all available
9231abe55efSEd Tanous         // ethernet interfaces
92477179532SEd Tanous         std::vector<std::string> ifaceList;
9252c70f800SEd Tanous         ifaceList.reserve(resp.size());
9268b24275dSEd Tanous         if (ec)
9271abe55efSEd Tanous         {
9282c70f800SEd Tanous             callback(false, ifaceList);
9299391bb9cSRapkiewicz, Pawel             return;
9309391bb9cSRapkiewicz, Pawel         }
9319391bb9cSRapkiewicz, Pawel 
9329391bb9cSRapkiewicz, Pawel         // Iterate over all retrieved ObjectPaths.
9334a0cb85cSEd Tanous         for (const auto& objpath : resp)
9341abe55efSEd Tanous         {
9359391bb9cSRapkiewicz, Pawel             // And all interfaces available for certain ObjectPath.
9364a0cb85cSEd Tanous             for (const auto& interface : objpath.second)
9371abe55efSEd Tanous             {
9381abe55efSEd Tanous                 // If interface is
9394a0cb85cSEd Tanous                 // xyz.openbmc_project.Network.EthernetInterface, this is
9404a0cb85cSEd Tanous                 // what we're looking for.
9419391bb9cSRapkiewicz, Pawel                 if (interface.first ==
9421abe55efSEd Tanous                     "xyz.openbmc_project.Network.EthernetInterface")
9431abe55efSEd Tanous                 {
9442dfd18efSEd Tanous                     std::string ifaceId = objpath.first.filename();
9452dfd18efSEd Tanous                     if (ifaceId.empty())
9461abe55efSEd Tanous                     {
9472dfd18efSEd Tanous                         continue;
9489391bb9cSRapkiewicz, Pawel                     }
9492dfd18efSEd Tanous                     // and put it into output vector.
95077179532SEd Tanous                     ifaceList.emplace_back(ifaceId);
9519391bb9cSRapkiewicz, Pawel                 }
9529391bb9cSRapkiewicz, Pawel             }
9539391bb9cSRapkiewicz, Pawel         }
9542c5875a2SEd Tanous 
9553544d2a7SEd Tanous         std::ranges::sort(ifaceList, AlphanumLess<std::string>());
9562c5875a2SEd Tanous 
957a434f2bdSEd Tanous         // Finally make a callback with useful data
9582c70f800SEd Tanous         callback(true, ifaceList);
959f5892d0dSGeorge Liu     });
960271584abSEd Tanous }
9619391bb9cSRapkiewicz, Pawel 
9624f48d5f6SEd Tanous inline void
9634f48d5f6SEd Tanous     handleHostnamePatch(const std::string& hostname,
9648d1b46d7Szhanghch05                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
9651abe55efSEd Tanous {
966ab6554f1SJoshi-Mansi     // SHOULD handle host names of up to 255 characters(RFC 1123)
967ab6554f1SJoshi-Mansi     if (hostname.length() > 255)
968ab6554f1SJoshi-Mansi     {
969ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, hostname,
970ab6554f1SJoshi-Mansi                                            "HostName");
971ab6554f1SJoshi-Mansi         return;
972ab6554f1SJoshi-Mansi     }
9739ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9749ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
9759ae226faSGeorge Liu         "/xyz/openbmc_project/network/config",
9769ae226faSGeorge Liu         "xyz.openbmc_project.Network.SystemConfiguration", "HostName", hostname,
9775e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
9784a0cb85cSEd Tanous         if (ec)
9794a0cb85cSEd Tanous         {
980a08b46ccSJason M. Bills             messages::internalError(asyncResp->res);
9811abe55efSEd Tanous         }
9829ae226faSGeorge Liu     });
983588c3f0dSKowalski, Kamil }
984588c3f0dSKowalski, Kamil 
9854f48d5f6SEd Tanous inline void
98635fb5311STejas Patil     handleMTUSizePatch(const std::string& ifaceId, const size_t mtuSize,
98735fb5311STejas Patil                        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
98835fb5311STejas Patil {
98989492a15SPatrick Williams     sdbusplus::message::object_path objPath = "/xyz/openbmc_project/network/" +
99089492a15SPatrick Williams                                               ifaceId;
9919ae226faSGeorge Liu     sdbusplus::asio::setProperty(
9929ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network", objPath,
9939ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "MTU", mtuSize,
9945e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
99535fb5311STejas Patil         if (ec)
99635fb5311STejas Patil         {
99735fb5311STejas Patil             messages::internalError(asyncResp->res);
99835fb5311STejas Patil         }
9999ae226faSGeorge Liu     });
100035fb5311STejas Patil }
100135fb5311STejas Patil 
100235fb5311STejas Patil inline void
10034f48d5f6SEd Tanous     handleDomainnamePatch(const std::string& ifaceId,
1004bf648f77SEd Tanous                           const std::string& domainname,
10058d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1006ab6554f1SJoshi-Mansi {
1007ab6554f1SJoshi-Mansi     std::vector<std::string> vectorDomainname = {domainname};
10089ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10099ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10109ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10119ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "DomainName",
10129ae226faSGeorge Liu         vectorDomainname, [asyncResp](const boost::system::error_code& ec) {
1013ab6554f1SJoshi-Mansi         if (ec)
1014ab6554f1SJoshi-Mansi         {
1015ab6554f1SJoshi-Mansi             messages::internalError(asyncResp->res);
1016ab6554f1SJoshi-Mansi         }
10179ae226faSGeorge Liu     });
1018ab6554f1SJoshi-Mansi }
1019ab6554f1SJoshi-Mansi 
10204f48d5f6SEd Tanous inline bool isHostnameValid(const std::string& hostname)
1021bf648f77SEd Tanous {
1022bf648f77SEd Tanous     // A valid host name can never have the dotted-decimal form (RFC 1123)
10233544d2a7SEd Tanous     if (std::ranges::all_of(hostname, ::isdigit))
1024bf648f77SEd Tanous     {
1025bf648f77SEd Tanous         return false;
1026bf648f77SEd Tanous     }
1027bf648f77SEd Tanous     // Each label(hostname/subdomains) within a valid FQDN
1028bf648f77SEd Tanous     // MUST handle host names of up to 63 characters (RFC 1123)
1029bf648f77SEd Tanous     // labels cannot start or end with hyphens (RFC 952)
1030bf648f77SEd Tanous     // labels can start with numbers (RFC 1123)
10314b242749SEd Tanous     const static std::regex pattern(
1032bf648f77SEd Tanous         "^[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9]$");
1033bf648f77SEd Tanous 
1034bf648f77SEd Tanous     return std::regex_match(hostname, pattern);
1035bf648f77SEd Tanous }
1036bf648f77SEd Tanous 
10374f48d5f6SEd Tanous inline bool isDomainnameValid(const std::string& domainname)
1038bf648f77SEd Tanous {
1039bf648f77SEd Tanous     // Can have multiple subdomains
1040bf648f77SEd Tanous     // Top Level Domain's min length is 2 character
10414b242749SEd Tanous     const static std::regex pattern(
10420fda0f12SGeorge Liu         "^([A-Za-z0-9][a-zA-Z0-9\\-]{1,61}|[a-zA-Z0-9]{1,30}\\.)*[a-zA-Z]{2,}$");
1043bf648f77SEd Tanous 
1044bf648f77SEd Tanous     return std::regex_match(domainname, pattern);
1045bf648f77SEd Tanous }
1046bf648f77SEd Tanous 
10474f48d5f6SEd Tanous inline void handleFqdnPatch(const std::string& ifaceId, const std::string& fqdn,
10488d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1049ab6554f1SJoshi-Mansi {
1050ab6554f1SJoshi-Mansi     // Total length of FQDN must not exceed 255 characters(RFC 1035)
1051ab6554f1SJoshi-Mansi     if (fqdn.length() > 255)
1052ab6554f1SJoshi-Mansi     {
1053ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1054ab6554f1SJoshi-Mansi         return;
1055ab6554f1SJoshi-Mansi     }
1056ab6554f1SJoshi-Mansi 
1057ab6554f1SJoshi-Mansi     size_t pos = fqdn.find('.');
1058ab6554f1SJoshi-Mansi     if (pos == std::string::npos)
1059ab6554f1SJoshi-Mansi     {
1060ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1061ab6554f1SJoshi-Mansi         return;
1062ab6554f1SJoshi-Mansi     }
1063ab6554f1SJoshi-Mansi 
1064ab6554f1SJoshi-Mansi     std::string hostname;
1065ab6554f1SJoshi-Mansi     std::string domainname;
1066ab6554f1SJoshi-Mansi     domainname = (fqdn).substr(pos + 1);
1067ab6554f1SJoshi-Mansi     hostname = (fqdn).substr(0, pos);
1068ab6554f1SJoshi-Mansi 
1069ab6554f1SJoshi-Mansi     if (!isHostnameValid(hostname) || !isDomainnameValid(domainname))
1070ab6554f1SJoshi-Mansi     {
1071ab6554f1SJoshi-Mansi         messages::propertyValueFormatError(asyncResp->res, fqdn, "FQDN");
1072ab6554f1SJoshi-Mansi         return;
1073ab6554f1SJoshi-Mansi     }
1074ab6554f1SJoshi-Mansi 
1075ab6554f1SJoshi-Mansi     handleHostnamePatch(hostname, asyncResp);
1076ab6554f1SJoshi-Mansi     handleDomainnamePatch(ifaceId, domainname, asyncResp);
1077ab6554f1SJoshi-Mansi }
1078ab6554f1SJoshi-Mansi 
10794f48d5f6SEd Tanous inline void
10804f48d5f6SEd Tanous     handleMACAddressPatch(const std::string& ifaceId,
1081bf648f77SEd Tanous                           const std::string& macAddress,
10828d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1083d577665bSRatan Gupta {
108458283f41SJohnathan Mantey     static constexpr std::string_view dbusNotAllowedError =
108558283f41SJohnathan Mantey         "xyz.openbmc_project.Common.Error.NotAllowed";
108658283f41SJohnathan Mantey 
10879ae226faSGeorge Liu     sdbusplus::asio::setProperty(
10889ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
10899ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
10909ae226faSGeorge Liu         "xyz.openbmc_project.Network.MACAddress", "MACAddress", macAddress,
10919ae226faSGeorge Liu         [asyncResp](const boost::system::error_code& ec,
10925b378546SPatrick Williams                     const sdbusplus::message_t& msg) {
1093d577665bSRatan Gupta         if (ec)
1094d577665bSRatan Gupta         {
109558283f41SJohnathan Mantey             const sd_bus_error* err = msg.get_error();
109658283f41SJohnathan Mantey             if (err == nullptr)
109758283f41SJohnathan Mantey             {
109858283f41SJohnathan Mantey                 messages::internalError(asyncResp->res);
109958283f41SJohnathan Mantey                 return;
110058283f41SJohnathan Mantey             }
110158283f41SJohnathan Mantey             if (err->name == dbusNotAllowedError)
110258283f41SJohnathan Mantey             {
110358283f41SJohnathan Mantey                 messages::propertyNotWritable(asyncResp->res, "MACAddress");
110458283f41SJohnathan Mantey                 return;
110558283f41SJohnathan Mantey             }
1106d577665bSRatan Gupta             messages::internalError(asyncResp->res);
1107d577665bSRatan Gupta             return;
1108d577665bSRatan Gupta         }
11099ae226faSGeorge Liu     });
1110d577665bSRatan Gupta }
1111286b9118SJohnathan Mantey 
11124f48d5f6SEd Tanous inline void setDHCPEnabled(const std::string& ifaceId,
11134f48d5f6SEd Tanous                            const std::string& propertyName, const bool v4Value,
11144f48d5f6SEd Tanous                            const bool v6Value,
11158d1b46d7Szhanghch05                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1116da131a9aSJennifer Lee {
11172c70f800SEd Tanous     const std::string dhcp = getDhcpEnabledEnumeration(v4Value, v6Value);
11189ae226faSGeorge Liu     sdbusplus::asio::setProperty(
11199ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
11209ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
11219ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, dhcp,
11225e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1123da131a9aSJennifer Lee         if (ec)
1124da131a9aSJennifer Lee         {
112562598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1126da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1127da131a9aSJennifer Lee             return;
1128da131a9aSJennifer Lee         }
11298f7e9c19SJayaprakash Mutyala         messages::success(asyncResp->res);
11309ae226faSGeorge Liu     });
1131da131a9aSJennifer Lee }
11321f8c7b5dSJohnathan Mantey 
11334f48d5f6SEd Tanous inline void setEthernetInterfaceBoolProperty(
1134eeedda23SJohnathan Mantey     const std::string& ifaceId, const std::string& propertyName,
11358d1b46d7Szhanghch05     const bool& value, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1136eeedda23SJohnathan Mantey {
11379ae226faSGeorge Liu     sdbusplus::asio::setProperty(
11389ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
11399ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
11409ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", propertyName, value,
11415e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1142eeedda23SJohnathan Mantey         if (ec)
1143eeedda23SJohnathan Mantey         {
114462598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1145eeedda23SJohnathan Mantey             messages::internalError(asyncResp->res);
1146eeedda23SJohnathan Mantey             return;
1147eeedda23SJohnathan Mantey         }
11489ae226faSGeorge Liu     });
1149eeedda23SJohnathan Mantey }
1150eeedda23SJohnathan Mantey 
1151e4588158SJishnu CM enum class NetworkType
1152e4588158SJishnu CM {
1153e4588158SJishnu CM     dhcp4,
1154e4588158SJishnu CM     dhcp6
1155e4588158SJishnu CM };
1156e4588158SJishnu CM 
1157e4588158SJishnu CM inline void setDHCPConfig(const std::string& propertyName, const bool& value,
1158e4588158SJishnu CM                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1159e4588158SJishnu CM                           const std::string& ethifaceId, NetworkType type)
1160da131a9aSJennifer Lee {
116162598e31SEd Tanous     BMCWEB_LOG_DEBUG("{} = {}", propertyName, value);
1162e4588158SJishnu CM     sdbusplus::message::object_path path("/xyz/openbmc_project/network/");
1163e4588158SJishnu CM     path /= ethifaceId;
1164e4588158SJishnu CM 
1165e4588158SJishnu CM     if (type == NetworkType::dhcp4)
1166e4588158SJishnu CM     {
1167e4588158SJishnu CM         path /= "dhcp4";
1168e4588158SJishnu CM     }
1169e4588158SJishnu CM     else
1170e4588158SJishnu CM     {
1171e4588158SJishnu CM         path /= "dhcp6";
1172e4588158SJishnu CM     }
1173e4588158SJishnu CM 
11749ae226faSGeorge Liu     sdbusplus::asio::setProperty(
1175e4588158SJishnu CM         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
11769ae226faSGeorge Liu         "xyz.openbmc_project.Network.DHCPConfiguration", propertyName, value,
11775e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1178da131a9aSJennifer Lee         if (ec)
1179da131a9aSJennifer Lee         {
118062598e31SEd Tanous             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1181da131a9aSJennifer Lee             messages::internalError(asyncResp->res);
1182da131a9aSJennifer Lee             return;
1183da131a9aSJennifer Lee         }
11849ae226faSGeorge Liu     });
1185da131a9aSJennifer Lee }
1186d577665bSRatan Gupta 
1187b10d8db0SRavi Teja inline void handleSLAACAutoConfigPatch(
1188b10d8db0SRavi Teja     const std::string& ifaceId, bool ipv6AutoConfigEnabled,
1189b10d8db0SRavi Teja     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1190b10d8db0SRavi Teja {
1191b10d8db0SRavi Teja     sdbusplus::message::object_path path("/xyz/openbmc_project/network");
1192b10d8db0SRavi Teja     path /= ifaceId;
1193b10d8db0SRavi Teja     sdbusplus::asio::setProperty(
1194b10d8db0SRavi Teja         *crow::connections::systemBus, "xyz.openbmc_project.Network", path,
1195b10d8db0SRavi Teja         "xyz.openbmc_project.Network.EthernetInterface", "IPv6AcceptRA",
1196b10d8db0SRavi Teja         ipv6AutoConfigEnabled,
1197b10d8db0SRavi Teja         [asyncResp](const boost::system::error_code& ec) {
1198b10d8db0SRavi Teja         if (ec)
1199b10d8db0SRavi Teja         {
1200b10d8db0SRavi Teja             BMCWEB_LOG_ERROR("D-Bus responses error: {}", ec);
1201b10d8db0SRavi Teja             messages::internalError(asyncResp->res);
1202b10d8db0SRavi Teja             return;
1203b10d8db0SRavi Teja         }
1204b10d8db0SRavi Teja         messages::success(asyncResp->res);
1205b10d8db0SRavi Teja     });
1206b10d8db0SRavi Teja }
1207b10d8db0SRavi Teja 
12084f48d5f6SEd Tanous inline void handleDHCPPatch(const std::string& ifaceId,
12091f8c7b5dSJohnathan Mantey                             const EthernetInterfaceData& ethData,
1210f23b7296SEd Tanous                             const DHCPParameters& v4dhcpParms,
1211f23b7296SEd Tanous                             const DHCPParameters& v6dhcpParms,
12128d1b46d7Szhanghch05                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1213da131a9aSJennifer Lee {
121482695a5bSJiaqing Zhao     bool ipv4Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
121582695a5bSJiaqing Zhao     bool ipv6Active = translateDhcpEnabledToBool(ethData.dhcpEnabled, false);
1216da131a9aSJennifer Lee 
12171f8c7b5dSJohnathan Mantey     bool nextv4DHCPState =
12181f8c7b5dSJohnathan Mantey         v4dhcpParms.dhcpv4Enabled ? *v4dhcpParms.dhcpv4Enabled : ipv4Active;
12191f8c7b5dSJohnathan Mantey 
12201f8c7b5dSJohnathan Mantey     bool nextv6DHCPState{};
12211f8c7b5dSJohnathan Mantey     if (v6dhcpParms.dhcpv6OperatingMode)
1222da131a9aSJennifer Lee     {
1223b10d8db0SRavi Teja         if ((*v6dhcpParms.dhcpv6OperatingMode != "Enabled") &&
12241f8c7b5dSJohnathan Mantey             (*v6dhcpParms.dhcpv6OperatingMode != "Disabled"))
12251f8c7b5dSJohnathan Mantey         {
1226bf648f77SEd Tanous             messages::propertyValueFormatError(asyncResp->res,
1227bf648f77SEd Tanous                                                *v6dhcpParms.dhcpv6OperatingMode,
12281f8c7b5dSJohnathan Mantey                                                "OperatingMode");
1229da131a9aSJennifer Lee             return;
1230da131a9aSJennifer Lee         }
1231b10d8db0SRavi Teja         nextv6DHCPState = (*v6dhcpParms.dhcpv6OperatingMode == "Enabled");
12321f8c7b5dSJohnathan Mantey     }
12331f8c7b5dSJohnathan Mantey     else
1234da131a9aSJennifer Lee     {
12351f8c7b5dSJohnathan Mantey         nextv6DHCPState = ipv6Active;
12361f8c7b5dSJohnathan Mantey     }
12371f8c7b5dSJohnathan Mantey 
1238e4588158SJishnu CM     bool nextDNSv4 = ethData.dnsv4Enabled;
1239e4588158SJishnu CM     bool nextDNSv6 = ethData.dnsv6Enabled;
1240e4588158SJishnu CM     if (v4dhcpParms.useDnsServers)
12411f8c7b5dSJohnathan Mantey     {
1242e4588158SJishnu CM         nextDNSv4 = *v4dhcpParms.useDnsServers;
12431f8c7b5dSJohnathan Mantey     }
1244e4588158SJishnu CM     if (v6dhcpParms.useDnsServers)
12451f8c7b5dSJohnathan Mantey     {
1246e4588158SJishnu CM         nextDNSv6 = *v6dhcpParms.useDnsServers;
12471f8c7b5dSJohnathan Mantey     }
12481f8c7b5dSJohnathan Mantey 
1249e4588158SJishnu CM     bool nextNTPv4 = ethData.ntpv4Enabled;
1250e4588158SJishnu CM     bool nextNTPv6 = ethData.ntpv6Enabled;
1251e4588158SJishnu CM     if (v4dhcpParms.useNtpServers)
12521f8c7b5dSJohnathan Mantey     {
1253e4588158SJishnu CM         nextNTPv4 = *v4dhcpParms.useNtpServers;
12541f8c7b5dSJohnathan Mantey     }
1255e4588158SJishnu CM     if (v6dhcpParms.useNtpServers)
12561f8c7b5dSJohnathan Mantey     {
1257e4588158SJishnu CM         nextNTPv6 = *v6dhcpParms.useNtpServers;
12581f8c7b5dSJohnathan Mantey     }
12591f8c7b5dSJohnathan Mantey 
1260*91c441ecSRavi Teja     bool nextUsev4Domain = ethData.domainv4Enabled;
1261*91c441ecSRavi Teja     bool nextUsev6Domain = ethData.domainv6Enabled;
1262e4588158SJishnu CM     if (v4dhcpParms.useDomainName)
12631f8c7b5dSJohnathan Mantey     {
1264e4588158SJishnu CM         nextUsev4Domain = *v4dhcpParms.useDomainName;
12651f8c7b5dSJohnathan Mantey     }
1266e4588158SJishnu CM     if (v6dhcpParms.useDomainName)
12671f8c7b5dSJohnathan Mantey     {
1268e4588158SJishnu CM         nextUsev6Domain = *v6dhcpParms.useDomainName;
12691f8c7b5dSJohnathan Mantey     }
12701f8c7b5dSJohnathan Mantey 
127162598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DHCPEnabled...");
12721f8c7b5dSJohnathan Mantey     setDHCPEnabled(ifaceId, "DHCPEnabled", nextv4DHCPState, nextv6DHCPState,
12731f8c7b5dSJohnathan Mantey                    asyncResp);
127462598e31SEd Tanous     BMCWEB_LOG_DEBUG("set DNSEnabled...");
1275e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv4, asyncResp, ifaceId,
1276e4588158SJishnu CM                   NetworkType::dhcp4);
127762598e31SEd Tanous     BMCWEB_LOG_DEBUG("set NTPEnabled...");
1278e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv4, asyncResp, ifaceId,
1279e4588158SJishnu CM                   NetworkType::dhcp4);
1280*91c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled...");
1281*91c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev4Domain, asyncResp, ifaceId,
1282e4588158SJishnu CM                   NetworkType::dhcp4);
1283e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set DNSEnabled for dhcp6...");
1284e4588158SJishnu CM     setDHCPConfig("DNSEnabled", nextDNSv6, asyncResp, ifaceId,
1285e4588158SJishnu CM                   NetworkType::dhcp6);
1286e4588158SJishnu CM     BMCWEB_LOG_DEBUG("set NTPEnabled for dhcp6...");
1287e4588158SJishnu CM     setDHCPConfig("NTPEnabled", nextNTPv6, asyncResp, ifaceId,
1288e4588158SJishnu CM                   NetworkType::dhcp6);
1289*91c441ecSRavi Teja     BMCWEB_LOG_DEBUG("set DomainEnabled for dhcp6...");
1290*91c441ecSRavi Teja     setDHCPConfig("DomainEnabled", nextUsev6Domain, asyncResp, ifaceId,
1291e4588158SJishnu CM                   NetworkType::dhcp6);
1292da131a9aSJennifer Lee }
129301784826SJohnathan Mantey 
129477179532SEd Tanous inline std::vector<IPv4AddressData>::const_iterator getNextStaticIpEntry(
129577179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& head,
129677179532SEd Tanous     const std::vector<IPv4AddressData>::const_iterator& end)
129701784826SJohnathan Mantey {
129817a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv4AddressData& value) {
129917a897dfSManojkiran Eda         return value.origin == "Static";
130017a897dfSManojkiran Eda     });
130101784826SJohnathan Mantey }
130201784826SJohnathan Mantey 
130377179532SEd Tanous inline std::vector<IPv6AddressData>::const_iterator getNextStaticIpEntry(
130477179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& head,
130577179532SEd Tanous     const std::vector<IPv6AddressData>::const_iterator& end)
130601784826SJohnathan Mantey {
130717a897dfSManojkiran Eda     return std::find_if(head, end, [](const IPv6AddressData& value) {
130817a897dfSManojkiran Eda         return value.origin == "Static";
130917a897dfSManojkiran Eda     });
131001784826SJohnathan Mantey }
131101784826SJohnathan Mantey 
131277179532SEd Tanous inline void
1313ddd70dcaSEd Tanous     handleIPv4StaticPatch(const std::string& ifaceId,
1314ddd70dcaSEd Tanous                           nlohmann::json::array_t& input,
131577179532SEd Tanous                           const std::vector<IPv4AddressData>& ipv4Data,
13168d1b46d7Szhanghch05                           const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
13171abe55efSEd Tanous {
1318ddd70dcaSEd Tanous     if (input.empty())
1319f476acbfSRatan Gupta     {
13202e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1321d1d50814SRavi Teja                                          "IPv4StaticAddresses");
1322f476acbfSRatan Gupta         return;
1323f476acbfSRatan Gupta     }
1324f476acbfSRatan Gupta 
1325271584abSEd Tanous     unsigned entryIdx = 1;
132601784826SJohnathan Mantey     // Find the first static IP address currently active on the NIC and
132701784826SJohnathan Mantey     // match it to the first JSON element in the IPv4StaticAddresses array.
132801784826SJohnathan Mantey     // Match each subsequent JSON element to the next static IP programmed
132901784826SJohnathan Mantey     // into the NIC.
133077179532SEd Tanous     std::vector<IPv4AddressData>::const_iterator nicIpEntry =
13312c70f800SEd Tanous         getNextStaticIpEntry(ipv4Data.cbegin(), ipv4Data.cend());
133201784826SJohnathan Mantey 
1333537174c4SEd Tanous     for (nlohmann::json& thisJson : input)
13341abe55efSEd Tanous     {
133589492a15SPatrick Williams         std::string pathString = "IPv4StaticAddresses/" +
133689492a15SPatrick Williams                                  std::to_string(entryIdx);
1337179db1d7SKowalski, Kamil 
133801784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1339f476acbfSRatan Gupta         {
1340537174c4SEd Tanous             std::optional<std::string> address;
1341537174c4SEd Tanous             std::optional<std::string> subnetMask;
1342537174c4SEd Tanous             std::optional<std::string> gateway;
1343537174c4SEd Tanous 
1344537174c4SEd Tanous             if (!json_util::readJson(thisJson, asyncResp->res, "Address",
13457e27d832SJohnathan Mantey                                      address, "SubnetMask", subnetMask,
13467e27d832SJohnathan Mantey                                      "Gateway", gateway))
1347537174c4SEd Tanous             {
1348f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
134971f52d96SEd Tanous                                                    pathString);
1350537174c4SEd Tanous                 return;
1351179db1d7SKowalski, Kamil             }
1352179db1d7SKowalski, Kamil 
135301784826SJohnathan Mantey             // Find the address/subnet/gateway values. Any values that are
135401784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
135501784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
135601784826SJohnathan Mantey             // current request.
1357537174c4SEd Tanous             if (address)
13581abe55efSEd Tanous             {
1359e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*address))
136001784826SJohnathan Mantey                 {
1361bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *address,
1362bf648f77SEd Tanous                                                        pathString + "/Address");
1363e01d0c36SEd Tanous                     return;
136401784826SJohnathan Mantey                 }
136501784826SJohnathan Mantey             }
136685ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
136701784826SJohnathan Mantey             {
1368e01d0c36SEd Tanous                 address = (nicIpEntry->address);
136901784826SJohnathan Mantey             }
137001784826SJohnathan Mantey             else
137101784826SJohnathan Mantey             {
137201784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
137301784826SJohnathan Mantey                                           pathString + "/Address");
1374e01d0c36SEd Tanous                 return;
13754a0cb85cSEd Tanous             }
13764a0cb85cSEd Tanous 
1377e01d0c36SEd Tanous             uint8_t prefixLength = 0;
1378537174c4SEd Tanous             if (subnetMask)
13794a0cb85cSEd Tanous             {
1380033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*subnetMask,
1381033f1e4dSEd Tanous                                                          &prefixLength))
13824a0cb85cSEd Tanous                 {
1383f12894f8SJason M. Bills                     messages::propertyValueFormatError(
1384537174c4SEd Tanous                         asyncResp->res, *subnetMask,
13854a0cb85cSEd Tanous                         pathString + "/SubnetMask");
1386e01d0c36SEd Tanous                     return;
13874a0cb85cSEd Tanous                 }
13884a0cb85cSEd Tanous             }
138985ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
13904a0cb85cSEd Tanous             {
1391033f1e4dSEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(nicIpEntry->netmask,
139201784826SJohnathan Mantey                                                          &prefixLength))
13934a0cb85cSEd Tanous                 {
139401784826SJohnathan Mantey                     messages::propertyValueFormatError(
139585ffe86aSJiaqing Zhao                         asyncResp->res, nicIpEntry->netmask,
139601784826SJohnathan Mantey                         pathString + "/SubnetMask");
1397e01d0c36SEd Tanous                     return;
13984a0cb85cSEd Tanous                 }
13994a0cb85cSEd Tanous             }
14001abe55efSEd Tanous             else
14011abe55efSEd Tanous             {
140201784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
140301784826SJohnathan Mantey                                           pathString + "/SubnetMask");
1404e01d0c36SEd Tanous                 return;
140501784826SJohnathan Mantey             }
140601784826SJohnathan Mantey 
140701784826SJohnathan Mantey             if (gateway)
140801784826SJohnathan Mantey             {
1409e01d0c36SEd Tanous                 if (!ip_util::ipv4VerifyIpAndGetBitcount(*gateway))
141001784826SJohnathan Mantey                 {
1411bf648f77SEd Tanous                     messages::propertyValueFormatError(asyncResp->res, *gateway,
1412bf648f77SEd Tanous                                                        pathString + "/Gateway");
1413e01d0c36SEd Tanous                     return;
141401784826SJohnathan Mantey                 }
141501784826SJohnathan Mantey             }
141685ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv4Data.cend())
141701784826SJohnathan Mantey             {
1418e01d0c36SEd Tanous                 gateway = nicIpEntry->gateway;
141901784826SJohnathan Mantey             }
142001784826SJohnathan Mantey             else
14211abe55efSEd Tanous             {
1422a08b46ccSJason M. Bills                 messages::propertyMissing(asyncResp->res,
14234a0cb85cSEd Tanous                                           pathString + "/Gateway");
142401784826SJohnathan Mantey                 return;
14254a0cb85cSEd Tanous             }
14264a0cb85cSEd Tanous 
142785ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
14281abe55efSEd Tanous             {
14299c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV4, ifaceId,
143077eb0153SEd Tanous                                          nicIpEntry->id, prefixLength, *address,
143177eb0153SEd Tanous                                          *gateway, asyncResp);
143289492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
143389492a15SPatrick Williams                                                   ipv4Data.cend());
1434588c3f0dSKowalski, Kamil             }
143501784826SJohnathan Mantey             else
143601784826SJohnathan Mantey             {
1437cb13a392SEd Tanous                 createIPv4(ifaceId, prefixLength, *gateway, *address,
1438cb13a392SEd Tanous                            asyncResp);
14394a0cb85cSEd Tanous             }
14404a0cb85cSEd Tanous             entryIdx++;
14414a0cb85cSEd Tanous         }
144201784826SJohnathan Mantey         else
144301784826SJohnathan Mantey         {
144485ffe86aSJiaqing Zhao             if (nicIpEntry == ipv4Data.cend())
144501784826SJohnathan Mantey             {
144601784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
144701784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
144801784826SJohnathan Mantey                 // in error, so bail out.
144901784826SJohnathan Mantey                 if (thisJson.is_null())
145001784826SJohnathan Mantey                 {
145101784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
145201784826SJohnathan Mantey                     return;
145301784826SJohnathan Mantey                 }
1454f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
145571f52d96SEd Tanous                                                    pathString);
145601784826SJohnathan Mantey                 return;
145701784826SJohnathan Mantey             }
145801784826SJohnathan Mantey 
145901784826SJohnathan Mantey             if (thisJson.is_null())
146001784826SJohnathan Mantey             {
14619c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
146201784826SJohnathan Mantey             }
146385ffe86aSJiaqing Zhao             if (nicIpEntry != ipv4Data.cend())
146401784826SJohnathan Mantey             {
146589492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
146689492a15SPatrick Williams                                                   ipv4Data.cend());
146701784826SJohnathan Mantey             }
146801784826SJohnathan Mantey             entryIdx++;
146901784826SJohnathan Mantey         }
147001784826SJohnathan Mantey     }
14714a0cb85cSEd Tanous }
14724a0cb85cSEd Tanous 
14734f48d5f6SEd Tanous inline void handleStaticNameServersPatch(
1474f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::string& ifaceId,
1475f85837bfSRAJESWARAN THILLAIGOVINDAN     const std::vector<std::string>& updatedStaticNameServers,
14768d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1477f85837bfSRAJESWARAN THILLAIGOVINDAN {
14789ae226faSGeorge Liu     sdbusplus::asio::setProperty(
14799ae226faSGeorge Liu         *crow::connections::systemBus, "xyz.openbmc_project.Network",
14809ae226faSGeorge Liu         "/xyz/openbmc_project/network/" + ifaceId,
14819ae226faSGeorge Liu         "xyz.openbmc_project.Network.EthernetInterface", "StaticNameServers",
14829ae226faSGeorge Liu         updatedStaticNameServers,
14835e7e2dc5SEd Tanous         [asyncResp](const boost::system::error_code& ec) {
1484f85837bfSRAJESWARAN THILLAIGOVINDAN         if (ec)
1485f85837bfSRAJESWARAN THILLAIGOVINDAN         {
1486f85837bfSRAJESWARAN THILLAIGOVINDAN             messages::internalError(asyncResp->res);
1487f85837bfSRAJESWARAN THILLAIGOVINDAN             return;
1488f85837bfSRAJESWARAN THILLAIGOVINDAN         }
14899ae226faSGeorge Liu     });
1490f85837bfSRAJESWARAN THILLAIGOVINDAN }
1491f85837bfSRAJESWARAN THILLAIGOVINDAN 
14924f48d5f6SEd Tanous inline void handleIPv6StaticAddressesPatch(
1493ddd70dcaSEd Tanous     const std::string& ifaceId, const nlohmann::json::array_t& input,
149477179532SEd Tanous     const std::vector<IPv6AddressData>& ipv6Data,
14958d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
1496e48c0fc5SRavi Teja {
1497ddd70dcaSEd Tanous     if (input.empty())
1498e48c0fc5SRavi Teja     {
14992e8c4bdaSEd Tanous         messages::propertyValueTypeError(asyncResp->res, input,
1500e48c0fc5SRavi Teja                                          "IPv6StaticAddresses");
1501e48c0fc5SRavi Teja         return;
1502e48c0fc5SRavi Teja     }
1503271584abSEd Tanous     size_t entryIdx = 1;
150477179532SEd Tanous     std::vector<IPv6AddressData>::const_iterator nicIpEntry =
15052c70f800SEd Tanous         getNextStaticIpEntry(ipv6Data.cbegin(), ipv6Data.cend());
1506f23b7296SEd Tanous     for (const nlohmann::json& thisJson : input)
1507e48c0fc5SRavi Teja     {
150889492a15SPatrick Williams         std::string pathString = "IPv6StaticAddresses/" +
150989492a15SPatrick Williams                                  std::to_string(entryIdx);
1510e48c0fc5SRavi Teja 
151101784826SJohnathan Mantey         if (!thisJson.is_null() && !thisJson.empty())
1512e48c0fc5SRavi Teja         {
1513e48c0fc5SRavi Teja             std::optional<std::string> address;
1514e48c0fc5SRavi Teja             std::optional<uint8_t> prefixLength;
1515f23b7296SEd Tanous             nlohmann::json thisJsonCopy = thisJson;
1516bf648f77SEd Tanous             if (!json_util::readJson(thisJsonCopy, asyncResp->res, "Address",
1517bf648f77SEd Tanous                                      address, "PrefixLength", prefixLength))
1518e48c0fc5SRavi Teja             {
1519f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
152071f52d96SEd Tanous                                                    pathString);
1521e48c0fc5SRavi Teja                 return;
1522e48c0fc5SRavi Teja             }
1523e48c0fc5SRavi Teja 
1524543f4400SEd Tanous             const std::string* addr = nullptr;
1525543f4400SEd Tanous             uint8_t prefix = 0;
152601784826SJohnathan Mantey 
152701784826SJohnathan Mantey             // Find the address and prefixLength values. Any values that are
152801784826SJohnathan Mantey             // not explicitly provided are assumed to be unmodified from the
152901784826SJohnathan Mantey             // current state of the interface. Merge existing state into the
153001784826SJohnathan Mantey             // current request.
1531e48c0fc5SRavi Teja             if (address)
1532e48c0fc5SRavi Teja             {
153301784826SJohnathan Mantey                 addr = &(*address);
1534e48c0fc5SRavi Teja             }
153585ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
153601784826SJohnathan Mantey             {
153785ffe86aSJiaqing Zhao                 addr = &(nicIpEntry->address);
153801784826SJohnathan Mantey             }
153901784826SJohnathan Mantey             else
154001784826SJohnathan Mantey             {
154101784826SJohnathan Mantey                 messages::propertyMissing(asyncResp->res,
154201784826SJohnathan Mantey                                           pathString + "/Address");
154301784826SJohnathan Mantey                 return;
1544e48c0fc5SRavi Teja             }
1545e48c0fc5SRavi Teja 
1546e48c0fc5SRavi Teja             if (prefixLength)
1547e48c0fc5SRavi Teja             {
154801784826SJohnathan Mantey                 prefix = *prefixLength;
154901784826SJohnathan Mantey             }
155085ffe86aSJiaqing Zhao             else if (nicIpEntry != ipv6Data.end())
1551e48c0fc5SRavi Teja             {
155285ffe86aSJiaqing Zhao                 prefix = nicIpEntry->prefixLength;
1553e48c0fc5SRavi Teja             }
1554e48c0fc5SRavi Teja             else
1555e48c0fc5SRavi Teja             {
1556e48c0fc5SRavi Teja                 messages::propertyMissing(asyncResp->res,
1557e48c0fc5SRavi Teja                                           pathString + "/PrefixLength");
155801784826SJohnathan Mantey                 return;
1559e48c0fc5SRavi Teja             }
1560e48c0fc5SRavi Teja 
156185ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.end())
1562e48c0fc5SRavi Teja             {
15639c5e585cSRavi Teja                 deleteAndCreateIPAddress(IpVersion::IpV6, ifaceId,
156477eb0153SEd Tanous                                          nicIpEntry->id, prefix, *addr, "",
1565e48c0fc5SRavi Teja                                          asyncResp);
156689492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
156789492a15SPatrick Williams                                                   ipv6Data.cend());
156801784826SJohnathan Mantey             }
156901784826SJohnathan Mantey             else
157001784826SJohnathan Mantey             {
157101784826SJohnathan Mantey                 createIPv6(ifaceId, *prefixLength, *addr, asyncResp);
1572e48c0fc5SRavi Teja             }
1573e48c0fc5SRavi Teja             entryIdx++;
1574e48c0fc5SRavi Teja         }
157501784826SJohnathan Mantey         else
157601784826SJohnathan Mantey         {
157785ffe86aSJiaqing Zhao             if (nicIpEntry == ipv6Data.end())
157801784826SJohnathan Mantey             {
157901784826SJohnathan Mantey                 // Requesting a DELETE/DO NOT MODIFY action for an item
158001784826SJohnathan Mantey                 // that isn't present on the eth(n) interface. Input JSON is
158101784826SJohnathan Mantey                 // in error, so bail out.
158201784826SJohnathan Mantey                 if (thisJson.is_null())
158301784826SJohnathan Mantey                 {
158401784826SJohnathan Mantey                     messages::resourceCannotBeDeleted(asyncResp->res);
158501784826SJohnathan Mantey                     return;
158601784826SJohnathan Mantey                 }
1587f818b04dSEd Tanous                 messages::propertyValueFormatError(asyncResp->res, thisJson,
158871f52d96SEd Tanous                                                    pathString);
158901784826SJohnathan Mantey                 return;
159001784826SJohnathan Mantey             }
159101784826SJohnathan Mantey 
159201784826SJohnathan Mantey             if (thisJson.is_null())
159301784826SJohnathan Mantey             {
15949c5e585cSRavi Teja                 deleteIPAddress(ifaceId, nicIpEntry->id, asyncResp);
159501784826SJohnathan Mantey             }
159685ffe86aSJiaqing Zhao             if (nicIpEntry != ipv6Data.cend())
159701784826SJohnathan Mantey             {
159889492a15SPatrick Williams                 nicIpEntry = getNextStaticIpEntry(++nicIpEntry,
159989492a15SPatrick Williams                                                   ipv6Data.cend());
160001784826SJohnathan Mantey             }
160101784826SJohnathan Mantey             entryIdx++;
160201784826SJohnathan Mantey         }
160301784826SJohnathan Mantey     }
1604e48c0fc5SRavi Teja }
1605e48c0fc5SRavi Teja 
16067857cb8dSJiaqing Zhao inline std::string extractParentInterfaceName(const std::string& ifaceId)
16077857cb8dSJiaqing Zhao {
16087857cb8dSJiaqing Zhao     std::size_t pos = ifaceId.find('_');
16097857cb8dSJiaqing Zhao     return ifaceId.substr(0, pos);
16107857cb8dSJiaqing Zhao }
16117857cb8dSJiaqing Zhao 
161277179532SEd Tanous inline void
161377179532SEd Tanous     parseInterfaceData(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
161477179532SEd Tanous                        const std::string& ifaceId,
161577179532SEd Tanous                        const EthernetInterfaceData& ethData,
161677179532SEd Tanous                        const std::vector<IPv4AddressData>& ipv4Data,
161777179532SEd Tanous                        const std::vector<IPv6AddressData>& ipv6Data)
16184a0cb85cSEd Tanous {
16192c70f800SEd Tanous     nlohmann::json& jsonResponse = asyncResp->res.jsonValue;
162081ce609eSEd Tanous     jsonResponse["Id"] = ifaceId;
1621ef4c65b7SEd Tanous     jsonResponse["@odata.id"] = boost::urls::format(
1622ef4c65b7SEd Tanous         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", ifaceId);
16232c70f800SEd Tanous     jsonResponse["InterfaceEnabled"] = ethData.nicEnabled;
1624eeedda23SJohnathan Mantey 
162513451e39SWilly Tu     if constexpr (bmcwebEnableHealthPopulate)
162613451e39SWilly Tu     {
162713451e39SWilly Tu         constexpr std::array<std::string_view, 1> inventoryForEthernet = {
162813451e39SWilly Tu             "xyz.openbmc_project.Inventory.Item.Ethernet"};
1629eeedda23SJohnathan Mantey         auto health = std::make_shared<HealthPopulate>(asyncResp);
16307a1dbc48SGeorge Liu         dbus::utility::getSubTreePaths(
16317a1dbc48SGeorge Liu             "/", 0, inventoryForEthernet,
16327a1dbc48SGeorge Liu             [health](const boost::system::error_code& ec,
1633b9d36b47SEd Tanous                      const dbus::utility::MapperGetSubTreePathsResponse& resp) {
1634eeedda23SJohnathan Mantey             if (ec)
1635029573d4SEd Tanous             {
1636eeedda23SJohnathan Mantey                 return;
1637eeedda23SJohnathan Mantey             }
1638eeedda23SJohnathan Mantey 
1639914e2d5dSEd Tanous             health->inventory = resp;
16407a1dbc48SGeorge Liu         });
1641eeedda23SJohnathan Mantey 
1642eeedda23SJohnathan Mantey         health->populate();
164313451e39SWilly Tu     }
1644eeedda23SJohnathan Mantey 
1645eeedda23SJohnathan Mantey     if (ethData.nicEnabled)
1646eeedda23SJohnathan Mantey     {
16470ef0e289SJohnathan Mantey         jsonResponse["LinkStatus"] = ethData.linkUp ? "LinkUp" : "LinkDown";
16482c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Enabled";
1649029573d4SEd Tanous     }
1650029573d4SEd Tanous     else
1651029573d4SEd Tanous     {
16522c70f800SEd Tanous         jsonResponse["LinkStatus"] = "NoLink";
16532c70f800SEd Tanous         jsonResponse["Status"]["State"] = "Disabled";
1654029573d4SEd Tanous     }
1655aa05fb27SJohnathan Mantey 
16562c70f800SEd Tanous     jsonResponse["SpeedMbps"] = ethData.speed;
165735fb5311STejas Patil     jsonResponse["MTUSize"] = ethData.mtuSize;
165882695a5bSJiaqing Zhao     jsonResponse["MACAddress"] = ethData.macAddress;
16592c70f800SEd Tanous     jsonResponse["DHCPv4"]["DHCPEnabled"] =
166082695a5bSJiaqing Zhao         translateDhcpEnabledToBool(ethData.dhcpEnabled, true);
1661e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseNTPServers"] = ethData.ntpv4Enabled;
1662e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDNSServers"] = ethData.dnsv4Enabled;
1663e4588158SJishnu CM     jsonResponse["DHCPv4"]["UseDomainName"] = ethData.hostNamev4Enabled;
16642c70f800SEd Tanous     jsonResponse["DHCPv6"]["OperatingMode"] =
1665b10d8db0SRavi Teja         translateDhcpEnabledToBool(ethData.dhcpEnabled, false) ? "Enabled"
16661f8c7b5dSJohnathan Mantey                                                                : "Disabled";
1667e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseNTPServers"] = ethData.ntpv6Enabled;
1668e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDNSServers"] = ethData.dnsv6Enabled;
1669e4588158SJishnu CM     jsonResponse["DHCPv6"]["UseDomainName"] = ethData.hostNamev6Enabled;
1670b10d8db0SRavi Teja     jsonResponse["StatelessAddressAutoConfig"]["IPv6AutoConfigEnabled"] =
1671b10d8db0SRavi Teja         ethData.ipv6AcceptRa;
16722a133282Smanojkiraneda 
167382695a5bSJiaqing Zhao     if (!ethData.hostName.empty())
16744a0cb85cSEd Tanous     {
167582695a5bSJiaqing Zhao         jsonResponse["HostName"] = ethData.hostName;
1676ab6554f1SJoshi-Mansi 
1677ab6554f1SJoshi-Mansi         // When domain name is empty then it means, that it is a network
1678ab6554f1SJoshi-Mansi         // without domain names, and the host name itself must be treated as
1679ab6554f1SJoshi-Mansi         // FQDN
168082695a5bSJiaqing Zhao         std::string fqdn = ethData.hostName;
1681d24bfc7aSJennifer Lee         if (!ethData.domainnames.empty())
1682d24bfc7aSJennifer Lee         {
16832c70f800SEd Tanous             fqdn += "." + ethData.domainnames[0];
1684d24bfc7aSJennifer Lee         }
16852c70f800SEd Tanous         jsonResponse["FQDN"] = fqdn;
16864a0cb85cSEd Tanous     }
16874a0cb85cSEd Tanous 
16887857cb8dSJiaqing Zhao     if (ethData.vlanId)
16897857cb8dSJiaqing Zhao     {
16907857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Virtual";
16917857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANEnable"] = true;
16927857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["VLANId"] = *ethData.vlanId;
16937857cb8dSJiaqing Zhao         jsonResponse["VLAN"]["Tagged"] = true;
16947857cb8dSJiaqing Zhao 
16957857cb8dSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
16967857cb8dSJiaqing Zhao         nlohmann::json& parentInterface = relatedInterfaces.emplace_back();
16977857cb8dSJiaqing Zhao         parentInterface["@odata.id"] =
16987857cb8dSJiaqing Zhao             boost::urls::format("/redfish/v1/Managers/bmc/EthernetInterfaces",
16997857cb8dSJiaqing Zhao                                 extractParentInterfaceName(ifaceId));
17007857cb8dSJiaqing Zhao         jsonResponse["Links"]["RelatedInterfaces"] =
17017857cb8dSJiaqing Zhao             std::move(relatedInterfaces);
17027857cb8dSJiaqing Zhao     }
17037857cb8dSJiaqing Zhao     else
17047857cb8dSJiaqing Zhao     {
17057857cb8dSJiaqing Zhao         jsonResponse["EthernetInterfaceType"] = "Physical";
17067857cb8dSJiaqing Zhao     }
17077857cb8dSJiaqing Zhao 
17082c70f800SEd Tanous     jsonResponse["NameServers"] = ethData.nameServers;
17092c70f800SEd Tanous     jsonResponse["StaticNameServers"] = ethData.staticNameServers;
17104a0cb85cSEd Tanous 
17112c70f800SEd Tanous     nlohmann::json& ipv4Array = jsonResponse["IPv4Addresses"];
17122c70f800SEd Tanous     nlohmann::json& ipv4StaticArray = jsonResponse["IPv4StaticAddresses"];
17132c70f800SEd Tanous     ipv4Array = nlohmann::json::array();
17142c70f800SEd Tanous     ipv4StaticArray = nlohmann::json::array();
17159eb808c1SEd Tanous     for (const auto& ipv4Config : ipv4Data)
17164a0cb85cSEd Tanous     {
17172c70f800SEd Tanous         std::string gatewayStr = ipv4Config.gateway;
1718fa5053a6SGunnar Mills         if (gatewayStr.empty())
1719fa5053a6SGunnar Mills         {
1720fa5053a6SGunnar Mills             gatewayStr = "0.0.0.0";
1721fa5053a6SGunnar Mills         }
17221476687dSEd Tanous         nlohmann::json::object_t ipv4;
17231476687dSEd Tanous         ipv4["AddressOrigin"] = ipv4Config.origin;
17241476687dSEd Tanous         ipv4["SubnetMask"] = ipv4Config.netmask;
17251476687dSEd Tanous         ipv4["Address"] = ipv4Config.address;
17261476687dSEd Tanous         ipv4["Gateway"] = gatewayStr;
1727fa5053a6SGunnar Mills 
17282c70f800SEd Tanous         if (ipv4Config.origin == "Static")
1729d1d50814SRavi Teja         {
17301476687dSEd Tanous             ipv4StaticArray.push_back(ipv4);
1731d1d50814SRavi Teja         }
17321476687dSEd Tanous 
1733b2ba3072SPatrick Williams         ipv4Array.emplace_back(std::move(ipv4));
173401784826SJohnathan Mantey     }
1735d1d50814SRavi Teja 
173682695a5bSJiaqing Zhao     std::string ipv6GatewayStr = ethData.ipv6DefaultGateway;
17377ea79e5eSRavi Teja     if (ipv6GatewayStr.empty())
17387ea79e5eSRavi Teja     {
17397ea79e5eSRavi Teja         ipv6GatewayStr = "0:0:0:0:0:0:0:0";
17407ea79e5eSRavi Teja     }
17417ea79e5eSRavi Teja 
17427ea79e5eSRavi Teja     jsonResponse["IPv6DefaultGateway"] = ipv6GatewayStr;
1743e48c0fc5SRavi Teja 
17442c70f800SEd Tanous     nlohmann::json& ipv6Array = jsonResponse["IPv6Addresses"];
17452c70f800SEd Tanous     nlohmann::json& ipv6StaticArray = jsonResponse["IPv6StaticAddresses"];
17462c70f800SEd Tanous     ipv6Array = nlohmann::json::array();
17472c70f800SEd Tanous     ipv6StaticArray = nlohmann::json::array();
17487f2e23e9SJohnathan Mantey     nlohmann::json& ipv6AddrPolicyTable =
17492c70f800SEd Tanous         jsonResponse["IPv6AddressPolicyTable"];
17507f2e23e9SJohnathan Mantey     ipv6AddrPolicyTable = nlohmann::json::array();
17519eb808c1SEd Tanous     for (const auto& ipv6Config : ipv6Data)
1752e48c0fc5SRavi Teja     {
17531476687dSEd Tanous         nlohmann::json::object_t ipv6;
17541476687dSEd Tanous         ipv6["Address"] = ipv6Config.address;
17551476687dSEd Tanous         ipv6["PrefixLength"] = ipv6Config.prefixLength;
17561476687dSEd Tanous         ipv6["AddressOrigin"] = ipv6Config.origin;
1757f8361275SSunitha Harish 
1758b2ba3072SPatrick Williams         ipv6Array.emplace_back(std::move(ipv6));
17592c70f800SEd Tanous         if (ipv6Config.origin == "Static")
1760e48c0fc5SRavi Teja         {
17611476687dSEd Tanous             nlohmann::json::object_t ipv6Static;
17621476687dSEd Tanous             ipv6Static["Address"] = ipv6Config.address;
17631476687dSEd Tanous             ipv6Static["PrefixLength"] = ipv6Config.prefixLength;
1764b2ba3072SPatrick Williams             ipv6StaticArray.emplace_back(std::move(ipv6Static));
176501784826SJohnathan Mantey         }
1766e48c0fc5SRavi Teja     }
1767588c3f0dSKowalski, Kamil }
1768588c3f0dSKowalski, Kamil 
1769e7caf250SJiaqing Zhao inline void afterDelete(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1770e7caf250SJiaqing Zhao                         const std::string& ifaceId,
1771e7caf250SJiaqing Zhao                         const boost::system::error_code& ec,
1772e7caf250SJiaqing Zhao                         const sdbusplus::message_t& m)
1773e7caf250SJiaqing Zhao {
1774e7caf250SJiaqing Zhao     if (!ec)
1775e7caf250SJiaqing Zhao     {
1776e7caf250SJiaqing Zhao         return;
1777e7caf250SJiaqing Zhao     }
1778e7caf250SJiaqing Zhao     const sd_bus_error* dbusError = m.get_error();
1779e7caf250SJiaqing Zhao     if (dbusError == nullptr)
1780e7caf250SJiaqing Zhao     {
1781e7caf250SJiaqing Zhao         messages::internalError(asyncResp->res);
1782e7caf250SJiaqing Zhao         return;
1783e7caf250SJiaqing Zhao     }
178462598e31SEd Tanous     BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1785e7caf250SJiaqing Zhao 
1786e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownObject") ==
1787e7caf250SJiaqing Zhao         dbusError->name)
1788e7caf250SJiaqing Zhao     {
1789e7caf250SJiaqing Zhao         messages::resourceNotFound(asyncResp->res, "EthernetInterface",
1790e7caf250SJiaqing Zhao                                    ifaceId);
1791e7caf250SJiaqing Zhao         return;
1792e7caf250SJiaqing Zhao     }
1793e7caf250SJiaqing Zhao     if (std::string_view("org.freedesktop.DBus.Error.UnknownMethod") ==
1794e7caf250SJiaqing Zhao         dbusError->name)
1795e7caf250SJiaqing Zhao     {
1796e7caf250SJiaqing Zhao         messages::resourceCannotBeDeleted(asyncResp->res);
1797e7caf250SJiaqing Zhao         return;
1798e7caf250SJiaqing Zhao     }
1799e7caf250SJiaqing Zhao     messages::internalError(asyncResp->res);
1800e7caf250SJiaqing Zhao }
1801e7caf250SJiaqing Zhao 
1802b5ca3fdcSJiaqing Zhao inline void afterVlanCreate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1803b5ca3fdcSJiaqing Zhao                             const std::string& parentInterfaceUri,
1804b5ca3fdcSJiaqing Zhao                             const std::string& vlanInterface,
1805b5ca3fdcSJiaqing Zhao                             const boost::system::error_code& ec,
1806b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m
1807b5ca3fdcSJiaqing Zhao 
1808b5ca3fdcSJiaqing Zhao )
1809b5ca3fdcSJiaqing Zhao {
1810b5ca3fdcSJiaqing Zhao     if (ec)
1811b5ca3fdcSJiaqing Zhao     {
1812b5ca3fdcSJiaqing Zhao         const sd_bus_error* dbusError = m.get_error();
1813b5ca3fdcSJiaqing Zhao         if (dbusError == nullptr)
1814b5ca3fdcSJiaqing Zhao         {
1815b5ca3fdcSJiaqing Zhao             messages::internalError(asyncResp->res);
1816b5ca3fdcSJiaqing Zhao             return;
1817b5ca3fdcSJiaqing Zhao         }
181862598e31SEd Tanous         BMCWEB_LOG_DEBUG("DBus error: {}", dbusError->name);
1819b5ca3fdcSJiaqing Zhao 
1820b5ca3fdcSJiaqing Zhao         if (std::string_view(
1821b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.ResourceNotFound") ==
1822b5ca3fdcSJiaqing Zhao             dbusError->name)
1823b5ca3fdcSJiaqing Zhao         {
1824b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1825b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1826b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1827b5ca3fdcSJiaqing Zhao             return;
1828b5ca3fdcSJiaqing Zhao         }
1829b5ca3fdcSJiaqing Zhao         if (std::string_view(
1830b5ca3fdcSJiaqing Zhao                 "xyz.openbmc_project.Common.Error.InvalidArgument") ==
1831b5ca3fdcSJiaqing Zhao             dbusError->name)
1832b5ca3fdcSJiaqing Zhao         {
1833b5ca3fdcSJiaqing Zhao             messages::resourceAlreadyExists(asyncResp->res, "EthernetInterface",
1834b5ca3fdcSJiaqing Zhao                                             "Id", vlanInterface);
1835b5ca3fdcSJiaqing Zhao             return;
1836b5ca3fdcSJiaqing Zhao         }
1837b5ca3fdcSJiaqing Zhao         messages::internalError(asyncResp->res);
1838b5ca3fdcSJiaqing Zhao         return;
1839b5ca3fdcSJiaqing Zhao     }
1840b5ca3fdcSJiaqing Zhao 
1841b5ca3fdcSJiaqing Zhao     const boost::urls::url vlanInterfaceUri = boost::urls::format(
1842b5ca3fdcSJiaqing Zhao         "/redfish/v1/Managers/bmc/EthernetInterfaces/{}", vlanInterface);
1843b5ca3fdcSJiaqing Zhao     asyncResp->res.addHeader("Location", vlanInterfaceUri.buffer());
1844b5ca3fdcSJiaqing Zhao }
1845b5ca3fdcSJiaqing Zhao 
1846bf648f77SEd Tanous inline void requestEthernetInterfacesRoutes(App& app)
1847bf648f77SEd Tanous {
1848bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1849ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterfaceCollection)
18501476687dSEd Tanous         .methods(boost::beast::http::verb::get)(
18511476687dSEd Tanous             [&app](const crow::Request& req,
18521476687dSEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
18533ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
185445ca1b86SEd Tanous         {
185545ca1b86SEd Tanous             return;
185645ca1b86SEd Tanous         }
185745ca1b86SEd Tanous 
1858bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
1859bf648f77SEd Tanous             "#EthernetInterfaceCollection.EthernetInterfaceCollection";
1860bf648f77SEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
1861bf648f77SEd Tanous             "/redfish/v1/Managers/bmc/EthernetInterfaces";
1862bf648f77SEd Tanous         asyncResp->res.jsonValue["Name"] =
1863bf648f77SEd Tanous             "Ethernet Network Interface Collection";
1864bf648f77SEd Tanous         asyncResp->res.jsonValue["Description"] =
1865bf648f77SEd Tanous             "Collection of EthernetInterfaces for this Manager";
1866bf648f77SEd Tanous 
1867bf648f77SEd Tanous         // Get eth interface list, and call the below callback for JSON
1868bf648f77SEd Tanous         // preparation
1869002d39b4SEd Tanous         getEthernetIfaceList(
187077179532SEd Tanous             [asyncResp](const bool& success,
187177179532SEd Tanous                         const std::vector<std::string>& ifaceList) {
1872bf648f77SEd Tanous             if (!success)
18731abe55efSEd Tanous             {
1874f12894f8SJason M. Bills                 messages::internalError(asyncResp->res);
18759391bb9cSRapkiewicz, Pawel                 return;
18769391bb9cSRapkiewicz, Pawel             }
18779391bb9cSRapkiewicz, Pawel 
1878002d39b4SEd Tanous             nlohmann::json& ifaceArray = asyncResp->res.jsonValue["Members"];
1879bf648f77SEd Tanous             ifaceArray = nlohmann::json::array();
1880bf648f77SEd Tanous             for (const std::string& ifaceItem : ifaceList)
1881bf648f77SEd Tanous             {
18821476687dSEd Tanous                 nlohmann::json::object_t iface;
1883ef4c65b7SEd Tanous                 iface["@odata.id"] = boost::urls::format(
1884ef4c65b7SEd Tanous                     "/redfish/v1/Managers/bmc/EthernetInterfaces/{}",
1885ef4c65b7SEd Tanous                     ifaceItem);
18867857cb8dSJiaqing Zhao                 ifaceArray.push_back(std::move(iface));
1887bf648f77SEd Tanous             }
1888bf648f77SEd Tanous 
1889002d39b4SEd Tanous             asyncResp->res.jsonValue["Members@odata.count"] = ifaceArray.size();
1890bf648f77SEd Tanous             asyncResp->res.jsonValue["@odata.id"] =
1891bf648f77SEd Tanous                 "/redfish/v1/Managers/bmc/EthernetInterfaces";
1892bf648f77SEd Tanous         });
1893bf648f77SEd Tanous     });
1894bf648f77SEd Tanous 
1895b5ca3fdcSJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/")
1896b5ca3fdcSJiaqing Zhao         .privileges(redfish::privileges::postEthernetInterfaceCollection)
1897b5ca3fdcSJiaqing Zhao         .methods(boost::beast::http::verb::post)(
1898b5ca3fdcSJiaqing Zhao             [&app](const crow::Request& req,
1899b5ca3fdcSJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1900b5ca3fdcSJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
1901b5ca3fdcSJiaqing Zhao         {
1902b5ca3fdcSJiaqing Zhao             return;
1903b5ca3fdcSJiaqing Zhao         }
1904b5ca3fdcSJiaqing Zhao 
1905b5ca3fdcSJiaqing Zhao         bool vlanEnable = false;
1906b5ca3fdcSJiaqing Zhao         uint32_t vlanId = 0;
1907b5ca3fdcSJiaqing Zhao         nlohmann::json::array_t relatedInterfaces;
1908b5ca3fdcSJiaqing Zhao 
1909b5ca3fdcSJiaqing Zhao         if (!json_util::readJsonPatch(req, asyncResp->res, "VLAN/VLANEnable",
1910b5ca3fdcSJiaqing Zhao                                       vlanEnable, "VLAN/VLANId", vlanId,
1911b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces",
1912b5ca3fdcSJiaqing Zhao                                       relatedInterfaces))
1913b5ca3fdcSJiaqing Zhao         {
1914b5ca3fdcSJiaqing Zhao             return;
1915b5ca3fdcSJiaqing Zhao         }
1916b5ca3fdcSJiaqing Zhao 
1917b5ca3fdcSJiaqing Zhao         if (relatedInterfaces.size() != 1)
1918b5ca3fdcSJiaqing Zhao         {
1919b5ca3fdcSJiaqing Zhao             messages::arraySizeTooLong(asyncResp->res,
1920b5ca3fdcSJiaqing Zhao                                        "Links/RelatedInterfaces",
1921b5ca3fdcSJiaqing Zhao                                        relatedInterfaces.size());
1922b5ca3fdcSJiaqing Zhao             return;
1923b5ca3fdcSJiaqing Zhao         }
1924b5ca3fdcSJiaqing Zhao 
1925b5ca3fdcSJiaqing Zhao         std::string parentInterfaceUri;
1926b5ca3fdcSJiaqing Zhao         if (!json_util::readJson(relatedInterfaces[0], asyncResp->res,
1927b5ca3fdcSJiaqing Zhao                                  "@odata.id", parentInterfaceUri))
1928b5ca3fdcSJiaqing Zhao         {
1929b5ca3fdcSJiaqing Zhao             messages::propertyMissing(asyncResp->res,
1930b5ca3fdcSJiaqing Zhao                                       "Links/RelatedInterfaces/0/@odata.id");
1931b5ca3fdcSJiaqing Zhao             return;
1932b5ca3fdcSJiaqing Zhao         }
193362598e31SEd Tanous         BMCWEB_LOG_INFO("Parent Interface URI: {}", parentInterfaceUri);
1934b5ca3fdcSJiaqing Zhao 
19356fd29553SEd Tanous         boost::system::result<boost::urls::url_view> parsedUri =
1936b5ca3fdcSJiaqing Zhao             boost::urls::parse_relative_ref(parentInterfaceUri);
1937b5ca3fdcSJiaqing Zhao         if (!parsedUri)
1938b5ca3fdcSJiaqing Zhao         {
1939b5ca3fdcSJiaqing Zhao             messages::propertyValueFormatError(
1940b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1941b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1942b5ca3fdcSJiaqing Zhao             return;
1943b5ca3fdcSJiaqing Zhao         }
1944b5ca3fdcSJiaqing Zhao 
1945b5ca3fdcSJiaqing Zhao         std::string parentInterface;
1946b5ca3fdcSJiaqing Zhao         if (!crow::utility::readUrlSegments(
1947b5ca3fdcSJiaqing Zhao                 *parsedUri, "redfish", "v1", "Managers", "bmc",
1948b5ca3fdcSJiaqing Zhao                 "EthernetInterfaces", std::ref(parentInterface)))
1949b5ca3fdcSJiaqing Zhao         {
1950b5ca3fdcSJiaqing Zhao             messages::propertyValueNotInList(
1951b5ca3fdcSJiaqing Zhao                 asyncResp->res, parentInterfaceUri,
1952b5ca3fdcSJiaqing Zhao                 "Links/RelatedInterfaces/0/@odata.id");
1953b5ca3fdcSJiaqing Zhao             return;
1954b5ca3fdcSJiaqing Zhao         }
1955b5ca3fdcSJiaqing Zhao 
1956b5ca3fdcSJiaqing Zhao         if (!vlanEnable)
1957b5ca3fdcSJiaqing Zhao         {
1958b5ca3fdcSJiaqing Zhao             // In OpenBMC implementation, VLANEnable cannot be false on
1959b5ca3fdcSJiaqing Zhao             // create
1960b5ca3fdcSJiaqing Zhao             messages::propertyValueIncorrect(asyncResp->res, "VLAN/VLANEnable",
1961b5ca3fdcSJiaqing Zhao                                              "false");
1962b5ca3fdcSJiaqing Zhao             return;
1963b5ca3fdcSJiaqing Zhao         }
1964b5ca3fdcSJiaqing Zhao 
1965b5ca3fdcSJiaqing Zhao         std::string vlanInterface = parentInterface + "_" +
1966b5ca3fdcSJiaqing Zhao                                     std::to_string(vlanId);
1967b5ca3fdcSJiaqing Zhao         crow::connections::systemBus->async_method_call(
1968b5ca3fdcSJiaqing Zhao             [asyncResp, parentInterfaceUri,
1969b5ca3fdcSJiaqing Zhao              vlanInterface](const boost::system::error_code& ec,
1970b5ca3fdcSJiaqing Zhao                             const sdbusplus::message_t& m) {
1971b5ca3fdcSJiaqing Zhao             afterVlanCreate(asyncResp, parentInterfaceUri, vlanInterface, ec,
1972b5ca3fdcSJiaqing Zhao                             m);
1973b5ca3fdcSJiaqing Zhao         },
1974b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network", "/xyz/openbmc_project/network",
1975b5ca3fdcSJiaqing Zhao             "xyz.openbmc_project.Network.VLAN.Create", "VLAN", parentInterface,
1976b5ca3fdcSJiaqing Zhao             vlanId);
1977b5ca3fdcSJiaqing Zhao     });
1978b5ca3fdcSJiaqing Zhao 
1979bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
1980ed398213SEd Tanous         .privileges(redfish::privileges::getEthernetInterface)
1981bf648f77SEd Tanous         .methods(boost::beast::http::verb::get)(
198245ca1b86SEd Tanous             [&app](const crow::Request& req,
1983bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1984bf648f77SEd Tanous                    const std::string& ifaceId) {
19853ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
198645ca1b86SEd Tanous         {
198745ca1b86SEd Tanous             return;
198845ca1b86SEd Tanous         }
19894a0cb85cSEd Tanous         getEthernetIfaceData(
1990bf648f77SEd Tanous             ifaceId,
199177179532SEd Tanous             [asyncResp, ifaceId](const bool& success,
199277179532SEd Tanous                                  const EthernetInterfaceData& ethData,
199377179532SEd Tanous                                  const std::vector<IPv4AddressData>& ipv4Data,
199477179532SEd Tanous                                  const std::vector<IPv6AddressData>& ipv6Data) {
19954a0cb85cSEd Tanous             if (!success)
19961abe55efSEd Tanous             {
1997bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
1998bf648f77SEd Tanous                 // existing object, and other errors
1999002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2000002d39b4SEd Tanous                                            ifaceId);
20014a0cb85cSEd Tanous                 return;
20029391bb9cSRapkiewicz, Pawel             }
20034c9afe43SEd Tanous 
20040f74e643SEd Tanous             asyncResp->res.jsonValue["@odata.type"] =
200593bbc953SJiaqing Zhao                 "#EthernetInterface.v1_9_0.EthernetInterface";
2006002d39b4SEd Tanous             asyncResp->res.jsonValue["Name"] = "Manager Ethernet Interface";
20070f74e643SEd Tanous             asyncResp->res.jsonValue["Description"] =
20080f74e643SEd Tanous                 "Management Network Interface";
20090f74e643SEd Tanous 
2010002d39b4SEd Tanous             parseInterfaceData(asyncResp, ifaceId, ethData, ipv4Data, ipv6Data);
20119391bb9cSRapkiewicz, Pawel         });
2012bf648f77SEd Tanous     });
20139391bb9cSRapkiewicz, Pawel 
2014bf648f77SEd Tanous     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2015ed398213SEd Tanous         .privileges(redfish::privileges::patchEthernetInterface)
2016bf648f77SEd Tanous         .methods(boost::beast::http::verb::patch)(
201745ca1b86SEd Tanous             [&app](const crow::Request& req,
2018bf648f77SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2019bf648f77SEd Tanous                    const std::string& ifaceId) {
20203ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
202145ca1b86SEd Tanous         {
202245ca1b86SEd Tanous             return;
202345ca1b86SEd Tanous         }
2024bc0bd6e0SEd Tanous         std::optional<std::string> hostname;
2025ab6554f1SJoshi-Mansi         std::optional<std::string> fqdn;
2026d577665bSRatan Gupta         std::optional<std::string> macAddress;
20279a6fc6feSRavi Teja         std::optional<std::string> ipv6DefaultGateway;
2028ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv4StaticAddresses;
2029ddd70dcaSEd Tanous         std::optional<nlohmann::json::array_t> ipv6StaticAddresses;
2030f85837bfSRAJESWARAN THILLAIGOVINDAN         std::optional<std::vector<std::string>> staticNameServers;
2031da131a9aSJennifer Lee         std::optional<nlohmann::json> dhcpv4;
20321f8c7b5dSJohnathan Mantey         std::optional<nlohmann::json> dhcpv6;
2033b10d8db0SRavi Teja         std::optional<bool> ipv6AutoConfigEnabled;
2034eeedda23SJohnathan Mantey         std::optional<bool> interfaceEnabled;
203535fb5311STejas Patil         std::optional<size_t> mtuSize;
20361f8c7b5dSJohnathan Mantey         DHCPParameters v4dhcpParms;
20371f8c7b5dSJohnathan Mantey         DHCPParameters v6dhcpParms;
2038b10d8db0SRavi Teja         // clang-format off
203915ed6780SWilly Tu         if (!json_util::readJsonPatch(
2040b10d8db0SRavi Teja                 req, asyncResp->res,
2041b10d8db0SRavi Teja                 "DHCPv4", dhcpv4,
2042b10d8db0SRavi Teja                 "DHCPv6", dhcpv6,
2043b10d8db0SRavi Teja                 "FQDN", fqdn,
2044b10d8db0SRavi Teja                 "HostName", hostname,
2045b10d8db0SRavi Teja                 "IPv4StaticAddresses", ipv4StaticAddresses,
2046b10d8db0SRavi Teja                 "IPv6DefaultGateway", ipv6DefaultGateway,
2047b10d8db0SRavi Teja                 "IPv6StaticAddresses", ipv6StaticAddresses,
2048b10d8db0SRavi Teja                 "InterfaceEnabled", interfaceEnabled,
2049b10d8db0SRavi Teja                 "MACAddress", macAddress,
2050b10d8db0SRavi Teja                 "MTUSize", mtuSize,
2051b10d8db0SRavi Teja                 "StatelessAddressAutoConfig/IPv6AutoConfigEnabled", ipv6AutoConfigEnabled,
2052b10d8db0SRavi Teja                 "StaticNameServers", staticNameServers
2053b10d8db0SRavi Teja                 )
2054b10d8db0SRavi Teja             )
20551abe55efSEd Tanous         {
2056588c3f0dSKowalski, Kamil             return;
2057588c3f0dSKowalski, Kamil         }
2058b10d8db0SRavi Teja         //clang-format on
2059da131a9aSJennifer Lee         if (dhcpv4)
2060da131a9aSJennifer Lee         {
2061002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv4, asyncResp->res, "DHCPEnabled",
20621f8c7b5dSJohnathan Mantey                                      v4dhcpParms.dhcpv4Enabled, "UseDNSServers",
206382695a5bSJiaqing Zhao                                      v4dhcpParms.useDnsServers, "UseNTPServers",
206482695a5bSJiaqing Zhao                                      v4dhcpParms.useNtpServers, "UseDomainName",
206582695a5bSJiaqing Zhao                                      v4dhcpParms.useDomainName))
20661f8c7b5dSJohnathan Mantey             {
20671f8c7b5dSJohnathan Mantey                 return;
20681f8c7b5dSJohnathan Mantey             }
20691f8c7b5dSJohnathan Mantey         }
20701f8c7b5dSJohnathan Mantey 
20711f8c7b5dSJohnathan Mantey         if (dhcpv6)
20721f8c7b5dSJohnathan Mantey         {
2073002d39b4SEd Tanous             if (!json_util::readJson(*dhcpv6, asyncResp->res, "OperatingMode",
2074002d39b4SEd Tanous                                      v6dhcpParms.dhcpv6OperatingMode,
2075002d39b4SEd Tanous                                      "UseDNSServers", v6dhcpParms.useDnsServers,
2076002d39b4SEd Tanous                                      "UseNTPServers", v6dhcpParms.useNtpServers,
2077002d39b4SEd Tanous                                      "UseDomainName",
207882695a5bSJiaqing Zhao                                      v6dhcpParms.useDomainName))
20791f8c7b5dSJohnathan Mantey             {
20801f8c7b5dSJohnathan Mantey                 return;
20811f8c7b5dSJohnathan Mantey             }
2082da131a9aSJennifer Lee         }
2083da131a9aSJennifer Lee 
2084bf648f77SEd Tanous         // Get single eth interface data, and call the below callback
2085bf648f77SEd Tanous         // for JSON preparation
20864a0cb85cSEd Tanous         getEthernetIfaceData(
20872c70f800SEd Tanous             ifaceId,
2088bf648f77SEd Tanous             [asyncResp, ifaceId, hostname = std::move(hostname),
2089ab6554f1SJoshi-Mansi              fqdn = std::move(fqdn), macAddress = std::move(macAddress),
2090d1d50814SRavi Teja              ipv4StaticAddresses = std::move(ipv4StaticAddresses),
20919a6fc6feSRavi Teja              ipv6DefaultGateway = std::move(ipv6DefaultGateway),
2092e48c0fc5SRavi Teja              ipv6StaticAddresses = std::move(ipv6StaticAddresses),
20931f8c7b5dSJohnathan Mantey              staticNameServers = std::move(staticNameServers),
2094bc20089aSEd Tanous              dhcpv4 = std::move(dhcpv4), dhcpv6 = std::move(dhcpv6), mtuSize,
2095b10d8db0SRavi Teja              ipv6AutoConfigEnabled, v4dhcpParms = std::move(v4dhcpParms),
2096f23b7296SEd Tanous              v6dhcpParms = std::move(v6dhcpParms), interfaceEnabled](
2097002d39b4SEd Tanous                 const bool& success, const EthernetInterfaceData& ethData,
209877179532SEd Tanous                 const std::vector<IPv4AddressData>& ipv4Data,
209977179532SEd Tanous                 const std::vector<IPv6AddressData>& ipv6Data) {
21001abe55efSEd Tanous             if (!success)
21011abe55efSEd Tanous             {
2102588c3f0dSKowalski, Kamil                 // ... otherwise return error
2103bf648f77SEd Tanous                 // TODO(Pawel)consider distinguish between non
2104bf648f77SEd Tanous                 // existing object, and other errors
2105002d39b4SEd Tanous                 messages::resourceNotFound(asyncResp->res, "EthernetInterface",
2106002d39b4SEd Tanous                                            ifaceId);
2107588c3f0dSKowalski, Kamil                 return;
2108588c3f0dSKowalski, Kamil             }
2109588c3f0dSKowalski, Kamil 
21101f8c7b5dSJohnathan Mantey             if (dhcpv4 || dhcpv6)
21111f8c7b5dSJohnathan Mantey             {
2112002d39b4SEd Tanous                 handleDHCPPatch(ifaceId, ethData, v4dhcpParms, v6dhcpParms,
2113002d39b4SEd Tanous                                 asyncResp);
21141f8c7b5dSJohnathan Mantey             }
21151f8c7b5dSJohnathan Mantey 
21160627a2c7SEd Tanous             if (hostname)
21171abe55efSEd Tanous             {
21180627a2c7SEd Tanous                 handleHostnamePatch(*hostname, asyncResp);
21191abe55efSEd Tanous             }
21200627a2c7SEd Tanous 
2121b10d8db0SRavi Teja             if (ipv6AutoConfigEnabled)
2122b10d8db0SRavi Teja             {
2123b10d8db0SRavi Teja                 handleSLAACAutoConfigPatch(ifaceId, *ipv6AutoConfigEnabled,
2124b10d8db0SRavi Teja                                            asyncResp);
2125b10d8db0SRavi Teja             }
2126b10d8db0SRavi Teja 
2127ab6554f1SJoshi-Mansi             if (fqdn)
2128ab6554f1SJoshi-Mansi             {
21292c70f800SEd Tanous                 handleFqdnPatch(ifaceId, *fqdn, asyncResp);
2130ab6554f1SJoshi-Mansi             }
2131ab6554f1SJoshi-Mansi 
2132d577665bSRatan Gupta             if (macAddress)
2133d577665bSRatan Gupta             {
2134002d39b4SEd Tanous                 handleMACAddressPatch(ifaceId, *macAddress, asyncResp);
2135d577665bSRatan Gupta             }
2136d577665bSRatan Gupta 
2137d1d50814SRavi Teja             if (ipv4StaticAddresses)
2138d1d50814SRavi Teja             {
2139bf648f77SEd Tanous                 // TODO(ed) for some reason the capture of
2140bf648f77SEd Tanous                 // ipv4Addresses above is returning a const value,
2141bf648f77SEd Tanous                 // not a non-const value. This doesn't really work
2142bf648f77SEd Tanous                 // for us, as we need to be able to efficiently move
2143bf648f77SEd Tanous                 // out the intermedia nlohmann::json objects. This
2144bf648f77SEd Tanous                 // makes a copy of the structure, and operates on
2145bf648f77SEd Tanous                 // that, but could be done more efficiently
2146ddd70dcaSEd Tanous                 nlohmann::json::array_t ipv4Static = *ipv4StaticAddresses;
2147002d39b4SEd Tanous                 handleIPv4StaticPatch(ifaceId, ipv4Static, ipv4Data, asyncResp);
21481abe55efSEd Tanous             }
21490627a2c7SEd Tanous 
2150f85837bfSRAJESWARAN THILLAIGOVINDAN             if (staticNameServers)
2151f85837bfSRAJESWARAN THILLAIGOVINDAN             {
2152002d39b4SEd Tanous                 handleStaticNameServersPatch(ifaceId, *staticNameServers,
2153002d39b4SEd Tanous                                              asyncResp);
2154f85837bfSRAJESWARAN THILLAIGOVINDAN             }
21559a6fc6feSRavi Teja 
21569a6fc6feSRavi Teja             if (ipv6DefaultGateway)
21579a6fc6feSRavi Teja             {
21589a6fc6feSRavi Teja                 messages::propertyNotWritable(asyncResp->res,
21599a6fc6feSRavi Teja                                               "IPv6DefaultGateway");
21609a6fc6feSRavi Teja             }
2161e48c0fc5SRavi Teja 
2162e48c0fc5SRavi Teja             if (ipv6StaticAddresses)
2163e48c0fc5SRavi Teja             {
2164ddd70dcaSEd Tanous                 handleIPv6StaticAddressesPatch(ifaceId, *ipv6StaticAddresses,
2165ddd70dcaSEd Tanous                                                ipv6Data, asyncResp);
2166e48c0fc5SRavi Teja             }
2167eeedda23SJohnathan Mantey 
2168eeedda23SJohnathan Mantey             if (interfaceEnabled)
2169eeedda23SJohnathan Mantey             {
2170002d39b4SEd Tanous                 setEthernetInterfaceBoolProperty(ifaceId, "NICEnabled",
2171002d39b4SEd Tanous                                                  *interfaceEnabled, asyncResp);
2172eeedda23SJohnathan Mantey             }
217335fb5311STejas Patil 
217435fb5311STejas Patil             if (mtuSize)
217535fb5311STejas Patil             {
217635fb5311STejas Patil                 handleMTUSizePatch(ifaceId, *mtuSize, asyncResp);
217735fb5311STejas Patil             }
2178588c3f0dSKowalski, Kamil             });
2179bf648f77SEd Tanous         });
2180e7caf250SJiaqing Zhao 
2181e7caf250SJiaqing Zhao     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/EthernetInterfaces/<str>/")
2182e7caf250SJiaqing Zhao         .privileges(redfish::privileges::deleteEthernetInterface)
2183e7caf250SJiaqing Zhao         .methods(boost::beast::http::verb::delete_)(
2184e7caf250SJiaqing Zhao             [&app](const crow::Request& req,
2185e7caf250SJiaqing Zhao                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
2186e7caf250SJiaqing Zhao                    const std::string& ifaceId) {
2187e7caf250SJiaqing Zhao         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
2188e7caf250SJiaqing Zhao         {
2189e7caf250SJiaqing Zhao             return;
2190e7caf250SJiaqing Zhao         }
2191e7caf250SJiaqing Zhao 
2192e7caf250SJiaqing Zhao         crow::connections::systemBus->async_method_call(
2193e7caf250SJiaqing Zhao             [asyncResp, ifaceId](const boost::system::error_code& ec,
2194e7caf250SJiaqing Zhao                                  const sdbusplus::message_t& m) {
2195e7caf250SJiaqing Zhao             afterDelete(asyncResp, ifaceId, ec, m);
2196e7caf250SJiaqing Zhao             },
2197e7caf250SJiaqing Zhao             "xyz.openbmc_project.Network",
2198e7caf250SJiaqing Zhao             std::string("/xyz/openbmc_project/network/") + ifaceId,
2199e7caf250SJiaqing Zhao             "xyz.openbmc_project.Object.Delete", "Delete");
2200e7caf250SJiaqing Zhao         });
22014a0cb85cSEd Tanous }
2202bf648f77SEd Tanous 
22039391bb9cSRapkiewicz, Pawel } // namespace redfish
2204