blob: 7c1f1874c9b08e01d179876b0a036ce15f56f725 [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>
Ratan Gupta2b106532017-07-25 16:05:02 +053022#include <sstream>
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080023#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070024#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070025#include <stdplus/zstring.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053026#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070027#include <unordered_map>
28#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070029#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053030
Ratan Gupta91a99cc2017-04-14 16:32:09 +053031namespace phosphor
32{
33namespace network
34{
35
36using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053037using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053038using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
39using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050040using Argument = xyz::openbmc_project::Common::InvalidArgument;
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/";
45constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053046
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080047static stdplus::Fd& getIFSock()
48{
49 using namespace stdplus::fd;
50 static auto fd =
51 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
52 return fd;
53}
54
Patrick Williamsc38b0712022-07-22 19:26:54 -050055EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
Ratan Gupta91a99cc2017-04-14 16:32:09 +053056 const std::string& objPath,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070057 const config::Parser& config,
William A. Kennington III0caf2212022-08-18 18:15:51 -070058 Manager& parent, bool emitSignal,
William A. Kennington III26275a32021-07-13 20:32:42 -070059 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050060 Ifaces(bus, objPath.c_str(),
61 emitSignal ? Ifaces::action::defer_emit
62 : Ifaces::action::emit_no_signals),
Gunnar Mills57d9c502018-09-14 14:42:34 -050063 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053064{
65 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053066 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053067 interfaceName(intfName);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070068 auto dhcpVal = getDHCPValue(config);
69 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
70 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070071 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -070072 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070073 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
74 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050075 std::string defaultGateway;
76 std::string defaultGateway6;
77
William A. Kennington IIIe0564842021-10-23 16:02:22 -070078 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050079 {
80 if (gateway.first == intfName)
81 {
82 defaultGateway = gateway.second;
83 break;
84 }
85 }
86
William A. Kennington IIIe0564842021-10-23 16:02:22 -070087 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050088 {
89 if (gateway6.first == intfName)
90 {
91 defaultGateway6 = gateway6.second;
92 break;
93 }
94 }
95
96 EthernetInterfaceIntf::defaultGateway(defaultGateway);
97 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +053098 // Don't get the mac address from the system as the mac address
99 // would be same as parent interface.
100 if (intfName.find(".") == std::string::npos)
101 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500102 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530103 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700104 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700105 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530106
107 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530108 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530109
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700110#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700111 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
112
113 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
114 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800115#endif
Ratan Gupta6dec3902017-08-20 15:28:12 +0530116
Ratan Gupta29b0e432017-05-25 12:51:40 +0530117 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530118 if (emitSignal)
119 {
120 this->emit_object_added();
121 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530122}
123
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700124static IP::Protocol getProtocol(const InAddrAny& addr)
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800125{
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700126 if (std::holds_alternative<in_addr>(addr))
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800127 {
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700128 return IP::Protocol::IPv4;
129 }
130 else if (std::holds_alternative<in6_addr>(addr))
131 {
132 return IP::Protocol::IPv6;
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800133 }
134
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700135 throw std::runtime_error("Invalid addr type");
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800136}
137
William A. Kennington III24957b92021-12-03 13:59:19 -0800138bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800139{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700140 switch (family)
141 {
142 case IP::Protocol::IPv6:
143 return dhcp6();
144 case IP::Protocol::IPv4:
145 return dhcp4();
146 }
147 throw std::logic_error("Unreachable");
Johnathan Mantey817012a2020-01-30 15:07:39 -0800148}
149
Johnathan Mantey817012a2020-01-30 15:07:39 -0800150bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
151{
152 return (
153#ifdef LINK_LOCAL_AUTOCONFIGURATION
154 (origin == IP::AddressOrigin::Static)
155#else
156 (origin == IP::AddressOrigin::Static ||
157 origin == IP::AddressOrigin::LinkLocal)
158#endif
159
160 );
161}
162
Ratan Gupta87c13982017-06-15 09:27:27 +0530163void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530164{
Ratan Gupta87c13982017-06-15 09:27:27 +0530165 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530166
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700167 AddressFilter filter;
168 filter.interface = ifIndex();
169 auto currentAddrs = getCurrentAddresses(filter);
170 for (const auto& addr : currentAddrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530171 {
William A. Kennington III13d17082021-11-04 21:36:54 -0700172 if (addr.flags & IFA_F_DEPRECATED)
173 {
174 continue;
175 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700176 auto address = toString(addr.address);
177 IP::Protocol addressType = getProtocol(addr.address);
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800178 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800179 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530180 {
181 origin = IP::AddressOrigin::DHCP;
182 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700183 if (addr.scope == RT_SCOPE_LINK)
Ratan Guptafc2c7242017-05-29 08:46:06 +0530184 {
185 origin = IP::AddressOrigin::LinkLocal;
186 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700187 // Obsolete parameter
188 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530189
Gunnar Mills57d9c502018-09-14 14:42:34 -0500190 std::string ipAddressObjectPath = generateObjectPath(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700191 addressType, address, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530192
Lei YU7233c582021-04-08 14:39:43 +0800193 this->addrs.insert_or_assign(
William A. Kennington III9a20a6e2022-10-05 13:41:12 -0700194 address, std::make_unique<IPAddress>(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700195 bus, ipAddressObjectPath.c_str(), *this, addressType,
196 address, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530197 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530198}
199
William A. Kennington III08505792019-01-30 16:00:04 -0800200void EthernetInterface::createStaticNeighborObjects()
201{
202 staticNeighbors.clear();
203
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700204 NeighborFilter filter;
205 filter.interface = ifIndex();
206 filter.state = NUD_PERMANENT;
207 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800208 for (const auto& neighbor : neighbors)
209 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700210 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800211 {
212 continue;
213 }
214 std::string ip = toString(neighbor.address);
215 std::string mac = mac_address::toString(*neighbor.mac);
216 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
William A. Kennington III9a20a6e2022-10-05 13:41:12 -0700217 staticNeighbors.emplace(
218 ip, std::make_unique<Neighbor>(bus, objectPath.c_str(), *this, ip,
219 mac, Neighbor::State::Permanent));
William A. Kennington III08505792019-01-30 16:00:04 -0800220 }
221}
222
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700223unsigned EthernetInterface::ifIndex() const
224{
225 unsigned idx = if_nametoindex(interfaceName().c_str());
226 if (idx == 0)
227 {
228 throw std::system_error(errno, std::generic_category(),
229 "if_nametoindex");
230 }
231 return idx;
232}
233
Patrick Williams6aef7692021-05-01 06:39:41 -0500234ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500235 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530236{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800237 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530238 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700239 log<level::INFO>("DHCP enabled on the interface, disabling"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500240 entry("INTERFACE=%s", interfaceName().c_str());
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700241 switch (protType)
242 {
243 case IP::Protocol::IPv4:
244 dhcp4(false);
245 break;
246 case IP::Protocol::IPv6:
247 dhcp6(false);
248 break;
249 }
Ravi Teja07450442022-07-07 04:30:57 -0500250 // Delete the IP address object and that reloads the networkd
251 // to allow the same IP address to be set as Static IP
252 deleteObject(ipaddress);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500253 }
254
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500255 IP::AddressOrigin origin = IP::AddressOrigin::Static;
256
257 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
258
259 if (!isValidIP(addressFamily, ipaddress))
260 {
261 log<level::ERR>("Not a valid IP address"),
262 entry("ADDRESS=%s", ipaddress.c_str());
263 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
264 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
265 }
266
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700267 // Gateway is an obsolete parameter
268 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500269
270 if (!isValidPrefix(addressFamily, prefixLength))
271 {
272 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700273 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500274 elog<InvalidArgument>(
275 Argument::ARGUMENT_NAME("prefixLength"),
276 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530277 }
278
Gunnar Mills57d9c502018-09-14 14:42:34 -0500279 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800280 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
William A. Kennington III9a20a6e2022-10-05 13:41:12 -0700281 this->addrs.insert_or_assign(
282 ipaddress,
283 std::make_unique<IPAddress>(bus, objectPath.c_str(), *this, protType,
284 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530285
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700286 writeConfigurationFile();
287 manager.reloadConfigs();
288
raviteja-bce379562019-03-28 05:59:36 -0500289 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530290}
291
Patrick Williams6aef7692021-05-01 06:39:41 -0500292ObjectPath EthernetInterface::neighbor(std::string ipAddress,
293 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800294{
William A. Kennington IIIff12acb2022-10-07 19:06:56 -0700295 if (!isValidIP(ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800296 {
297 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500298 entry("ADDRESS=%s", ipAddress.c_str()));
299 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
300 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800301 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500302 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800303 {
304 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500305 entry("MACADDRESS=%s", ipAddress.c_str()));
306 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
307 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800308 }
309
310 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500311 generateStaticNeighborObjectPath(ipAddress, macAddress);
William A. Kennington III9a20a6e2022-10-05 13:41:12 -0700312 staticNeighbors.emplace(
313 ipAddress,
314 std::make_unique<Neighbor>(bus, objectPath.c_str(), *this, ipAddress,
315 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700316
317 writeConfigurationFile();
318 manager.reloadConfigs();
319
William A. Kennington III08505792019-01-30 16:00:04 -0800320 return objectPath;
321}
322
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700323#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530324/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800325 Enable this code if your NIC driver supports the ETHTOOL features.
326 Do this by adding the following to your phosphor-network*.bbappend file.
327 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
328 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530329*/
330InterfaceInfo EthernetInterface::getInterfaceInfo() const
331{
William A. Kennington III05368f12021-05-13 18:40:47 -0700332 ifreq ifr = {};
333 ethtool_cmd edata = {};
334 LinkSpeed speed = {};
335 Autoneg autoneg = {};
336 DuplexMode duplex = {};
337 LinkUp linkState = {};
338 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530339 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530340
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800341 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
342 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530343
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800344 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800345 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800346 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800347 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530348 speed = edata.speed;
349 duplex = edata.duplex;
350 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530351 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800352 catch (const std::exception& e)
353 {
354 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800355
William A. Kennington III96203312021-05-07 12:50:41 -0700356 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800357 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530358 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800359
Tejas Patil2c0fc562021-08-03 19:13:46 +0530360 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530361}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800362#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530363
364/** @brief get the mac address of the interface.
365 * @return macaddress on success
366 */
367
Gunnar Mills57d9c502018-09-14 14:42:34 -0500368std::string
369 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530370{
Patrick Williams6aef7692021-05-01 06:39:41 -0500371 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530372
William A. Kennington III05368f12021-05-13 18:40:47 -0700373 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800374 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800375 try
376 {
377 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
378 }
379 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530380 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530381 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800382 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700383 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530384 }
William A. Kennington III7c4c9a92022-10-07 19:08:09 -0700385 return mac_address::toString(
386 stdplus::raw::refFrom<ether_addr>(ifr.ifr_hwaddr.sa_data));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530387}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530388
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530389std::string EthernetInterface::generateId(const std::string& ipaddress,
390 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800391 const std::string& gateway,
392 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530393{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530394 std::stringstream hexId;
395 std::string hashString = ipaddress;
396 hashString += std::to_string(prefixLength);
397 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800398 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530399
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530400 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500401 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530402 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530403}
404
Patrick Williams6aef7692021-05-01 06:39:41 -0500405std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
406 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800407{
408 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500409 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800410
411 // Only want 8 hex digits.
412 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
413 return hexId.str();
414}
415
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530416void EthernetInterface::deleteObject(const std::string& ipaddress)
417{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530418 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530419 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530420 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530421 log<level::ERR>("DeleteObject:Unable to find the object.");
422 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530423 }
424 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700425
426 writeConfigurationFile();
427 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530428}
429
Patrick Williams6aef7692021-05-01 06:39:41 -0500430void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800431{
Patrick Williams6aef7692021-05-01 06:39:41 -0500432 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800433 if (it == staticNeighbors.end())
434 {
435 log<level::ERR>(
436 "DeleteStaticNeighborObject:Unable to find the object.");
437 return;
438 }
439 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700440
441 writeConfigurationFile();
442 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800443}
444
Ratan Guptae9c9b812017-09-22 17:15:37 +0530445void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530446{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700447 const auto& confDir = manager.getConfDir();
448 auto networkFile = config::pathForIntfConf(confDir, interface);
449 auto deviceFile = config::pathForIntfDev(confDir, interface);
Ratan Guptabc886292017-07-25 18:29:57 +0530450
451 // delete the vlan network file
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700452 std::error_code ec;
William A. Kennington III95530ec2022-08-19 01:44:39 -0700453 std::filesystem::remove(networkFile, ec);
454 std::filesystem::remove(deviceFile, ec);
Ratan Guptabc886292017-07-25 18:29:57 +0530455
456 // TODO systemd doesn't delete the virtual network interface
457 // even after deleting all the related configuartion.
458 // https://github.com/systemd/systemd/issues/6600
459 try
460 {
461 deleteInterface(interface);
462 }
Patrick Williams5758db32021-10-06 12:29:22 -0500463 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530464 {
465 commit<InternalFailure>();
466 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530467}
468
469void EthernetInterface::deleteVLANObject(const std::string& interface)
470{
471 auto it = vlanInterfaces.find(interface);
472 if (it == vlanInterfaces.end())
473 {
474 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500475 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530476 return;
477 }
478
479 deleteVLANFromSystem(interface);
480 // delete the interface
481 vlanInterfaces.erase(it);
482
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700483 writeConfigurationFile();
484 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530485}
486
Gunnar Mills57d9c502018-09-14 14:42:34 -0500487std::string EthernetInterface::generateObjectPath(
488 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800489 uint8_t prefixLength, const std::string& gateway,
490 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530491{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530492 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530493 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530494 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
495
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530496 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530497 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530498 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800499 objectPath /=
500 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530501 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530502}
503
William A. Kennington III08505792019-01-30 16:00:04 -0800504std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500505 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800506{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530507 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800508 objectPath /= objPath;
509 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500510 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800511 return objectPath.string();
512}
513
Patrick Williams6aef7692021-05-01 06:39:41 -0500514bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700515{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700516 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700517 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700518 writeConfigurationFile();
519 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700520 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700521 return value;
522}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700523
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700524bool EthernetInterface::dhcp4(bool value)
525{
526 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
527 {
528 writeConfigurationFile();
529 manager.reloadConfigs();
530 }
531 return value;
532}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700533
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700534bool EthernetInterface::dhcp6(bool value)
535{
536 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
537 {
538 writeConfigurationFile();
539 manager.reloadConfigs();
540 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700541 return value;
542}
543
Patrick Williams6aef7692021-05-01 06:39:41 -0500544EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530545{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700546 auto old4 = EthernetInterfaceIntf::dhcp4();
547 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
548 value == DHCPConf::v4v6stateless ||
549 value == DHCPConf::both);
550 auto old6 = EthernetInterfaceIntf::dhcp6();
551 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
552 value == DHCPConf::both);
553 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
554 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
555 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
556 value == DHCPConf::v6 || value == DHCPConf::both);
557
558 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530559 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700560 writeConfigurationFile();
561 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530562 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530563 return value;
564}
565
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700566EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
567{
568 if (dhcp6())
569 {
570 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
571 }
572 else if (dhcp4())
573 {
574 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
575 }
576 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
577}
578
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800579bool EthernetInterface::linkUp() const
580{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800581 bool value = EthernetInterfaceIntf::linkUp();
582
William A. Kennington III05368f12021-05-13 18:40:47 -0700583 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800584 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800585 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800586 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800587 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800588 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
589 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800590 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800591 {
592 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800593 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800594 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700595 return value;
596}
597
Tejas Patil2c0fc562021-08-03 19:13:46 +0530598size_t EthernetInterface::mtu() const
599{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530600 size_t value = EthernetInterfaceIntf::mtu();
601
Tejas Patil2c0fc562021-08-03 19:13:46 +0530602 ifreq ifr = {};
603 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800604 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530605 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800606 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530607 value = ifr.ifr_mtu;
608 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800609 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530610 {
611 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800612 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530613 }
614 return value;
615}
616
617size_t EthernetInterface::mtu(size_t value)
618{
619 if (value == EthernetInterfaceIntf::mtu())
620 {
621 return value;
622 }
623 else if (value == 0)
624 {
625 return EthernetInterfaceIntf::mtu();
626 }
627
Tejas Patil2c0fc562021-08-03 19:13:46 +0530628 ifreq ifr = {};
629 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
630 ifr.ifr_mtu = value;
631
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800632 try
633 {
634 getIFSock().ioctl(SIOCSIFMTU, &ifr);
635 }
636 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530637 {
638 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
639 entry("ERROR=%s", strerror(errno)));
640 return EthernetInterfaceIntf::mtu();
641 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530642
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800643 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530644 return value;
645}
646
William A. Kennington III26275a32021-07-13 20:32:42 -0700647bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700648{
William A. Kennington III26275a32021-07-13 20:32:42 -0700649 constexpr auto svc = "org.freedesktop.network1";
650 constexpr auto intf = "org.freedesktop.network1.Link";
651 constexpr auto prop = "AdministrativeState";
652 char* rpath;
653 sd_bus_path_encode("/org/freedesktop/network1/link",
654 std::to_string(ifIndex()).c_str(), &rpath);
655 std::string path(rpath);
656 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700657
William A. Kennington III26275a32021-07-13 20:32:42 -0700658 // Store / Parser for the AdministrativeState return value
659 std::optional<bool> ret;
660 auto cb = [&](const std::string& state) {
661 if (state != "initialized")
662 {
663 ret = state != "unmanaged";
664 }
665 };
666
667 // Build a matcher before making the property call to ensure we
668 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500669 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700670 bus,
671 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
672 "'PropertiesChanged',arg0='{}',",
673 svc, path, PROPERTY_INTERFACE, intf)
674 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500675 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700676 std::string intf;
677 std::unordered_map<std::string, std::variant<std::string>> values;
678 try
679 {
680 m.read(intf, values);
681 auto it = values.find(prop);
682 // Ignore properties that aren't AdministrativeState
683 if (it != values.end())
684 {
685 cb(std::get<std::string>(it->second));
686 }
687 }
688 catch (const std::exception& e)
689 {
690 log<level::ERR>(
691 fmt::format(
692 "AdministrativeState match parsing failed on {}: {}",
693 interfaceName(), e.what())
694 .c_str(),
695 entry("INTERFACE=%s", interfaceName().c_str()),
696 entry("ERROR=%s", e.what()));
697 }
698 });
699
700 // Actively call for the value in case the interface is already configured
701 auto method =
702 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
703 method.append(intf, prop);
704 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700705 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700706 auto reply = bus.call(method);
707 std::variant<std::string> state;
708 reply.read(state);
709 cb(std::get<std::string>(state));
710 }
711 catch (const std::exception& e)
712 {
713 log<level::ERR>(
714 fmt::format("Failed to get AdministrativeState on {}: {}",
715 interfaceName(), e.what())
716 .c_str(),
717 entry("INTERFACE=%s", interfaceName().c_str()),
718 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700719 }
720
William A. Kennington III26275a32021-07-13 20:32:42 -0700721 // The interface is not yet configured by systemd-networkd, wait until it
722 // signals us a valid state.
723 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700724 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700725 bus.wait();
726 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700727 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700728
729 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700730}
731
William A. Kennington III69f45542022-09-24 23:28:14 -0700732static void setNICAdminState(stdplus::const_zstring intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700733{
734 ifreq ifr = {};
William A. Kennington III69f45542022-09-24 23:28:14 -0700735 std::strncpy(ifr.ifr_name, intf.data(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800736 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700737
738 ifr.ifr_flags &= ~IFF_UP;
739 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800740 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700741}
742
Patrick Williams6aef7692021-05-01 06:39:41 -0500743bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700744{
Patrick Williams6aef7692021-05-01 06:39:41 -0500745 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700746 {
747 return value;
748 }
749
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800750 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700751 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800752 if (!value)
753 {
754 // We only need to bring down the interface, networkd will always bring
755 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700756 manager.addReloadPreHook(
757 [ifname = interfaceName()]() { setNICAdminState(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800758 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700759 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800760
761 return value;
762}
763
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530764ServerList EthernetInterface::staticNameServers(ServerList value)
765{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530766 for (const auto& nameserverip : value)
767 {
William A. Kennington IIIff12acb2022-10-07 19:06:56 -0700768 if (!isValidIP(nameserverip))
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530769 {
770 log<level::ERR>("Not a valid IP address"),
771 entry("ADDRESS=%s", nameserverip.c_str());
772 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530773 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530774 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
775 }
776 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530777 try
778 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530779 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700780
Ratan Gupta6dec3902017-08-20 15:28:12 +0530781 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700782 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530783 }
Patrick Williams5758db32021-10-06 12:29:22 -0500784 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530785 {
786 log<level::ERR>("Exception processing DNS entries");
787 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530788 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530789}
790
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700791void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530792{
793 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700794 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700795 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530796}
797
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530798ServerList EthernetInterface::getNameServerFromResolvd()
799{
800 ServerList servers;
801 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
802
803 /*
804 The DNS property under org.freedesktop.resolve1.Link interface contains
805 an array containing all DNS servers currently used by resolved. It
806 contains similar information as the DNS server data written to
807 /run/systemd/resolve/resolv.conf.
808
809 Each structure in the array consists of a numeric network interface index,
810 an address family, and a byte array containing the DNS server address
811 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
812 The array contains DNS servers configured system-wide, including those
813 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
814 /etc/systemd/resolved.conf, as well as per-interface DNS server
815 information either retrieved from systemd-networkd or configured by
816 external software via SetLinkDNS().
817 */
818
819 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
820 std::variant<type> name; // Variable to capture the DNS property
821 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
822 PROPERTY_INTERFACE, METHOD_GET);
823
824 method.append(RESOLVED_INTERFACE, "DNS");
825 auto reply = bus.call(method);
826
827 try
828 {
829 reply.read(name);
830 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500831 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530832 {
833 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
834 }
835 auto tupleVector = std::get_if<type>(&name);
836 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
837 {
Alexander Filippov983da552021-02-08 15:26:54 +0300838 int addressFamily = std::get<0>(*i);
839 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
840
841 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530842 {
Alexander Filippov983da552021-02-08 15:26:54 +0300843 case AF_INET:
844 if (ipaddress.size() == sizeof(struct in_addr))
845 {
846 servers.push_back(toString(
847 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
848 }
849 else
850 {
851 log<level::ERR>(
852 "Invalid data recived from Systemd-Resolved");
853 }
854 break;
855
856 case AF_INET6:
857 if (ipaddress.size() == sizeof(struct in6_addr))
858 {
859 servers.push_back(toString(
860 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
861 }
862 else
863 {
864 log<level::ERR>(
865 "Invalid data recived from Systemd-Resolved");
866 }
867 break;
868
869 default:
870 log<level::ERR>(
871 "Unsupported address family in DNS from Systemd-Resolved");
872 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530873 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530874 }
875 return servers;
876}
877
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700878std::string EthernetInterface::vlanIntfName(VlanId id) const
879{
880 return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
881}
882
883std::string EthernetInterface::vlanObjPath(VlanId id) const
884{
885 return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
886}
887
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530888void EthernetInterface::loadVLAN(VlanId id)
889{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700890 auto vlanInterfaceName = vlanIntfName(id);
891 auto path = vlanObjPath(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530892
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700893 config::Parser config(
894 config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
895
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530896 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700897 bus, path.c_str(), config, EthernetInterfaceIntf::nicEnabled(), id,
898 *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530899
Gunnar Mills57d9c502018-09-14 14:42:34 -0500900 // Fetch the ip address from the system
901 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530902 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800903 vlanIntf->createStaticNeighborObjects();
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700904 vlanIntf->loadNameServers(config);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530905
906 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
907 std::move(vlanIntf));
908}
909
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700910ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530911{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700912 auto vlanInterfaceName = vlanIntfName(id);
913 if (this->vlanInterfaces.find(vlanInterfaceName) !=
914 this->vlanInterfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800915 {
916 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
917 elog<InvalidArgument>(
918 Argument::ARGUMENT_NAME("VLANId"),
919 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
920 }
921
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700922 auto path = vlanObjPath(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530923
Patrick Williams6aef7692021-05-01 06:39:41 -0500924 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530925 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530926 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington III0caf2212022-08-18 18:15:51 -0700927 bus, path.c_str(), config::Parser(),
Patrick Williams6aef7692021-05-01 06:39:41 -0500928 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530929
930 // write the device file for the vlan interface.
931 vlanIntf->writeDeviceFile();
932
Gunnar Mills57d9c502018-09-14 14:42:34 -0500933 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700934
935 writeConfigurationFile();
936 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700937
938 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530939}
Ratan Gupta2b106532017-07-25 16:05:02 +0530940
Patrick Williams6aef7692021-05-01 06:39:41 -0500941ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530942{
Patrick Williams6aef7692021-05-01 06:39:41 -0500943 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530944
945 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700946 manager.reloadConfigs();
947
Ratan Gupta497c0c92017-08-22 19:15:59 +0530948 return ntpServers;
949}
Ratan Gupta2b106532017-07-25 16:05:02 +0530950// Need to merge the below function with the code which writes the
951// config file during factory reset.
952// TODO openbmc/openbmc#1751
953
954void EthernetInterface::writeConfigurationFile()
955{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500956 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530957 {
958 intf.second->writeConfigurationFile();
959 }
960
William A. Kennington III95a49a22022-08-18 17:50:05 -0700961 config::Parser config;
962 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530963 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700964 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800965#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700966 auto mac = MacAddressIntf::macAddress();
967 if (!mac.empty())
968 {
969 link["MACAddress"].emplace_back(mac);
970 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800971#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700972 if (!EthernetInterfaceIntf::nicEnabled())
973 {
974 link["Unmanaged"].emplace_back("yes");
975 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700976 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700977 {
978 auto& network = config.map["Network"].emplace_back();
979 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400980#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700981 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400982#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700983 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400984#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700985 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
986 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
987 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600988 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700989 auto& vlans = network["VLAN"];
990 for (const auto& intf : vlanInterfaces)
991 {
992 vlans.emplace_back(
993 intf.second->EthernetInterface::interfaceName());
994 }
995 }
996 {
997 auto& ntps = network["NTP"];
998 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
999 {
1000 ntps.emplace_back(ntp);
1001 }
1002 }
1003 {
1004 auto& dnss = network["DNS"];
1005 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
1006 {
1007 dnss.emplace_back(dns);
1008 }
1009 }
1010 {
1011 auto& address = network["Address"];
1012 for (const auto& addr : getAddresses())
1013 {
1014 if (originIsManuallyAssigned(addr.second->origin()) &&
1015 !dhcpIsEnabled(addr.second->type()))
1016 {
1017 address.emplace_back(
1018 fmt::format("{}/{}", addr.second->address(),
1019 addr.second->prefixLength()));
1020 }
1021 }
1022 }
1023 {
1024 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001025 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001026 {
1027 auto gateway = EthernetInterfaceIntf::defaultGateway();
1028 if (!gateway.empty())
1029 {
1030 gateways.emplace_back(gateway);
1031 }
1032 }
Ratan Gupta2b106532017-07-25 16:05:02 +05301033
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001034 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -07001035 {
1036 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1037 if (!gateway6.empty())
1038 {
1039 gateways.emplace_back(gateway6);
1040 }
1041 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001042 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001043 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001044 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -07001045 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -05001046 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001047 auto& neighbors = config.map["Neighbor"];
1048 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +08001049 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001050 auto& neighbor = neighbors.emplace_back();
1051 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
1052 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +08001053 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001054 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001055 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001056 auto& dhcp = config.map["DHCP"].emplace_back();
1057 dhcp["ClientIdentifier"].emplace_back("mac");
1058 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +08001059 {
William A. Kennington III95a49a22022-08-18 17:50:05 -07001060 const auto& conf = *manager.getDHCPConf();
1061 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
1062 dhcp["UseDNS"].emplace_back(dns_enabled);
1063 dhcp["UseDomains"].emplace_back(dns_enabled);
1064 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
1065 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
1066 : "false");
1067 dhcp["SendHostname"].emplace_back(
1068 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +08001069 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001070 }
William A. Kennington III95a49a22022-08-18 17:50:05 -07001071 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
1072 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -07001073 auto msg = fmt::format("Wrote networkd file: {}", path.native());
1074 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +05301075}
1076
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001077std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301078{
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001079#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001080 ether_addr newMAC;
1081 try
1082 {
1083 newMAC = mac_address::fromString(value);
1084 }
Patrick Williams5758db32021-10-06 12:29:22 -05001085 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001086 {
1087 log<level::ERR>("MACAddress is not valid.",
1088 entry("MAC=%s", value.c_str()));
1089 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1090 Argument::ARGUMENT_VALUE(value.c_str()));
1091 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001092 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301093 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001094 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001095 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001096 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1097 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301098 }
1099
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001100 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001101 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001102
William A. Kennington III1137a972019-04-20 20:49:58 -07001103 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001104 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001105 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301106 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001107 // Update everything that depends on the MAC value
1108 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301109 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001110 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301111 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001112 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301113
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001114 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001115 manager.addReloadPreHook([interface]() {
1116 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III69f45542022-09-24 23:28:14 -07001117 setNICAdminState(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001118 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001119 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301120 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001121
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001122#ifdef HAVE_UBOOT_ENV
1123 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -07001124 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001125 if (envVar)
1126 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001127 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1128 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1129 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1130 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001131 }
1132#endif // HAVE_UBOOT_ENV
1133
William A. Kennington III1137a972019-04-20 20:49:58 -07001134 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001135#else
1136 elog<NotAllowed>(
1137 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1138#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301139}
1140
Ratan Guptae9c9b812017-09-22 17:15:37 +05301141void EthernetInterface::deleteAll()
1142{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301143 // clear all the ip on the interface
1144 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001145
1146 writeConfigurationFile();
1147 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301148}
1149
Ravi Tejaa5a09442020-07-17 00:57:33 -05001150std::string EthernetInterface::defaultGateway(std::string gateway)
1151{
1152 auto gw = EthernetInterfaceIntf::defaultGateway();
1153 if (gw == gateway)
1154 {
1155 return gw;
1156 }
1157
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001158 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001159 {
1160 log<level::ERR>("Not a valid v4 Gateway",
1161 entry("GATEWAY=%s", gateway.c_str()));
1162 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1163 Argument::ARGUMENT_VALUE(gateway.c_str()));
1164 }
1165 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001166
1167 writeConfigurationFile();
1168 manager.reloadConfigs();
1169
Ravi Tejaa5a09442020-07-17 00:57:33 -05001170 return gw;
1171}
1172
1173std::string EthernetInterface::defaultGateway6(std::string gateway)
1174{
1175 auto gw = EthernetInterfaceIntf::defaultGateway6();
1176 if (gw == gateway)
1177 {
1178 return gw;
1179 }
1180
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001181 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001182 {
1183 log<level::ERR>("Not a valid v6 Gateway",
1184 entry("GATEWAY=%s", gateway.c_str()));
1185 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1186 Argument::ARGUMENT_VALUE(gateway.c_str()));
1187 }
1188 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001189
1190 writeConfigurationFile();
1191 manager.reloadConfigs();
1192
Ravi Tejaa5a09442020-07-17 00:57:33 -05001193 return gw;
1194}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001195} // namespace network
1196} // namespace phosphor