blob: e836268395d8123bc80110d1d2487d0f9484d7a8 [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 IIIe21a5cf2022-08-09 12:19:14 -070099 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700100 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530101
William A. Kennington IIId298f932022-10-17 14:31:38 -0700102 updateInfo(info);
103
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700104 if (info.vlan_id)
105 {
106 if (!info.parent_idx)
107 {
108 std::runtime_error("Missing parent link");
109 }
110 vlan.emplace(bus, this->objPath.c_str(), info, *this, emitSignal);
111 }
112
Ratan Gupta29b0e432017-05-25 12:51:40 +0530113 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530114 if (emitSignal)
115 {
116 this->emit_object_added();
117 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530118}
119
William A. Kennington III454a0de2022-11-12 01:01:04 -0800120void EthernetInterface::updateInfo(const InterfaceInfo& info)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700121{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700122 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700123 if (info.mac)
124 {
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700125 MacAddressIntf::macAddress(std::to_string(*info.mac));
William A. Kennington IIId298f932022-10-17 14:31:38 -0700126 }
127 if (info.mtu)
128 {
129 EthernetInterfaceIntf::mtu(*info.mtu);
130 }
William A. Kennington III21539662022-11-15 14:53:11 -0800131 if (ifIdx > 0)
132 {
133 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
134 return system::getEthInfo(*info.name);
135 });
136 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg);
137 EthernetInterfaceIntf::speed(ethInfo.speed);
138 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700139}
140
Johnathan Mantey817012a2020-01-30 15:07:39 -0800141bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
142{
143 return (
144#ifdef LINK_LOCAL_AUTOCONFIGURATION
145 (origin == IP::AddressOrigin::Static)
146#else
147 (origin == IP::AddressOrigin::Static ||
148 origin == IP::AddressOrigin::LinkLocal)
149#endif
150
151 );
152}
153
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800154void EthernetInterface::addAddr(const AddressInfo& info)
155{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800156 IP::AddressOrigin origin = IP::AddressOrigin::Static;
157 if (dhcpIsEnabled(info.ifaddr.getAddr()))
158 {
159 origin = IP::AddressOrigin::DHCP;
160 }
161#ifdef LINK_LOCAL_AUTOCONFIGURATION
162 if (info.scope == RT_SCOPE_LINK)
163 {
164 origin = IP::AddressOrigin::LinkLocal;
165 }
166#endif
167
William A. Kennington III77747f62022-11-07 23:11:15 -0800168 auto it = addrs.find(info.ifaddr);
169 if (it == addrs.end())
170 {
171 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
172 bus, std::string_view(objPath), *this,
173 info.ifaddr, origin));
174 }
175 else
176 {
177 it->second->IPIfaces::origin(origin);
178 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800179}
180
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800181void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
182{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800183 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800184 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800185 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800186 log<level::ERR>(msg.c_str());
187 return;
188 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800189
190 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
191 {
192 it->second->NeighborObj::macAddress(std::to_string(*info.mac));
193 }
194 else
195 {
196 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
197 bus, std::string_view(objPath),
198 *this, *info.addr, *info.mac,
199 Neighbor::State::Permanent));
200 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800201}
202
Patrick Williams6aef7692021-05-01 06:39:41 -0500203ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700204 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530205{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700206 InAddrAny addr;
207 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530208 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700209 switch (protType)
210 {
211 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700212 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700213 break;
214 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700215 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700216 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700217 default:
218 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700219 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500220 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700221 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500222 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700223 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
224 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500225 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
226 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
227 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700228 IfAddr ifaddr;
229 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500230 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700231 ifaddr = {addr, prefixLength};
232 }
233 catch (const std::exception& e)
234 {
235 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
236 e.what());
237 log<level::ERR>(msg.c_str(),
238 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500239 elog<InvalidArgument>(
240 Argument::ARGUMENT_NAME("prefixLength"),
241 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530242 }
243
William A. Kennington III434a9432022-11-04 18:38:46 -0700244 auto [it, _] = this->addrs.insert_or_assign(
245 ifaddr,
William A. Kennington III59e5b912022-11-02 02:49:46 -0700246 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III434a9432022-11-04 18:38:46 -0700247 ifaddr, IP::AddressOrigin::Static));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530248
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700249 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800250 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700251
William A. Kennington III434a9432022-11-04 18:38:46 -0700252 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530253}
254
Patrick Williams6aef7692021-05-01 06:39:41 -0500255ObjectPath EthernetInterface::neighbor(std::string ipAddress,
256 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800257{
William A. Kennington III434a9432022-11-04 18:38:46 -0700258 InAddrAny addr;
259 try
William A. Kennington III08505792019-01-30 16:00:04 -0800260 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700261 addr = ToAddr<InAddrAny>{}(ipAddress);
262 }
263 catch (const std::exception& e)
264 {
265 auto msg =
266 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
267 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500268 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
269 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800270 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700271
272 ether_addr lladdr;
273 try
William A. Kennington III08505792019-01-30 16:00:04 -0800274 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700275 lladdr = ToAddr<ether_addr>{}(macAddress);
276 }
277 catch (const std::exception& e)
278 {
279 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
280 e.what());
281 log<level::ERR>(msg.c_str(),
282 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500283 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
284 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800285 }
286
William A. Kennington III434a9432022-11-04 18:38:46 -0700287 auto [it, _] = staticNeighbors.emplace(
288 addr,
289 std::make_unique<Neighbor>(bus, std::string_view(objPath), *this, addr,
290 lladdr, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700291
292 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800293 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700294
William A. Kennington III434a9432022-11-04 18:38:46 -0700295 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800296}
297
Patrick Williams6aef7692021-05-01 06:39:41 -0500298bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700299{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700300 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700301 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700302 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800303 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700304 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700305 return value;
306}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700307
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700308bool EthernetInterface::dhcp4(bool value)
309{
310 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
311 {
312 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800313 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700314 }
315 return value;
316}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700317
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700318bool EthernetInterface::dhcp6(bool value)
319{
320 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
321 {
322 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800323 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700324 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700325 return value;
326}
327
Patrick Williams6aef7692021-05-01 06:39:41 -0500328EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530329{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700330 auto old4 = EthernetInterfaceIntf::dhcp4();
331 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
332 value == DHCPConf::v4v6stateless ||
333 value == DHCPConf::both);
334 auto old6 = EthernetInterfaceIntf::dhcp6();
335 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
336 value == DHCPConf::both);
337 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
338 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
339 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
340 value == DHCPConf::v6 || value == DHCPConf::both);
341
342 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530343 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700344 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800345 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530346 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530347 return value;
348}
349
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700350EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
351{
352 if (dhcp6())
353 {
354 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
355 }
356 else if (dhcp4())
357 {
358 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
359 }
360 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
361}
362
Tejas Patil2c0fc562021-08-03 19:13:46 +0530363size_t EthernetInterface::mtu(size_t value)
364{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700365 const size_t old = EthernetInterfaceIntf::mtu();
366 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530367 {
368 return value;
369 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700370 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700371 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700372 system::setMTU(ifname, value);
373 return value;
374 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530375}
376
Patrick Williams6aef7692021-05-01 06:39:41 -0500377bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700378{
Patrick Williams6aef7692021-05-01 06:39:41 -0500379 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700380 {
381 return value;
382 }
383
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800384 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700385 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800386 if (!value)
387 {
388 // We only need to bring down the interface, networkd will always bring
389 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700390 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700391 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800392 }
William A. Kennington III5b179382022-11-15 15:23:26 -0800393 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800394
395 return value;
396}
397
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530398ServerList EthernetInterface::staticNameServers(ServerList value)
399{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700400 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530401 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700402 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530403 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700404 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
405 }
406 catch (const std::exception& e)
407 {
408 auto msg =
409 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
410 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
411 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
412 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530413 }
414 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530415 try
416 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530417 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700418
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530419 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800420 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530421 }
Patrick Williams5758db32021-10-06 12:29:22 -0500422 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530423 {
424 log<level::ERR>("Exception processing DNS entries");
425 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530426 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530427}
428
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600429void EthernetInterface::loadNTPServers(const config::Parser& config)
430{
431 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
432 EthernetInterfaceIntf::staticNTPServers(
433 config.map.getValueStrings("Network", "NTP"));
434}
435
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700436void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530437{
438 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700439 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700440 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530441}
442
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600443ServerList EthernetInterface::getNTPServerFromTimeSyncd()
444{
445 ServerList servers; // Variable to capture the NTP Server IPs
446 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
447 PROPERTY_INTERFACE, METHOD_GET);
448
449 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
450
451 try
452 {
453 auto reply = bus.call(method);
454 std::variant<ServerList> response;
455 reply.read(response);
456 servers = std::get<ServerList>(response);
457 }
458 catch (const sdbusplus::exception::SdBusError& e)
459 {
460 log<level::ERR>(
461 "Failed to get NTP server information from Systemd-Timesyncd");
462 }
463
464 return servers;
465}
466
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530467ServerList EthernetInterface::getNameServerFromResolvd()
468{
469 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700470 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530471
472 /*
473 The DNS property under org.freedesktop.resolve1.Link interface contains
474 an array containing all DNS servers currently used by resolved. It
475 contains similar information as the DNS server data written to
476 /run/systemd/resolve/resolv.conf.
477
478 Each structure in the array consists of a numeric network interface index,
479 an address family, and a byte array containing the DNS server address
480 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
481 The array contains DNS servers configured system-wide, including those
482 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
483 /etc/systemd/resolved.conf, as well as per-interface DNS server
484 information either retrieved from systemd-networkd or configured by
485 external software via SetLinkDNS().
486 */
487
488 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
489 std::variant<type> name; // Variable to capture the DNS property
490 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
491 PROPERTY_INTERFACE, METHOD_GET);
492
493 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530494
495 try
496 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500497 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530498 reply.read(name);
499 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500500 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530501 {
502 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
503 }
504 auto tupleVector = std::get_if<type>(&name);
505 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
506 {
Alexander Filippov983da552021-02-08 15:26:54 +0300507 int addressFamily = std::get<0>(*i);
508 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700509 servers.push_back(std::to_string(
510 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530511 }
512 return servers;
513}
514
William A. Kennington IIId298f932022-10-17 14:31:38 -0700515ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530516{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700517 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
518 auto idStr = std::to_string(id);
519 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800520 {
521 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700522 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
523 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800524 }
525
William A. Kennington IIId298f932022-10-17 14:31:38 -0700526 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700527 auto macStr = MacAddressIntf::macAddress();
528 std::optional<ether_addr> mac;
529 if (!macStr.empty())
530 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700531 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700532 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800533 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700534 .idx = 0, // TODO: Query the correct value after creation
535 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700536 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700537 .mac = std::move(mac),
538 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700539 .parent_idx = ifIdx,
540 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700541 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530542
Patrick Williams6aef7692021-05-01 06:39:41 -0500543 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530544 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700545 auto vlanIntf = std::make_unique<EthernetInterface>(
546 bus, manager, info, objRoot, config::Parser(), /*emit=*/true,
William A. Kennington IIId298f932022-10-17 14:31:38 -0700547 nicEnabled());
548 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530549
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700550 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530551
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700552 // write the device file for the vlan interface.
553 config::Parser config;
554 auto& netdev = config.map["NetDev"].emplace_back();
555 netdev["Name"].emplace_back(intfName);
556 netdev["Kind"].emplace_back("vlan");
557 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
558 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700559
560 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800561 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700562
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800563 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530564}
Ratan Gupta2b106532017-07-25 16:05:02 +0530565
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600566ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530567{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600568 try
569 {
570 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530571
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600572 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800573 manager.reloadConfigs();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600574 }
575 catch (InternalFailure& e)
576 {
577 log<level::ERR>("Exception processing NTP entries");
578 }
579 return EthernetInterfaceIntf::staticNTPServers();
580}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700581
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600582ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
583{
584 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530585}
Ratan Gupta2b106532017-07-25 16:05:02 +0530586// Need to merge the below function with the code which writes the
587// config file during factory reset.
588// TODO openbmc/openbmc#1751
589
590void EthernetInterface::writeConfigurationFile()
591{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700592 config::Parser config;
593 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530594 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700595 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800596#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700597 auto mac = MacAddressIntf::macAddress();
598 if (!mac.empty())
599 {
600 link["MACAddress"].emplace_back(mac);
601 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800602#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700603 if (!EthernetInterfaceIntf::nicEnabled())
604 {
605 link["Unmanaged"].emplace_back("yes");
606 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700607 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700608 {
609 auto& network = config.map["Network"].emplace_back();
610 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400611#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700612 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400613#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700614 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400615#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700616 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
617 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
618 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600619 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700620 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700621 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700622 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700623 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
624 {
625 vlans.emplace_back(intf->interfaceName());
626 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700627 }
628 }
629 {
630 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600631 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700632 {
633 ntps.emplace_back(ntp);
634 }
635 }
636 {
637 auto& dnss = network["DNS"];
638 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
639 {
640 dnss.emplace_back(dns);
641 }
642 }
643 {
644 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700645 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700646 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700647 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 {
649 address.emplace_back(
650 fmt::format("{}/{}", addr.second->address(),
651 addr.second->prefixLength()));
652 }
653 }
654 }
655 {
656 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700657 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700658 {
659 auto gateway = EthernetInterfaceIntf::defaultGateway();
660 if (!gateway.empty())
661 {
662 gateways.emplace_back(gateway);
663 }
664 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530665
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700666 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700667 {
668 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
669 if (!gateway6.empty())
670 {
671 gateways.emplace_back(gateway6);
672 }
673 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600674 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800675 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700676 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700677 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500678 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700679 auto& neighbors = config.map["Neighbor"];
680 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800681 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700682 auto& neighbor = neighbors.emplace_back();
683 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
684 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800685 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500686 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500687 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700688 auto& dhcp = config.map["DHCP"].emplace_back();
689 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III5b179382022-11-15 15:23:26 -0800690 const auto& conf = manager.getDHCPConf();
691 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
692 dhcp["UseDNS"].emplace_back(dns_enabled);
693 dhcp["UseDomains"].emplace_back(dns_enabled);
694 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
695 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
696 : "false");
697 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
698 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500699 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700700 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
701 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700702 auto msg = fmt::format("Wrote networkd file: {}", path.native());
703 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530704}
705
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800706std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530707{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700708 if (vlan)
709 {
710 log<level::ERR>("Tried to set MAC address on VLAN");
711 elog<InternalFailure>();
712 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800713#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600714 ether_addr newMAC;
715 try
716 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700717 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600718 }
Patrick Williams5758db32021-10-06 12:29:22 -0500719 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600720 {
721 log<level::ERR>("MACAddress is not valid.",
722 entry("MAC=%s", value.c_str()));
723 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
724 Argument::ARGUMENT_VALUE(value.c_str()));
725 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700726 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530727 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500728 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500729 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500730 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
731 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530732 }
733
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300734 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700735 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300736
William A. Kennington III1137a972019-04-20 20:49:58 -0700737 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700738 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700739 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530740 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700741 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700742 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530743 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700744 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
745 {
746 intf->MacAddressIntf::macAddress(validMAC);
747 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530748 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500749 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530750
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700751 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800752 manager.addReloadPreHook([interface]() {
753 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700754 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800755 });
William A. Kennington III5b179382022-11-15 15:23:26 -0800756 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530757 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700758
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300759#ifdef HAVE_UBOOT_ENV
760 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700761 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300762 if (envVar)
763 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500764 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
765 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
766 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
767 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300768 }
769#endif // HAVE_UBOOT_ENV
770
William A. Kennington III1137a972019-04-20 20:49:58 -0700771 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800772#else
773 elog<NotAllowed>(
774 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
775#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530776}
777
Ratan Guptae9c9b812017-09-22 17:15:37 +0530778void EthernetInterface::deleteAll()
779{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530780 // clear all the ip on the interface
781 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700782
783 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800784 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530785}
786
Ravi Tejaa5a09442020-07-17 00:57:33 -0500787std::string EthernetInterface::defaultGateway(std::string gateway)
788{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700789 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500790 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700791 if (!gateway.empty())
792 {
793 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
794 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500795 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700796 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500797 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700798 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
799 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500800 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
801 Argument::ARGUMENT_VALUE(gateway.c_str()));
802 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700803
804 if (EthernetInterfaceIntf::defaultGateway() == gateway)
805 {
806 return gateway;
807 }
808 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700809
810 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800811 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700812
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700813 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500814}
815
816std::string EthernetInterface::defaultGateway6(std::string gateway)
817{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700818 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500819 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700820 if (!gateway.empty())
821 {
822 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
823 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500824 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700825 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500826 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700827 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
828 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500829 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
830 Argument::ARGUMENT_VALUE(gateway.c_str()));
831 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700832
833 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
834 {
835 return gateway;
836 }
837 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700838
839 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800840 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700841
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700842 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500843}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700844
845EthernetInterface::VlanProperties::VlanProperties(
846 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III454a0de2022-11-12 01:01:04 -0800847 const InterfaceInfo& info, EthernetInterface& eth, bool emitSignal) :
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700848 VlanIfaces(bus, objPath.c_str(),
849 emitSignal ? VlanIfaces::action::defer_emit
850 : VlanIfaces::action::emit_no_signals),
851 parentIdx(*info.parent_idx), eth(eth)
852{
853 VlanIntf::id(*info.vlan_id);
854 if (emitSignal)
855 {
856 this->emit_object_added();
857 }
858}
859
860void EthernetInterface::VlanProperties::delete_()
861{
862 auto intf = eth.interfaceName();
863
864 // Remove all configs for the current interface
865 const auto& confDir = eth.manager.getConfDir();
866 std::error_code ec;
867 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
868 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
869
870 // Write an updated parent interface since it has a VLAN entry
871 for (const auto& [_, intf] : eth.manager.interfaces)
872 {
873 if (intf->ifIdx == parentIdx)
874 {
875 intf->writeConfigurationFile();
876 }
877 }
878
879 // We need to forcibly delete the interface as systemd does not
880 deleteInterface(intf);
881
William A. Kennington III67b09da2022-10-31 14:09:53 -0700882 if (eth.ifIdx > 0)
883 {
884 eth.manager.interfacesByIdx.erase(eth.ifIdx);
885 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700886 eth.manager.interfaces.erase(intf);
887}
888
Gunnar Mills57d9c502018-09-14 14:42:34 -0500889} // namespace network
890} // namespace phosphor