blob: bc33243bdf44c32b27cfb16f76787af09529f234 [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 III2e09d272022-10-14 17:15:00 -070012#include <linux/neighbour.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070013#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070014#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015
Ratan Gupta82549cc2017-04-21 08:45:23 +053016#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053017#include <filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070018#include <phosphor-logging/elog-errors.hpp>
19#include <phosphor-logging/log.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070020#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070021#include <stdplus/zstring.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053022#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070023#include <unordered_map>
24#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070025#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053026
Ratan Gupta91a99cc2017-04-14 16:32:09 +053027namespace phosphor
28{
29namespace network
30{
31
32using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053033using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053034using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
35using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050036using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070037using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053038constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
39constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
40constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
41constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060042
43constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
44constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
45constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
46
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053047constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053048
William A. Kennington III2e09d272022-10-14 17:15:00 -070049template <typename Func>
50inline decltype(std::declval<Func>()())
51 ignoreError(std::string_view msg, stdplus::zstring_view intf,
52 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080053{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070054 try
55 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070056 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070057 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070058 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070059 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070060 auto err = fmt::format("{} failed on {}: {}", msg, intf, e.what());
61 log<level::ERR>(err.c_str(), entry("INTERFACE=%s", intf.c_str()));
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070062 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070063 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070064}
William A. Kennington IIId298f932022-10-17 14:31:38 -070065
William A. Kennington IIId298f932022-10-17 14:31:38 -070066static std::string makeObjPath(std::string_view root, std::string_view intf)
67{
68 auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
69 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
70 return ret;
71}
72
73EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080074 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070075 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070076 const config::Parser& config,
William A. Kennington III80d29012022-11-12 02:31:40 -080077 bool emitSignal, bool enabled) :
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070078 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.name),
William A. Kennington IIId298f932022-10-17 14:31:38 -070079 config, emitSignal, enabled)
80{
81}
82
83EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080084 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070085 std::string&& objPath,
86 const config::Parser& config,
William A. Kennington III80d29012022-11-12 02:31:40 -080087 bool emitSignal, bool enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050088 Ifaces(bus, objPath.c_str(),
89 emitSignal ? Ifaces::action::defer_emit
90 : Ifaces::action::emit_no_signals),
William A. Kennington III59e5b912022-11-02 02:49:46 -070091 manager(manager), bus(bus), objPath(std::move(objPath)), ifIdx(info.idx)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053092{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070093 interfaceName(*info.name);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070094 auto dhcpVal = getDHCPValue(config);
95 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
96 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070097 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III80d29012022-11-12 02:31:40 -080098 EthernetInterfaceIntf::nicEnabled(enabled);
Ravi Tejaa5a09442020-07-17 00:57:33 -050099 {
William A. Kennington III2bd35d62022-10-26 19:20:29 -0700100 const auto& gws = manager.getRouteTable().getDefaultGateway();
101 auto it = gws.find(ifIdx);
102 if (it != gws.end())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500103 {
William A. Kennington III2bd35d62022-10-26 19:20:29 -0700104 EthernetInterfaceIntf::defaultGateway(std::to_string(it->second));
105 }
106 }
107 {
108 const auto& gws = manager.getRouteTable().getDefaultGateway6();
109 auto it = gws.find(ifIdx);
110 if (it != gws.end())
111 {
112 EthernetInterfaceIntf::defaultGateway6(std::to_string(it->second));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500113 }
114 }
115
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700116 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700117 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530118
William A. Kennington III3e471c52022-10-27 19:46:07 -0700119 if (ifIdx > 0)
120 {
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700121 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
122 return system::getEthInfo(*info.name);
William A. Kennington III3e471c52022-10-27 19:46:07 -0700123 });
124 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg);
125 EthernetInterfaceIntf::speed(ethInfo.speed);
126 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530127
William A. Kennington IIId298f932022-10-17 14:31:38 -0700128 updateInfo(info);
129
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700130 if (info.vlan_id)
131 {
132 if (!info.parent_idx)
133 {
134 std::runtime_error("Missing parent link");
135 }
136 vlan.emplace(bus, this->objPath.c_str(), info, *this, emitSignal);
137 }
138
Ratan Gupta29b0e432017-05-25 12:51:40 +0530139 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530140 if (emitSignal)
141 {
142 this->emit_object_added();
143 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530144}
145
William A. Kennington III454a0de2022-11-12 01:01:04 -0800146void EthernetInterface::updateInfo(const InterfaceInfo& info)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700147{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700148 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700149 if (info.mac)
150 {
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700151 MacAddressIntf::macAddress(std::to_string(*info.mac));
William A. Kennington IIId298f932022-10-17 14:31:38 -0700152 }
153 if (info.mtu)
154 {
155 EthernetInterfaceIntf::mtu(*info.mtu);
156 }
157}
158
Johnathan Mantey817012a2020-01-30 15:07:39 -0800159bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
160{
161 return (
162#ifdef LINK_LOCAL_AUTOCONFIGURATION
163 (origin == IP::AddressOrigin::Static)
164#else
165 (origin == IP::AddressOrigin::Static ||
166 origin == IP::AddressOrigin::LinkLocal)
167#endif
168
169 );
170}
171
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800172void EthernetInterface::addAddr(const AddressInfo& info)
173{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800174 IP::AddressOrigin origin = IP::AddressOrigin::Static;
175 if (dhcpIsEnabled(info.ifaddr.getAddr()))
176 {
177 origin = IP::AddressOrigin::DHCP;
178 }
179#ifdef LINK_LOCAL_AUTOCONFIGURATION
180 if (info.scope == RT_SCOPE_LINK)
181 {
182 origin = IP::AddressOrigin::LinkLocal;
183 }
184#endif
185
William A. Kennington III77747f62022-11-07 23:11:15 -0800186 auto it = addrs.find(info.ifaddr);
187 if (it == addrs.end())
188 {
189 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
190 bus, std::string_view(objPath), *this,
191 info.ifaddr, origin));
192 }
193 else
194 {
195 it->second->IPIfaces::origin(origin);
196 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800197}
198
Ratan Gupta87c13982017-06-15 09:27:27 +0530199void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530200{
Ratan Gupta87c13982017-06-15 09:27:27 +0530201 addrs.clear();
William A. Kennington III6a923632022-11-06 18:17:33 -0800202 for (const auto& addr : system::getAddresses({.ifidx = ifIdx}))
Ratan Gupta82549cc2017-04-21 08:45:23 +0530203 {
William A. Kennington III57ca9612022-11-14 15:26:47 -0800204 manager.addAddress(addr);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530205 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530206}
207
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800208void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
209{
210 if ((info.state & NUD_PERMANENT) == 0)
211 {
212 return;
213 }
William A. Kennington IIId3615142022-11-12 01:28:33 -0800214 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800215 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800216 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800217 log<level::ERR>(msg.c_str());
218 return;
219 }
220 staticNeighbors.emplace(
William A. Kennington IIId3615142022-11-12 01:28:33 -0800221 *info.addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
222 *this, *info.addr, *info.mac,
223 Neighbor::State::Permanent));
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800224}
225
William A. Kennington III08505792019-01-30 16:00:04 -0800226void EthernetInterface::createStaticNeighborObjects()
227{
228 staticNeighbors.clear();
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800229 for (const auto& neighbor : system::getNeighbors({.ifidx = ifIdx}))
William A. Kennington III08505792019-01-30 16:00:04 -0800230 {
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800231 addStaticNeigh(neighbor);
William A. Kennington III08505792019-01-30 16:00:04 -0800232 }
233}
234
Patrick Williams6aef7692021-05-01 06:39:41 -0500235ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700236 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530237{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700238 InAddrAny addr;
239 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530240 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700241 switch (protType)
242 {
243 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700244 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700245 break;
246 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700247 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700248 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700249 default:
250 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700251 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500252 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700253 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500254 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700255 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
256 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500257 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
258 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
259 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700260 IfAddr ifaddr;
261 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500262 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700263 ifaddr = {addr, prefixLength};
264 }
265 catch (const std::exception& e)
266 {
267 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
268 e.what());
269 log<level::ERR>(msg.c_str(),
270 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500271 elog<InvalidArgument>(
272 Argument::ARGUMENT_NAME("prefixLength"),
273 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530274 }
275
William A. Kennington III434a9432022-11-04 18:38:46 -0700276 auto [it, _] = this->addrs.insert_or_assign(
277 ifaddr,
William A. Kennington III59e5b912022-11-02 02:49:46 -0700278 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III434a9432022-11-04 18:38:46 -0700279 ifaddr, IP::AddressOrigin::Static));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530280
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700281 writeConfigurationFile();
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800282 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700283
William A. Kennington III434a9432022-11-04 18:38:46 -0700284 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530285}
286
Patrick Williams6aef7692021-05-01 06:39:41 -0500287ObjectPath EthernetInterface::neighbor(std::string ipAddress,
288 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800289{
William A. Kennington III434a9432022-11-04 18:38:46 -0700290 InAddrAny addr;
291 try
William A. Kennington III08505792019-01-30 16:00:04 -0800292 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700293 addr = ToAddr<InAddrAny>{}(ipAddress);
294 }
295 catch (const std::exception& e)
296 {
297 auto msg =
298 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
299 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500300 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
301 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800302 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700303
304 ether_addr lladdr;
305 try
William A. Kennington III08505792019-01-30 16:00:04 -0800306 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700307 lladdr = ToAddr<ether_addr>{}(macAddress);
308 }
309 catch (const std::exception& e)
310 {
311 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
312 e.what());
313 log<level::ERR>(msg.c_str(),
314 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500315 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
316 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800317 }
318
William A. Kennington III434a9432022-11-04 18:38:46 -0700319 auto [it, _] = staticNeighbors.emplace(
320 addr,
321 std::make_unique<Neighbor>(bus, std::string_view(objPath), *this, addr,
322 lladdr, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700323
324 writeConfigurationFile();
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800325 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700326
William A. Kennington III434a9432022-11-04 18:38:46 -0700327 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800328}
329
Patrick Williams6aef7692021-05-01 06:39:41 -0500330bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700331{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700332 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700333 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700334 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800335 manager.reloadConfigsNoRefresh();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700336 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700337 return value;
338}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700339
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700340bool EthernetInterface::dhcp4(bool value)
341{
342 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
343 {
344 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800345 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700346 }
347 return value;
348}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700349
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700350bool EthernetInterface::dhcp6(bool value)
351{
352 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
353 {
354 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800355 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700356 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700357 return value;
358}
359
Patrick Williams6aef7692021-05-01 06:39:41 -0500360EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530361{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700362 auto old4 = EthernetInterfaceIntf::dhcp4();
363 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
364 value == DHCPConf::v4v6stateless ||
365 value == DHCPConf::both);
366 auto old6 = EthernetInterfaceIntf::dhcp6();
367 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
368 value == DHCPConf::both);
369 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
370 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
371 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
372 value == DHCPConf::v6 || value == DHCPConf::both);
373
374 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530375 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700376 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800377 manager.reloadConfigsNoRefresh();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530378 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530379 return value;
380}
381
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700382EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
383{
384 if (dhcp6())
385 {
386 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
387 }
388 else if (dhcp4())
389 {
390 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
391 }
392 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
393}
394
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800395bool EthernetInterface::linkUp() const
396{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700397 if (ifIdx == 0)
398 {
399 return EthernetInterfaceIntf::linkUp();
400 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700401 return system::intfIsRunning(interfaceName());
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700402}
403
Tejas Patil2c0fc562021-08-03 19:13:46 +0530404size_t EthernetInterface::mtu() const
405{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700406 if (ifIdx == 0)
407 {
408 return EthernetInterfaceIntf::mtu();
409 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700410 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700411 return ignoreError("GetMTU", ifname, std::nullopt,
William A. Kennington III2e09d272022-10-14 17:15:00 -0700412 [&] { return system::getMTU(ifname); })
413 .value_or(EthernetInterfaceIntf::mtu());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530414}
415
416size_t EthernetInterface::mtu(size_t value)
417{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700418 const size_t old = EthernetInterfaceIntf::mtu();
419 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530420 {
421 return value;
422 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700423 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700424 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700425 system::setMTU(ifname, value);
426 return value;
427 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530428}
429
Patrick Williams6aef7692021-05-01 06:39:41 -0500430bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700431{
Patrick Williams6aef7692021-05-01 06:39:41 -0500432 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700433 {
434 return value;
435 }
436
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800437 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700438 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800439 if (!value)
440 {
441 // We only need to bring down the interface, networkd will always bring
442 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700443 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700444 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800445 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700446 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800447
448 return value;
449}
450
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530451ServerList EthernetInterface::staticNameServers(ServerList value)
452{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700453 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530454 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700455 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530456 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700457 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
458 }
459 catch (const std::exception& e)
460 {
461 auto msg =
462 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
463 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
464 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
465 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530466 }
467 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530468 try
469 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530470 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700471
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530472 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800473 manager.reloadConfigsNoRefresh();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530474 }
Patrick Williams5758db32021-10-06 12:29:22 -0500475 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530476 {
477 log<level::ERR>("Exception processing DNS entries");
478 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530479 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530480}
481
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600482void EthernetInterface::loadNTPServers(const config::Parser& config)
483{
484 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
485 EthernetInterfaceIntf::staticNTPServers(
486 config.map.getValueStrings("Network", "NTP"));
487}
488
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700489void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530490{
491 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700492 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700493 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530494}
495
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600496ServerList EthernetInterface::getNTPServerFromTimeSyncd()
497{
498 ServerList servers; // Variable to capture the NTP Server IPs
499 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
500 PROPERTY_INTERFACE, METHOD_GET);
501
502 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
503
504 try
505 {
506 auto reply = bus.call(method);
507 std::variant<ServerList> response;
508 reply.read(response);
509 servers = std::get<ServerList>(response);
510 }
511 catch (const sdbusplus::exception::SdBusError& e)
512 {
513 log<level::ERR>(
514 "Failed to get NTP server information from Systemd-Timesyncd");
515 }
516
517 return servers;
518}
519
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530520ServerList EthernetInterface::getNameServerFromResolvd()
521{
522 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700523 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530524
525 /*
526 The DNS property under org.freedesktop.resolve1.Link interface contains
527 an array containing all DNS servers currently used by resolved. It
528 contains similar information as the DNS server data written to
529 /run/systemd/resolve/resolv.conf.
530
531 Each structure in the array consists of a numeric network interface index,
532 an address family, and a byte array containing the DNS server address
533 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
534 The array contains DNS servers configured system-wide, including those
535 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
536 /etc/systemd/resolved.conf, as well as per-interface DNS server
537 information either retrieved from systemd-networkd or configured by
538 external software via SetLinkDNS().
539 */
540
541 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
542 std::variant<type> name; // Variable to capture the DNS property
543 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
544 PROPERTY_INTERFACE, METHOD_GET);
545
546 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530547
548 try
549 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500550 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530551 reply.read(name);
552 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500553 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530554 {
555 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
556 }
557 auto tupleVector = std::get_if<type>(&name);
558 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
559 {
Alexander Filippov983da552021-02-08 15:26:54 +0300560 int addressFamily = std::get<0>(*i);
561 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700562 servers.push_back(std::to_string(
563 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530564 }
565 return servers;
566}
567
William A. Kennington IIId298f932022-10-17 14:31:38 -0700568ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530569{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700570 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
571 auto idStr = std::to_string(id);
572 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800573 {
574 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700575 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
576 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800577 }
578
William A. Kennington IIId298f932022-10-17 14:31:38 -0700579 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700580 auto macStr = MacAddressIntf::macAddress();
581 std::optional<ether_addr> mac;
582 if (!macStr.empty())
583 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700584 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700585 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800586 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700587 .idx = 0, // TODO: Query the correct value after creation
588 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700589 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700590 .mac = std::move(mac),
591 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700592 .parent_idx = ifIdx,
593 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700594 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530595
Patrick Williams6aef7692021-05-01 06:39:41 -0500596 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530597 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700598 auto vlanIntf = std::make_unique<EthernetInterface>(
599 bus, manager, info, objRoot, config::Parser(), /*emit=*/true,
William A. Kennington IIId298f932022-10-17 14:31:38 -0700600 nicEnabled());
601 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530602
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700603 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530604
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700605 // write the device file for the vlan interface.
606 config::Parser config;
607 auto& netdev = config.map["NetDev"].emplace_back();
608 netdev["Name"].emplace_back(intfName);
609 netdev["Kind"].emplace_back("vlan");
610 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
611 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700612
613 writeConfigurationFile();
614 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700615
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800616 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530617}
Ratan Gupta2b106532017-07-25 16:05:02 +0530618
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600619ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530620{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600621 try
622 {
623 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530624
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600625 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800626 manager.reloadConfigsNoRefresh();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600627 }
628 catch (InternalFailure& e)
629 {
630 log<level::ERR>("Exception processing NTP entries");
631 }
632 return EthernetInterfaceIntf::staticNTPServers();
633}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700634
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600635ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
636{
637 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530638}
Ratan Gupta2b106532017-07-25 16:05:02 +0530639// Need to merge the below function with the code which writes the
640// config file during factory reset.
641// TODO openbmc/openbmc#1751
642
643void EthernetInterface::writeConfigurationFile()
644{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700645 config::Parser config;
646 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530647 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800649#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700650 auto mac = MacAddressIntf::macAddress();
651 if (!mac.empty())
652 {
653 link["MACAddress"].emplace_back(mac);
654 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800655#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700656 if (!EthernetInterfaceIntf::nicEnabled())
657 {
658 link["Unmanaged"].emplace_back("yes");
659 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700660 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700661 {
662 auto& network = config.map["Network"].emplace_back();
663 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400664#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700665 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400666#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700667 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400668#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700669 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
670 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
671 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600672 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700673 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700674 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700675 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700676 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
677 {
678 vlans.emplace_back(intf->interfaceName());
679 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700680 }
681 }
682 {
683 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600684 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700685 {
686 ntps.emplace_back(ntp);
687 }
688 }
689 {
690 auto& dnss = network["DNS"];
691 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
692 {
693 dnss.emplace_back(dns);
694 }
695 }
696 {
697 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700698 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700699 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700700 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700701 {
702 address.emplace_back(
703 fmt::format("{}/{}", addr.second->address(),
704 addr.second->prefixLength()));
705 }
706 }
707 }
708 {
709 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700710 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700711 {
712 auto gateway = EthernetInterfaceIntf::defaultGateway();
713 if (!gateway.empty())
714 {
715 gateways.emplace_back(gateway);
716 }
717 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530718
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700719 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700720 {
721 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
722 if (!gateway6.empty())
723 {
724 gateways.emplace_back(gateway6);
725 }
726 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600727 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800728 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700729 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700730 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500731 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700732 auto& neighbors = config.map["Neighbor"];
733 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800734 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700735 auto& neighbor = neighbors.emplace_back();
736 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
737 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800738 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500739 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500740 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700741 auto& dhcp = config.map["DHCP"].emplace_back();
742 dhcp["ClientIdentifier"].emplace_back("mac");
743 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +0800744 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700745 const auto& conf = *manager.getDHCPConf();
746 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
747 dhcp["UseDNS"].emplace_back(dns_enabled);
748 dhcp["UseDomains"].emplace_back(dns_enabled);
749 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
750 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
751 : "false");
752 dhcp["SendHostname"].emplace_back(
753 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +0800754 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500755 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700756 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
757 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700758 auto msg = fmt::format("Wrote networkd file: {}", path.native());
759 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530760}
761
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800762std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530763{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700764 if (vlan)
765 {
766 log<level::ERR>("Tried to set MAC address on VLAN");
767 elog<InternalFailure>();
768 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800769#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600770 ether_addr newMAC;
771 try
772 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700773 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600774 }
Patrick Williams5758db32021-10-06 12:29:22 -0500775 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600776 {
777 log<level::ERR>("MACAddress is not valid.",
778 entry("MAC=%s", value.c_str()));
779 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
780 Argument::ARGUMENT_VALUE(value.c_str()));
781 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700782 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530783 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500784 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500785 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500786 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
787 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530788 }
789
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300790 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700791 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300792
William A. Kennington III1137a972019-04-20 20:49:58 -0700793 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700794 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700795 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530796 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700797 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700798 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530799 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700800 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
801 {
802 intf->MacAddressIntf::macAddress(validMAC);
803 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530804 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500805 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530806
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700807 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800808 manager.addReloadPreHook([interface]() {
809 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700810 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800811 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700812 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530813 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700814
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300815#ifdef HAVE_UBOOT_ENV
816 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700817 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300818 if (envVar)
819 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500820 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
821 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
822 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
823 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300824 }
825#endif // HAVE_UBOOT_ENV
826
William A. Kennington III1137a972019-04-20 20:49:58 -0700827 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800828#else
829 elog<NotAllowed>(
830 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
831#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530832}
833
Ratan Guptae9c9b812017-09-22 17:15:37 +0530834void EthernetInterface::deleteAll()
835{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530836 // clear all the ip on the interface
837 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700838
839 writeConfigurationFile();
840 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530841}
842
Ravi Tejaa5a09442020-07-17 00:57:33 -0500843std::string EthernetInterface::defaultGateway(std::string gateway)
844{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700845 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500846 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700847 if (!gateway.empty())
848 {
849 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
850 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500851 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700852 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500853 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700854 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
855 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500856 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
857 Argument::ARGUMENT_VALUE(gateway.c_str()));
858 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700859
860 if (EthernetInterfaceIntf::defaultGateway() == gateway)
861 {
862 return gateway;
863 }
864 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700865
866 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700867 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700868
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700869 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500870}
871
872std::string EthernetInterface::defaultGateway6(std::string gateway)
873{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700874 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500875 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700876 if (!gateway.empty())
877 {
878 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
879 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500880 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700881 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500882 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700883 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
884 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500885 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
886 Argument::ARGUMENT_VALUE(gateway.c_str()));
887 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700888
889 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
890 {
891 return gateway;
892 }
893 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700894
895 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700896 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700897
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700898 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500899}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700900
901EthernetInterface::VlanProperties::VlanProperties(
902 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III454a0de2022-11-12 01:01:04 -0800903 const InterfaceInfo& info, EthernetInterface& eth, bool emitSignal) :
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700904 VlanIfaces(bus, objPath.c_str(),
905 emitSignal ? VlanIfaces::action::defer_emit
906 : VlanIfaces::action::emit_no_signals),
907 parentIdx(*info.parent_idx), eth(eth)
908{
909 VlanIntf::id(*info.vlan_id);
910 if (emitSignal)
911 {
912 this->emit_object_added();
913 }
914}
915
916void EthernetInterface::VlanProperties::delete_()
917{
918 auto intf = eth.interfaceName();
919
920 // Remove all configs for the current interface
921 const auto& confDir = eth.manager.getConfDir();
922 std::error_code ec;
923 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
924 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
925
926 // Write an updated parent interface since it has a VLAN entry
927 for (const auto& [_, intf] : eth.manager.interfaces)
928 {
929 if (intf->ifIdx == parentIdx)
930 {
931 intf->writeConfigurationFile();
932 }
933 }
934
935 // We need to forcibly delete the interface as systemd does not
936 deleteInterface(intf);
937
William A. Kennington III67b09da2022-10-31 14:09:53 -0700938 if (eth.ifIdx > 0)
939 {
940 eth.manager.interfacesByIdx.erase(eth.ifIdx);
941 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700942 eth.manager.interfaces.erase(intf);
943}
944
Gunnar Mills57d9c502018-09-14 14:42:34 -0500945} // namespace network
946} // namespace phosphor