blob: ff5a21b8aa580d45997dbf65cc9391b2986c46e9 [file] [log] [blame]
Gunnar Mills57d9c502018-09-14 14:42:34 -05001#include "config.h"
2
Patrick Venture189d44e2018-07-09 12:30:59 -07003#include "ethernet_interface.hpp"
4
Ratan Gupta497c0c92017-08-22 19:15:59 +05305#include "config_parser.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05306#include "network_manager.hpp"
William A. Kennington III95530ec2022-08-19 01:44:39 -07007#include "util.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05308
Ratan Gupta82549cc2017-04-21 08:45:23 +05309#include <arpa/inet.h>
William A. Kennington IIIa520a392022-08-08 12:17:34 -070010#include <fmt/compile.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070011#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053012#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070013#include <linux/rtnetlink.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053015#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053016
Ratan Gupta82549cc2017-04-21 08:45:23 +053017#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053018#include <filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070019#include <phosphor-logging/elog-errors.hpp>
20#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070021#include <sdbusplus/bus/match.hpp>
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080022#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070023#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070024#include <stdplus/zstring.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053025#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070026#include <unordered_map>
27#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070028#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053029
Ratan Gupta91a99cc2017-04-14 16:32:09 +053030namespace phosphor
31{
32namespace network
33{
34
35using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053036using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053037using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
38using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050039using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070040using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053041constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
42constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
43constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
44constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060045
46constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
47constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
48constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
49
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053050constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053051
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080052static stdplus::Fd& getIFSock()
53{
54 using namespace stdplus::fd;
55 static auto fd =
56 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
57 return fd;
58}
59
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070060struct LinkInfo
61{
62 bool autoneg;
63 uint16_t speed;
64};
65
66static LinkInfo getLinkInfo(stdplus::zstring_view ifname)
67{
68 LinkInfo ret;
69 try
70 {
71 ethtool_cmd edata = {};
72 edata.cmd = ETHTOOL_GSET;
73
74 ifreq ifr = {};
75 const auto copied = std::min<std::size_t>(ifname.size(), IFNAMSIZ - 1);
76 std::copy_n(ifname.begin(), copied, ifr.ifr_name);
77 ifr.ifr_data = reinterpret_cast<char*>(&edata);
78
79 getIFSock().ioctl(SIOCETHTOOL, &ifr);
80
81 ret.speed = edata.speed;
82 ret.autoneg = edata.autoneg;
83 }
84 catch (const std::system_error& e)
85 {
86 if (e.code() == std::errc::operation_not_supported)
87 {
88 auto msg = fmt::format("ETHTOOL not supported on {}", ifname);
89 log<level::NOTICE>(msg.c_str(),
90 entry("INTERFACE=%s", ifname.c_str()));
91 }
92 else
93 {
94 auto msg =
95 fmt::format("ETHTOOL failed on {}: {}", ifname, e.what());
96 log<level::ERR>(msg.c_str(), entry("INTERFACE=%s", ifname.c_str()));
97 }
98 }
99 return ret;
100}
101
Patrick Williamsc38b0712022-07-22 19:26:54 -0500102EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700103 stdplus::zstring_view objPath,
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700104 const config::Parser& config,
William A. Kennington III0caf2212022-08-18 18:15:51 -0700105 Manager& parent, bool emitSignal,
William A. Kennington III26275a32021-07-13 20:32:42 -0700106 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -0500107 Ifaces(bus, objPath.c_str(),
108 emitSignal ? Ifaces::action::defer_emit
109 : Ifaces::action::emit_no_signals),
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700110 bus(bus), manager(parent), objPath(objPath.c_str())
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530111{
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700112 auto intfName = std::string(objPath.substr(objPath.rfind('/') + 1));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530113 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530114 interfaceName(intfName);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700115 auto dhcpVal = getDHCPValue(config);
116 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
117 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700118 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -0700119 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -0700120 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
121 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500122 std::string defaultGateway;
123 std::string defaultGateway6;
124
William A. Kennington IIIe0564842021-10-23 16:02:22 -0700125 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500126 {
127 if (gateway.first == intfName)
128 {
129 defaultGateway = gateway.second;
130 break;
131 }
132 }
133
William A. Kennington IIIe0564842021-10-23 16:02:22 -0700134 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500135 {
136 if (gateway6.first == intfName)
137 {
138 defaultGateway6 = gateway6.second;
139 break;
140 }
141 }
142
143 EthernetInterfaceIntf::defaultGateway(defaultGateway);
144 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530145 // Don't get the mac address from the system as the mac address
146 // would be same as parent interface.
147 if (intfName.find(".") == std::string::npos)
148 {
William A. Kennington III9ecb90e2022-10-14 03:12:43 -0700149 try
150 {
151 MacAddressIntf::macAddress(getMACAddress(intfName));
152 }
153 catch (const std::exception& e)
154 {
155 auto msg =
156 fmt::format("Failed to get MAC for {}: {}", intfName, e.what());
157 log<level::ERR>(msg.c_str(),
158 entry("INTERFACE=%s", intfName.c_str()));
159 }
Ratan Gupta99801ce2020-01-09 18:37:16 +0530160 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700161 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700162 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530163
164 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530165 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530166
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -0700167 auto info = getLinkInfo(intfName);
168 EthernetInterfaceIntf::autoNeg(info.autoneg);
169 EthernetInterfaceIntf::speed(info.speed);
Ratan Gupta6dec3902017-08-20 15:28:12 +0530170
Ratan Gupta29b0e432017-05-25 12:51:40 +0530171 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530172 if (emitSignal)
173 {
174 this->emit_object_added();
175 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530176}
177
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700178static IP::Protocol getProtocol(const InAddrAny& addr)
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800179{
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700180 if (std::holds_alternative<in_addr>(addr))
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800181 {
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700182 return IP::Protocol::IPv4;
183 }
184 else if (std::holds_alternative<in6_addr>(addr))
185 {
186 return IP::Protocol::IPv6;
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800187 }
188
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700189 throw std::runtime_error("Invalid addr type");
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800190}
191
William A. Kennington III24957b92021-12-03 13:59:19 -0800192bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800193{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700194 switch (family)
195 {
196 case IP::Protocol::IPv6:
197 return dhcp6();
198 case IP::Protocol::IPv4:
199 return dhcp4();
200 }
201 throw std::logic_error("Unreachable");
Johnathan Mantey817012a2020-01-30 15:07:39 -0800202}
203
Johnathan Mantey817012a2020-01-30 15:07:39 -0800204bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
205{
206 return (
207#ifdef LINK_LOCAL_AUTOCONFIGURATION
208 (origin == IP::AddressOrigin::Static)
209#else
210 (origin == IP::AddressOrigin::Static ||
211 origin == IP::AddressOrigin::LinkLocal)
212#endif
213
214 );
215}
216
Ratan Gupta87c13982017-06-15 09:27:27 +0530217void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530218{
Ratan Gupta87c13982017-06-15 09:27:27 +0530219 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530220
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700221 AddressFilter filter;
222 filter.interface = ifIndex();
223 auto currentAddrs = getCurrentAddresses(filter);
224 for (const auto& addr : currentAddrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530225 {
William A. Kennington III13d17082021-11-04 21:36:54 -0700226 if (addr.flags & IFA_F_DEPRECATED)
227 {
228 continue;
229 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700230 auto address = toString(addr.address);
231 IP::Protocol addressType = getProtocol(addr.address);
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800232 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800233 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530234 {
235 origin = IP::AddressOrigin::DHCP;
236 }
Ali El-Haj-Mahmoud300ed5c2022-10-26 09:58:04 -0400237#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700238 if (addr.scope == RT_SCOPE_LINK)
Ratan Guptafc2c7242017-05-29 08:46:06 +0530239 {
240 origin = IP::AddressOrigin::LinkLocal;
241 }
Ali El-Haj-Mahmoud300ed5c2022-10-26 09:58:04 -0400242#endif
Ratan Gupta82549cc2017-04-21 08:45:23 +0530243
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700244 auto ipAddressObjectPath =
245 generateObjectPath(addressType, address, addr.prefix, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530246
Lei YU7233c582021-04-08 14:39:43 +0800247 this->addrs.insert_or_assign(
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700248 address, std::make_unique<IPAddress>(bus, ipAddressObjectPath,
249 *this, addressType, address,
250 origin, addr.prefix));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530251 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530252}
253
William A. Kennington III08505792019-01-30 16:00:04 -0800254void EthernetInterface::createStaticNeighborObjects()
255{
256 staticNeighbors.clear();
257
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700258 NeighborFilter filter;
259 filter.interface = ifIndex();
260 filter.state = NUD_PERMANENT;
261 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800262 for (const auto& neighbor : neighbors)
263 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700264 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800265 {
266 continue;
267 }
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700268 auto ip = toString(neighbor.address);
269 auto mac = mac_address::toString(*neighbor.mac);
270 auto objectPath = generateStaticNeighborObjectPath(ip, mac);
William A. Kennington III9a20a6e2022-10-05 13:41:12 -0700271 staticNeighbors.emplace(
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700272 ip, std::make_unique<Neighbor>(bus, objectPath, *this, ip, mac,
273 Neighbor::State::Permanent));
William A. Kennington III08505792019-01-30 16:00:04 -0800274 }
275}
276
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700277unsigned EthernetInterface::ifIndex() const
278{
279 unsigned idx = if_nametoindex(interfaceName().c_str());
280 if (idx == 0)
281 {
282 throw std::system_error(errno, std::generic_category(),
283 "if_nametoindex");
284 }
285 return idx;
286}
287
Patrick Williams6aef7692021-05-01 06:39:41 -0500288ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700289 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530290{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800291 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530292 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700293 log<level::INFO>("DHCP enabled on the interface, disabling"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500294 entry("INTERFACE=%s", interfaceName().c_str());
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700295 switch (protType)
296 {
297 case IP::Protocol::IPv4:
298 dhcp4(false);
299 break;
300 case IP::Protocol::IPv6:
301 dhcp6(false);
302 break;
303 }
Ravi Teja07450442022-07-07 04:30:57 -0500304 // Delete the IP address object and that reloads the networkd
305 // to allow the same IP address to be set as Static IP
306 deleteObject(ipaddress);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500307 }
308
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500309 IP::AddressOrigin origin = IP::AddressOrigin::Static;
310
311 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
312
313 if (!isValidIP(addressFamily, ipaddress))
314 {
315 log<level::ERR>("Not a valid IP address"),
316 entry("ADDRESS=%s", ipaddress.c_str());
317 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
318 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
319 }
320
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500321 if (!isValidPrefix(addressFamily, prefixLength))
322 {
323 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700324 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500325 elog<InvalidArgument>(
326 Argument::ARGUMENT_NAME("prefixLength"),
327 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530328 }
329
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700330 auto objectPath =
331 generateObjectPath(protType, ipaddress, prefixLength, origin);
William A. Kennington III9a20a6e2022-10-05 13:41:12 -0700332 this->addrs.insert_or_assign(
333 ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700334 std::make_unique<IPAddress>(bus, objectPath, *this, protType, ipaddress,
335 origin, prefixLength));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530336
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700337 writeConfigurationFile();
338 manager.reloadConfigs();
339
raviteja-bce379562019-03-28 05:59:36 -0500340 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530341}
342
Patrick Williams6aef7692021-05-01 06:39:41 -0500343ObjectPath EthernetInterface::neighbor(std::string ipAddress,
344 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800345{
William A. Kennington IIIff12acb2022-10-07 19:06:56 -0700346 if (!isValidIP(ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800347 {
348 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500349 entry("ADDRESS=%s", ipAddress.c_str()));
350 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
351 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800352 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500353 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800354 {
355 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500356 entry("MACADDRESS=%s", ipAddress.c_str()));
357 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
358 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800359 }
360
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700361 auto objectPath = generateStaticNeighborObjectPath(ipAddress, macAddress);
William A. Kennington III9a20a6e2022-10-05 13:41:12 -0700362 staticNeighbors.emplace(
363 ipAddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700364 std::make_unique<Neighbor>(bus, objectPath, *this, ipAddress,
William A. Kennington III9a20a6e2022-10-05 13:41:12 -0700365 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700366
367 writeConfigurationFile();
368 manager.reloadConfigs();
369
William A. Kennington III08505792019-01-30 16:00:04 -0800370 return objectPath;
371}
372
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530373/** @brief get the mac address of the interface.
374 * @return macaddress on success
375 */
376
Gunnar Mills57d9c502018-09-14 14:42:34 -0500377std::string
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700378 EthernetInterface::getMACAddress(stdplus::const_zstring interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530379{
Patrick Williams6aef7692021-05-01 06:39:41 -0500380 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530381
William A. Kennington III05368f12021-05-13 18:40:47 -0700382 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800383 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800384 try
385 {
386 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
387 }
388 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530389 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530390 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800391 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700392 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530393 }
William A. Kennington III7c4c9a92022-10-07 19:08:09 -0700394 return mac_address::toString(
395 stdplus::raw::refFrom<ether_addr>(ifr.ifr_hwaddr.sa_data));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530396}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530397
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700398void EthernetInterface::deleteObject(std::string_view ipaddress)
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530399{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530400 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530401 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530402 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530403 log<level::ERR>("DeleteObject:Unable to find the object.");
404 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530405 }
406 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700407
408 writeConfigurationFile();
409 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530410}
411
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700412void EthernetInterface::deleteStaticNeighborObject(std::string_view ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800413{
Patrick Williams6aef7692021-05-01 06:39:41 -0500414 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800415 if (it == staticNeighbors.end())
416 {
417 log<level::ERR>(
418 "DeleteStaticNeighborObject:Unable to find the object.");
419 return;
420 }
421 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700422
423 writeConfigurationFile();
424 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800425}
426
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700427void EthernetInterface::deleteVLANFromSystem(stdplus::zstring_view interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530428{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700429 const auto& confDir = manager.getConfDir();
430 auto networkFile = config::pathForIntfConf(confDir, interface);
431 auto deviceFile = config::pathForIntfDev(confDir, interface);
Ratan Guptabc886292017-07-25 18:29:57 +0530432
433 // delete the vlan network file
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700434 std::error_code ec;
William A. Kennington III95530ec2022-08-19 01:44:39 -0700435 std::filesystem::remove(networkFile, ec);
436 std::filesystem::remove(deviceFile, ec);
Ratan Guptabc886292017-07-25 18:29:57 +0530437
438 // TODO systemd doesn't delete the virtual network interface
439 // even after deleting all the related configuartion.
440 // https://github.com/systemd/systemd/issues/6600
441 try
442 {
443 deleteInterface(interface);
444 }
Patrick Williams5758db32021-10-06 12:29:22 -0500445 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530446 {
447 commit<InternalFailure>();
448 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530449}
450
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700451void EthernetInterface::deleteVLANObject(stdplus::zstring_view interface)
Ratan Guptae9c9b812017-09-22 17:15:37 +0530452{
453 auto it = vlanInterfaces.find(interface);
454 if (it == vlanInterfaces.end())
455 {
456 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500457 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530458 return;
459 }
460
461 deleteVLANFromSystem(interface);
462 // delete the interface
463 vlanInterfaces.erase(it);
464
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700465 writeConfigurationFile();
466 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530467}
468
Gunnar Mills57d9c502018-09-14 14:42:34 -0500469std::string EthernetInterface::generateObjectPath(
William A. Kennington III991a8e82022-10-11 15:02:47 -0700470 IP::Protocol addressType, std::string_view ipAddress, uint8_t prefixLength,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700471 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530472{
William A. Kennington III991a8e82022-10-11 15:02:47 -0700473 std::string_view type;
474 switch (addressType)
475 {
476 case IP::Protocol::IPv4:
477 type = "ipv4"sv;
478 break;
479 case IP::Protocol::IPv6:
480 type = "ipv6"sv;
481 break;
482 }
483 return fmt::format(
484 FMT_COMPILE("{}/{}/{:08x}"), objPath, type,
485 static_cast<uint32_t>(hash_multi(
486 ipAddress, prefixLength,
487 static_cast<std::underlying_type_t<IP::AddressOrigin>>(origin))));
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530488}
489
William A. Kennington III08505792019-01-30 16:00:04 -0800490std::string EthernetInterface::generateStaticNeighborObjectPath(
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700491 std::string_view ipAddress, std::string_view macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800492{
William A. Kennington III991a8e82022-10-11 15:02:47 -0700493 return fmt::format(
494 FMT_COMPILE("{}/static_neighbor/{:08x}"), objPath,
495 static_cast<uint32_t>(hash_multi(ipAddress, macAddress)));
William A. Kennington III08505792019-01-30 16:00:04 -0800496}
497
Patrick Williams6aef7692021-05-01 06:39:41 -0500498bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700499{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700500 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700501 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700502 writeConfigurationFile();
503 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700504 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700505 return value;
506}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700507
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700508bool EthernetInterface::dhcp4(bool value)
509{
510 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
511 {
512 writeConfigurationFile();
513 manager.reloadConfigs();
514 }
515 return value;
516}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700517
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700518bool EthernetInterface::dhcp6(bool value)
519{
520 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
521 {
522 writeConfigurationFile();
523 manager.reloadConfigs();
524 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700525 return value;
526}
527
Patrick Williams6aef7692021-05-01 06:39:41 -0500528EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530529{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700530 auto old4 = EthernetInterfaceIntf::dhcp4();
531 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
532 value == DHCPConf::v4v6stateless ||
533 value == DHCPConf::both);
534 auto old6 = EthernetInterfaceIntf::dhcp6();
535 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
536 value == DHCPConf::both);
537 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
538 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
539 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
540 value == DHCPConf::v6 || value == DHCPConf::both);
541
542 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530543 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700544 writeConfigurationFile();
545 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530546 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530547 return value;
548}
549
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700550EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
551{
552 if (dhcp6())
553 {
554 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
555 }
556 else if (dhcp4())
557 {
558 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
559 }
560 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
561}
562
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800563bool EthernetInterface::linkUp() const
564{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800565 bool value = EthernetInterfaceIntf::linkUp();
566
William A. Kennington III05368f12021-05-13 18:40:47 -0700567 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800568 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800569 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800570 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800571 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800572 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
573 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800574 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800575 {
576 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800577 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800578 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700579 return value;
580}
581
Tejas Patil2c0fc562021-08-03 19:13:46 +0530582size_t EthernetInterface::mtu() const
583{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530584 size_t value = EthernetInterfaceIntf::mtu();
585
Tejas Patil2c0fc562021-08-03 19:13:46 +0530586 ifreq ifr = {};
587 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800588 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530589 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800590 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530591 value = ifr.ifr_mtu;
592 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800593 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530594 {
595 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800596 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530597 }
598 return value;
599}
600
601size_t EthernetInterface::mtu(size_t value)
602{
603 if (value == EthernetInterfaceIntf::mtu())
604 {
605 return value;
606 }
607 else if (value == 0)
608 {
609 return EthernetInterfaceIntf::mtu();
610 }
611
Tejas Patil2c0fc562021-08-03 19:13:46 +0530612 ifreq ifr = {};
613 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
614 ifr.ifr_mtu = value;
615
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800616 try
617 {
618 getIFSock().ioctl(SIOCSIFMTU, &ifr);
619 }
620 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530621 {
622 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
623 entry("ERROR=%s", strerror(errno)));
624 return EthernetInterfaceIntf::mtu();
625 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530626
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800627 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530628 return value;
629}
630
William A. Kennington III26275a32021-07-13 20:32:42 -0700631bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700632{
William A. Kennington III26275a32021-07-13 20:32:42 -0700633 constexpr auto svc = "org.freedesktop.network1";
634 constexpr auto intf = "org.freedesktop.network1.Link";
635 constexpr auto prop = "AdministrativeState";
636 char* rpath;
637 sd_bus_path_encode("/org/freedesktop/network1/link",
638 std::to_string(ifIndex()).c_str(), &rpath);
639 std::string path(rpath);
640 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700641
William A. Kennington III26275a32021-07-13 20:32:42 -0700642 // Store / Parser for the AdministrativeState return value
643 std::optional<bool> ret;
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700644 auto cb = [&](std::string_view state) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700645 if (state != "initialized")
646 {
647 ret = state != "unmanaged";
648 }
649 };
650
651 // Build a matcher before making the property call to ensure we
652 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500653 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700654 bus,
655 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
656 "'PropertiesChanged',arg0='{}',",
657 svc, path, PROPERTY_INTERFACE, intf)
658 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500659 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700660 std::string intf;
661 std::unordered_map<std::string, std::variant<std::string>> values;
662 try
663 {
664 m.read(intf, values);
665 auto it = values.find(prop);
666 // Ignore properties that aren't AdministrativeState
667 if (it != values.end())
668 {
669 cb(std::get<std::string>(it->second));
670 }
671 }
672 catch (const std::exception& e)
673 {
674 log<level::ERR>(
675 fmt::format(
676 "AdministrativeState match parsing failed on {}: {}",
677 interfaceName(), e.what())
678 .c_str(),
679 entry("INTERFACE=%s", interfaceName().c_str()),
680 entry("ERROR=%s", e.what()));
681 }
682 });
683
684 // Actively call for the value in case the interface is already configured
685 auto method =
686 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
687 method.append(intf, prop);
688 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700689 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700690 auto reply = bus.call(method);
691 std::variant<std::string> state;
692 reply.read(state);
693 cb(std::get<std::string>(state));
694 }
695 catch (const std::exception& e)
696 {
697 log<level::ERR>(
698 fmt::format("Failed to get AdministrativeState on {}: {}",
699 interfaceName(), e.what())
700 .c_str(),
701 entry("INTERFACE=%s", interfaceName().c_str()),
702 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700703 }
704
William A. Kennington III26275a32021-07-13 20:32:42 -0700705 // The interface is not yet configured by systemd-networkd, wait until it
706 // signals us a valid state.
707 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700708 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700709 bus.wait();
710 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700711 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700712
713 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700714}
715
William A. Kennington III69f45542022-09-24 23:28:14 -0700716static void setNICAdminState(stdplus::const_zstring intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700717{
718 ifreq ifr = {};
William A. Kennington III69f45542022-09-24 23:28:14 -0700719 std::strncpy(ifr.ifr_name, intf.data(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800720 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700721
722 ifr.ifr_flags &= ~IFF_UP;
723 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800724 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700725}
726
Patrick Williams6aef7692021-05-01 06:39:41 -0500727bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700728{
Patrick Williams6aef7692021-05-01 06:39:41 -0500729 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700730 {
731 return value;
732 }
733
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800734 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700735 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800736 if (!value)
737 {
738 // We only need to bring down the interface, networkd will always bring
739 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700740 manager.addReloadPreHook(
741 [ifname = interfaceName()]() { setNICAdminState(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800742 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700743 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800744
745 return value;
746}
747
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530748ServerList EthernetInterface::staticNameServers(ServerList value)
749{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530750 for (const auto& nameserverip : value)
751 {
William A. Kennington IIIff12acb2022-10-07 19:06:56 -0700752 if (!isValidIP(nameserverip))
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530753 {
754 log<level::ERR>("Not a valid IP address"),
755 entry("ADDRESS=%s", nameserverip.c_str());
756 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530757 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530758 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
759 }
760 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530761 try
762 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530763 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700764
Ratan Gupta6dec3902017-08-20 15:28:12 +0530765 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700766 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530767 }
Patrick Williams5758db32021-10-06 12:29:22 -0500768 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530769 {
770 log<level::ERR>("Exception processing DNS entries");
771 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530772 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530773}
774
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600775void EthernetInterface::loadNTPServers(const config::Parser& config)
776{
777 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
778 EthernetInterfaceIntf::staticNTPServers(
779 config.map.getValueStrings("Network", "NTP"));
780}
781
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700782void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530783{
784 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700785 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700786 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530787}
788
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600789ServerList EthernetInterface::getNTPServerFromTimeSyncd()
790{
791 ServerList servers; // Variable to capture the NTP Server IPs
792 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
793 PROPERTY_INTERFACE, METHOD_GET);
794
795 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
796
797 try
798 {
799 auto reply = bus.call(method);
800 std::variant<ServerList> response;
801 reply.read(response);
802 servers = std::get<ServerList>(response);
803 }
804 catch (const sdbusplus::exception::SdBusError& e)
805 {
806 log<level::ERR>(
807 "Failed to get NTP server information from Systemd-Timesyncd");
808 }
809
810 return servers;
811}
812
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530813ServerList EthernetInterface::getNameServerFromResolvd()
814{
815 ServerList servers;
816 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
817
818 /*
819 The DNS property under org.freedesktop.resolve1.Link interface contains
820 an array containing all DNS servers currently used by resolved. It
821 contains similar information as the DNS server data written to
822 /run/systemd/resolve/resolv.conf.
823
824 Each structure in the array consists of a numeric network interface index,
825 an address family, and a byte array containing the DNS server address
826 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
827 The array contains DNS servers configured system-wide, including those
828 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
829 /etc/systemd/resolved.conf, as well as per-interface DNS server
830 information either retrieved from systemd-networkd or configured by
831 external software via SetLinkDNS().
832 */
833
834 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
835 std::variant<type> name; // Variable to capture the DNS property
836 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
837 PROPERTY_INTERFACE, METHOD_GET);
838
839 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530840
841 try
842 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500843 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530844 reply.read(name);
845 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500846 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530847 {
848 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
849 }
850 auto tupleVector = std::get_if<type>(&name);
851 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
852 {
Alexander Filippov983da552021-02-08 15:26:54 +0300853 int addressFamily = std::get<0>(*i);
854 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
855
856 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530857 {
Alexander Filippov983da552021-02-08 15:26:54 +0300858 case AF_INET:
859 if (ipaddress.size() == sizeof(struct in_addr))
860 {
861 servers.push_back(toString(
862 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
863 }
864 else
865 {
866 log<level::ERR>(
867 "Invalid data recived from Systemd-Resolved");
868 }
869 break;
870
871 case AF_INET6:
872 if (ipaddress.size() == sizeof(struct in6_addr))
873 {
874 servers.push_back(toString(
875 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
876 }
877 else
878 {
879 log<level::ERR>(
880 "Invalid data recived from Systemd-Resolved");
881 }
882 break;
883
884 default:
885 log<level::ERR>(
886 "Unsupported address family in DNS from Systemd-Resolved");
887 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530888 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530889 }
890 return servers;
891}
892
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700893std::string EthernetInterface::vlanIntfName(VlanId id) const
894{
895 return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
896}
897
898std::string EthernetInterface::vlanObjPath(VlanId id) const
899{
900 return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
901}
902
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530903void EthernetInterface::loadVLAN(VlanId id)
904{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700905 auto vlanInterfaceName = vlanIntfName(id);
906 auto path = vlanObjPath(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530907
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700908 config::Parser config(
909 config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
910
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530911 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700912 bus, path.c_str(), config, EthernetInterfaceIntf::nicEnabled(), id,
913 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530914
Gunnar Mills57d9c502018-09-14 14:42:34 -0500915 // Fetch the ip address from the system
916 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530917 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800918 vlanIntf->createStaticNeighborObjects();
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700919 vlanIntf->loadNameServers(config);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600920 vlanIntf->loadNTPServers(config);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530921
922 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
923 std::move(vlanIntf));
924}
925
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700926ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530927{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700928 auto vlanInterfaceName = vlanIntfName(id);
929 if (this->vlanInterfaces.find(vlanInterfaceName) !=
930 this->vlanInterfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800931 {
932 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
933 elog<InvalidArgument>(
934 Argument::ARGUMENT_NAME("VLANId"),
935 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
936 }
937
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700938 auto path = vlanObjPath(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530939
Patrick Williams6aef7692021-05-01 06:39:41 -0500940 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530941 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530942 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700943 bus, path.c_str(), config::Parser(),
Patrick Williams6aef7692021-05-01 06:39:41 -0500944 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530945
946 // write the device file for the vlan interface.
947 vlanIntf->writeDeviceFile();
948
Gunnar Mills57d9c502018-09-14 14:42:34 -0500949 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700950
951 writeConfigurationFile();
952 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700953
954 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530955}
Ratan Gupta2b106532017-07-25 16:05:02 +0530956
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600957ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530958{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600959 try
960 {
961 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530962
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600963 writeConfigurationFile();
964 manager.reloadConfigs();
965 }
966 catch (InternalFailure& e)
967 {
968 log<level::ERR>("Exception processing NTP entries");
969 }
970 return EthernetInterfaceIntf::staticNTPServers();
971}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700972
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600973ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
974{
975 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530976}
Ratan Gupta2b106532017-07-25 16:05:02 +0530977// Need to merge the below function with the code which writes the
978// config file during factory reset.
979// TODO openbmc/openbmc#1751
980
981void EthernetInterface::writeConfigurationFile()
982{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500983 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530984 {
985 intf.second->writeConfigurationFile();
986 }
987
William A. Kennington III95a49a22022-08-18 17:50:05 -0700988 config::Parser config;
989 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530990 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700991 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800992#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700993 auto mac = MacAddressIntf::macAddress();
994 if (!mac.empty())
995 {
996 link["MACAddress"].emplace_back(mac);
997 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800998#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700999 if (!EthernetInterfaceIntf::nicEnabled())
1000 {
1001 link["Unmanaged"].emplace_back("yes");
1002 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -07001003 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001004 {
1005 auto& network = config.map["Network"].emplace_back();
1006 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -04001007#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -07001008 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -04001009#else
William A. Kennington III95a49a22022-08-18 17:50:05 -07001010 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -04001011#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001012 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
1013 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
1014 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001015 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001016 auto& vlans = network["VLAN"];
1017 for (const auto& intf : vlanInterfaces)
1018 {
1019 vlans.emplace_back(
1020 intf.second->EthernetInterface::interfaceName());
1021 }
1022 }
1023 {
1024 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -06001025 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001026 {
1027 ntps.emplace_back(ntp);
1028 }
1029 }
1030 {
1031 auto& dnss = network["DNS"];
1032 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
1033 {
1034 dnss.emplace_back(dns);
1035 }
1036 }
1037 {
1038 auto& address = network["Address"];
1039 for (const auto& addr : getAddresses())
1040 {
1041 if (originIsManuallyAssigned(addr.second->origin()) &&
1042 !dhcpIsEnabled(addr.second->type()))
1043 {
1044 address.emplace_back(
1045 fmt::format("{}/{}", addr.second->address(),
1046 addr.second->prefixLength()));
1047 }
1048 }
1049 }
1050 {
1051 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001052 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001053 {
1054 auto gateway = EthernetInterfaceIntf::defaultGateway();
1055 if (!gateway.empty())
1056 {
1057 gateways.emplace_back(gateway);
1058 }
1059 }
Ratan Gupta2b106532017-07-25 16:05:02 +05301060
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001061 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001062 {
1063 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1064 if (!gateway6.empty())
1065 {
1066 gateways.emplace_back(gateway6);
1067 }
1068 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001069 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001070 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001071 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001072 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -05001073 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001074 auto& neighbors = config.map["Neighbor"];
1075 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +08001076 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001077 auto& neighbor = neighbors.emplace_back();
1078 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
1079 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +08001080 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001081 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001082 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001083 auto& dhcp = config.map["DHCP"].emplace_back();
1084 dhcp["ClientIdentifier"].emplace_back("mac");
1085 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +08001086 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001087 const auto& conf = *manager.getDHCPConf();
1088 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
1089 dhcp["UseDNS"].emplace_back(dns_enabled);
1090 dhcp["UseDomains"].emplace_back(dns_enabled);
1091 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
1092 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
1093 : "false");
1094 dhcp["SendHostname"].emplace_back(
1095 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +08001096 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001097 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001098 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
1099 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -07001100 auto msg = fmt::format("Wrote networkd file: {}", path.native());
1101 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +05301102}
1103
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001104std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301105{
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001106#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001107 ether_addr newMAC;
1108 try
1109 {
1110 newMAC = mac_address::fromString(value);
1111 }
Patrick Williams5758db32021-10-06 12:29:22 -05001112 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001113 {
1114 log<level::ERR>("MACAddress is not valid.",
1115 entry("MAC=%s", value.c_str()));
1116 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1117 Argument::ARGUMENT_VALUE(value.c_str()));
1118 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001119 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301120 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001121 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001122 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001123 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1124 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301125 }
1126
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001127 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001128 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001129
William A. Kennington III1137a972019-04-20 20:49:58 -07001130 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001131 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001132 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301133 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001134 // Update everything that depends on the MAC value
1135 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301136 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001137 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301138 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001139 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301140
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001141 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001142 manager.addReloadPreHook([interface]() {
1143 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III69f45542022-09-24 23:28:14 -07001144 setNICAdminState(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001145 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001146 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301147 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001148
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001149#ifdef HAVE_UBOOT_ENV
1150 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -07001151 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001152 if (envVar)
1153 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001154 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1155 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1156 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1157 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001158 }
1159#endif // HAVE_UBOOT_ENV
1160
William A. Kennington III1137a972019-04-20 20:49:58 -07001161 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001162#else
1163 elog<NotAllowed>(
1164 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1165#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301166}
1167
Ratan Guptae9c9b812017-09-22 17:15:37 +05301168void EthernetInterface::deleteAll()
1169{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301170 // clear all the ip on the interface
1171 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001172
1173 writeConfigurationFile();
1174 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301175}
1176
Ravi Tejaa5a09442020-07-17 00:57:33 -05001177std::string EthernetInterface::defaultGateway(std::string gateway)
1178{
1179 auto gw = EthernetInterfaceIntf::defaultGateway();
1180 if (gw == gateway)
1181 {
1182 return gw;
1183 }
1184
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001185 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001186 {
1187 log<level::ERR>("Not a valid v4 Gateway",
1188 entry("GATEWAY=%s", gateway.c_str()));
1189 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1190 Argument::ARGUMENT_VALUE(gateway.c_str()));
1191 }
1192 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001193
1194 writeConfigurationFile();
1195 manager.reloadConfigs();
1196
Ravi Tejaa5a09442020-07-17 00:57:33 -05001197 return gw;
1198}
1199
1200std::string EthernetInterface::defaultGateway6(std::string gateway)
1201{
1202 auto gw = EthernetInterfaceIntf::defaultGateway6();
1203 if (gw == gateway)
1204 {
1205 return gw;
1206 }
1207
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001208 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001209 {
1210 log<level::ERR>("Not a valid v6 Gateway",
1211 entry("GATEWAY=%s", gateway.c_str()));
1212 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1213 Argument::ARGUMENT_VALUE(gateway.c_str()));
1214 }
1215 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001216
1217 writeConfigurationFile();
1218 manager.reloadConfigs();
1219
Ravi Tejaa5a09442020-07-17 00:57:33 -05001220 return gw;
1221}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001222} // namespace network
1223} // namespace phosphor