blob: 5da144014f59372558d6f979ce1596508cfb35c9 [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 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800215
216 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
217 {
218 it->second->NeighborObj::macAddress(std::to_string(*info.mac));
219 }
220 else
221 {
222 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
223 bus, std::string_view(objPath),
224 *this, *info.addr, *info.mac,
225 Neighbor::State::Permanent));
226 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800227}
228
William A. Kennington III08505792019-01-30 16:00:04 -0800229void EthernetInterface::createStaticNeighborObjects()
230{
231 staticNeighbors.clear();
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800232 for (const auto& neighbor : system::getNeighbors({.ifidx = ifIdx}))
William A. Kennington III08505792019-01-30 16:00:04 -0800233 {
William A. Kennington III7310ac72022-11-14 15:44:00 -0800234 manager.addNeighbor(neighbor);
William A. Kennington III08505792019-01-30 16:00:04 -0800235 }
236}
237
Patrick Williams6aef7692021-05-01 06:39:41 -0500238ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700239 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530240{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700241 InAddrAny addr;
242 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530243 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700244 switch (protType)
245 {
246 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700247 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700248 break;
249 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700250 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700251 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700252 default:
253 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700254 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500255 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700256 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500257 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700258 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
259 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500260 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
261 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
262 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700263 IfAddr ifaddr;
264 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500265 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700266 ifaddr = {addr, prefixLength};
267 }
268 catch (const std::exception& e)
269 {
270 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
271 e.what());
272 log<level::ERR>(msg.c_str(),
273 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500274 elog<InvalidArgument>(
275 Argument::ARGUMENT_NAME("prefixLength"),
276 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530277 }
278
William A. Kennington III434a9432022-11-04 18:38:46 -0700279 auto [it, _] = this->addrs.insert_or_assign(
280 ifaddr,
William A. Kennington III59e5b912022-11-02 02:49:46 -0700281 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III434a9432022-11-04 18:38:46 -0700282 ifaddr, IP::AddressOrigin::Static));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530283
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700284 writeConfigurationFile();
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800285 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700286
William A. Kennington III434a9432022-11-04 18:38:46 -0700287 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530288}
289
Patrick Williams6aef7692021-05-01 06:39:41 -0500290ObjectPath EthernetInterface::neighbor(std::string ipAddress,
291 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800292{
William A. Kennington III434a9432022-11-04 18:38:46 -0700293 InAddrAny addr;
294 try
William A. Kennington III08505792019-01-30 16:00:04 -0800295 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700296 addr = ToAddr<InAddrAny>{}(ipAddress);
297 }
298 catch (const std::exception& e)
299 {
300 auto msg =
301 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
302 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500303 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
304 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800305 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700306
307 ether_addr lladdr;
308 try
William A. Kennington III08505792019-01-30 16:00:04 -0800309 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700310 lladdr = ToAddr<ether_addr>{}(macAddress);
311 }
312 catch (const std::exception& e)
313 {
314 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
315 e.what());
316 log<level::ERR>(msg.c_str(),
317 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500318 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
319 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800320 }
321
William A. Kennington III434a9432022-11-04 18:38:46 -0700322 auto [it, _] = staticNeighbors.emplace(
323 addr,
324 std::make_unique<Neighbor>(bus, std::string_view(objPath), *this, addr,
325 lladdr, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700326
327 writeConfigurationFile();
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800328 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700329
William A. Kennington III434a9432022-11-04 18:38:46 -0700330 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800331}
332
Patrick Williams6aef7692021-05-01 06:39:41 -0500333bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700334{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700335 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700336 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700337 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800338 manager.reloadConfigsNoRefresh();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700339 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700340 return value;
341}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700342
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700343bool EthernetInterface::dhcp4(bool value)
344{
345 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
346 {
347 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800348 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700349 }
350 return value;
351}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700352
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700353bool EthernetInterface::dhcp6(bool value)
354{
355 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
356 {
357 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800358 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700359 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700360 return value;
361}
362
Patrick Williams6aef7692021-05-01 06:39:41 -0500363EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530364{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700365 auto old4 = EthernetInterfaceIntf::dhcp4();
366 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
367 value == DHCPConf::v4v6stateless ||
368 value == DHCPConf::both);
369 auto old6 = EthernetInterfaceIntf::dhcp6();
370 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
371 value == DHCPConf::both);
372 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
373 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
374 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
375 value == DHCPConf::v6 || value == DHCPConf::both);
376
377 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530378 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700379 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800380 manager.reloadConfigsNoRefresh();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530381 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530382 return value;
383}
384
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700385EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
386{
387 if (dhcp6())
388 {
389 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
390 }
391 else if (dhcp4())
392 {
393 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
394 }
395 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
396}
397
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800398bool EthernetInterface::linkUp() const
399{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700400 if (ifIdx == 0)
401 {
402 return EthernetInterfaceIntf::linkUp();
403 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700404 return system::intfIsRunning(interfaceName());
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700405}
406
Tejas Patil2c0fc562021-08-03 19:13:46 +0530407size_t EthernetInterface::mtu() const
408{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700409 if (ifIdx == 0)
410 {
411 return EthernetInterfaceIntf::mtu();
412 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700413 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700414 return ignoreError("GetMTU", ifname, std::nullopt,
William A. Kennington III2e09d272022-10-14 17:15:00 -0700415 [&] { return system::getMTU(ifname); })
416 .value_or(EthernetInterfaceIntf::mtu());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530417}
418
419size_t EthernetInterface::mtu(size_t value)
420{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700421 const size_t old = EthernetInterfaceIntf::mtu();
422 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530423 {
424 return value;
425 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700426 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700427 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700428 system::setMTU(ifname, value);
429 return value;
430 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530431}
432
Patrick Williams6aef7692021-05-01 06:39:41 -0500433bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700434{
Patrick Williams6aef7692021-05-01 06:39:41 -0500435 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700436 {
437 return value;
438 }
439
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800440 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700441 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800442 if (!value)
443 {
444 // We only need to bring down the interface, networkd will always bring
445 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700446 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700447 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800448 }
William A. Kennington III4ca36012022-11-14 17:43:43 -0800449 manager.reloadConfigsNoRefresh();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800450
451 return value;
452}
453
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530454ServerList EthernetInterface::staticNameServers(ServerList value)
455{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700456 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530457 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700458 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530459 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700460 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
461 }
462 catch (const std::exception& e)
463 {
464 auto msg =
465 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
466 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
467 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
468 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530469 }
470 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530471 try
472 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530473 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700474
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530475 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800476 manager.reloadConfigsNoRefresh();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530477 }
Patrick Williams5758db32021-10-06 12:29:22 -0500478 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530479 {
480 log<level::ERR>("Exception processing DNS entries");
481 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530482 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530483}
484
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600485void EthernetInterface::loadNTPServers(const config::Parser& config)
486{
487 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
488 EthernetInterfaceIntf::staticNTPServers(
489 config.map.getValueStrings("Network", "NTP"));
490}
491
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700492void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530493{
494 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700495 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700496 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530497}
498
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600499ServerList EthernetInterface::getNTPServerFromTimeSyncd()
500{
501 ServerList servers; // Variable to capture the NTP Server IPs
502 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
503 PROPERTY_INTERFACE, METHOD_GET);
504
505 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
506
507 try
508 {
509 auto reply = bus.call(method);
510 std::variant<ServerList> response;
511 reply.read(response);
512 servers = std::get<ServerList>(response);
513 }
514 catch (const sdbusplus::exception::SdBusError& e)
515 {
516 log<level::ERR>(
517 "Failed to get NTP server information from Systemd-Timesyncd");
518 }
519
520 return servers;
521}
522
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530523ServerList EthernetInterface::getNameServerFromResolvd()
524{
525 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700526 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530527
528 /*
529 The DNS property under org.freedesktop.resolve1.Link interface contains
530 an array containing all DNS servers currently used by resolved. It
531 contains similar information as the DNS server data written to
532 /run/systemd/resolve/resolv.conf.
533
534 Each structure in the array consists of a numeric network interface index,
535 an address family, and a byte array containing the DNS server address
536 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
537 The array contains DNS servers configured system-wide, including those
538 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
539 /etc/systemd/resolved.conf, as well as per-interface DNS server
540 information either retrieved from systemd-networkd or configured by
541 external software via SetLinkDNS().
542 */
543
544 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
545 std::variant<type> name; // Variable to capture the DNS property
546 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
547 PROPERTY_INTERFACE, METHOD_GET);
548
549 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530550
551 try
552 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500553 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530554 reply.read(name);
555 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500556 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530557 {
558 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
559 }
560 auto tupleVector = std::get_if<type>(&name);
561 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
562 {
Alexander Filippov983da552021-02-08 15:26:54 +0300563 int addressFamily = std::get<0>(*i);
564 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700565 servers.push_back(std::to_string(
566 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530567 }
568 return servers;
569}
570
William A. Kennington IIId298f932022-10-17 14:31:38 -0700571ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530572{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700573 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
574 auto idStr = std::to_string(id);
575 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800576 {
577 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700578 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
579 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800580 }
581
William A. Kennington IIId298f932022-10-17 14:31:38 -0700582 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700583 auto macStr = MacAddressIntf::macAddress();
584 std::optional<ether_addr> mac;
585 if (!macStr.empty())
586 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700587 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700588 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800589 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700590 .idx = 0, // TODO: Query the correct value after creation
591 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700592 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700593 .mac = std::move(mac),
594 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700595 .parent_idx = ifIdx,
596 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700597 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530598
Patrick Williams6aef7692021-05-01 06:39:41 -0500599 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530600 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700601 auto vlanIntf = std::make_unique<EthernetInterface>(
602 bus, manager, info, objRoot, config::Parser(), /*emit=*/true,
William A. Kennington IIId298f932022-10-17 14:31:38 -0700603 nicEnabled());
604 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530605
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700606 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530607
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700608 // write the device file for the vlan interface.
609 config::Parser config;
610 auto& netdev = config.map["NetDev"].emplace_back();
611 netdev["Name"].emplace_back(intfName);
612 netdev["Kind"].emplace_back("vlan");
613 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
614 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700615
616 writeConfigurationFile();
William A. Kennington III4ca36012022-11-14 17:43:43 -0800617 manager.reloadConfigsNoRefresh();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700618
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800619 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530620}
Ratan Gupta2b106532017-07-25 16:05:02 +0530621
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600622ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530623{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600624 try
625 {
626 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530627
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600628 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800629 manager.reloadConfigsNoRefresh();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600630 }
631 catch (InternalFailure& e)
632 {
633 log<level::ERR>("Exception processing NTP entries");
634 }
635 return EthernetInterfaceIntf::staticNTPServers();
636}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700637
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600638ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
639{
640 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530641}
Ratan Gupta2b106532017-07-25 16:05:02 +0530642// Need to merge the below function with the code which writes the
643// config file during factory reset.
644// TODO openbmc/openbmc#1751
645
646void EthernetInterface::writeConfigurationFile()
647{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 config::Parser config;
649 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530650 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700651 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800652#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700653 auto mac = MacAddressIntf::macAddress();
654 if (!mac.empty())
655 {
656 link["MACAddress"].emplace_back(mac);
657 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800658#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700659 if (!EthernetInterfaceIntf::nicEnabled())
660 {
661 link["Unmanaged"].emplace_back("yes");
662 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700663 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700664 {
665 auto& network = config.map["Network"].emplace_back();
666 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400667#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700668 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400669#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700670 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400671#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700672 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
673 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
674 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600675 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700676 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700677 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700678 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700679 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
680 {
681 vlans.emplace_back(intf->interfaceName());
682 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700683 }
684 }
685 {
686 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600687 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700688 {
689 ntps.emplace_back(ntp);
690 }
691 }
692 {
693 auto& dnss = network["DNS"];
694 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
695 {
696 dnss.emplace_back(dns);
697 }
698 }
699 {
700 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700701 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700702 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700703 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700704 {
705 address.emplace_back(
706 fmt::format("{}/{}", addr.second->address(),
707 addr.second->prefixLength()));
708 }
709 }
710 }
711 {
712 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700713 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700714 {
715 auto gateway = EthernetInterfaceIntf::defaultGateway();
716 if (!gateway.empty())
717 {
718 gateways.emplace_back(gateway);
719 }
720 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530721
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700722 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700723 {
724 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
725 if (!gateway6.empty())
726 {
727 gateways.emplace_back(gateway6);
728 }
729 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600730 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800731 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700732 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700733 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500734 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700735 auto& neighbors = config.map["Neighbor"];
736 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800737 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700738 auto& neighbor = neighbors.emplace_back();
739 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
740 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800741 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500742 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500743 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700744 auto& dhcp = config.map["DHCP"].emplace_back();
745 dhcp["ClientIdentifier"].emplace_back("mac");
746 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +0800747 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700748 const auto& conf = *manager.getDHCPConf();
749 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
750 dhcp["UseDNS"].emplace_back(dns_enabled);
751 dhcp["UseDomains"].emplace_back(dns_enabled);
752 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
753 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
754 : "false");
755 dhcp["SendHostname"].emplace_back(
756 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +0800757 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500758 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700759 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
760 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700761 auto msg = fmt::format("Wrote networkd file: {}", path.native());
762 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530763}
764
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800765std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530766{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700767 if (vlan)
768 {
769 log<level::ERR>("Tried to set MAC address on VLAN");
770 elog<InternalFailure>();
771 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800772#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600773 ether_addr newMAC;
774 try
775 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700776 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600777 }
Patrick Williams5758db32021-10-06 12:29:22 -0500778 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600779 {
780 log<level::ERR>("MACAddress is not valid.",
781 entry("MAC=%s", value.c_str()));
782 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
783 Argument::ARGUMENT_VALUE(value.c_str()));
784 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700785 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530786 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500787 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500788 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500789 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
790 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530791 }
792
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300793 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700794 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300795
William A. Kennington III1137a972019-04-20 20:49:58 -0700796 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700797 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700798 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530799 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700800 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700801 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530802 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700803 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
804 {
805 intf->MacAddressIntf::macAddress(validMAC);
806 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530807 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500808 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530809
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700810 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800811 manager.addReloadPreHook([interface]() {
812 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700813 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800814 });
William A. Kennington III4ca36012022-11-14 17:43:43 -0800815 manager.reloadConfigsNoRefresh();
Ratan Gupta677ae122017-09-18 16:28:50 +0530816 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700817
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300818#ifdef HAVE_UBOOT_ENV
819 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700820 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300821 if (envVar)
822 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500823 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
824 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
825 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
826 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300827 }
828#endif // HAVE_UBOOT_ENV
829
William A. Kennington III1137a972019-04-20 20:49:58 -0700830 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800831#else
832 elog<NotAllowed>(
833 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
834#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530835}
836
Ratan Guptae9c9b812017-09-22 17:15:37 +0530837void EthernetInterface::deleteAll()
838{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530839 // clear all the ip on the interface
840 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700841
842 writeConfigurationFile();
William A. Kennington III4ca36012022-11-14 17:43:43 -0800843 manager.reloadConfigsNoRefresh();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530844}
845
Ravi Tejaa5a09442020-07-17 00:57:33 -0500846std::string EthernetInterface::defaultGateway(std::string gateway)
847{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700848 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500849 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700850 if (!gateway.empty())
851 {
852 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
853 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500854 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700855 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500856 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700857 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
858 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500859 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
860 Argument::ARGUMENT_VALUE(gateway.c_str()));
861 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700862
863 if (EthernetInterfaceIntf::defaultGateway() == gateway)
864 {
865 return gateway;
866 }
867 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700868
869 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700870 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700871
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700872 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500873}
874
875std::string EthernetInterface::defaultGateway6(std::string gateway)
876{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700877 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500878 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700879 if (!gateway.empty())
880 {
881 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
882 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500883 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700884 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500885 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700886 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
887 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500888 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
889 Argument::ARGUMENT_VALUE(gateway.c_str()));
890 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700891
892 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
893 {
894 return gateway;
895 }
896 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700897
898 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700899 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700900
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700901 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500902}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700903
904EthernetInterface::VlanProperties::VlanProperties(
905 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III454a0de2022-11-12 01:01:04 -0800906 const InterfaceInfo& info, EthernetInterface& eth, bool emitSignal) :
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700907 VlanIfaces(bus, objPath.c_str(),
908 emitSignal ? VlanIfaces::action::defer_emit
909 : VlanIfaces::action::emit_no_signals),
910 parentIdx(*info.parent_idx), eth(eth)
911{
912 VlanIntf::id(*info.vlan_id);
913 if (emitSignal)
914 {
915 this->emit_object_added();
916 }
917}
918
919void EthernetInterface::VlanProperties::delete_()
920{
921 auto intf = eth.interfaceName();
922
923 // Remove all configs for the current interface
924 const auto& confDir = eth.manager.getConfDir();
925 std::error_code ec;
926 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
927 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
928
929 // Write an updated parent interface since it has a VLAN entry
930 for (const auto& [_, intf] : eth.manager.interfaces)
931 {
932 if (intf->ifIdx == parentIdx)
933 {
934 intf->writeConfigurationFile();
935 }
936 }
937
938 // We need to forcibly delete the interface as systemd does not
939 deleteInterface(intf);
940
William A. Kennington III67b09da2022-10-31 14:09:53 -0700941 if (eth.ifIdx > 0)
942 {
943 eth.manager.interfacesByIdx.erase(eth.ifIdx);
944 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700945 eth.manager.interfaces.erase(intf);
946}
947
Gunnar Mills57d9c502018-09-14 14:42:34 -0500948} // namespace network
949} // namespace phosphor