blob: 1c77f8d49c5cc6d8543c12492f8508fd6ebfdb4a [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"
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -07006#include "ipaddress.hpp"
William A. Kennington III08505792019-01-30 16:00:04 -08007#include "neighbor.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05308#include "network_manager.hpp"
William A. Kennington III95530ec2022-08-19 01:44:39 -07009#include "util.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +053010#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +053011
Ratan Gupta82549cc2017-04-21 08:45:23 +053012#include <arpa/inet.h>
William A. Kennington IIIa520a392022-08-08 12:17:34 -070013#include <fmt/compile.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070014#include <fmt/format.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070016#include <linux/rtnetlink.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053017#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053018#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053019
Ratan Gupta82549cc2017-04-21 08:45:23 +053020#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053021#include <filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070022#include <phosphor-logging/elog-errors.hpp>
23#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070024#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053025#include <sstream>
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080026#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070027#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053028#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070029#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070030#include <unordered_map>
31#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070032#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053033
Ratan Gupta91a99cc2017-04-14 16:32:09 +053034namespace phosphor
35{
36namespace network
37{
38
39using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053040using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053041using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
42using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050043using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053044constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
45constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
46constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
47constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
48constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053049
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080050static stdplus::Fd& getIFSock()
51{
52 using namespace stdplus::fd;
53 static auto fd =
54 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
55 return fd;
56}
57
Patrick Williamsc38b0712022-07-22 19:26:54 -050058EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
Ratan Gupta91a99cc2017-04-14 16:32:09 +053059 const std::string& objPath,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070060 const config::Parser& config,
William A. Kennington III0caf2212022-08-18 18:15:51 -070061 Manager& parent, bool emitSignal,
William A. Kennington III26275a32021-07-13 20:32:42 -070062 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050063 Ifaces(bus, objPath.c_str(),
64 emitSignal ? Ifaces::action::defer_emit
65 : Ifaces::action::emit_no_signals),
Gunnar Mills57d9c502018-09-14 14:42:34 -050066 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053067{
68 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053069 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053070 interfaceName(intfName);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070071 auto dhcpVal = getDHCPValue(config);
72 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
73 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070074 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -070075 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070076 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
77 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050078 std::string defaultGateway;
79 std::string defaultGateway6;
80
William A. Kennington IIIe0564842021-10-23 16:02:22 -070081 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050082 {
83 if (gateway.first == intfName)
84 {
85 defaultGateway = gateway.second;
86 break;
87 }
88 }
89
William A. Kennington IIIe0564842021-10-23 16:02:22 -070090 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050091 {
92 if (gateway6.first == intfName)
93 {
94 defaultGateway6 = gateway6.second;
95 break;
96 }
97 }
98
99 EthernetInterfaceIntf::defaultGateway(defaultGateway);
100 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530101 // Don't get the mac address from the system as the mac address
102 // would be same as parent interface.
103 if (intfName.find(".") == std::string::npos)
104 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500105 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530106 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700107 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700108 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530109
110 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530111 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530112
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700113#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700114 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
115
116 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
117 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800118#endif
Ratan Gupta6dec3902017-08-20 15:28:12 +0530119
Ratan Gupta29b0e432017-05-25 12:51:40 +0530120 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530121 if (emitSignal)
122 {
123 this->emit_object_added();
124 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530125}
126
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700127static IP::Protocol getProtocol(const InAddrAny& addr)
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800128{
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700129 if (std::holds_alternative<in_addr>(addr))
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800130 {
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700131 return IP::Protocol::IPv4;
132 }
133 else if (std::holds_alternative<in6_addr>(addr))
134 {
135 return IP::Protocol::IPv6;
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800136 }
137
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700138 throw std::runtime_error("Invalid addr type");
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800139}
140
William A. Kennington III24957b92021-12-03 13:59:19 -0800141bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800142{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700143 switch (family)
144 {
145 case IP::Protocol::IPv6:
146 return dhcp6();
147 case IP::Protocol::IPv4:
148 return dhcp4();
149 }
150 throw std::logic_error("Unreachable");
Johnathan Mantey817012a2020-01-30 15:07:39 -0800151}
152
Johnathan Mantey817012a2020-01-30 15:07:39 -0800153bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
154{
155 return (
156#ifdef LINK_LOCAL_AUTOCONFIGURATION
157 (origin == IP::AddressOrigin::Static)
158#else
159 (origin == IP::AddressOrigin::Static ||
160 origin == IP::AddressOrigin::LinkLocal)
161#endif
162
163 );
164}
165
Ratan Gupta87c13982017-06-15 09:27:27 +0530166void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530167{
Ratan Gupta87c13982017-06-15 09:27:27 +0530168 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530169
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700170 AddressFilter filter;
171 filter.interface = ifIndex();
172 auto currentAddrs = getCurrentAddresses(filter);
173 for (const auto& addr : currentAddrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530174 {
William A. Kennington III13d17082021-11-04 21:36:54 -0700175 if (addr.flags & IFA_F_DEPRECATED)
176 {
177 continue;
178 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700179 auto address = toString(addr.address);
180 IP::Protocol addressType = getProtocol(addr.address);
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800181 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800182 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530183 {
184 origin = IP::AddressOrigin::DHCP;
185 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700186 if (addr.scope == RT_SCOPE_LINK)
Ratan Guptafc2c7242017-05-29 08:46:06 +0530187 {
188 origin = IP::AddressOrigin::LinkLocal;
189 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700190 // Obsolete parameter
191 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530192
Gunnar Mills57d9c502018-09-14 14:42:34 -0500193 std::string ipAddressObjectPath = generateObjectPath(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700194 addressType, address, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530195
Lei YU7233c582021-04-08 14:39:43 +0800196 this->addrs.insert_or_assign(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700197 address, std::make_shared<phosphor::network::IPAddress>(
198 bus, ipAddressObjectPath.c_str(), *this, addressType,
199 address, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530200 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530201}
202
William A. Kennington III08505792019-01-30 16:00:04 -0800203void EthernetInterface::createStaticNeighborObjects()
204{
205 staticNeighbors.clear();
206
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700207 NeighborFilter filter;
208 filter.interface = ifIndex();
209 filter.state = NUD_PERMANENT;
210 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800211 for (const auto& neighbor : neighbors)
212 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700213 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800214 {
215 continue;
216 }
217 std::string ip = toString(neighbor.address);
218 std::string mac = mac_address::toString(*neighbor.mac);
219 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
220 staticNeighbors.emplace(ip,
221 std::make_shared<phosphor::network::Neighbor>(
222 bus, objectPath.c_str(), *this, ip, mac,
223 Neighbor::State::Permanent));
224 }
225}
226
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700227unsigned EthernetInterface::ifIndex() const
228{
229 unsigned idx = if_nametoindex(interfaceName().c_str());
230 if (idx == 0)
231 {
232 throw std::system_error(errno, std::generic_category(),
233 "if_nametoindex");
234 }
235 return idx;
236}
237
Patrick Williams6aef7692021-05-01 06:39:41 -0500238ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500239 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530240{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800241 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530242 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700243 log<level::INFO>("DHCP enabled on the interface, disabling"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500244 entry("INTERFACE=%s", interfaceName().c_str());
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700245 switch (protType)
246 {
247 case IP::Protocol::IPv4:
248 dhcp4(false);
249 break;
250 case IP::Protocol::IPv6:
251 dhcp6(false);
252 break;
253 }
Ravi Teja07450442022-07-07 04:30:57 -0500254 // Delete the IP address object and that reloads the networkd
255 // to allow the same IP address to be set as Static IP
256 deleteObject(ipaddress);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500257 }
258
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500259 IP::AddressOrigin origin = IP::AddressOrigin::Static;
260
261 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
262
263 if (!isValidIP(addressFamily, ipaddress))
264 {
265 log<level::ERR>("Not a valid IP address"),
266 entry("ADDRESS=%s", ipaddress.c_str());
267 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
268 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
269 }
270
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700271 // Gateway is an obsolete parameter
272 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500273
274 if (!isValidPrefix(addressFamily, prefixLength))
275 {
276 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700277 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500278 elog<InvalidArgument>(
279 Argument::ARGUMENT_NAME("prefixLength"),
280 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530281 }
282
Gunnar Mills57d9c502018-09-14 14:42:34 -0500283 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800284 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800285 this->addrs.insert_or_assign(ipaddress,
286 std::make_shared<phosphor::network::IPAddress>(
287 bus, objectPath.c_str(), *this, protType,
288 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530289
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700290 writeConfigurationFile();
291 manager.reloadConfigs();
292
raviteja-bce379562019-03-28 05:59:36 -0500293 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530294}
295
Patrick Williams6aef7692021-05-01 06:39:41 -0500296ObjectPath EthernetInterface::neighbor(std::string ipAddress,
297 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800298{
Patrick Williams6aef7692021-05-01 06:39:41 -0500299 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800300 {
301 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500302 entry("ADDRESS=%s", ipAddress.c_str()));
303 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
304 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800305 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500306 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800307 {
308 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500309 entry("MACADDRESS=%s", ipAddress.c_str()));
310 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
311 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800312 }
313
314 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500315 generateStaticNeighborObjectPath(ipAddress, macAddress);
316 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800317 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500318 bus, objectPath.c_str(), *this, ipAddress,
319 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700320
321 writeConfigurationFile();
322 manager.reloadConfigs();
323
William A. Kennington III08505792019-01-30 16:00:04 -0800324 return objectPath;
325}
326
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700327#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530328/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800329 Enable this code if your NIC driver supports the ETHTOOL features.
330 Do this by adding the following to your phosphor-network*.bbappend file.
331 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
332 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530333*/
334InterfaceInfo EthernetInterface::getInterfaceInfo() const
335{
William A. Kennington III05368f12021-05-13 18:40:47 -0700336 ifreq ifr = {};
337 ethtool_cmd edata = {};
338 LinkSpeed speed = {};
339 Autoneg autoneg = {};
340 DuplexMode duplex = {};
341 LinkUp linkState = {};
342 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530343 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530344
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800345 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
346 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530347
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800348 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800349 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800350 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800351 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530352 speed = edata.speed;
353 duplex = edata.duplex;
354 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530355 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800356 catch (const std::exception& e)
357 {
358 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800359
William A. Kennington III96203312021-05-07 12:50:41 -0700360 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800361 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530362 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800363
Tejas Patil2c0fc562021-08-03 19:13:46 +0530364 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530365}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800366#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530367
368/** @brief get the mac address of the interface.
369 * @return macaddress on success
370 */
371
Gunnar Mills57d9c502018-09-14 14:42:34 -0500372std::string
373 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530374{
Patrick Williams6aef7692021-05-01 06:39:41 -0500375 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530376
William A. Kennington III05368f12021-05-13 18:40:47 -0700377 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800378 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800379 try
380 {
381 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
382 }
383 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530384 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530385 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800386 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700387 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530388 }
389
William A. Kennington III1137a972019-04-20 20:49:58 -0700390 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
391 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
392 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700393 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530394}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530395
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530396std::string EthernetInterface::generateId(const std::string& ipaddress,
397 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800398 const std::string& gateway,
399 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530400{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530401 std::stringstream hexId;
402 std::string hashString = ipaddress;
403 hashString += std::to_string(prefixLength);
404 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800405 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530406
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530407 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500408 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530409 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530410}
411
Patrick Williams6aef7692021-05-01 06:39:41 -0500412std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
413 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800414{
415 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500416 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800417
418 // Only want 8 hex digits.
419 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
420 return hexId.str();
421}
422
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530423void EthernetInterface::deleteObject(const std::string& ipaddress)
424{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530425 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530426 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530427 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530428 log<level::ERR>("DeleteObject:Unable to find the object.");
429 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530430 }
431 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700432
433 writeConfigurationFile();
434 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530435}
436
Patrick Williams6aef7692021-05-01 06:39:41 -0500437void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800438{
Patrick Williams6aef7692021-05-01 06:39:41 -0500439 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800440 if (it == staticNeighbors.end())
441 {
442 log<level::ERR>(
443 "DeleteStaticNeighborObject:Unable to find the object.");
444 return;
445 }
446 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700447
448 writeConfigurationFile();
449 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800450}
451
Ratan Guptae9c9b812017-09-22 17:15:37 +0530452void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530453{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700454 const auto& confDir = manager.getConfDir();
455 auto networkFile = config::pathForIntfConf(confDir, interface);
456 auto deviceFile = config::pathForIntfDev(confDir, interface);
Ratan Guptabc886292017-07-25 18:29:57 +0530457
458 // delete the vlan network file
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700459 std::error_code ec;
William A. Kennington III95530ec2022-08-19 01:44:39 -0700460 std::filesystem::remove(networkFile, ec);
461 std::filesystem::remove(deviceFile, ec);
Ratan Guptabc886292017-07-25 18:29:57 +0530462
463 // TODO systemd doesn't delete the virtual network interface
464 // even after deleting all the related configuartion.
465 // https://github.com/systemd/systemd/issues/6600
466 try
467 {
468 deleteInterface(interface);
469 }
Patrick Williams5758db32021-10-06 12:29:22 -0500470 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530471 {
472 commit<InternalFailure>();
473 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530474}
475
476void EthernetInterface::deleteVLANObject(const std::string& interface)
477{
478 auto it = vlanInterfaces.find(interface);
479 if (it == vlanInterfaces.end())
480 {
481 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500482 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530483 return;
484 }
485
486 deleteVLANFromSystem(interface);
487 // delete the interface
488 vlanInterfaces.erase(it);
489
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700490 writeConfigurationFile();
491 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530492}
493
Gunnar Mills57d9c502018-09-14 14:42:34 -0500494std::string EthernetInterface::generateObjectPath(
495 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800496 uint8_t prefixLength, const std::string& gateway,
497 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530498{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530499 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530500 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530501 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
502
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530503 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530504 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530505 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800506 objectPath /=
507 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530508 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530509}
510
William A. Kennington III08505792019-01-30 16:00:04 -0800511std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500512 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800513{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530514 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800515 objectPath /= objPath;
516 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500517 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800518 return objectPath.string();
519}
520
Patrick Williams6aef7692021-05-01 06:39:41 -0500521bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700522{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700523 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700524 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700525 writeConfigurationFile();
526 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700527 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700528 return value;
529}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700530
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700531bool EthernetInterface::dhcp4(bool value)
532{
533 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
534 {
535 writeConfigurationFile();
536 manager.reloadConfigs();
537 }
538 return value;
539}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700540
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700541bool EthernetInterface::dhcp6(bool value)
542{
543 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
544 {
545 writeConfigurationFile();
546 manager.reloadConfigs();
547 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700548 return value;
549}
550
Patrick Williams6aef7692021-05-01 06:39:41 -0500551EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530552{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700553 auto old4 = EthernetInterfaceIntf::dhcp4();
554 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
555 value == DHCPConf::v4v6stateless ||
556 value == DHCPConf::both);
557 auto old6 = EthernetInterfaceIntf::dhcp6();
558 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
559 value == DHCPConf::both);
560 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
561 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
562 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
563 value == DHCPConf::v6 || value == DHCPConf::both);
564
565 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530566 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700567 writeConfigurationFile();
568 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530569 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530570 return value;
571}
572
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700573EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
574{
575 if (dhcp6())
576 {
577 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
578 }
579 else if (dhcp4())
580 {
581 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
582 }
583 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
584}
585
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800586bool EthernetInterface::linkUp() const
587{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800588 bool value = EthernetInterfaceIntf::linkUp();
589
William A. Kennington III05368f12021-05-13 18:40:47 -0700590 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800591 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800592 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800593 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800594 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800595 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
596 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800597 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800598 {
599 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800600 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800601 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700602 return value;
603}
604
Tejas Patil2c0fc562021-08-03 19:13:46 +0530605size_t EthernetInterface::mtu() const
606{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530607 size_t value = EthernetInterfaceIntf::mtu();
608
Tejas Patil2c0fc562021-08-03 19:13:46 +0530609 ifreq ifr = {};
610 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800611 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530612 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800613 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530614 value = ifr.ifr_mtu;
615 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800616 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530617 {
618 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800619 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530620 }
621 return value;
622}
623
624size_t EthernetInterface::mtu(size_t value)
625{
626 if (value == EthernetInterfaceIntf::mtu())
627 {
628 return value;
629 }
630 else if (value == 0)
631 {
632 return EthernetInterfaceIntf::mtu();
633 }
634
Tejas Patil2c0fc562021-08-03 19:13:46 +0530635 ifreq ifr = {};
636 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
637 ifr.ifr_mtu = value;
638
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800639 try
640 {
641 getIFSock().ioctl(SIOCSIFMTU, &ifr);
642 }
643 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530644 {
645 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
646 entry("ERROR=%s", strerror(errno)));
647 return EthernetInterfaceIntf::mtu();
648 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530649
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800650 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530651 return value;
652}
653
William A. Kennington III26275a32021-07-13 20:32:42 -0700654bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700655{
William A. Kennington III26275a32021-07-13 20:32:42 -0700656 constexpr auto svc = "org.freedesktop.network1";
657 constexpr auto intf = "org.freedesktop.network1.Link";
658 constexpr auto prop = "AdministrativeState";
659 char* rpath;
660 sd_bus_path_encode("/org/freedesktop/network1/link",
661 std::to_string(ifIndex()).c_str(), &rpath);
662 std::string path(rpath);
663 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700664
William A. Kennington III26275a32021-07-13 20:32:42 -0700665 // Store / Parser for the AdministrativeState return value
666 std::optional<bool> ret;
667 auto cb = [&](const std::string& state) {
668 if (state != "initialized")
669 {
670 ret = state != "unmanaged";
671 }
672 };
673
674 // Build a matcher before making the property call to ensure we
675 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500676 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700677 bus,
678 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
679 "'PropertiesChanged',arg0='{}',",
680 svc, path, PROPERTY_INTERFACE, intf)
681 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500682 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700683 std::string intf;
684 std::unordered_map<std::string, std::variant<std::string>> values;
685 try
686 {
687 m.read(intf, values);
688 auto it = values.find(prop);
689 // Ignore properties that aren't AdministrativeState
690 if (it != values.end())
691 {
692 cb(std::get<std::string>(it->second));
693 }
694 }
695 catch (const std::exception& e)
696 {
697 log<level::ERR>(
698 fmt::format(
699 "AdministrativeState match parsing failed on {}: {}",
700 interfaceName(), e.what())
701 .c_str(),
702 entry("INTERFACE=%s", interfaceName().c_str()),
703 entry("ERROR=%s", e.what()));
704 }
705 });
706
707 // Actively call for the value in case the interface is already configured
708 auto method =
709 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
710 method.append(intf, prop);
711 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700712 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700713 auto reply = bus.call(method);
714 std::variant<std::string> state;
715 reply.read(state);
716 cb(std::get<std::string>(state));
717 }
718 catch (const std::exception& e)
719 {
720 log<level::ERR>(
721 fmt::format("Failed to get AdministrativeState on {}: {}",
722 interfaceName(), e.what())
723 .c_str(),
724 entry("INTERFACE=%s", interfaceName().c_str()),
725 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700726 }
727
William A. Kennington III26275a32021-07-13 20:32:42 -0700728 // The interface is not yet configured by systemd-networkd, wait until it
729 // signals us a valid state.
730 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700731 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700732 bus.wait();
733 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700734 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700735
736 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700737}
738
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800739static void setNICAdminState(const char* intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700740{
741 ifreq ifr = {};
742 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800743 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700744
745 ifr.ifr_flags &= ~IFF_UP;
746 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800747 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700748}
749
Patrick Williams6aef7692021-05-01 06:39:41 -0500750bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700751{
Patrick Williams6aef7692021-05-01 06:39:41 -0500752 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700753 {
754 return value;
755 }
756
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800757 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700758 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800759 if (!value)
760 {
761 // We only need to bring down the interface, networkd will always bring
762 // up managed interfaces
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800763 manager.addReloadPreHook([ifname = interfaceName()]() {
764 setNICAdminState(ifname.c_str(), false);
765 });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800766 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700767 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800768
769 return value;
770}
771
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530772ServerList EthernetInterface::staticNameServers(ServerList value)
773{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530774 for (const auto& nameserverip : value)
775 {
776 if (!isValidIP(AF_INET, nameserverip) &&
777 !isValidIP(AF_INET6, nameserverip))
778 {
779 log<level::ERR>("Not a valid IP address"),
780 entry("ADDRESS=%s", nameserverip.c_str());
781 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530782 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530783 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
784 }
785 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530786 try
787 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530788 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700789
Ratan Gupta6dec3902017-08-20 15:28:12 +0530790 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700791 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530792 }
Patrick Williams5758db32021-10-06 12:29:22 -0500793 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530794 {
795 log<level::ERR>("Exception processing DNS entries");
796 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530797 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530798}
799
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700800void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530801{
802 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700803 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700804 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530805}
806
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530807ServerList EthernetInterface::getNameServerFromResolvd()
808{
809 ServerList servers;
810 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
811
812 /*
813 The DNS property under org.freedesktop.resolve1.Link interface contains
814 an array containing all DNS servers currently used by resolved. It
815 contains similar information as the DNS server data written to
816 /run/systemd/resolve/resolv.conf.
817
818 Each structure in the array consists of a numeric network interface index,
819 an address family, and a byte array containing the DNS server address
820 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
821 The array contains DNS servers configured system-wide, including those
822 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
823 /etc/systemd/resolved.conf, as well as per-interface DNS server
824 information either retrieved from systemd-networkd or configured by
825 external software via SetLinkDNS().
826 */
827
828 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
829 std::variant<type> name; // Variable to capture the DNS property
830 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
831 PROPERTY_INTERFACE, METHOD_GET);
832
833 method.append(RESOLVED_INTERFACE, "DNS");
834 auto reply = bus.call(method);
835
836 try
837 {
838 reply.read(name);
839 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500840 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530841 {
842 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
843 }
844 auto tupleVector = std::get_if<type>(&name);
845 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
846 {
Alexander Filippov983da552021-02-08 15:26:54 +0300847 int addressFamily = std::get<0>(*i);
848 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
849
850 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530851 {
Alexander Filippov983da552021-02-08 15:26:54 +0300852 case AF_INET:
853 if (ipaddress.size() == sizeof(struct in_addr))
854 {
855 servers.push_back(toString(
856 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
857 }
858 else
859 {
860 log<level::ERR>(
861 "Invalid data recived from Systemd-Resolved");
862 }
863 break;
864
865 case AF_INET6:
866 if (ipaddress.size() == sizeof(struct in6_addr))
867 {
868 servers.push_back(toString(
869 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
870 }
871 else
872 {
873 log<level::ERR>(
874 "Invalid data recived from Systemd-Resolved");
875 }
876 break;
877
878 default:
879 log<level::ERR>(
880 "Unsupported address family in DNS from Systemd-Resolved");
881 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530882 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530883 }
884 return servers;
885}
886
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700887std::string EthernetInterface::vlanIntfName(VlanId id) const
888{
889 return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
890}
891
892std::string EthernetInterface::vlanObjPath(VlanId id) const
893{
894 return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
895}
896
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530897void EthernetInterface::loadVLAN(VlanId id)
898{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700899 auto vlanInterfaceName = vlanIntfName(id);
900 auto path = vlanObjPath(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530901
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700902 config::Parser config(
903 config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
904
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530905 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700906 bus, path.c_str(), config, EthernetInterfaceIntf::nicEnabled(), id,
907 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530908
Gunnar Mills57d9c502018-09-14 14:42:34 -0500909 // Fetch the ip address from the system
910 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530911 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800912 vlanIntf->createStaticNeighborObjects();
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700913 vlanIntf->loadNameServers(config);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530914
915 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
916 std::move(vlanIntf));
917}
918
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700919ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530920{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700921 auto vlanInterfaceName = vlanIntfName(id);
922 if (this->vlanInterfaces.find(vlanInterfaceName) !=
923 this->vlanInterfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800924 {
925 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
926 elog<InvalidArgument>(
927 Argument::ARGUMENT_NAME("VLANId"),
928 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
929 }
930
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700931 auto path = vlanObjPath(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530932
Patrick Williams6aef7692021-05-01 06:39:41 -0500933 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530934 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530935 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700936 bus, path.c_str(), config::Parser(),
Patrick Williams6aef7692021-05-01 06:39:41 -0500937 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530938
939 // write the device file for the vlan interface.
940 vlanIntf->writeDeviceFile();
941
Gunnar Mills57d9c502018-09-14 14:42:34 -0500942 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700943
944 writeConfigurationFile();
945 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700946
947 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530948}
Ratan Gupta2b106532017-07-25 16:05:02 +0530949
Patrick Williams6aef7692021-05-01 06:39:41 -0500950ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530951{
Patrick Williams6aef7692021-05-01 06:39:41 -0500952 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530953
954 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700955 manager.reloadConfigs();
956
Ratan Gupta497c0c92017-08-22 19:15:59 +0530957 return ntpServers;
958}
Ratan Gupta2b106532017-07-25 16:05:02 +0530959// Need to merge the below function with the code which writes the
960// config file during factory reset.
961// TODO openbmc/openbmc#1751
962
963void EthernetInterface::writeConfigurationFile()
964{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500965 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530966 {
967 intf.second->writeConfigurationFile();
968 }
969
William A. Kennington III95a49a22022-08-18 17:50:05 -0700970 config::Parser config;
971 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530972 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700973 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800974#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700975 auto mac = MacAddressIntf::macAddress();
976 if (!mac.empty())
977 {
978 link["MACAddress"].emplace_back(mac);
979 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800980#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700981 if (!EthernetInterfaceIntf::nicEnabled())
982 {
983 link["Unmanaged"].emplace_back("yes");
984 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700985 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700986 {
987 auto& network = config.map["Network"].emplace_back();
988 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400989#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700990 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400991#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700992 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400993#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700994 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
995 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
996 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600997 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700998 auto& vlans = network["VLAN"];
999 for (const auto& intf : vlanInterfaces)
1000 {
1001 vlans.emplace_back(
1002 intf.second->EthernetInterface::interfaceName());
1003 }
1004 }
1005 {
1006 auto& ntps = network["NTP"];
1007 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
1008 {
1009 ntps.emplace_back(ntp);
1010 }
1011 }
1012 {
1013 auto& dnss = network["DNS"];
1014 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
1015 {
1016 dnss.emplace_back(dns);
1017 }
1018 }
1019 {
1020 auto& address = network["Address"];
1021 for (const auto& addr : getAddresses())
1022 {
1023 if (originIsManuallyAssigned(addr.second->origin()) &&
1024 !dhcpIsEnabled(addr.second->type()))
1025 {
1026 address.emplace_back(
1027 fmt::format("{}/{}", addr.second->address(),
1028 addr.second->prefixLength()));
1029 }
1030 }
1031 }
1032 {
1033 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001034 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001035 {
1036 auto gateway = EthernetInterfaceIntf::defaultGateway();
1037 if (!gateway.empty())
1038 {
1039 gateways.emplace_back(gateway);
1040 }
1041 }
Ratan Gupta2b106532017-07-25 16:05:02 +05301042
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001043 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001044 {
1045 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1046 if (!gateway6.empty())
1047 {
1048 gateways.emplace_back(gateway6);
1049 }
1050 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001051 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001052 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001053 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001054 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -05001055 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001056 auto& neighbors = config.map["Neighbor"];
1057 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +08001058 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001059 auto& neighbor = neighbors.emplace_back();
1060 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
1061 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +08001062 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001063 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001064 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001065 auto& dhcp = config.map["DHCP"].emplace_back();
1066 dhcp["ClientIdentifier"].emplace_back("mac");
1067 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +08001068 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001069 const auto& conf = *manager.getDHCPConf();
1070 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
1071 dhcp["UseDNS"].emplace_back(dns_enabled);
1072 dhcp["UseDomains"].emplace_back(dns_enabled);
1073 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
1074 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
1075 : "false");
1076 dhcp["SendHostname"].emplace_back(
1077 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +08001078 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001079 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001080 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
1081 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -07001082 auto msg = fmt::format("Wrote networkd file: {}", path.native());
1083 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +05301084}
1085
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001086std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301087{
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001088#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001089 ether_addr newMAC;
1090 try
1091 {
1092 newMAC = mac_address::fromString(value);
1093 }
Patrick Williams5758db32021-10-06 12:29:22 -05001094 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001095 {
1096 log<level::ERR>("MACAddress is not valid.",
1097 entry("MAC=%s", value.c_str()));
1098 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1099 Argument::ARGUMENT_VALUE(value.c_str()));
1100 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001101 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301102 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001103 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001104 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001105 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1106 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301107 }
1108
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001109 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001110 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001111
William A. Kennington III1137a972019-04-20 20:49:58 -07001112 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001113 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001114 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301115 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001116 // Update everything that depends on the MAC value
1117 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301118 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001119 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301120 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001121 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301122
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001123 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001124 manager.addReloadPreHook([interface]() {
1125 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III5dad2aa2022-01-21 16:00:17 -08001126 setNICAdminState(interface.c_str(), false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001127 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001128 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301129 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001130
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001131#ifdef HAVE_UBOOT_ENV
1132 // Ensure that the valid address is stored in the u-boot-env
1133 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1134 if (envVar)
1135 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001136 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1137 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1138 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1139 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001140 }
1141#endif // HAVE_UBOOT_ENV
1142
William A. Kennington III1137a972019-04-20 20:49:58 -07001143 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001144#else
1145 elog<NotAllowed>(
1146 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1147#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301148}
1149
Ratan Guptae9c9b812017-09-22 17:15:37 +05301150void EthernetInterface::deleteAll()
1151{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301152 // clear all the ip on the interface
1153 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001154
1155 writeConfigurationFile();
1156 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301157}
1158
Ravi Tejaa5a09442020-07-17 00:57:33 -05001159std::string EthernetInterface::defaultGateway(std::string gateway)
1160{
1161 auto gw = EthernetInterfaceIntf::defaultGateway();
1162 if (gw == gateway)
1163 {
1164 return gw;
1165 }
1166
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001167 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001168 {
1169 log<level::ERR>("Not a valid v4 Gateway",
1170 entry("GATEWAY=%s", gateway.c_str()));
1171 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1172 Argument::ARGUMENT_VALUE(gateway.c_str()));
1173 }
1174 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001175
1176 writeConfigurationFile();
1177 manager.reloadConfigs();
1178
Ravi Tejaa5a09442020-07-17 00:57:33 -05001179 return gw;
1180}
1181
1182std::string EthernetInterface::defaultGateway6(std::string gateway)
1183{
1184 auto gw = EthernetInterfaceIntf::defaultGateway6();
1185 if (gw == gateway)
1186 {
1187 return gw;
1188 }
1189
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001190 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001191 {
1192 log<level::ERR>("Not a valid v6 Gateway",
1193 entry("GATEWAY=%s", gateway.c_str()));
1194 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1195 Argument::ARGUMENT_VALUE(gateway.c_str()));
1196 }
1197 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001198
1199 writeConfigurationFile();
1200 manager.reloadConfigs();
1201
Ravi Tejaa5a09442020-07-17 00:57:33 -05001202 return gw;
1203}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001204} // namespace network
1205} // namespace phosphor