blob: 67dd16bd33c00ab093bdf47d6a44ec9681fb591e [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 III2e09d272022-10-14 17:15:00 -07007#include "system_queries.hpp"
William A. Kennington III95530ec2022-08-19 01:44:39 -07008#include "util.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05309
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>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070012#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070013#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014
Ratan Gupta82549cc2017-04-21 08:45:23 +053015#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053016#include <filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070017#include <phosphor-logging/elog-errors.hpp>
18#include <phosphor-logging/log.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070019#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070020#include <stdplus/zstring.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053021#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070022#include <unordered_map>
23#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070024#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053025
Ratan Gupta91a99cc2017-04-14 16:32:09 +053026namespace phosphor
27{
28namespace network
29{
30
31using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053032using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053033using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
34using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050035using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070036using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053037constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
38constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
39constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
40constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060041
42constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
43constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
44constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
45
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053046constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053047
William A. Kennington III2e09d272022-10-14 17:15:00 -070048template <typename Func>
49inline decltype(std::declval<Func>()())
50 ignoreError(std::string_view msg, stdplus::zstring_view intf,
51 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080052{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070053 try
54 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070055 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070056 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070057 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070058 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070059 auto err = fmt::format("{} failed on {}: {}", msg, intf, e.what());
60 log<level::ERR>(err.c_str(), entry("INTERFACE=%s", intf.c_str()));
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070061 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070062 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070063}
William A. Kennington IIId298f932022-10-17 14:31:38 -070064
William A. Kennington IIId298f932022-10-17 14:31:38 -070065static std::string makeObjPath(std::string_view root, std::string_view intf)
66{
67 auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
68 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
69 return ret;
70}
71
72EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080073 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070074 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070075 const config::Parser& config,
William A. Kennington III80d29012022-11-12 02:31:40 -080076 bool emitSignal, bool enabled) :
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070077 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.name),
William A. Kennington IIId298f932022-10-17 14:31:38 -070078 config, emitSignal, enabled)
79{
80}
81
82EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080083 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070084 std::string&& objPath,
85 const config::Parser& config,
William A. Kennington III80d29012022-11-12 02:31:40 -080086 bool emitSignal, bool enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050087 Ifaces(bus, objPath.c_str(),
88 emitSignal ? Ifaces::action::defer_emit
89 : Ifaces::action::emit_no_signals),
William A. Kennington III59e5b912022-11-02 02:49:46 -070090 manager(manager), bus(bus), objPath(std::move(objPath)), ifIdx(info.idx)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053091{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070092 interfaceName(*info.name);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070093 auto dhcpVal = getDHCPValue(config);
94 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
95 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070096 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III80d29012022-11-12 02:31:40 -080097 EthernetInterfaceIntf::nicEnabled(enabled);
Ravi Tejaa5a09442020-07-17 00:57:33 -050098 {
William A. Kennington III2bd35d62022-10-26 19:20:29 -070099 const auto& gws = manager.getRouteTable().getDefaultGateway();
100 auto it = gws.find(ifIdx);
101 if (it != gws.end())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500102 {
William A. Kennington III2bd35d62022-10-26 19:20:29 -0700103 EthernetInterfaceIntf::defaultGateway(std::to_string(it->second));
104 }
105 }
106 {
107 const auto& gws = manager.getRouteTable().getDefaultGateway6();
108 auto it = gws.find(ifIdx);
109 if (it != gws.end())
110 {
111 EthernetInterfaceIntf::defaultGateway6(std::to_string(it->second));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500112 }
113 }
114
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700115 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700116 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530117
William A. Kennington IIId298f932022-10-17 14:31:38 -0700118 updateInfo(info);
119
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700120 if (info.vlan_id)
121 {
122 if (!info.parent_idx)
123 {
124 std::runtime_error("Missing parent link");
125 }
126 vlan.emplace(bus, this->objPath.c_str(), info, *this, emitSignal);
127 }
128
Ratan Gupta29b0e432017-05-25 12:51:40 +0530129 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530130 if (emitSignal)
131 {
132 this->emit_object_added();
133 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530134}
135
William A. Kennington III454a0de2022-11-12 01:01:04 -0800136void EthernetInterface::updateInfo(const InterfaceInfo& info)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700137{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700138 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700139 if (info.mac)
140 {
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700141 MacAddressIntf::macAddress(std::to_string(*info.mac));
William A. Kennington IIId298f932022-10-17 14:31:38 -0700142 }
143 if (info.mtu)
144 {
145 EthernetInterfaceIntf::mtu(*info.mtu);
146 }
William A. Kennington III21539662022-11-15 14:53:11 -0800147 if (ifIdx > 0)
148 {
149 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
150 return system::getEthInfo(*info.name);
151 });
152 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg);
153 EthernetInterfaceIntf::speed(ethInfo.speed);
154 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700155}
156
Johnathan Mantey817012a2020-01-30 15:07:39 -0800157bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
158{
159 return (
160#ifdef LINK_LOCAL_AUTOCONFIGURATION
161 (origin == IP::AddressOrigin::Static)
162#else
163 (origin == IP::AddressOrigin::Static ||
164 origin == IP::AddressOrigin::LinkLocal)
165#endif
166
167 );
168}
169
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800170void EthernetInterface::addAddr(const AddressInfo& info)
171{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800172 IP::AddressOrigin origin = IP::AddressOrigin::Static;
173 if (dhcpIsEnabled(info.ifaddr.getAddr()))
174 {
175 origin = IP::AddressOrigin::DHCP;
176 }
177#ifdef LINK_LOCAL_AUTOCONFIGURATION
178 if (info.scope == RT_SCOPE_LINK)
179 {
180 origin = IP::AddressOrigin::LinkLocal;
181 }
182#endif
183
William A. Kennington III77747f62022-11-07 23:11:15 -0800184 auto it = addrs.find(info.ifaddr);
185 if (it == addrs.end())
186 {
187 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
188 bus, std::string_view(objPath), *this,
189 info.ifaddr, origin));
190 }
191 else
192 {
193 it->second->IPIfaces::origin(origin);
194 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800195}
196
Ratan Gupta87c13982017-06-15 09:27:27 +0530197void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530198{
Ratan Gupta87c13982017-06-15 09:27:27 +0530199 addrs.clear();
William A. Kennington III6a923632022-11-06 18:17:33 -0800200 for (const auto& addr : system::getAddresses({.ifidx = ifIdx}))
Ratan Gupta82549cc2017-04-21 08:45:23 +0530201 {
William A. Kennington III57ca9612022-11-14 15:26:47 -0800202 manager.addAddress(addr);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530203 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530204}
205
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800206void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
207{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800208 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800209 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800210 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800211 log<level::ERR>(msg.c_str());
212 return;
213 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800214
215 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
216 {
217 it->second->NeighborObj::macAddress(std::to_string(*info.mac));
218 }
219 else
220 {
221 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
222 bus, std::string_view(objPath),
223 *this, *info.addr, *info.mac,
224 Neighbor::State::Permanent));
225 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800226}
227
William A. Kennington III08505792019-01-30 16:00:04 -0800228void EthernetInterface::createStaticNeighborObjects()
229{
230 staticNeighbors.clear();
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800231 for (const auto& neighbor : system::getNeighbors({.ifidx = ifIdx}))
William A. Kennington III08505792019-01-30 16:00:04 -0800232 {
William A. Kennington III7310ac72022-11-14 15:44:00 -0800233 manager.addNeighbor(neighbor);
William A. Kennington III08505792019-01-30 16:00:04 -0800234 }
235}
236
Patrick Williams6aef7692021-05-01 06:39:41 -0500237ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700238 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530239{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700240 InAddrAny addr;
241 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530242 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700243 switch (protType)
244 {
245 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700246 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700247 break;
248 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700249 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700250 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700251 default:
252 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700253 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500254 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700255 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500256 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700257 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
258 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500259 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
260 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
261 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700262 IfAddr ifaddr;
263 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500264 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700265 ifaddr = {addr, prefixLength};
266 }
267 catch (const std::exception& e)
268 {
269 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
270 e.what());
271 log<level::ERR>(msg.c_str(),
272 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500273 elog<InvalidArgument>(
274 Argument::ARGUMENT_NAME("prefixLength"),
275 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530276 }
277
William A. Kennington III434a9432022-11-04 18:38:46 -0700278 auto [it, _] = this->addrs.insert_or_assign(
279 ifaddr,
William A. Kennington III59e5b912022-11-02 02:49:46 -0700280 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III434a9432022-11-04 18:38:46 -0700281 ifaddr, IP::AddressOrigin::Static));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530282
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700283 writeConfigurationFile();
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800284 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700285
William A. Kennington III434a9432022-11-04 18:38:46 -0700286 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530287}
288
Patrick Williams6aef7692021-05-01 06:39:41 -0500289ObjectPath EthernetInterface::neighbor(std::string ipAddress,
290 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800291{
William A. Kennington III434a9432022-11-04 18:38:46 -0700292 InAddrAny addr;
293 try
William A. Kennington III08505792019-01-30 16:00:04 -0800294 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700295 addr = ToAddr<InAddrAny>{}(ipAddress);
296 }
297 catch (const std::exception& e)
298 {
299 auto msg =
300 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
301 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500302 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
303 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800304 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700305
306 ether_addr lladdr;
307 try
William A. Kennington III08505792019-01-30 16:00:04 -0800308 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700309 lladdr = ToAddr<ether_addr>{}(macAddress);
310 }
311 catch (const std::exception& e)
312 {
313 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
314 e.what());
315 log<level::ERR>(msg.c_str(),
316 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500317 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
318 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800319 }
320
William A. Kennington III434a9432022-11-04 18:38:46 -0700321 auto [it, _] = staticNeighbors.emplace(
322 addr,
323 std::make_unique<Neighbor>(bus, std::string_view(objPath), *this, addr,
324 lladdr, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700325
326 writeConfigurationFile();
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800327 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700328
William A. Kennington III434a9432022-11-04 18:38:46 -0700329 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800330}
331
Patrick Williams6aef7692021-05-01 06:39:41 -0500332bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700333{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700334 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700335 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700336 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800337 manager.reloadConfigsNoRefresh();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700338 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700339 return value;
340}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700341
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700342bool EthernetInterface::dhcp4(bool value)
343{
344 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
345 {
346 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800347 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700348 }
349 return value;
350}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700351
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700352bool EthernetInterface::dhcp6(bool value)
353{
354 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
355 {
356 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800357 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700358 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700359 return value;
360}
361
Patrick Williams6aef7692021-05-01 06:39:41 -0500362EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530363{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700364 auto old4 = EthernetInterfaceIntf::dhcp4();
365 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
366 value == DHCPConf::v4v6stateless ||
367 value == DHCPConf::both);
368 auto old6 = EthernetInterfaceIntf::dhcp6();
369 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
370 value == DHCPConf::both);
371 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
372 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
373 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
374 value == DHCPConf::v6 || value == DHCPConf::both);
375
376 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530377 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700378 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800379 manager.reloadConfigsNoRefresh();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530380 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530381 return value;
382}
383
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700384EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
385{
386 if (dhcp6())
387 {
388 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
389 }
390 else if (dhcp4())
391 {
392 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
393 }
394 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
395}
396
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800397bool EthernetInterface::linkUp() const
398{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700399 if (ifIdx == 0)
400 {
401 return EthernetInterfaceIntf::linkUp();
402 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700403 return system::intfIsRunning(interfaceName());
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700404}
405
Tejas Patil2c0fc562021-08-03 19:13:46 +0530406size_t EthernetInterface::mtu() const
407{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700408 if (ifIdx == 0)
409 {
410 return EthernetInterfaceIntf::mtu();
411 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700412 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700413 return ignoreError("GetMTU", ifname, std::nullopt,
William A. Kennington III2e09d272022-10-14 17:15:00 -0700414 [&] { return system::getMTU(ifname); })
415 .value_or(EthernetInterfaceIntf::mtu());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530416}
417
418size_t EthernetInterface::mtu(size_t value)
419{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700420 const size_t old = EthernetInterfaceIntf::mtu();
421 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530422 {
423 return value;
424 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700425 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700426 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700427 system::setMTU(ifname, value);
428 return value;
429 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530430}
431
Patrick Williams6aef7692021-05-01 06:39:41 -0500432bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700433{
Patrick Williams6aef7692021-05-01 06:39:41 -0500434 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700435 {
436 return value;
437 }
438
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800439 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700440 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800441 if (!value)
442 {
443 // We only need to bring down the interface, networkd will always bring
444 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700445 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700446 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800447 }
William A. Kennington III4ca36012022-11-14 17:43:43 -0800448 manager.reloadConfigsNoRefresh();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800449
450 return value;
451}
452
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530453ServerList EthernetInterface::staticNameServers(ServerList value)
454{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700455 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530456 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700457 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530458 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700459 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
460 }
461 catch (const std::exception& e)
462 {
463 auto msg =
464 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
465 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
466 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
467 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530468 }
469 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530470 try
471 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530472 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700473
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530474 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800475 manager.reloadConfigsNoRefresh();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530476 }
Patrick Williams5758db32021-10-06 12:29:22 -0500477 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530478 {
479 log<level::ERR>("Exception processing DNS entries");
480 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530481 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530482}
483
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600484void EthernetInterface::loadNTPServers(const config::Parser& config)
485{
486 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
487 EthernetInterfaceIntf::staticNTPServers(
488 config.map.getValueStrings("Network", "NTP"));
489}
490
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700491void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530492{
493 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700494 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700495 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530496}
497
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600498ServerList EthernetInterface::getNTPServerFromTimeSyncd()
499{
500 ServerList servers; // Variable to capture the NTP Server IPs
501 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
502 PROPERTY_INTERFACE, METHOD_GET);
503
504 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
505
506 try
507 {
508 auto reply = bus.call(method);
509 std::variant<ServerList> response;
510 reply.read(response);
511 servers = std::get<ServerList>(response);
512 }
513 catch (const sdbusplus::exception::SdBusError& e)
514 {
515 log<level::ERR>(
516 "Failed to get NTP server information from Systemd-Timesyncd");
517 }
518
519 return servers;
520}
521
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530522ServerList EthernetInterface::getNameServerFromResolvd()
523{
524 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700525 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530526
527 /*
528 The DNS property under org.freedesktop.resolve1.Link interface contains
529 an array containing all DNS servers currently used by resolved. It
530 contains similar information as the DNS server data written to
531 /run/systemd/resolve/resolv.conf.
532
533 Each structure in the array consists of a numeric network interface index,
534 an address family, and a byte array containing the DNS server address
535 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
536 The array contains DNS servers configured system-wide, including those
537 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
538 /etc/systemd/resolved.conf, as well as per-interface DNS server
539 information either retrieved from systemd-networkd or configured by
540 external software via SetLinkDNS().
541 */
542
543 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
544 std::variant<type> name; // Variable to capture the DNS property
545 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
546 PROPERTY_INTERFACE, METHOD_GET);
547
548 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530549
550 try
551 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500552 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530553 reply.read(name);
554 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500555 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530556 {
557 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
558 }
559 auto tupleVector = std::get_if<type>(&name);
560 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
561 {
Alexander Filippov983da552021-02-08 15:26:54 +0300562 int addressFamily = std::get<0>(*i);
563 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700564 servers.push_back(std::to_string(
565 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530566 }
567 return servers;
568}
569
William A. Kennington IIId298f932022-10-17 14:31:38 -0700570ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530571{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700572 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
573 auto idStr = std::to_string(id);
574 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800575 {
576 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700577 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
578 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800579 }
580
William A. Kennington IIId298f932022-10-17 14:31:38 -0700581 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700582 auto macStr = MacAddressIntf::macAddress();
583 std::optional<ether_addr> mac;
584 if (!macStr.empty())
585 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700586 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700587 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800588 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700589 .idx = 0, // TODO: Query the correct value after creation
590 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700591 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700592 .mac = std::move(mac),
593 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700594 .parent_idx = ifIdx,
595 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700596 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530597
Patrick Williams6aef7692021-05-01 06:39:41 -0500598 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530599 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700600 auto vlanIntf = std::make_unique<EthernetInterface>(
601 bus, manager, info, objRoot, config::Parser(), /*emit=*/true,
William A. Kennington IIId298f932022-10-17 14:31:38 -0700602 nicEnabled());
603 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530604
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700605 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530606
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700607 // write the device file for the vlan interface.
608 config::Parser config;
609 auto& netdev = config.map["NetDev"].emplace_back();
610 netdev["Name"].emplace_back(intfName);
611 netdev["Kind"].emplace_back("vlan");
612 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
613 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700614
615 writeConfigurationFile();
William A. Kennington III4ca36012022-11-14 17:43:43 -0800616 manager.reloadConfigsNoRefresh();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700617
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800618 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530619}
Ratan Gupta2b106532017-07-25 16:05:02 +0530620
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600621ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530622{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600623 try
624 {
625 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530626
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600627 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800628 manager.reloadConfigsNoRefresh();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600629 }
630 catch (InternalFailure& e)
631 {
632 log<level::ERR>("Exception processing NTP entries");
633 }
634 return EthernetInterfaceIntf::staticNTPServers();
635}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700636
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600637ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
638{
639 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530640}
Ratan Gupta2b106532017-07-25 16:05:02 +0530641// Need to merge the below function with the code which writes the
642// config file during factory reset.
643// TODO openbmc/openbmc#1751
644
645void EthernetInterface::writeConfigurationFile()
646{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700647 config::Parser config;
648 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530649 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700650 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800651#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700652 auto mac = MacAddressIntf::macAddress();
653 if (!mac.empty())
654 {
655 link["MACAddress"].emplace_back(mac);
656 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800657#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700658 if (!EthernetInterfaceIntf::nicEnabled())
659 {
660 link["Unmanaged"].emplace_back("yes");
661 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700662 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700663 {
664 auto& network = config.map["Network"].emplace_back();
665 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400666#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700667 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400668#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700669 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400670#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700671 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
672 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
673 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600674 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700675 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700676 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700677 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700678 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
679 {
680 vlans.emplace_back(intf->interfaceName());
681 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700682 }
683 }
684 {
685 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600686 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700687 {
688 ntps.emplace_back(ntp);
689 }
690 }
691 {
692 auto& dnss = network["DNS"];
693 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
694 {
695 dnss.emplace_back(dns);
696 }
697 }
698 {
699 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700700 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700701 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700702 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700703 {
704 address.emplace_back(
705 fmt::format("{}/{}", addr.second->address(),
706 addr.second->prefixLength()));
707 }
708 }
709 }
710 {
711 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700712 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700713 {
714 auto gateway = EthernetInterfaceIntf::defaultGateway();
715 if (!gateway.empty())
716 {
717 gateways.emplace_back(gateway);
718 }
719 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530720
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700721 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700722 {
723 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
724 if (!gateway6.empty())
725 {
726 gateways.emplace_back(gateway6);
727 }
728 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600729 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800730 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700731 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700732 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500733 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700734 auto& neighbors = config.map["Neighbor"];
735 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800736 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700737 auto& neighbor = neighbors.emplace_back();
738 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
739 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800740 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500741 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500742 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700743 auto& dhcp = config.map["DHCP"].emplace_back();
744 dhcp["ClientIdentifier"].emplace_back("mac");
745 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +0800746 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700747 const auto& conf = *manager.getDHCPConf();
748 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
749 dhcp["UseDNS"].emplace_back(dns_enabled);
750 dhcp["UseDomains"].emplace_back(dns_enabled);
751 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
752 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
753 : "false");
754 dhcp["SendHostname"].emplace_back(
755 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +0800756 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500757 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700758 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
759 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700760 auto msg = fmt::format("Wrote networkd file: {}", path.native());
761 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530762}
763
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800764std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530765{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700766 if (vlan)
767 {
768 log<level::ERR>("Tried to set MAC address on VLAN");
769 elog<InternalFailure>();
770 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800771#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600772 ether_addr newMAC;
773 try
774 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700775 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600776 }
Patrick Williams5758db32021-10-06 12:29:22 -0500777 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600778 {
779 log<level::ERR>("MACAddress is not valid.",
780 entry("MAC=%s", value.c_str()));
781 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
782 Argument::ARGUMENT_VALUE(value.c_str()));
783 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700784 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530785 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500786 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500787 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500788 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
789 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530790 }
791
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300792 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700793 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300794
William A. Kennington III1137a972019-04-20 20:49:58 -0700795 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700796 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700797 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530798 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700799 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700800 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530801 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700802 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
803 {
804 intf->MacAddressIntf::macAddress(validMAC);
805 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530806 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500807 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530808
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700809 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800810 manager.addReloadPreHook([interface]() {
811 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700812 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800813 });
William A. Kennington III4ca36012022-11-14 17:43:43 -0800814 manager.reloadConfigsNoRefresh();
Ratan Gupta677ae122017-09-18 16:28:50 +0530815 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700816
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300817#ifdef HAVE_UBOOT_ENV
818 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700819 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300820 if (envVar)
821 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500822 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
823 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
824 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
825 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300826 }
827#endif // HAVE_UBOOT_ENV
828
William A. Kennington III1137a972019-04-20 20:49:58 -0700829 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800830#else
831 elog<NotAllowed>(
832 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
833#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530834}
835
Ratan Guptae9c9b812017-09-22 17:15:37 +0530836void EthernetInterface::deleteAll()
837{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530838 // clear all the ip on the interface
839 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700840
841 writeConfigurationFile();
William A. Kennington III4ca36012022-11-14 17:43:43 -0800842 manager.reloadConfigsNoRefresh();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530843}
844
Ravi Tejaa5a09442020-07-17 00:57:33 -0500845std::string EthernetInterface::defaultGateway(std::string gateway)
846{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700847 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500848 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700849 if (!gateway.empty())
850 {
851 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
852 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500853 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700854 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500855 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700856 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
857 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500858 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
859 Argument::ARGUMENT_VALUE(gateway.c_str()));
860 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700861
862 if (EthernetInterfaceIntf::defaultGateway() == gateway)
863 {
864 return gateway;
865 }
866 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700867
868 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700869 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700870
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700871 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500872}
873
874std::string EthernetInterface::defaultGateway6(std::string gateway)
875{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700876 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500877 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700878 if (!gateway.empty())
879 {
880 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
881 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500882 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700883 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500884 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700885 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
886 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500887 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
888 Argument::ARGUMENT_VALUE(gateway.c_str()));
889 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700890
891 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
892 {
893 return gateway;
894 }
895 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700896
897 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700898 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700899
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700900 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500901}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700902
903EthernetInterface::VlanProperties::VlanProperties(
904 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III454a0de2022-11-12 01:01:04 -0800905 const InterfaceInfo& info, EthernetInterface& eth, bool emitSignal) :
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700906 VlanIfaces(bus, objPath.c_str(),
907 emitSignal ? VlanIfaces::action::defer_emit
908 : VlanIfaces::action::emit_no_signals),
909 parentIdx(*info.parent_idx), eth(eth)
910{
911 VlanIntf::id(*info.vlan_id);
912 if (emitSignal)
913 {
914 this->emit_object_added();
915 }
916}
917
918void EthernetInterface::VlanProperties::delete_()
919{
920 auto intf = eth.interfaceName();
921
922 // Remove all configs for the current interface
923 const auto& confDir = eth.manager.getConfDir();
924 std::error_code ec;
925 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
926 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
927
928 // Write an updated parent interface since it has a VLAN entry
929 for (const auto& [_, intf] : eth.manager.interfaces)
930 {
931 if (intf->ifIdx == parentIdx)
932 {
933 intf->writeConfigurationFile();
934 }
935 }
936
937 // We need to forcibly delete the interface as systemd does not
938 deleteInterface(intf);
939
William A. Kennington III67b09da2022-10-31 14:09:53 -0700940 if (eth.ifIdx > 0)
941 {
942 eth.manager.interfacesByIdx.erase(eth.ifIdx);
943 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700944 eth.manager.interfaces.erase(intf);
945}
946
Gunnar Mills57d9c502018-09-14 14:42:34 -0500947} // namespace network
948} // namespace phosphor