blob: 0408219bd75bd8ddb553bea454d2e4e8575adbdf [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/if_addr.h>
13#include <linux/neighbour.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070014#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070015#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053016
Ratan Gupta82549cc2017-04-21 08:45:23 +053017#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053018#include <filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070019#include <phosphor-logging/elog-errors.hpp>
20#include <phosphor-logging/log.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070021#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070022#include <stdplus/zstring.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053023#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070024#include <unordered_map>
25#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070026#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053027
Ratan Gupta91a99cc2017-04-14 16:32:09 +053028namespace phosphor
29{
30namespace network
31{
32
33using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053034using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053035using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
36using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050037using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070038using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053039constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
40constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
41constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
42constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060043
44constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
45constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
46constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
47
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053048constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053049
William A. Kennington III2e09d272022-10-14 17:15:00 -070050template <typename Func>
51inline decltype(std::declval<Func>()())
52 ignoreError(std::string_view msg, stdplus::zstring_view intf,
53 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080054{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070055 try
56 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070057 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070058 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070059 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070060 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070061 auto err = fmt::format("{} failed on {}: {}", msg, intf, e.what());
62 log<level::ERR>(err.c_str(), entry("INTERFACE=%s", intf.c_str()));
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070063 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070064 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070065}
William A. Kennington IIId298f932022-10-17 14:31:38 -070066
William A. Kennington IIId298f932022-10-17 14:31:38 -070067static std::string makeObjPath(std::string_view root, std::string_view intf)
68{
69 auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
70 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
71 return ret;
72}
73
74EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080075 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070076 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070077 const config::Parser& config,
William A. Kennington III80d29012022-11-12 02:31:40 -080078 bool emitSignal, bool enabled) :
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070079 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.name),
William A. Kennington IIId298f932022-10-17 14:31:38 -070080 config, emitSignal, enabled)
81{
82}
83
84EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080085 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070086 std::string&& objPath,
87 const config::Parser& config,
William A. Kennington III80d29012022-11-12 02:31:40 -080088 bool emitSignal, bool enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050089 Ifaces(bus, objPath.c_str(),
90 emitSignal ? Ifaces::action::defer_emit
91 : Ifaces::action::emit_no_signals),
William A. Kennington III59e5b912022-11-02 02:49:46 -070092 manager(manager), bus(bus), objPath(std::move(objPath)), ifIdx(info.idx)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053093{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070094 interfaceName(*info.name);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070095 auto dhcpVal = getDHCPValue(config);
96 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
97 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070098 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III80d29012022-11-12 02:31:40 -080099 EthernetInterfaceIntf::nicEnabled(enabled);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500100 {
William A. Kennington III2bd35d62022-10-26 19:20:29 -0700101 const auto& gws = manager.getRouteTable().getDefaultGateway();
102 auto it = gws.find(ifIdx);
103 if (it != gws.end())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500104 {
William A. Kennington III2bd35d62022-10-26 19:20:29 -0700105 EthernetInterfaceIntf::defaultGateway(std::to_string(it->second));
106 }
107 }
108 {
109 const auto& gws = manager.getRouteTable().getDefaultGateway6();
110 auto it = gws.find(ifIdx);
111 if (it != gws.end())
112 {
113 EthernetInterfaceIntf::defaultGateway6(std::to_string(it->second));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500114 }
115 }
116
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700117 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700118 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530119
William A. Kennington III3e471c52022-10-27 19:46:07 -0700120 if (ifIdx > 0)
121 {
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700122 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
123 return system::getEthInfo(*info.name);
William A. Kennington III3e471c52022-10-27 19:46:07 -0700124 });
125 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg);
126 EthernetInterfaceIntf::speed(ethInfo.speed);
127 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530128
William A. Kennington IIId298f932022-10-17 14:31:38 -0700129 updateInfo(info);
130
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700131 if (info.vlan_id)
132 {
133 if (!info.parent_idx)
134 {
135 std::runtime_error("Missing parent link");
136 }
137 vlan.emplace(bus, this->objPath.c_str(), info, *this, emitSignal);
138 }
139
Ratan Gupta29b0e432017-05-25 12:51:40 +0530140 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530141 if (emitSignal)
142 {
143 this->emit_object_added();
144 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530145}
146
William A. Kennington III454a0de2022-11-12 01:01:04 -0800147void EthernetInterface::updateInfo(const InterfaceInfo& info)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700148{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700149 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700150 if (info.mac)
151 {
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700152 MacAddressIntf::macAddress(std::to_string(*info.mac));
William A. Kennington IIId298f932022-10-17 14:31:38 -0700153 }
154 if (info.mtu)
155 {
156 EthernetInterfaceIntf::mtu(*info.mtu);
157 }
158}
159
Johnathan Mantey817012a2020-01-30 15:07:39 -0800160bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
161{
162 return (
163#ifdef LINK_LOCAL_AUTOCONFIGURATION
164 (origin == IP::AddressOrigin::Static)
165#else
166 (origin == IP::AddressOrigin::Static ||
167 origin == IP::AddressOrigin::LinkLocal)
168#endif
169
170 );
171}
172
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800173void EthernetInterface::addAddr(const AddressInfo& info)
174{
175 if (info.flags & IFA_F_DEPRECATED)
176 {
177 return;
178 }
179 IP::AddressOrigin origin = IP::AddressOrigin::Static;
180 if (dhcpIsEnabled(info.ifaddr.getAddr()))
181 {
182 origin = IP::AddressOrigin::DHCP;
183 }
184#ifdef LINK_LOCAL_AUTOCONFIGURATION
185 if (info.scope == RT_SCOPE_LINK)
186 {
187 origin = IP::AddressOrigin::LinkLocal;
188 }
189#endif
190
William A. Kennington III77747f62022-11-07 23:11:15 -0800191 auto it = addrs.find(info.ifaddr);
192 if (it == addrs.end())
193 {
194 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
195 bus, std::string_view(objPath), *this,
196 info.ifaddr, origin));
197 }
198 else
199 {
200 it->second->IPIfaces::origin(origin);
201 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800202}
203
Ratan Gupta87c13982017-06-15 09:27:27 +0530204void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530205{
Ratan Gupta87c13982017-06-15 09:27:27 +0530206 addrs.clear();
William A. Kennington III6a923632022-11-06 18:17:33 -0800207 for (const auto& addr : system::getAddresses({.ifidx = ifIdx}))
Ratan Gupta82549cc2017-04-21 08:45:23 +0530208 {
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800209 addAddr(addr);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530210 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530211}
212
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800213void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
214{
215 if ((info.state & NUD_PERMANENT) == 0)
216 {
217 return;
218 }
William A. Kennington IIId3615142022-11-12 01:28:33 -0800219 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800220 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800221 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800222 log<level::ERR>(msg.c_str());
223 return;
224 }
225 staticNeighbors.emplace(
William A. Kennington IIId3615142022-11-12 01:28:33 -0800226 *info.addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
227 *this, *info.addr, *info.mac,
228 Neighbor::State::Permanent));
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800229}
230
William A. Kennington III08505792019-01-30 16:00:04 -0800231void EthernetInterface::createStaticNeighborObjects()
232{
233 staticNeighbors.clear();
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800234 for (const auto& neighbor : system::getNeighbors({.ifidx = ifIdx}))
William A. Kennington III08505792019-01-30 16:00:04 -0800235 {
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800236 addStaticNeigh(neighbor);
William A. Kennington III08505792019-01-30 16:00:04 -0800237 }
238}
239
Patrick Williams6aef7692021-05-01 06:39:41 -0500240ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700241 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530242{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700243 InAddrAny addr;
244 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530245 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700246 switch (protType)
247 {
248 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700249 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700250 break;
251 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700252 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700253 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700254 default:
255 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700256 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500257 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700258 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500259 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700260 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
261 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500262 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
263 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
264 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700265 IfAddr ifaddr;
266 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500267 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700268 ifaddr = {addr, prefixLength};
269 }
270 catch (const std::exception& e)
271 {
272 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
273 e.what());
274 log<level::ERR>(msg.c_str(),
275 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500276 elog<InvalidArgument>(
277 Argument::ARGUMENT_NAME("prefixLength"),
278 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530279 }
280
William A. Kennington III434a9432022-11-04 18:38:46 -0700281 auto [it, _] = this->addrs.insert_or_assign(
282 ifaddr,
William A. Kennington III59e5b912022-11-02 02:49:46 -0700283 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III434a9432022-11-04 18:38:46 -0700284 ifaddr, IP::AddressOrigin::Static));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530285
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700286 writeConfigurationFile();
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800287 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700288
William A. Kennington III434a9432022-11-04 18:38:46 -0700289 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530290}
291
Patrick Williams6aef7692021-05-01 06:39:41 -0500292ObjectPath EthernetInterface::neighbor(std::string ipAddress,
293 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800294{
William A. Kennington III434a9432022-11-04 18:38:46 -0700295 InAddrAny addr;
296 try
William A. Kennington III08505792019-01-30 16:00:04 -0800297 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700298 addr = ToAddr<InAddrAny>{}(ipAddress);
299 }
300 catch (const std::exception& e)
301 {
302 auto msg =
303 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
304 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500305 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
306 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800307 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700308
309 ether_addr lladdr;
310 try
William A. Kennington III08505792019-01-30 16:00:04 -0800311 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700312 lladdr = ToAddr<ether_addr>{}(macAddress);
313 }
314 catch (const std::exception& e)
315 {
316 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
317 e.what());
318 log<level::ERR>(msg.c_str(),
319 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500320 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
321 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800322 }
323
William A. Kennington III434a9432022-11-04 18:38:46 -0700324 auto [it, _] = staticNeighbors.emplace(
325 addr,
326 std::make_unique<Neighbor>(bus, std::string_view(objPath), *this, addr,
327 lladdr, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700328
329 writeConfigurationFile();
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800330 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700331
William A. Kennington III434a9432022-11-04 18:38:46 -0700332 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800333}
334
Patrick Williams6aef7692021-05-01 06:39:41 -0500335bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700336{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700337 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700338 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700339 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800340 manager.reloadConfigsNoRefresh();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700341 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700342 return value;
343}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700344
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700345bool EthernetInterface::dhcp4(bool value)
346{
347 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
348 {
349 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800350 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700351 }
352 return value;
353}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700354
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700355bool EthernetInterface::dhcp6(bool value)
356{
357 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
358 {
359 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800360 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700361 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700362 return value;
363}
364
Patrick Williams6aef7692021-05-01 06:39:41 -0500365EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530366{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700367 auto old4 = EthernetInterfaceIntf::dhcp4();
368 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
369 value == DHCPConf::v4v6stateless ||
370 value == DHCPConf::both);
371 auto old6 = EthernetInterfaceIntf::dhcp6();
372 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
373 value == DHCPConf::both);
374 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
375 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
376 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
377 value == DHCPConf::v6 || value == DHCPConf::both);
378
379 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530380 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700381 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800382 manager.reloadConfigsNoRefresh();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530383 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530384 return value;
385}
386
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700387EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
388{
389 if (dhcp6())
390 {
391 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
392 }
393 else if (dhcp4())
394 {
395 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
396 }
397 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
398}
399
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800400bool EthernetInterface::linkUp() const
401{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700402 if (ifIdx == 0)
403 {
404 return EthernetInterfaceIntf::linkUp();
405 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700406 return system::intfIsRunning(interfaceName());
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700407}
408
Tejas Patil2c0fc562021-08-03 19:13:46 +0530409size_t EthernetInterface::mtu() const
410{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700411 if (ifIdx == 0)
412 {
413 return EthernetInterfaceIntf::mtu();
414 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700415 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700416 return ignoreError("GetMTU", ifname, std::nullopt,
William A. Kennington III2e09d272022-10-14 17:15:00 -0700417 [&] { return system::getMTU(ifname); })
418 .value_or(EthernetInterfaceIntf::mtu());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530419}
420
421size_t EthernetInterface::mtu(size_t value)
422{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700423 const size_t old = EthernetInterfaceIntf::mtu();
424 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530425 {
426 return value;
427 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700428 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700429 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700430 system::setMTU(ifname, value);
431 return value;
432 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530433}
434
Patrick Williams6aef7692021-05-01 06:39:41 -0500435bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700436{
Patrick Williams6aef7692021-05-01 06:39:41 -0500437 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700438 {
439 return value;
440 }
441
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800442 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700443 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800444 if (!value)
445 {
446 // We only need to bring down the interface, networkd will always bring
447 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700448 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700449 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800450 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700451 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800452
453 return value;
454}
455
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530456ServerList EthernetInterface::staticNameServers(ServerList value)
457{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700458 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530459 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700460 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530461 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700462 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
463 }
464 catch (const std::exception& e)
465 {
466 auto msg =
467 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
468 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
469 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
470 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530471 }
472 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530473 try
474 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530475 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700476
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530477 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800478 manager.reloadConfigsNoRefresh();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530479 }
Patrick Williams5758db32021-10-06 12:29:22 -0500480 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530481 {
482 log<level::ERR>("Exception processing DNS entries");
483 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530484 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530485}
486
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600487void EthernetInterface::loadNTPServers(const config::Parser& config)
488{
489 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
490 EthernetInterfaceIntf::staticNTPServers(
491 config.map.getValueStrings("Network", "NTP"));
492}
493
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700494void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530495{
496 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700497 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700498 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530499}
500
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600501ServerList EthernetInterface::getNTPServerFromTimeSyncd()
502{
503 ServerList servers; // Variable to capture the NTP Server IPs
504 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
505 PROPERTY_INTERFACE, METHOD_GET);
506
507 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
508
509 try
510 {
511 auto reply = bus.call(method);
512 std::variant<ServerList> response;
513 reply.read(response);
514 servers = std::get<ServerList>(response);
515 }
516 catch (const sdbusplus::exception::SdBusError& e)
517 {
518 log<level::ERR>(
519 "Failed to get NTP server information from Systemd-Timesyncd");
520 }
521
522 return servers;
523}
524
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530525ServerList EthernetInterface::getNameServerFromResolvd()
526{
527 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700528 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530529
530 /*
531 The DNS property under org.freedesktop.resolve1.Link interface contains
532 an array containing all DNS servers currently used by resolved. It
533 contains similar information as the DNS server data written to
534 /run/systemd/resolve/resolv.conf.
535
536 Each structure in the array consists of a numeric network interface index,
537 an address family, and a byte array containing the DNS server address
538 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
539 The array contains DNS servers configured system-wide, including those
540 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
541 /etc/systemd/resolved.conf, as well as per-interface DNS server
542 information either retrieved from systemd-networkd or configured by
543 external software via SetLinkDNS().
544 */
545
546 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
547 std::variant<type> name; // Variable to capture the DNS property
548 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
549 PROPERTY_INTERFACE, METHOD_GET);
550
551 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530552
553 try
554 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500555 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530556 reply.read(name);
557 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500558 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530559 {
560 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
561 }
562 auto tupleVector = std::get_if<type>(&name);
563 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
564 {
Alexander Filippov983da552021-02-08 15:26:54 +0300565 int addressFamily = std::get<0>(*i);
566 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700567 servers.push_back(std::to_string(
568 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530569 }
570 return servers;
571}
572
William A. Kennington IIId298f932022-10-17 14:31:38 -0700573ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530574{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700575 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
576 auto idStr = std::to_string(id);
577 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800578 {
579 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700580 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
581 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800582 }
583
William A. Kennington IIId298f932022-10-17 14:31:38 -0700584 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700585 auto macStr = MacAddressIntf::macAddress();
586 std::optional<ether_addr> mac;
587 if (!macStr.empty())
588 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700589 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700590 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800591 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700592 .idx = 0, // TODO: Query the correct value after creation
593 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700594 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700595 .mac = std::move(mac),
596 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700597 .parent_idx = ifIdx,
598 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700599 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530600
Patrick Williams6aef7692021-05-01 06:39:41 -0500601 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530602 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700603 auto vlanIntf = std::make_unique<EthernetInterface>(
604 bus, manager, info, objRoot, config::Parser(), /*emit=*/true,
William A. Kennington IIId298f932022-10-17 14:31:38 -0700605 nicEnabled());
606 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530607
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700608 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530609
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700610 // write the device file for the vlan interface.
611 config::Parser config;
612 auto& netdev = config.map["NetDev"].emplace_back();
613 netdev["Name"].emplace_back(intfName);
614 netdev["Kind"].emplace_back("vlan");
615 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
616 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700617
618 writeConfigurationFile();
619 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700620
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800621 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530622}
Ratan Gupta2b106532017-07-25 16:05:02 +0530623
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600624ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530625{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600626 try
627 {
628 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530629
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600630 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800631 manager.reloadConfigsNoRefresh();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600632 }
633 catch (InternalFailure& e)
634 {
635 log<level::ERR>("Exception processing NTP entries");
636 }
637 return EthernetInterfaceIntf::staticNTPServers();
638}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700639
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600640ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
641{
642 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530643}
Ratan Gupta2b106532017-07-25 16:05:02 +0530644// Need to merge the below function with the code which writes the
645// config file during factory reset.
646// TODO openbmc/openbmc#1751
647
648void EthernetInterface::writeConfigurationFile()
649{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700650 config::Parser config;
651 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530652 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700653 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800654#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700655 auto mac = MacAddressIntf::macAddress();
656 if (!mac.empty())
657 {
658 link["MACAddress"].emplace_back(mac);
659 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800660#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700661 if (!EthernetInterfaceIntf::nicEnabled())
662 {
663 link["Unmanaged"].emplace_back("yes");
664 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700665 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700666 {
667 auto& network = config.map["Network"].emplace_back();
668 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400669#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700670 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400671#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700672 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400673#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700674 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
675 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
676 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600677 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700678 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700679 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700680 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700681 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
682 {
683 vlans.emplace_back(intf->interfaceName());
684 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700685 }
686 }
687 {
688 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600689 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700690 {
691 ntps.emplace_back(ntp);
692 }
693 }
694 {
695 auto& dnss = network["DNS"];
696 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
697 {
698 dnss.emplace_back(dns);
699 }
700 }
701 {
702 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700703 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700704 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700705 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700706 {
707 address.emplace_back(
708 fmt::format("{}/{}", addr.second->address(),
709 addr.second->prefixLength()));
710 }
711 }
712 }
713 {
714 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700715 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 {
717 auto gateway = EthernetInterfaceIntf::defaultGateway();
718 if (!gateway.empty())
719 {
720 gateways.emplace_back(gateway);
721 }
722 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530723
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700724 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700725 {
726 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
727 if (!gateway6.empty())
728 {
729 gateways.emplace_back(gateway6);
730 }
731 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600732 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800733 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700734 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700735 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500736 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700737 auto& neighbors = config.map["Neighbor"];
738 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800739 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700740 auto& neighbor = neighbors.emplace_back();
741 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
742 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800743 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500744 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500745 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700746 auto& dhcp = config.map["DHCP"].emplace_back();
747 dhcp["ClientIdentifier"].emplace_back("mac");
748 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +0800749 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700750 const auto& conf = *manager.getDHCPConf();
751 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
752 dhcp["UseDNS"].emplace_back(dns_enabled);
753 dhcp["UseDomains"].emplace_back(dns_enabled);
754 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
755 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
756 : "false");
757 dhcp["SendHostname"].emplace_back(
758 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +0800759 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500760 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700761 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
762 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700763 auto msg = fmt::format("Wrote networkd file: {}", path.native());
764 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530765}
766
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800767std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530768{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700769 if (vlan)
770 {
771 log<level::ERR>("Tried to set MAC address on VLAN");
772 elog<InternalFailure>();
773 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800774#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600775 ether_addr newMAC;
776 try
777 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700778 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600779 }
Patrick Williams5758db32021-10-06 12:29:22 -0500780 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600781 {
782 log<level::ERR>("MACAddress is not valid.",
783 entry("MAC=%s", value.c_str()));
784 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
785 Argument::ARGUMENT_VALUE(value.c_str()));
786 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700787 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530788 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500789 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500790 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500791 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
792 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530793 }
794
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300795 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700796 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300797
William A. Kennington III1137a972019-04-20 20:49:58 -0700798 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700799 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700800 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530801 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700802 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700803 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530804 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700805 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
806 {
807 intf->MacAddressIntf::macAddress(validMAC);
808 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530809 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500810 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530811
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700812 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800813 manager.addReloadPreHook([interface]() {
814 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700815 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800816 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700817 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530818 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700819
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300820#ifdef HAVE_UBOOT_ENV
821 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700822 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300823 if (envVar)
824 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500825 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
826 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
827 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
828 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300829 }
830#endif // HAVE_UBOOT_ENV
831
William A. Kennington III1137a972019-04-20 20:49:58 -0700832 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800833#else
834 elog<NotAllowed>(
835 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
836#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530837}
838
Ratan Guptae9c9b812017-09-22 17:15:37 +0530839void EthernetInterface::deleteAll()
840{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530841 // clear all the ip on the interface
842 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700843
844 writeConfigurationFile();
845 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530846}
847
Ravi Tejaa5a09442020-07-17 00:57:33 -0500848std::string EthernetInterface::defaultGateway(std::string gateway)
849{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700850 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500851 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700852 if (!gateway.empty())
853 {
854 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
855 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500856 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700857 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500858 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700859 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
860 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500861 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
862 Argument::ARGUMENT_VALUE(gateway.c_str()));
863 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700864
865 if (EthernetInterfaceIntf::defaultGateway() == gateway)
866 {
867 return gateway;
868 }
869 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700870
871 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700872 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700873
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700874 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500875}
876
877std::string EthernetInterface::defaultGateway6(std::string gateway)
878{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700879 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500880 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700881 if (!gateway.empty())
882 {
883 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
884 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500885 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700886 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500887 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700888 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
889 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500890 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
891 Argument::ARGUMENT_VALUE(gateway.c_str()));
892 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700893
894 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
895 {
896 return gateway;
897 }
898 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700899
900 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700901 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700902
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700903 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500904}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700905
906EthernetInterface::VlanProperties::VlanProperties(
907 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III454a0de2022-11-12 01:01:04 -0800908 const InterfaceInfo& info, EthernetInterface& eth, bool emitSignal) :
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700909 VlanIfaces(bus, objPath.c_str(),
910 emitSignal ? VlanIfaces::action::defer_emit
911 : VlanIfaces::action::emit_no_signals),
912 parentIdx(*info.parent_idx), eth(eth)
913{
914 VlanIntf::id(*info.vlan_id);
915 if (emitSignal)
916 {
917 this->emit_object_added();
918 }
919}
920
921void EthernetInterface::VlanProperties::delete_()
922{
923 auto intf = eth.interfaceName();
924
925 // Remove all configs for the current interface
926 const auto& confDir = eth.manager.getConfDir();
927 std::error_code ec;
928 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
929 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
930
931 // Write an updated parent interface since it has a VLAN entry
932 for (const auto& [_, intf] : eth.manager.interfaces)
933 {
934 if (intf->ifIdx == parentIdx)
935 {
936 intf->writeConfigurationFile();
937 }
938 }
939
940 // We need to forcibly delete the interface as systemd does not
941 deleteInterface(intf);
942
William A. Kennington III67b09da2022-10-31 14:09:53 -0700943 if (eth.ifIdx > 0)
944 {
945 eth.manager.interfacesByIdx.erase(eth.ifIdx);
946 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700947 eth.manager.interfaces.erase(intf);
948}
949
Gunnar Mills57d9c502018-09-14 14:42:34 -0500950} // namespace network
951} // namespace phosphor