blob: 7f54f5eb7128dea5831b0c92ecedc1bb57bc46bb [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 III3e471c52022-10-27 19:46:07 -0700118 if (ifIdx > 0)
119 {
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700120 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
121 return system::getEthInfo(*info.name);
William A. Kennington III3e471c52022-10-27 19:46:07 -0700122 });
123 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg);
124 EthernetInterfaceIntf::speed(ethInfo.speed);
125 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530126
William A. Kennington IIId298f932022-10-17 14:31:38 -0700127 updateInfo(info);
128
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700129 if (info.vlan_id)
130 {
131 if (!info.parent_idx)
132 {
133 std::runtime_error("Missing parent link");
134 }
135 vlan.emplace(bus, this->objPath.c_str(), info, *this, emitSignal);
136 }
137
Ratan Gupta29b0e432017-05-25 12:51:40 +0530138 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530139 if (emitSignal)
140 {
141 this->emit_object_added();
142 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530143}
144
William A. Kennington III454a0de2022-11-12 01:01:04 -0800145void EthernetInterface::updateInfo(const InterfaceInfo& info)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700146{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700147 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700148 if (info.mac)
149 {
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700150 MacAddressIntf::macAddress(std::to_string(*info.mac));
William A. Kennington IIId298f932022-10-17 14:31:38 -0700151 }
152 if (info.mtu)
153 {
154 EthernetInterfaceIntf::mtu(*info.mtu);
155 }
156}
157
Johnathan Mantey817012a2020-01-30 15:07:39 -0800158bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
159{
160 return (
161#ifdef LINK_LOCAL_AUTOCONFIGURATION
162 (origin == IP::AddressOrigin::Static)
163#else
164 (origin == IP::AddressOrigin::Static ||
165 origin == IP::AddressOrigin::LinkLocal)
166#endif
167
168 );
169}
170
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800171void EthernetInterface::addAddr(const AddressInfo& info)
172{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800173 IP::AddressOrigin origin = IP::AddressOrigin::Static;
174 if (dhcpIsEnabled(info.ifaddr.getAddr()))
175 {
176 origin = IP::AddressOrigin::DHCP;
177 }
178#ifdef LINK_LOCAL_AUTOCONFIGURATION
179 if (info.scope == RT_SCOPE_LINK)
180 {
181 origin = IP::AddressOrigin::LinkLocal;
182 }
183#endif
184
William A. Kennington III77747f62022-11-07 23:11:15 -0800185 auto it = addrs.find(info.ifaddr);
186 if (it == addrs.end())
187 {
188 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
189 bus, std::string_view(objPath), *this,
190 info.ifaddr, origin));
191 }
192 else
193 {
194 it->second->IPIfaces::origin(origin);
195 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800196}
197
Ratan Gupta87c13982017-06-15 09:27:27 +0530198void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530199{
Ratan Gupta87c13982017-06-15 09:27:27 +0530200 addrs.clear();
William A. Kennington III6a923632022-11-06 18:17:33 -0800201 for (const auto& addr : system::getAddresses({.ifidx = ifIdx}))
Ratan Gupta82549cc2017-04-21 08:45:23 +0530202 {
William A. Kennington III57ca9612022-11-14 15:26:47 -0800203 manager.addAddress(addr);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530204 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530205}
206
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800207void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
208{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800209 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800210 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800211 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800212 log<level::ERR>(msg.c_str());
213 return;
214 }
215 staticNeighbors.emplace(
William A. Kennington IIId3615142022-11-12 01:28:33 -0800216 *info.addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
217 *this, *info.addr, *info.mac,
218 Neighbor::State::Permanent));
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800219}
220
William A. Kennington III08505792019-01-30 16:00:04 -0800221void EthernetInterface::createStaticNeighborObjects()
222{
223 staticNeighbors.clear();
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800224 for (const auto& neighbor : system::getNeighbors({.ifidx = ifIdx}))
William A. Kennington III08505792019-01-30 16:00:04 -0800225 {
William A. Kennington III7310ac72022-11-14 15:44:00 -0800226 manager.addNeighbor(neighbor);
William A. Kennington III08505792019-01-30 16:00:04 -0800227 }
228}
229
Patrick Williams6aef7692021-05-01 06:39:41 -0500230ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700231 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530232{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700233 InAddrAny addr;
234 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530235 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700236 switch (protType)
237 {
238 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700239 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700240 break;
241 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700242 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700243 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700244 default:
245 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700246 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500247 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700248 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500249 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700250 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
251 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500252 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
253 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
254 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700255 IfAddr ifaddr;
256 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500257 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700258 ifaddr = {addr, prefixLength};
259 }
260 catch (const std::exception& e)
261 {
262 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
263 e.what());
264 log<level::ERR>(msg.c_str(),
265 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500266 elog<InvalidArgument>(
267 Argument::ARGUMENT_NAME("prefixLength"),
268 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530269 }
270
William A. Kennington III434a9432022-11-04 18:38:46 -0700271 auto [it, _] = this->addrs.insert_or_assign(
272 ifaddr,
William A. Kennington III59e5b912022-11-02 02:49:46 -0700273 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III434a9432022-11-04 18:38:46 -0700274 ifaddr, IP::AddressOrigin::Static));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530275
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700276 writeConfigurationFile();
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800277 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700278
William A. Kennington III434a9432022-11-04 18:38:46 -0700279 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530280}
281
Patrick Williams6aef7692021-05-01 06:39:41 -0500282ObjectPath EthernetInterface::neighbor(std::string ipAddress,
283 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800284{
William A. Kennington III434a9432022-11-04 18:38:46 -0700285 InAddrAny addr;
286 try
William A. Kennington III08505792019-01-30 16:00:04 -0800287 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700288 addr = ToAddr<InAddrAny>{}(ipAddress);
289 }
290 catch (const std::exception& e)
291 {
292 auto msg =
293 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
294 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500295 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
296 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800297 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700298
299 ether_addr lladdr;
300 try
William A. Kennington III08505792019-01-30 16:00:04 -0800301 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700302 lladdr = ToAddr<ether_addr>{}(macAddress);
303 }
304 catch (const std::exception& e)
305 {
306 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
307 e.what());
308 log<level::ERR>(msg.c_str(),
309 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500310 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
311 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800312 }
313
William A. Kennington III434a9432022-11-04 18:38:46 -0700314 auto [it, _] = staticNeighbors.emplace(
315 addr,
316 std::make_unique<Neighbor>(bus, std::string_view(objPath), *this, addr,
317 lladdr, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700318
319 writeConfigurationFile();
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800320 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700321
William A. Kennington III434a9432022-11-04 18:38:46 -0700322 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800323}
324
Patrick Williams6aef7692021-05-01 06:39:41 -0500325bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700326{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700327 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700328 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700329 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800330 manager.reloadConfigsNoRefresh();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700331 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700332 return value;
333}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700334
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700335bool EthernetInterface::dhcp4(bool value)
336{
337 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
338 {
339 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800340 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700341 }
342 return value;
343}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700344
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700345bool EthernetInterface::dhcp6(bool value)
346{
347 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
348 {
349 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800350 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700351 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700352 return value;
353}
354
Patrick Williams6aef7692021-05-01 06:39:41 -0500355EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530356{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700357 auto old4 = EthernetInterfaceIntf::dhcp4();
358 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
359 value == DHCPConf::v4v6stateless ||
360 value == DHCPConf::both);
361 auto old6 = EthernetInterfaceIntf::dhcp6();
362 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
363 value == DHCPConf::both);
364 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
365 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
366 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
367 value == DHCPConf::v6 || value == DHCPConf::both);
368
369 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530370 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700371 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800372 manager.reloadConfigsNoRefresh();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530373 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530374 return value;
375}
376
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700377EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
378{
379 if (dhcp6())
380 {
381 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
382 }
383 else if (dhcp4())
384 {
385 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
386 }
387 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
388}
389
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800390bool EthernetInterface::linkUp() const
391{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700392 if (ifIdx == 0)
393 {
394 return EthernetInterfaceIntf::linkUp();
395 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700396 return system::intfIsRunning(interfaceName());
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700397}
398
Tejas Patil2c0fc562021-08-03 19:13:46 +0530399size_t EthernetInterface::mtu() const
400{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700401 if (ifIdx == 0)
402 {
403 return EthernetInterfaceIntf::mtu();
404 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700405 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700406 return ignoreError("GetMTU", ifname, std::nullopt,
William A. Kennington III2e09d272022-10-14 17:15:00 -0700407 [&] { return system::getMTU(ifname); })
408 .value_or(EthernetInterfaceIntf::mtu());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530409}
410
411size_t EthernetInterface::mtu(size_t value)
412{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700413 const size_t old = EthernetInterfaceIntf::mtu();
414 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530415 {
416 return value;
417 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700418 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700419 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700420 system::setMTU(ifname, value);
421 return value;
422 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530423}
424
Patrick Williams6aef7692021-05-01 06:39:41 -0500425bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700426{
Patrick Williams6aef7692021-05-01 06:39:41 -0500427 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700428 {
429 return value;
430 }
431
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800432 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700433 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800434 if (!value)
435 {
436 // We only need to bring down the interface, networkd will always bring
437 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700438 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700439 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800440 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700441 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800442
443 return value;
444}
445
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530446ServerList EthernetInterface::staticNameServers(ServerList value)
447{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700448 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530449 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700450 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530451 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700452 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
453 }
454 catch (const std::exception& e)
455 {
456 auto msg =
457 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
458 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
459 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
460 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530461 }
462 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530463 try
464 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530465 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700466
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530467 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800468 manager.reloadConfigsNoRefresh();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530469 }
Patrick Williams5758db32021-10-06 12:29:22 -0500470 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530471 {
472 log<level::ERR>("Exception processing DNS entries");
473 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530474 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530475}
476
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600477void EthernetInterface::loadNTPServers(const config::Parser& config)
478{
479 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
480 EthernetInterfaceIntf::staticNTPServers(
481 config.map.getValueStrings("Network", "NTP"));
482}
483
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700484void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530485{
486 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700487 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700488 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530489}
490
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600491ServerList EthernetInterface::getNTPServerFromTimeSyncd()
492{
493 ServerList servers; // Variable to capture the NTP Server IPs
494 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
495 PROPERTY_INTERFACE, METHOD_GET);
496
497 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
498
499 try
500 {
501 auto reply = bus.call(method);
502 std::variant<ServerList> response;
503 reply.read(response);
504 servers = std::get<ServerList>(response);
505 }
506 catch (const sdbusplus::exception::SdBusError& e)
507 {
508 log<level::ERR>(
509 "Failed to get NTP server information from Systemd-Timesyncd");
510 }
511
512 return servers;
513}
514
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530515ServerList EthernetInterface::getNameServerFromResolvd()
516{
517 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700518 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530519
520 /*
521 The DNS property under org.freedesktop.resolve1.Link interface contains
522 an array containing all DNS servers currently used by resolved. It
523 contains similar information as the DNS server data written to
524 /run/systemd/resolve/resolv.conf.
525
526 Each structure in the array consists of a numeric network interface index,
527 an address family, and a byte array containing the DNS server address
528 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
529 The array contains DNS servers configured system-wide, including those
530 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
531 /etc/systemd/resolved.conf, as well as per-interface DNS server
532 information either retrieved from systemd-networkd or configured by
533 external software via SetLinkDNS().
534 */
535
536 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
537 std::variant<type> name; // Variable to capture the DNS property
538 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
539 PROPERTY_INTERFACE, METHOD_GET);
540
541 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530542
543 try
544 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500545 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530546 reply.read(name);
547 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500548 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530549 {
550 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
551 }
552 auto tupleVector = std::get_if<type>(&name);
553 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
554 {
Alexander Filippov983da552021-02-08 15:26:54 +0300555 int addressFamily = std::get<0>(*i);
556 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700557 servers.push_back(std::to_string(
558 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530559 }
560 return servers;
561}
562
William A. Kennington IIId298f932022-10-17 14:31:38 -0700563ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530564{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700565 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
566 auto idStr = std::to_string(id);
567 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800568 {
569 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700570 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
571 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800572 }
573
William A. Kennington IIId298f932022-10-17 14:31:38 -0700574 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700575 auto macStr = MacAddressIntf::macAddress();
576 std::optional<ether_addr> mac;
577 if (!macStr.empty())
578 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700579 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700580 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800581 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700582 .idx = 0, // TODO: Query the correct value after creation
583 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700584 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700585 .mac = std::move(mac),
586 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700587 .parent_idx = ifIdx,
588 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700589 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530590
Patrick Williams6aef7692021-05-01 06:39:41 -0500591 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530592 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700593 auto vlanIntf = std::make_unique<EthernetInterface>(
594 bus, manager, info, objRoot, config::Parser(), /*emit=*/true,
William A. Kennington IIId298f932022-10-17 14:31:38 -0700595 nicEnabled());
596 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530597
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700598 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530599
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700600 // write the device file for the vlan interface.
601 config::Parser config;
602 auto& netdev = config.map["NetDev"].emplace_back();
603 netdev["Name"].emplace_back(intfName);
604 netdev["Kind"].emplace_back("vlan");
605 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
606 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700607
608 writeConfigurationFile();
609 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700610
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800611 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530612}
Ratan Gupta2b106532017-07-25 16:05:02 +0530613
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600614ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530615{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600616 try
617 {
618 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530619
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600620 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800621 manager.reloadConfigsNoRefresh();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600622 }
623 catch (InternalFailure& e)
624 {
625 log<level::ERR>("Exception processing NTP entries");
626 }
627 return EthernetInterfaceIntf::staticNTPServers();
628}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700629
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600630ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
631{
632 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530633}
Ratan Gupta2b106532017-07-25 16:05:02 +0530634// Need to merge the below function with the code which writes the
635// config file during factory reset.
636// TODO openbmc/openbmc#1751
637
638void EthernetInterface::writeConfigurationFile()
639{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700640 config::Parser config;
641 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530642 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700643 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800644#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700645 auto mac = MacAddressIntf::macAddress();
646 if (!mac.empty())
647 {
648 link["MACAddress"].emplace_back(mac);
649 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800650#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700651 if (!EthernetInterfaceIntf::nicEnabled())
652 {
653 link["Unmanaged"].emplace_back("yes");
654 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700655 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700656 {
657 auto& network = config.map["Network"].emplace_back();
658 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400659#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700660 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400661#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700662 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400663#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700664 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
665 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
666 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600667 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700668 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700669 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700670 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700671 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
672 {
673 vlans.emplace_back(intf->interfaceName());
674 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700675 }
676 }
677 {
678 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600679 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700680 {
681 ntps.emplace_back(ntp);
682 }
683 }
684 {
685 auto& dnss = network["DNS"];
686 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
687 {
688 dnss.emplace_back(dns);
689 }
690 }
691 {
692 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700693 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700694 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700695 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700696 {
697 address.emplace_back(
698 fmt::format("{}/{}", addr.second->address(),
699 addr.second->prefixLength()));
700 }
701 }
702 }
703 {
704 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700705 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700706 {
707 auto gateway = EthernetInterfaceIntf::defaultGateway();
708 if (!gateway.empty())
709 {
710 gateways.emplace_back(gateway);
711 }
712 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530713
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700714 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700715 {
716 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
717 if (!gateway6.empty())
718 {
719 gateways.emplace_back(gateway6);
720 }
721 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600722 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800723 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700724 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700725 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500726 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700727 auto& neighbors = config.map["Neighbor"];
728 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800729 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700730 auto& neighbor = neighbors.emplace_back();
731 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
732 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800733 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500734 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500735 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700736 auto& dhcp = config.map["DHCP"].emplace_back();
737 dhcp["ClientIdentifier"].emplace_back("mac");
738 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +0800739 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700740 const auto& conf = *manager.getDHCPConf();
741 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
742 dhcp["UseDNS"].emplace_back(dns_enabled);
743 dhcp["UseDomains"].emplace_back(dns_enabled);
744 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
745 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
746 : "false");
747 dhcp["SendHostname"].emplace_back(
748 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +0800749 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500750 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700751 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
752 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700753 auto msg = fmt::format("Wrote networkd file: {}", path.native());
754 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530755}
756
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800757std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530758{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700759 if (vlan)
760 {
761 log<level::ERR>("Tried to set MAC address on VLAN");
762 elog<InternalFailure>();
763 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800764#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600765 ether_addr newMAC;
766 try
767 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700768 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600769 }
Patrick Williams5758db32021-10-06 12:29:22 -0500770 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600771 {
772 log<level::ERR>("MACAddress is not valid.",
773 entry("MAC=%s", value.c_str()));
774 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
775 Argument::ARGUMENT_VALUE(value.c_str()));
776 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700777 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530778 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500779 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500780 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500781 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
782 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530783 }
784
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300785 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700786 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300787
William A. Kennington III1137a972019-04-20 20:49:58 -0700788 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700789 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700790 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530791 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700792 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700793 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530794 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700795 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
796 {
797 intf->MacAddressIntf::macAddress(validMAC);
798 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530799 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500800 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530801
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700802 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800803 manager.addReloadPreHook([interface]() {
804 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700805 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800806 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700807 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530808 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700809
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300810#ifdef HAVE_UBOOT_ENV
811 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700812 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300813 if (envVar)
814 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500815 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
816 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
817 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
818 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300819 }
820#endif // HAVE_UBOOT_ENV
821
William A. Kennington III1137a972019-04-20 20:49:58 -0700822 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800823#else
824 elog<NotAllowed>(
825 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
826#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530827}
828
Ratan Guptae9c9b812017-09-22 17:15:37 +0530829void EthernetInterface::deleteAll()
830{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530831 // clear all the ip on the interface
832 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700833
834 writeConfigurationFile();
835 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530836}
837
Ravi Tejaa5a09442020-07-17 00:57:33 -0500838std::string EthernetInterface::defaultGateway(std::string gateway)
839{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700840 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500841 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700842 if (!gateway.empty())
843 {
844 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
845 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500846 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700847 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500848 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700849 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
850 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500851 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
852 Argument::ARGUMENT_VALUE(gateway.c_str()));
853 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700854
855 if (EthernetInterfaceIntf::defaultGateway() == gateway)
856 {
857 return gateway;
858 }
859 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700860
861 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700862 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700863
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700864 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500865}
866
867std::string EthernetInterface::defaultGateway6(std::string gateway)
868{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700869 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500870 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700871 if (!gateway.empty())
872 {
873 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
874 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500875 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700876 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500877 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700878 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
879 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500880 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
881 Argument::ARGUMENT_VALUE(gateway.c_str()));
882 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700883
884 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
885 {
886 return gateway;
887 }
888 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700889
890 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700891 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700892
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700893 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500894}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700895
896EthernetInterface::VlanProperties::VlanProperties(
897 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III454a0de2022-11-12 01:01:04 -0800898 const InterfaceInfo& info, EthernetInterface& eth, bool emitSignal) :
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700899 VlanIfaces(bus, objPath.c_str(),
900 emitSignal ? VlanIfaces::action::defer_emit
901 : VlanIfaces::action::emit_no_signals),
902 parentIdx(*info.parent_idx), eth(eth)
903{
904 VlanIntf::id(*info.vlan_id);
905 if (emitSignal)
906 {
907 this->emit_object_added();
908 }
909}
910
911void EthernetInterface::VlanProperties::delete_()
912{
913 auto intf = eth.interfaceName();
914
915 // Remove all configs for the current interface
916 const auto& confDir = eth.manager.getConfDir();
917 std::error_code ec;
918 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
919 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
920
921 // Write an updated parent interface since it has a VLAN entry
922 for (const auto& [_, intf] : eth.manager.interfaces)
923 {
924 if (intf->ifIdx == parentIdx)
925 {
926 intf->writeConfigurationFile();
927 }
928 }
929
930 // We need to forcibly delete the interface as systemd does not
931 deleteInterface(intf);
932
William A. Kennington III67b09da2022-10-31 14:09:53 -0700933 if (eth.ifIdx > 0)
934 {
935 eth.manager.interfacesByIdx.erase(eth.ifIdx);
936 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700937 eth.manager.interfaces.erase(intf);
938}
939
Gunnar Mills57d9c502018-09-14 14:42:34 -0500940} // namespace network
941} // namespace phosphor