blob: a3b251967c8c5b74165660315b1ac326268839f6 [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 IIIc2e5e0e2019-04-22 01:26:06 -07009#include "types.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>
Ratan Gupta2b106532017-07-25 16:05:02 +053022#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070023#include <phosphor-logging/elog-errors.hpp>
24#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070025#include <sdbusplus/bus/match.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053026#include <sstream>
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080027#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070028#include <stdplus/raw.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053029#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070030#include <string_view>
William A. Kennington III26275a32021-07-13 20:32:42 -070031#include <unordered_map>
32#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070033#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053034
Ratan Gupta91a99cc2017-04-14 16:32:09 +053035namespace phosphor
36{
37namespace network
38{
39
40using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053041using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053042using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
43using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050044using Argument = xyz::openbmc_project::Common::InvalidArgument;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053045constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
46constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
47constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
48constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
49constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053050
Johnathan Mantey817012a2020-01-30 15:07:39 -080051std::map<EthernetInterface::DHCPConf, std::string> mapDHCPToSystemd = {
52 {EthernetInterface::DHCPConf::both, "true"},
53 {EthernetInterface::DHCPConf::v4, "ipv4"},
54 {EthernetInterface::DHCPConf::v6, "ipv6"},
55 {EthernetInterface::DHCPConf::none, "false"}};
56
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080057static stdplus::Fd& getIFSock()
58{
59 using namespace stdplus::fd;
60 static auto fd =
61 socket(SocketDomain::INet, SocketType::Datagram, SocketProto::IP);
62 return fd;
63}
64
Patrick Williamsc38b0712022-07-22 19:26:54 -050065EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus,
Ratan Gupta91a99cc2017-04-14 16:32:09 +053066 const std::string& objPath,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070067 const config::Parser& config,
Johnathan Mantey817012a2020-01-30 15:07:39 -080068 DHCPConf dhcpEnabled, Manager& parent,
William A. Kennington III26275a32021-07-13 20:32:42 -070069 bool emitSignal,
70 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050071 Ifaces(bus, objPath.c_str(),
72 emitSignal ? Ifaces::action::defer_emit
73 : Ifaces::action::emit_no_signals),
Gunnar Mills57d9c502018-09-14 14:42:34 -050074 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053075{
76 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053077 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053078 interfaceName(intfName);
Patrick Williams6aef7692021-05-01 06:39:41 -050079 EthernetInterfaceIntf::dhcpEnabled(dhcpEnabled);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070080 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -070081 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
William A. Kennington IIIe0564842021-10-23 16:02:22 -070082 const auto& gatewayList = manager.getRouteTable().getDefaultGateway();
83 const auto& gateway6List = manager.getRouteTable().getDefaultGateway6();
Ravi Tejaa5a09442020-07-17 00:57:33 -050084 std::string defaultGateway;
85 std::string defaultGateway6;
86
William A. Kennington IIIe0564842021-10-23 16:02:22 -070087 for (const auto& gateway : gatewayList)
Ravi Tejaa5a09442020-07-17 00:57:33 -050088 {
89 if (gateway.first == intfName)
90 {
91 defaultGateway = gateway.second;
92 break;
93 }
94 }
95
William A. Kennington IIIe0564842021-10-23 16:02:22 -070096 for (const auto& gateway6 : gateway6List)
Ravi Tejaa5a09442020-07-17 00:57:33 -050097 {
98 if (gateway6.first == intfName)
99 {
100 defaultGateway6 = gateway6.second;
101 break;
102 }
103 }
104
105 EthernetInterfaceIntf::defaultGateway(defaultGateway);
106 EthernetInterfaceIntf::defaultGateway6(defaultGateway6);
Ratan Gupta99801ce2020-01-09 18:37:16 +0530107 // Don't get the mac address from the system as the mac address
108 // would be same as parent interface.
109 if (intfName.find(".") == std::string::npos)
110 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500111 MacAddressIntf::macAddress(getMACAddress(intfName));
Ratan Gupta99801ce2020-01-09 18:37:16 +0530112 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700113 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700114 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530115
116 EthernetInterfaceIntf::linkUp(linkUp());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530117 EthernetInterfaceIntf::mtu(mtu());
Ratan Gupta613a0122020-04-24 15:18:53 +0530118
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700119#ifdef NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -0700120 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
121
122 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
123 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800124#endif
Ratan Gupta6dec3902017-08-20 15:28:12 +0530125
Ratan Gupta29b0e432017-05-25 12:51:40 +0530126 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530127 if (emitSignal)
128 {
129 this->emit_object_added();
130 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530131}
132
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700133static IP::Protocol getProtocol(const InAddrAny& addr)
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800134{
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700135 if (std::holds_alternative<in_addr>(addr))
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800136 {
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700137 return IP::Protocol::IPv4;
138 }
139 else if (std::holds_alternative<in6_addr>(addr))
140 {
141 return IP::Protocol::IPv6;
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800142 }
143
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700144 throw std::runtime_error("Invalid addr type");
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800145}
146
Johnathan Mantey817012a2020-01-30 15:07:39 -0800147void EthernetInterface::disableDHCP(IP::Protocol protocol)
148{
Patrick Williams6aef7692021-05-01 06:39:41 -0500149 DHCPConf dhcpState = EthernetInterfaceIntf::dhcpEnabled();
Johnathan Mantey817012a2020-01-30 15:07:39 -0800150 if (dhcpState == EthernetInterface::DHCPConf::both)
151 {
152 if (protocol == IP::Protocol::IPv4)
153 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500154 dhcpEnabled(EthernetInterface::DHCPConf::v6);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800155 }
156 else if (protocol == IP::Protocol::IPv6)
157 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500158 dhcpEnabled(EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800159 }
160 }
161 else if ((dhcpState == EthernetInterface::DHCPConf::v4) &&
162 (protocol == IP::Protocol::IPv4))
163 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500164 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800165 }
166 else if ((dhcpState == EthernetInterface::DHCPConf::v6) &&
167 (protocol == IP::Protocol::IPv6))
168 {
Patrick Williams6aef7692021-05-01 06:39:41 -0500169 dhcpEnabled(EthernetInterface::DHCPConf::none);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800170 }
171}
172
William A. Kennington III24957b92021-12-03 13:59:19 -0800173bool EthernetInterface::dhcpIsEnabled(IP::Protocol family)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800174{
William A. Kennington III24957b92021-12-03 13:59:19 -0800175 const auto cur = EthernetInterfaceIntf::dhcpEnabled();
176 return cur == EthernetInterface::DHCPConf::both ||
177 (family == IP::Protocol::IPv6 &&
178 cur == EthernetInterface::DHCPConf::v6) ||
179 (family == IP::Protocol::IPv4 &&
180 cur == EthernetInterface::DHCPConf::v4);
Johnathan Mantey817012a2020-01-30 15:07:39 -0800181}
182
Johnathan Mantey817012a2020-01-30 15:07:39 -0800183bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
184{
185 return (
186#ifdef LINK_LOCAL_AUTOCONFIGURATION
187 (origin == IP::AddressOrigin::Static)
188#else
189 (origin == IP::AddressOrigin::Static ||
190 origin == IP::AddressOrigin::LinkLocal)
191#endif
192
193 );
194}
195
Ratan Gupta87c13982017-06-15 09:27:27 +0530196void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530197{
Ratan Gupta87c13982017-06-15 09:27:27 +0530198 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530199
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700200 AddressFilter filter;
201 filter.interface = ifIndex();
202 auto currentAddrs = getCurrentAddresses(filter);
203 for (const auto& addr : currentAddrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530204 {
William A. Kennington III13d17082021-11-04 21:36:54 -0700205 if (addr.flags & IFA_F_DEPRECATED)
206 {
207 continue;
208 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700209 auto address = toString(addr.address);
210 IP::Protocol addressType = getProtocol(addr.address);
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800211 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Johnathan Mantey817012a2020-01-30 15:07:39 -0800212 if (dhcpIsEnabled(addressType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530213 {
214 origin = IP::AddressOrigin::DHCP;
215 }
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700216 if (addr.scope == RT_SCOPE_LINK)
Ratan Guptafc2c7242017-05-29 08:46:06 +0530217 {
218 origin = IP::AddressOrigin::LinkLocal;
219 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700220 // Obsolete parameter
221 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530222
Gunnar Mills57d9c502018-09-14 14:42:34 -0500223 std::string ipAddressObjectPath = generateObjectPath(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700224 addressType, address, addr.prefix, gateway, origin);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530225
Lei YU7233c582021-04-08 14:39:43 +0800226 this->addrs.insert_or_assign(
William A. Kennington IIIc2e5e0e2019-04-22 01:26:06 -0700227 address, std::make_shared<phosphor::network::IPAddress>(
228 bus, ipAddressObjectPath.c_str(), *this, addressType,
229 address, origin, addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530230 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530231}
232
William A. Kennington III08505792019-01-30 16:00:04 -0800233void EthernetInterface::createStaticNeighborObjects()
234{
235 staticNeighbors.clear();
236
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700237 NeighborFilter filter;
238 filter.interface = ifIndex();
239 filter.state = NUD_PERMANENT;
240 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800241 for (const auto& neighbor : neighbors)
242 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700243 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800244 {
245 continue;
246 }
247 std::string ip = toString(neighbor.address);
248 std::string mac = mac_address::toString(*neighbor.mac);
249 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
250 staticNeighbors.emplace(ip,
251 std::make_shared<phosphor::network::Neighbor>(
252 bus, objectPath.c_str(), *this, ip, mac,
253 Neighbor::State::Permanent));
254 }
255}
256
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700257unsigned EthernetInterface::ifIndex() const
258{
259 unsigned idx = if_nametoindex(interfaceName().c_str());
260 if (idx == 0)
261 {
262 throw std::system_error(errno, std::generic_category(),
263 "if_nametoindex");
264 }
265 return idx;
266}
267
Patrick Williams6aef7692021-05-01 06:39:41 -0500268ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
raviteja-bce379562019-03-28 05:59:36 -0500269 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530270{
Johnathan Mantey817012a2020-01-30 15:07:39 -0800271 if (dhcpIsEnabled(protType))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530272 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530273 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500274 entry("INTERFACE=%s", interfaceName().c_str());
Johnathan Mantey817012a2020-01-30 15:07:39 -0800275 disableDHCP(protType);
Ravi Teja07450442022-07-07 04:30:57 -0500276 // Delete the IP address object and that reloads the networkd
277 // to allow the same IP address to be set as Static IP
278 deleteObject(ipaddress);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500279 }
280
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500281 IP::AddressOrigin origin = IP::AddressOrigin::Static;
282
283 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
284
285 if (!isValidIP(addressFamily, ipaddress))
286 {
287 log<level::ERR>("Not a valid IP address"),
288 entry("ADDRESS=%s", ipaddress.c_str());
289 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
290 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
291 }
292
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700293 // Gateway is an obsolete parameter
294 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500295
296 if (!isValidPrefix(addressFamily, prefixLength))
297 {
298 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700299 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500300 elog<InvalidArgument>(
301 Argument::ARGUMENT_NAME("prefixLength"),
302 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530303 }
304
Gunnar Mills57d9c502018-09-14 14:42:34 -0500305 std::string objectPath =
Lei YU34027572021-08-11 15:23:52 +0800306 generateObjectPath(protType, ipaddress, prefixLength, gateway, origin);
Lei YU7233c582021-04-08 14:39:43 +0800307 this->addrs.insert_or_assign(ipaddress,
308 std::make_shared<phosphor::network::IPAddress>(
309 bus, objectPath.c_str(), *this, protType,
310 ipaddress, origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530311
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700312 writeConfigurationFile();
313 manager.reloadConfigs();
314
raviteja-bce379562019-03-28 05:59:36 -0500315 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530316}
317
Patrick Williams6aef7692021-05-01 06:39:41 -0500318ObjectPath EthernetInterface::neighbor(std::string ipAddress,
319 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800320{
Patrick Williams6aef7692021-05-01 06:39:41 -0500321 if (!isValidIP(AF_INET, ipAddress) && !isValidIP(AF_INET6, ipAddress))
William A. Kennington III08505792019-01-30 16:00:04 -0800322 {
323 log<level::ERR>("Not a valid IP address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500324 entry("ADDRESS=%s", ipAddress.c_str()));
325 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
326 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800327 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500328 if (!mac_address::isUnicast(mac_address::fromString(macAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800329 {
330 log<level::ERR>("Not a valid MAC address",
Patrick Williams6aef7692021-05-01 06:39:41 -0500331 entry("MACADDRESS=%s", ipAddress.c_str()));
332 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
333 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800334 }
335
336 std::string objectPath =
Patrick Williams6aef7692021-05-01 06:39:41 -0500337 generateStaticNeighborObjectPath(ipAddress, macAddress);
338 staticNeighbors.emplace(ipAddress,
William A. Kennington III08505792019-01-30 16:00:04 -0800339 std::make_shared<phosphor::network::Neighbor>(
Patrick Williams6aef7692021-05-01 06:39:41 -0500340 bus, objectPath.c_str(), *this, ipAddress,
341 macAddress, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700342
343 writeConfigurationFile();
344 manager.reloadConfigs();
345
William A. Kennington III08505792019-01-30 16:00:04 -0800346 return objectPath;
347}
348
William A. Kennington III6f39c5e2021-05-13 18:39:23 -0700349#ifdef NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530350/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800351 Enable this code if your NIC driver supports the ETHTOOL features.
352 Do this by adding the following to your phosphor-network*.bbappend file.
353 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
354 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530355*/
356InterfaceInfo EthernetInterface::getInterfaceInfo() const
357{
William A. Kennington III05368f12021-05-13 18:40:47 -0700358 ifreq ifr = {};
359 ethtool_cmd edata = {};
360 LinkSpeed speed = {};
361 Autoneg autoneg = {};
362 DuplexMode duplex = {};
363 LinkUp linkState = {};
364 NICEnabled enabled = {};
Tejas Patil2c0fc562021-08-03 19:13:46 +0530365 MTU mtuSize = {};
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530366
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800367 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
368 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530369
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800370 edata.cmd = ETHTOOL_GSET;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800371 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800372 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800373 getIFSock().ioctl(SIOCETHTOOL, &ifr);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530374 speed = edata.speed;
375 duplex = edata.duplex;
376 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530377 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800378 catch (const std::exception& e)
379 {
380 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800381
William A. Kennington III96203312021-05-07 12:50:41 -0700382 enabled = nicEnabled();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800383 linkState = linkUp();
Tejas Patil2c0fc562021-08-03 19:13:46 +0530384 mtuSize = mtu();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800385
Tejas Patil2c0fc562021-08-03 19:13:46 +0530386 return std::make_tuple(speed, duplex, autoneg, linkState, enabled, mtuSize);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530387}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800388#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530389
390/** @brief get the mac address of the interface.
391 * @return macaddress on success
392 */
393
Gunnar Mills57d9c502018-09-14 14:42:34 -0500394std::string
395 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530396{
Patrick Williams6aef7692021-05-01 06:39:41 -0500397 std::string activeMACAddr = MacAddressIntf::macAddress();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530398
William A. Kennington III05368f12021-05-13 18:40:47 -0700399 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800400 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800401 try
402 {
403 getIFSock().ioctl(SIOCGIFHWADDR, &ifr);
404 }
405 catch (const std::exception& e)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530406 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530407 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800408 entry("ERROR=%s", e.what()));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700409 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530410 }
411
William A. Kennington III1137a972019-04-20 20:49:58 -0700412 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
413 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
414 sizeof(ifr.ifr_hwaddr.sa_data));
William A. Kennington III12beaad2020-06-13 19:30:41 -0700415 return mac_address::toString(stdplus::raw::copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530416}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530417
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530418std::string EthernetInterface::generateId(const std::string& ipaddress,
419 uint8_t prefixLength,
Lei YU34027572021-08-11 15:23:52 +0800420 const std::string& gateway,
421 const std::string& origin)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530422{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530423 std::stringstream hexId;
424 std::string hashString = ipaddress;
425 hashString += std::to_string(prefixLength);
426 hashString += gateway;
Lei YU34027572021-08-11 15:23:52 +0800427 hashString += origin;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530428
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530429 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500430 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530431 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530432}
433
Patrick Williams6aef7692021-05-01 06:39:41 -0500434std::string EthernetInterface::generateNeighborId(const std::string& ipAddress,
435 const std::string& macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800436{
437 std::stringstream hexId;
Patrick Williams6aef7692021-05-01 06:39:41 -0500438 std::string hashString = ipAddress + macAddress;
William A. Kennington III08505792019-01-30 16:00:04 -0800439
440 // Only want 8 hex digits.
441 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
442 return hexId.str();
443}
444
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530445void EthernetInterface::deleteObject(const std::string& ipaddress)
446{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530447 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530448 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530449 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530450 log<level::ERR>("DeleteObject:Unable to find the object.");
451 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530452 }
453 this->addrs.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700454
455 writeConfigurationFile();
456 manager.reloadConfigs();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530457}
458
Patrick Williams6aef7692021-05-01 06:39:41 -0500459void EthernetInterface::deleteStaticNeighborObject(const std::string& ipAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800460{
Patrick Williams6aef7692021-05-01 06:39:41 -0500461 auto it = staticNeighbors.find(ipAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800462 if (it == staticNeighbors.end())
463 {
464 log<level::ERR>(
465 "DeleteStaticNeighborObject:Unable to find the object.");
466 return;
467 }
468 staticNeighbors.erase(it);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700469
470 writeConfigurationFile();
471 manager.reloadConfigs();
William A. Kennington III08505792019-01-30 16:00:04 -0800472}
473
Ratan Guptae9c9b812017-09-22 17:15:37 +0530474void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530475{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700476 const auto& confDir = manager.getConfDir();
477 auto networkFile = config::pathForIntfConf(confDir, interface);
478 auto deviceFile = config::pathForIntfDev(confDir, interface);
Ratan Guptabc886292017-07-25 18:29:57 +0530479
480 // delete the vlan network file
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700481 std::error_code ec;
482 fs::remove(networkFile, ec);
483 fs::remove(deviceFile, ec);
Ratan Guptabc886292017-07-25 18:29:57 +0530484
485 // TODO systemd doesn't delete the virtual network interface
486 // even after deleting all the related configuartion.
487 // https://github.com/systemd/systemd/issues/6600
488 try
489 {
490 deleteInterface(interface);
491 }
Patrick Williams5758db32021-10-06 12:29:22 -0500492 catch (const InternalFailure& e)
Ratan Guptabc886292017-07-25 18:29:57 +0530493 {
494 commit<InternalFailure>();
495 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530496}
497
498void EthernetInterface::deleteVLANObject(const std::string& interface)
499{
500 auto it = vlanInterfaces.find(interface);
501 if (it == vlanInterfaces.end())
502 {
503 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500504 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530505 return;
506 }
507
508 deleteVLANFromSystem(interface);
509 // delete the interface
510 vlanInterfaces.erase(it);
511
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700512 writeConfigurationFile();
513 manager.reloadConfigs();
Ratan Guptabc886292017-07-25 18:29:57 +0530514}
515
Gunnar Mills57d9c502018-09-14 14:42:34 -0500516std::string EthernetInterface::generateObjectPath(
517 IP::Protocol addressType, const std::string& ipaddress,
Lei YU34027572021-08-11 15:23:52 +0800518 uint8_t prefixLength, const std::string& gateway,
519 IP::AddressOrigin origin) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530520{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530521 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530522 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530523 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
524
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530525 std::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530526 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530527 objectPath /= type;
Lei YU34027572021-08-11 15:23:52 +0800528 objectPath /=
529 generateId(ipaddress, prefixLength, gateway, convertForMessage(origin));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530530 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530531}
532
William A. Kennington III08505792019-01-30 16:00:04 -0800533std::string EthernetInterface::generateStaticNeighborObjectPath(
Patrick Williams6aef7692021-05-01 06:39:41 -0500534 const std::string& ipAddress, const std::string& macAddress) const
William A. Kennington III08505792019-01-30 16:00:04 -0800535{
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530536 std::filesystem::path objectPath;
William A. Kennington III08505792019-01-30 16:00:04 -0800537 objectPath /= objPath;
538 objectPath /= "static_neighbor";
Patrick Williams6aef7692021-05-01 06:39:41 -0500539 objectPath /= generateNeighborId(ipAddress, macAddress);
William A. Kennington III08505792019-01-30 16:00:04 -0800540 return objectPath.string();
541}
542
Patrick Williams6aef7692021-05-01 06:39:41 -0500543bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700544{
Patrick Williams6aef7692021-05-01 06:39:41 -0500545 if (value == EthernetInterfaceIntf::ipv6AcceptRA())
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700546 {
547 return value;
548 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500549 EthernetInterfaceIntf::ipv6AcceptRA(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700550
551 writeConfigurationFile();
552 manager.reloadConfigs();
553
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700554 return value;
555}
556
Patrick Williams6aef7692021-05-01 06:39:41 -0500557EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530558{
Patrick Williams6aef7692021-05-01 06:39:41 -0500559 if (value == EthernetInterfaceIntf::dhcpEnabled())
Ratan Gupta5978dd12017-07-25 13:47:13 +0530560 {
561 return value;
562 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500563 EthernetInterfaceIntf::dhcpEnabled(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700564
565 writeConfigurationFile();
566 manager.reloadConfigs();
567
Ratan Gupta87c13982017-06-15 09:27:27 +0530568 return value;
569}
570
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800571bool EthernetInterface::linkUp() const
572{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800573 bool value = EthernetInterfaceIntf::linkUp();
574
William A. Kennington III05368f12021-05-13 18:40:47 -0700575 ifreq ifr = {};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800576 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800577 try
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800578 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800579 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800580 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
581 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800582 catch (const std::exception& e)
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800583 {
584 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800585 entry("ERROR=%s", e.what()));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800586 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700587 return value;
588}
589
Tejas Patil2c0fc562021-08-03 19:13:46 +0530590size_t EthernetInterface::mtu() const
591{
Tejas Patil2c0fc562021-08-03 19:13:46 +0530592 size_t value = EthernetInterfaceIntf::mtu();
593
Tejas Patil2c0fc562021-08-03 19:13:46 +0530594 ifreq ifr = {};
595 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800596 try
Tejas Patil2c0fc562021-08-03 19:13:46 +0530597 {
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800598 getIFSock().ioctl(SIOCGIFMTU, &ifr);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530599 value = ifr.ifr_mtu;
600 }
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800601 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530602 {
603 log<level::ERR>("ioctl failed for SIOCGIFMTU:",
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800604 entry("ERROR=%s", e.what()));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530605 }
606 return value;
607}
608
609size_t EthernetInterface::mtu(size_t value)
610{
611 if (value == EthernetInterfaceIntf::mtu())
612 {
613 return value;
614 }
615 else if (value == 0)
616 {
617 return EthernetInterfaceIntf::mtu();
618 }
619
Tejas Patil2c0fc562021-08-03 19:13:46 +0530620 ifreq ifr = {};
621 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
622 ifr.ifr_mtu = value;
623
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800624 try
625 {
626 getIFSock().ioctl(SIOCSIFMTU, &ifr);
627 }
628 catch (const std::exception& e)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530629 {
630 log<level::ERR>("ioctl failed for SIOCSIFMTU:",
631 entry("ERROR=%s", strerror(errno)));
632 return EthernetInterfaceIntf::mtu();
633 }
Tejas Patil2c0fc562021-08-03 19:13:46 +0530634
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800635 EthernetInterfaceIntf::mtu(value);
Tejas Patil2c0fc562021-08-03 19:13:46 +0530636 return value;
637}
638
William A. Kennington III26275a32021-07-13 20:32:42 -0700639bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700640{
William A. Kennington III26275a32021-07-13 20:32:42 -0700641 constexpr auto svc = "org.freedesktop.network1";
642 constexpr auto intf = "org.freedesktop.network1.Link";
643 constexpr auto prop = "AdministrativeState";
644 char* rpath;
645 sd_bus_path_encode("/org/freedesktop/network1/link",
646 std::to_string(ifIndex()).c_str(), &rpath);
647 std::string path(rpath);
648 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700649
William A. Kennington III26275a32021-07-13 20:32:42 -0700650 // Store / Parser for the AdministrativeState return value
651 std::optional<bool> ret;
652 auto cb = [&](const std::string& state) {
653 if (state != "initialized")
654 {
655 ret = state != "unmanaged";
656 }
657 };
658
659 // Build a matcher before making the property call to ensure we
660 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500661 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700662 bus,
663 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
664 "'PropertiesChanged',arg0='{}',",
665 svc, path, PROPERTY_INTERFACE, intf)
666 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500667 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700668 std::string intf;
669 std::unordered_map<std::string, std::variant<std::string>> values;
670 try
671 {
672 m.read(intf, values);
673 auto it = values.find(prop);
674 // Ignore properties that aren't AdministrativeState
675 if (it != values.end())
676 {
677 cb(std::get<std::string>(it->second));
678 }
679 }
680 catch (const std::exception& e)
681 {
682 log<level::ERR>(
683 fmt::format(
684 "AdministrativeState match parsing failed on {}: {}",
685 interfaceName(), e.what())
686 .c_str(),
687 entry("INTERFACE=%s", interfaceName().c_str()),
688 entry("ERROR=%s", e.what()));
689 }
690 });
691
692 // Actively call for the value in case the interface is already configured
693 auto method =
694 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
695 method.append(intf, prop);
696 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700697 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700698 auto reply = bus.call(method);
699 std::variant<std::string> state;
700 reply.read(state);
701 cb(std::get<std::string>(state));
702 }
703 catch (const std::exception& e)
704 {
705 log<level::ERR>(
706 fmt::format("Failed to get AdministrativeState on {}: {}",
707 interfaceName(), e.what())
708 .c_str(),
709 entry("INTERFACE=%s", interfaceName().c_str()),
710 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700711 }
712
William A. Kennington III26275a32021-07-13 20:32:42 -0700713 // The interface is not yet configured by systemd-networkd, wait until it
714 // signals us a valid state.
715 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700716 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700717 bus.wait();
718 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700719 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700720
721 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700722}
723
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800724static void setNICAdminState(const char* intf, bool up)
William A. Kennington III4209cee2021-10-23 18:14:21 -0700725{
726 ifreq ifr = {};
727 std::strncpy(ifr.ifr_name, intf, IF_NAMESIZE - 1);
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800728 getIFSock().ioctl(SIOCGIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700729
730 ifr.ifr_flags &= ~IFF_UP;
731 ifr.ifr_flags |= up ? IFF_UP : 0;
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800732 getIFSock().ioctl(SIOCSIFFLAGS, &ifr);
William A. Kennington III4209cee2021-10-23 18:14:21 -0700733}
734
Patrick Williams6aef7692021-05-01 06:39:41 -0500735bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700736{
Patrick Williams6aef7692021-05-01 06:39:41 -0500737 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700738 {
739 return value;
740 }
741
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800742 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700743 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800744 if (!value)
745 {
746 // We only need to bring down the interface, networkd will always bring
747 // up managed interfaces
William A. Kennington III5dad2aa2022-01-21 16:00:17 -0800748 manager.addReloadPreHook([ifname = interfaceName()]() {
749 setNICAdminState(ifname.c_str(), false);
750 });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800751 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700752 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800753
754 return value;
755}
756
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530757ServerList EthernetInterface::staticNameServers(ServerList value)
758{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530759 for (const auto& nameserverip : value)
760 {
761 if (!isValidIP(AF_INET, nameserverip) &&
762 !isValidIP(AF_INET6, nameserverip))
763 {
764 log<level::ERR>("Not a valid IP address"),
765 entry("ADDRESS=%s", nameserverip.c_str());
766 elog<InvalidArgument>(
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530767 Argument::ARGUMENT_NAME("StaticNameserver"),
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530768 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
769 }
770 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530771 try
772 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530773 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700774
Ratan Gupta6dec3902017-08-20 15:28:12 +0530775 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700776 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530777 }
Patrick Williams5758db32021-10-06 12:29:22 -0500778 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530779 {
780 log<level::ERR>("Exception processing DNS entries");
781 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530782 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530783}
784
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700785void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530786{
787 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700788 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700789 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530790}
791
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530792ServerList EthernetInterface::getNameServerFromResolvd()
793{
794 ServerList servers;
795 std::string OBJ_PATH = RESOLVED_SERVICE_PATH + std::to_string(ifIndex());
796
797 /*
798 The DNS property under org.freedesktop.resolve1.Link interface contains
799 an array containing all DNS servers currently used by resolved. It
800 contains similar information as the DNS server data written to
801 /run/systemd/resolve/resolv.conf.
802
803 Each structure in the array consists of a numeric network interface index,
804 an address family, and a byte array containing the DNS server address
805 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
806 The array contains DNS servers configured system-wide, including those
807 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
808 /etc/systemd/resolved.conf, as well as per-interface DNS server
809 information either retrieved from systemd-networkd or configured by
810 external software via SetLinkDNS().
811 */
812
813 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
814 std::variant<type> name; // Variable to capture the DNS property
815 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
816 PROPERTY_INTERFACE, METHOD_GET);
817
818 method.append(RESOLVED_INTERFACE, "DNS");
819 auto reply = bus.call(method);
820
821 try
822 {
823 reply.read(name);
824 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500825 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530826 {
827 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
828 }
829 auto tupleVector = std::get_if<type>(&name);
830 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
831 {
Alexander Filippov983da552021-02-08 15:26:54 +0300832 int addressFamily = std::get<0>(*i);
833 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
834
835 switch (addressFamily)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530836 {
Alexander Filippov983da552021-02-08 15:26:54 +0300837 case AF_INET:
838 if (ipaddress.size() == sizeof(struct in_addr))
839 {
840 servers.push_back(toString(
841 *reinterpret_cast<struct in_addr*>(ipaddress.data())));
842 }
843 else
844 {
845 log<level::ERR>(
846 "Invalid data recived from Systemd-Resolved");
847 }
848 break;
849
850 case AF_INET6:
851 if (ipaddress.size() == sizeof(struct in6_addr))
852 {
853 servers.push_back(toString(
854 *reinterpret_cast<struct in6_addr*>(ipaddress.data())));
855 }
856 else
857 {
858 log<level::ERR>(
859 "Invalid data recived from Systemd-Resolved");
860 }
861 break;
862
863 default:
864 log<level::ERR>(
865 "Unsupported address family in DNS from Systemd-Resolved");
866 break;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530867 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530868 }
869 return servers;
870}
871
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700872std::string EthernetInterface::vlanIntfName(VlanId id) const
873{
874 return fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
875}
876
877std::string EthernetInterface::vlanObjPath(VlanId id) const
878{
879 return fmt::format(FMT_COMPILE("{}_{}"), objPath, id);
880}
881
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530882void EthernetInterface::loadVLAN(VlanId id)
883{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700884 auto vlanInterfaceName = vlanIntfName(id);
885 auto path = vlanObjPath(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530886
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700887 config::Parser config(
888 config::pathForIntfConf(manager.getConfDir(), vlanInterfaceName));
889
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530890 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700891 bus, path.c_str(), config, getDHCPValue(config),
892 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530893
Gunnar Mills57d9c502018-09-14 14:42:34 -0500894 // Fetch the ip address from the system
895 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530896 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800897 vlanIntf->createStaticNeighborObjects();
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700898 vlanIntf->loadNameServers(config);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530899
900 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
901 std::move(vlanIntf));
902}
903
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700904ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530905{
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700906 auto vlanInterfaceName = vlanIntfName(id);
907 if (this->vlanInterfaces.find(vlanInterfaceName) !=
908 this->vlanInterfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800909 {
910 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
911 elog<InvalidArgument>(
912 Argument::ARGUMENT_NAME("VLANId"),
913 Argument::ARGUMENT_VALUE(std::to_string(id).c_str()));
914 }
915
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700916 auto path = vlanObjPath(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530917
Patrick Williams6aef7692021-05-01 06:39:41 -0500918 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530919 // VLAN interface can inherit.
Ratan Gupta5978dd12017-07-25 13:47:13 +0530920 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700921 bus, path.c_str(), config::Parser(), EthernetInterface::DHCPConf::none,
Patrick Williams6aef7692021-05-01 06:39:41 -0500922 EthernetInterfaceIntf::nicEnabled(), id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530923
924 // write the device file for the vlan interface.
925 vlanIntf->writeDeviceFile();
926
Gunnar Mills57d9c502018-09-14 14:42:34 -0500927 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700928
929 writeConfigurationFile();
930 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700931
932 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530933}
Ratan Gupta2b106532017-07-25 16:05:02 +0530934
Patrick Williams6aef7692021-05-01 06:39:41 -0500935ServerList EthernetInterface::ntpServers(ServerList servers)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530936{
Patrick Williams6aef7692021-05-01 06:39:41 -0500937 auto ntpServers = EthernetInterfaceIntf::ntpServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530938
939 writeConfigurationFile();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700940 manager.reloadConfigs();
941
Ratan Gupta497c0c92017-08-22 19:15:59 +0530942 return ntpServers;
943}
Ratan Gupta2b106532017-07-25 16:05:02 +0530944// Need to merge the below function with the code which writes the
945// config file during factory reset.
946// TODO openbmc/openbmc#1751
947
948void EthernetInterface::writeConfigurationFile()
949{
950 // write all the static ip address in the systemd-network conf file
951
952 using namespace std::string_literals;
Manojkiran Edaa879baa2020-06-13 14:39:08 +0530953 namespace fs = std::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +0530954
955 // if there is vlan interafce then write the configuration file
956 // for vlan also.
957
Gunnar Mills57d9c502018-09-14 14:42:34 -0500958 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530959 {
960 intf.second->writeConfigurationFile();
961 }
962
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700963 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
964 std::fstream stream(path.c_str(), std::fstream::out);
Ratan Gupta2b106532017-07-25 16:05:02 +0530965 if (!stream.is_open())
966 {
967 log<level::ERR>("Unable to open the file",
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700968 entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530969 elog<InternalFailure>();
970 }
971
972 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -0400973 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +0530974 stream << "Name=" << interfaceName() << "\n";
975
976 auto addrs = getAddresses();
977
William A. Kennington III15787212019-04-23 19:18:01 -0700978 // Write the link section
979 stream << "[Link]\n";
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800980#ifdef PERSIST_MAC
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800981 auto mac = MacAddressIntf::macAddress();
William A. Kennington III15787212019-04-23 19:18:01 -0700982 if (!mac.empty())
983 {
984 stream << "MACAddress=" << mac << "\n";
985 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800986#endif
William A. Kennington III15787212019-04-23 19:18:01 -0700987
Patrick Williams6aef7692021-05-01 06:39:41 -0500988 if (!EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700989 {
990 stream << "Unmanaged=yes\n";
991 }
992
Ratan Gupta2b106532017-07-25 16:05:02 +0530993 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -0400994 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -0400995#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -0500996 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -0400997#else
998 stream << "LinkLocalAddressing=no\n";
999#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -07001000 stream << std::boolalpha
Patrick Williams6aef7692021-05-01 06:39:41 -05001001 << "IPv6AcceptRA=" << EthernetInterfaceIntf::ipv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301002
1003 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -05001004 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301005 {
1006 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -05001007 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +05301008 }
Ratan Gupta046b2a02019-09-20 15:49:51 +05301009 // Add the NTP server
Patrick Williams6aef7692021-05-01 06:39:41 -05001010 for (const auto& ntp : EthernetInterfaceIntf::ntpServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301011 {
1012 stream << "NTP=" << ntp << "\n";
1013 }
1014
1015 // Add the DNS entry
Manojkiran Edaacd6dd52019-10-15 15:00:51 +05301016 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
Ratan Gupta046b2a02019-09-20 15:49:51 +05301017 {
1018 stream << "DNS=" << dns << "\n";
1019 }
1020
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001021 // Add the DHCP entry
Johnathan Mantey817012a2020-01-30 15:07:39 -08001022 stream << "DHCP="s +
Patrick Williams6aef7692021-05-01 06:39:41 -05001023 mapDHCPToSystemd[EthernetInterfaceIntf::dhcpEnabled()] + "\n";
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -05001024
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001025 stream << "[IPv6AcceptRA]\n";
1026 stream << "DHCPv6Client=";
1027 stream << (dhcpIsEnabled(IP::Protocol::IPv6) ? "true" : "false");
Johnathan Manteyb353ba02021-12-09 12:27:32 -08001028 stream << "\n";
William A. Kennington IIIe6d1c0e2021-12-03 14:00:30 -08001029
Johnathan Mantey817012a2020-01-30 15:07:39 -08001030 // Static IP addresses
1031 for (const auto& addr : addrs)
Ratan Gupta2b106532017-07-25 16:05:02 +05301032 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001033 if (originIsManuallyAssigned(addr.second->origin()) &&
1034 !dhcpIsEnabled(addr.second->type()))
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001035 {
Johnathan Mantey817012a2020-01-30 15:07:39 -08001036 // Process all static addresses
1037 std::string address = addr.second->address() + "/" +
1038 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +05301039
Johnathan Mantey817012a2020-01-30 15:07:39 -08001040 // build the address entries. Do not use [Network] shortcuts to
1041 // insert address entries.
1042 stream << "[Address]\n";
1043 stream << "Address=" << address << "\n";
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001044 }
Johnathan Mantey817012a2020-01-30 15:07:39 -08001045 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001046
Lei YUcb2d4082021-08-12 15:26:49 +08001047 if (!dhcpIsEnabled(IP::Protocol::IPv4))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001048 {
Lei YUcb2d4082021-08-12 15:26:49 +08001049 auto gateway = EthernetInterfaceIntf::defaultGateway();
1050 if (!gateway.empty())
1051 {
1052 stream << "[Route]\n";
1053 stream << "Gateway=" << gateway << "\n";
1054 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001055 }
1056
Lei YUcb2d4082021-08-12 15:26:49 +08001057 if (!dhcpIsEnabled(IP::Protocol::IPv6))
Ravi Tejaa5a09442020-07-17 00:57:33 -05001058 {
Lei YUcb2d4082021-08-12 15:26:49 +08001059 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
1060 if (!gateway6.empty())
1061 {
1062 stream << "[Route]\n";
1063 stream << "Gateway=" << gateway6 << "\n";
1064 }
Ravi Tejaa5a09442020-07-17 00:57:33 -05001065 }
1066
William A. Kennington III08505792019-01-30 16:00:04 -08001067 // Write the neighbor sections
1068 for (const auto& neighbor : staticNeighbors)
1069 {
1070 stream << "[Neighbor]"
1071 << "\n";
Patrick Williams6aef7692021-05-01 06:39:41 -05001072 stream << "Address=" << neighbor.second->ipAddress() << "\n";
1073 stream << "MACAddress=" << neighbor.second->macAddress() << "\n";
William A. Kennington III08505792019-01-30 16:00:04 -08001074 }
1075
Nagaraju Goruganti210420a2018-03-07 09:22:28 -06001076 // Write the dhcp section irrespective of whether DHCP is enabled or not
1077 writeDHCPSection(stream);
1078
Ratan Gupta2b106532017-07-25 16:05:02 +05301079 stream.close();
William A. Kennington IIIa520a392022-08-08 12:17:34 -07001080 auto msg = fmt::format("Wrote networkd file: {}", path.native());
1081 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +05301082}
1083
1084void EthernetInterface::writeDHCPSection(std::fstream& stream)
1085{
1086 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +05301087 // write the dhcp section
1088 stream << "[DHCP]\n";
1089
1090 // Hardcoding the client identifier to mac, to address below issue
1091 // https://github.com/openbmc/openbmc/issues/1280
1092 stream << "ClientIdentifier=mac\n";
1093 if (manager.getDHCPConf())
1094 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001095 auto value = manager.getDHCPConf()->dnsEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301096 stream << "UseDNS="s + value + "\n";
sunharisdd1e5922022-03-31 01:49:21 -05001097 stream << "UseDomains="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301098
Patrick Williams6aef7692021-05-01 06:39:41 -05001099 value = manager.getDHCPConf()->ntpEnabled() ? "true"s : "false"s;
Ratan Gupta2b106532017-07-25 16:05:02 +05301100 stream << "UseNTP="s + value + "\n";
1101
1102 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
1103 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -06001104
1105 value =
1106 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
1107 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +05301108 }
1109}
1110
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001111std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +05301112{
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001113#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001114 ether_addr newMAC;
1115 try
1116 {
1117 newMAC = mac_address::fromString(value);
1118 }
Patrick Williams5758db32021-10-06 12:29:22 -05001119 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -06001120 {
1121 log<level::ERR>("MACAddress is not valid.",
1122 entry("MAC=%s", value.c_str()));
1123 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1124 Argument::ARGUMENT_VALUE(value.c_str()));
1125 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001126 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301127 {
Gunnar Mills90480c42018-06-19 16:02:17 -05001128 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -05001129 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -05001130 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
1131 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +05301132 }
1133
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001134 auto interface = interfaceName();
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001135 std::string validMAC = mac_address::toString(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001136
William A. Kennington III1137a972019-04-20 20:49:58 -07001137 // We don't need to update the system if the address is unchanged
Patrick Williams6aef7692021-05-01 06:39:41 -05001138 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::macAddress());
William A. Kennington III12beaad2020-06-13 19:30:41 -07001139 if (!stdplus::raw::equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +05301140 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001141 // Update everything that depends on the MAC value
1142 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301143 {
Patrick Williams6aef7692021-05-01 06:39:41 -05001144 intf->MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301145 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001146 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301147
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001148 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001149 manager.addReloadPreHook([interface]() {
1150 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III5dad2aa2022-01-21 16:00:17 -08001151 setNICAdminState(interface.c_str(), false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001152 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001153 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301154 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001155
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001156#ifdef HAVE_UBOOT_ENV
1157 // Ensure that the valid address is stored in the u-boot-env
1158 auto envVar = interfaceToUbootEthAddr(interface.c_str());
1159 if (envVar)
1160 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -05001161 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
1162 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
1163 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
1164 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001165 }
1166#endif // HAVE_UBOOT_ENV
1167
William A. Kennington III1137a972019-04-20 20:49:58 -07001168 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001169#else
1170 elog<NotAllowed>(
1171 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1172#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301173}
1174
Ratan Guptae9c9b812017-09-22 17:15:37 +05301175void EthernetInterface::deleteAll()
1176{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301177 // clear all the ip on the interface
1178 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001179
1180 writeConfigurationFile();
1181 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301182}
1183
Ravi Tejaa5a09442020-07-17 00:57:33 -05001184std::string EthernetInterface::defaultGateway(std::string gateway)
1185{
1186 auto gw = EthernetInterfaceIntf::defaultGateway();
1187 if (gw == gateway)
1188 {
1189 return gw;
1190 }
1191
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001192 if (!isValidIP(AF_INET, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001193 {
1194 log<level::ERR>("Not a valid v4 Gateway",
1195 entry("GATEWAY=%s", gateway.c_str()));
1196 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1197 Argument::ARGUMENT_VALUE(gateway.c_str()));
1198 }
1199 gw = EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001200
1201 writeConfigurationFile();
1202 manager.reloadConfigs();
1203
Ravi Tejaa5a09442020-07-17 00:57:33 -05001204 return gw;
1205}
1206
1207std::string EthernetInterface::defaultGateway6(std::string gateway)
1208{
1209 auto gw = EthernetInterfaceIntf::defaultGateway6();
1210 if (gw == gateway)
1211 {
1212 return gw;
1213 }
1214
Jiaqing Zhaoc2e061f2022-04-07 21:55:48 +08001215 if (!isValidIP(AF_INET6, gateway) && !gateway.empty())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001216 {
1217 log<level::ERR>("Not a valid v6 Gateway",
1218 entry("GATEWAY=%s", gateway.c_str()));
1219 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
1220 Argument::ARGUMENT_VALUE(gateway.c_str()));
1221 }
1222 gw = EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001223
1224 writeConfigurationFile();
1225 manager.reloadConfigs();
1226
Ravi Tejaa5a09442020-07-17 00:57:33 -05001227 return gw;
1228}
Gunnar Mills57d9c502018-09-14 14:42:34 -05001229} // namespace network
1230} // namespace phosphor