blob: 1abcad2bfaa5c7a601e134811cdb36ae9047a4a1 [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 IIIa429c9d2022-11-15 18:00:45 -0800244 auto it = addrs.find(ifaddr);
245 if (it == addrs.end())
246 {
247 it = std::get<0>(addrs.emplace(
248 ifaddr,
249 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
250 ifaddr, IP::AddressOrigin::Static)));
251 }
252 else
253 {
254 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
255 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530256
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700257 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800258 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700259
William A. Kennington III434a9432022-11-04 18:38:46 -0700260 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530261}
262
Patrick Williams6aef7692021-05-01 06:39:41 -0500263ObjectPath EthernetInterface::neighbor(std::string ipAddress,
264 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800265{
William A. Kennington III434a9432022-11-04 18:38:46 -0700266 InAddrAny addr;
267 try
William A. Kennington III08505792019-01-30 16:00:04 -0800268 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700269 addr = ToAddr<InAddrAny>{}(ipAddress);
270 }
271 catch (const std::exception& e)
272 {
273 auto msg =
274 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
275 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500276 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
277 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800278 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700279
280 ether_addr lladdr;
281 try
William A. Kennington III08505792019-01-30 16:00:04 -0800282 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700283 lladdr = ToAddr<ether_addr>{}(macAddress);
284 }
285 catch (const std::exception& e)
286 {
287 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
288 e.what());
289 log<level::ERR>(msg.c_str(),
290 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500291 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
292 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800293 }
294
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800295 auto it = staticNeighbors.find(addr);
296 if (it == staticNeighbors.end())
297 {
298 it = std::get<0>(staticNeighbors.emplace(
299 addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
300 *this, addr, lladdr,
301 Neighbor::State::Permanent)));
302 }
303 else
304 {
305 it->second->NeighborObj::macAddress(std::to_string(lladdr));
306 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700307
308 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800309 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700310
William A. Kennington III434a9432022-11-04 18:38:46 -0700311 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800312}
313
Patrick Williams6aef7692021-05-01 06:39:41 -0500314bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700315{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700316 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700317 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700318 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800319 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700320 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700321 return value;
322}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700323
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700324bool EthernetInterface::dhcp4(bool value)
325{
326 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
327 {
328 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800329 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700330 }
331 return value;
332}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700333
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700334bool EthernetInterface::dhcp6(bool value)
335{
336 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
337 {
338 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800339 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700340 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700341 return value;
342}
343
Patrick Williams6aef7692021-05-01 06:39:41 -0500344EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530345{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700346 auto old4 = EthernetInterfaceIntf::dhcp4();
347 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
348 value == DHCPConf::v4v6stateless ||
349 value == DHCPConf::both);
350 auto old6 = EthernetInterfaceIntf::dhcp6();
351 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
352 value == DHCPConf::both);
353 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
354 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
355 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
356 value == DHCPConf::v6 || value == DHCPConf::both);
357
358 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530359 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700360 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800361 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530362 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530363 return value;
364}
365
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700366EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
367{
368 if (dhcp6())
369 {
370 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
371 }
372 else if (dhcp4())
373 {
374 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
375 }
376 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
377}
378
Tejas Patil2c0fc562021-08-03 19:13:46 +0530379size_t EthernetInterface::mtu(size_t value)
380{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700381 const size_t old = EthernetInterfaceIntf::mtu();
382 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530383 {
384 return value;
385 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700386 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700387 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700388 system::setMTU(ifname, value);
389 return value;
390 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530391}
392
Patrick Williams6aef7692021-05-01 06:39:41 -0500393bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700394{
Patrick Williams6aef7692021-05-01 06:39:41 -0500395 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700396 {
397 return value;
398 }
399
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800400 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700401 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800402 if (!value)
403 {
404 // We only need to bring down the interface, networkd will always bring
405 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700406 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700407 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800408 }
William A. Kennington III5b179382022-11-15 15:23:26 -0800409 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800410
411 return value;
412}
413
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530414ServerList EthernetInterface::staticNameServers(ServerList value)
415{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700416 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530417 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700418 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530419 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700420 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
421 }
422 catch (const std::exception& e)
423 {
424 auto msg =
425 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
426 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
427 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
428 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530429 }
430 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530431 try
432 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530433 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700434
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530435 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800436 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530437 }
Patrick Williams5758db32021-10-06 12:29:22 -0500438 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530439 {
440 log<level::ERR>("Exception processing DNS entries");
441 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530442 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530443}
444
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600445void EthernetInterface::loadNTPServers(const config::Parser& config)
446{
447 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
448 EthernetInterfaceIntf::staticNTPServers(
449 config.map.getValueStrings("Network", "NTP"));
450}
451
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700452void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530453{
454 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700455 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700456 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530457}
458
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600459ServerList EthernetInterface::getNTPServerFromTimeSyncd()
460{
461 ServerList servers; // Variable to capture the NTP Server IPs
462 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
463 PROPERTY_INTERFACE, METHOD_GET);
464
465 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
466
467 try
468 {
469 auto reply = bus.call(method);
470 std::variant<ServerList> response;
471 reply.read(response);
472 servers = std::get<ServerList>(response);
473 }
474 catch (const sdbusplus::exception::SdBusError& e)
475 {
476 log<level::ERR>(
477 "Failed to get NTP server information from Systemd-Timesyncd");
478 }
479
480 return servers;
481}
482
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530483ServerList EthernetInterface::getNameServerFromResolvd()
484{
485 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700486 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530487
488 /*
489 The DNS property under org.freedesktop.resolve1.Link interface contains
490 an array containing all DNS servers currently used by resolved. It
491 contains similar information as the DNS server data written to
492 /run/systemd/resolve/resolv.conf.
493
494 Each structure in the array consists of a numeric network interface index,
495 an address family, and a byte array containing the DNS server address
496 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
497 The array contains DNS servers configured system-wide, including those
498 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
499 /etc/systemd/resolved.conf, as well as per-interface DNS server
500 information either retrieved from systemd-networkd or configured by
501 external software via SetLinkDNS().
502 */
503
504 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
505 std::variant<type> name; // Variable to capture the DNS property
506 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
507 PROPERTY_INTERFACE, METHOD_GET);
508
509 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530510
511 try
512 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500513 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530514 reply.read(name);
515 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500516 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530517 {
518 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
519 }
520 auto tupleVector = std::get_if<type>(&name);
521 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
522 {
Alexander Filippov983da552021-02-08 15:26:54 +0300523 int addressFamily = std::get<0>(*i);
524 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700525 servers.push_back(std::to_string(
526 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530527 }
528 return servers;
529}
530
William A. Kennington IIId298f932022-10-17 14:31:38 -0700531ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530532{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700533 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
534 auto idStr = std::to_string(id);
535 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800536 {
537 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700538 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
539 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800540 }
541
William A. Kennington IIId298f932022-10-17 14:31:38 -0700542 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700543 auto macStr = MacAddressIntf::macAddress();
544 std::optional<ether_addr> mac;
545 if (!macStr.empty())
546 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700547 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700548 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800549 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700550 .idx = 0, // TODO: Query the correct value after creation
551 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700552 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700553 .mac = std::move(mac),
554 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700555 .parent_idx = ifIdx,
556 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700557 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530558
Patrick Williams6aef7692021-05-01 06:39:41 -0500559 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530560 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700561 auto vlanIntf = std::make_unique<EthernetInterface>(
562 bus, manager, info, objRoot, config::Parser(), /*emit=*/true,
William A. Kennington IIId298f932022-10-17 14:31:38 -0700563 nicEnabled());
564 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530565
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700566 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530567
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700568 // write the device file for the vlan interface.
569 config::Parser config;
570 auto& netdev = config.map["NetDev"].emplace_back();
571 netdev["Name"].emplace_back(intfName);
572 netdev["Kind"].emplace_back("vlan");
573 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
574 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700575
576 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800577 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700578
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800579 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530580}
Ratan Gupta2b106532017-07-25 16:05:02 +0530581
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600582ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530583{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600584 try
585 {
586 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530587
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600588 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800589 manager.reloadConfigs();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600590 }
591 catch (InternalFailure& e)
592 {
593 log<level::ERR>("Exception processing NTP entries");
594 }
595 return EthernetInterfaceIntf::staticNTPServers();
596}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700597
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600598ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
599{
600 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530601}
Ratan Gupta2b106532017-07-25 16:05:02 +0530602// Need to merge the below function with the code which writes the
603// config file during factory reset.
604// TODO openbmc/openbmc#1751
605
606void EthernetInterface::writeConfigurationFile()
607{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700608 config::Parser config;
609 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530610 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700611 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800612#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700613 auto mac = MacAddressIntf::macAddress();
614 if (!mac.empty())
615 {
616 link["MACAddress"].emplace_back(mac);
617 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800618#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700619 if (!EthernetInterfaceIntf::nicEnabled())
620 {
621 link["Unmanaged"].emplace_back("yes");
622 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700623 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700624 {
625 auto& network = config.map["Network"].emplace_back();
626 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400627#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700628 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400629#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700630 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400631#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700632 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
633 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
634 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600635 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700636 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700637 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700638 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700639 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
640 {
641 vlans.emplace_back(intf->interfaceName());
642 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700643 }
644 }
645 {
646 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600647 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 {
649 ntps.emplace_back(ntp);
650 }
651 }
652 {
653 auto& dnss = network["DNS"];
654 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
655 {
656 dnss.emplace_back(dns);
657 }
658 }
659 {
660 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700661 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700662 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700663 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700664 {
665 address.emplace_back(
666 fmt::format("{}/{}", addr.second->address(),
667 addr.second->prefixLength()));
668 }
669 }
670 }
671 {
672 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700673 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700674 {
675 auto gateway = EthernetInterfaceIntf::defaultGateway();
676 if (!gateway.empty())
677 {
678 gateways.emplace_back(gateway);
679 }
680 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530681
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700682 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700683 {
684 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
685 if (!gateway6.empty())
686 {
687 gateways.emplace_back(gateway6);
688 }
689 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600690 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800691 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700692 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700693 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500694 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700695 auto& neighbors = config.map["Neighbor"];
696 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800697 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700698 auto& neighbor = neighbors.emplace_back();
699 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
700 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800701 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500702 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500703 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700704 auto& dhcp = config.map["DHCP"].emplace_back();
705 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III5b179382022-11-15 15:23:26 -0800706 const auto& conf = manager.getDHCPConf();
707 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
708 dhcp["UseDNS"].emplace_back(dns_enabled);
709 dhcp["UseDomains"].emplace_back(dns_enabled);
710 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
711 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
712 : "false");
713 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
714 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500715 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
717 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700718 auto msg = fmt::format("Wrote networkd file: {}", path.native());
719 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530720}
721
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800722std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530723{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700724 if (vlan)
725 {
726 log<level::ERR>("Tried to set MAC address on VLAN");
727 elog<InternalFailure>();
728 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800729#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600730 ether_addr newMAC;
731 try
732 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700733 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600734 }
Patrick Williams5758db32021-10-06 12:29:22 -0500735 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600736 {
737 log<level::ERR>("MACAddress is not valid.",
738 entry("MAC=%s", value.c_str()));
739 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
740 Argument::ARGUMENT_VALUE(value.c_str()));
741 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700742 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530743 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500744 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500745 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500746 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
747 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530748 }
749
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300750 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700751 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300752
William A. Kennington III1137a972019-04-20 20:49:58 -0700753 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700754 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700755 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530756 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700757 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700758 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530759 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700760 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
761 {
762 intf->MacAddressIntf::macAddress(validMAC);
763 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530764 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500765 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530766
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700767 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800768 manager.addReloadPreHook([interface]() {
769 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700770 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800771 });
William A. Kennington III5b179382022-11-15 15:23:26 -0800772 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530773 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700774
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300775#ifdef HAVE_UBOOT_ENV
776 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700777 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300778 if (envVar)
779 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500780 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
781 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
782 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
783 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300784 }
785#endif // HAVE_UBOOT_ENV
786
William A. Kennington III1137a972019-04-20 20:49:58 -0700787 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800788#else
789 elog<NotAllowed>(
790 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
791#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530792}
793
Ratan Guptae9c9b812017-09-22 17:15:37 +0530794void EthernetInterface::deleteAll()
795{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530796 // clear all the ip on the interface
797 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700798
799 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800800 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530801}
802
Ravi Tejaa5a09442020-07-17 00:57:33 -0500803std::string EthernetInterface::defaultGateway(std::string gateway)
804{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700805 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500806 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700807 if (!gateway.empty())
808 {
809 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
810 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500811 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700812 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500813 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700814 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
815 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500816 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
817 Argument::ARGUMENT_VALUE(gateway.c_str()));
818 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700819
820 if (EthernetInterfaceIntf::defaultGateway() == gateway)
821 {
822 return gateway;
823 }
824 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700825
826 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800827 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700828
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700829 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500830}
831
832std::string EthernetInterface::defaultGateway6(std::string gateway)
833{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700834 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500835 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700836 if (!gateway.empty())
837 {
838 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
839 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500840 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700841 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500842 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700843 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
844 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500845 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
846 Argument::ARGUMENT_VALUE(gateway.c_str()));
847 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700848
849 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
850 {
851 return gateway;
852 }
853 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700854
855 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800856 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700857
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700858 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500859}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700860
861EthernetInterface::VlanProperties::VlanProperties(
862 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III454a0de2022-11-12 01:01:04 -0800863 const InterfaceInfo& info, EthernetInterface& eth, bool emitSignal) :
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700864 VlanIfaces(bus, objPath.c_str(),
865 emitSignal ? VlanIfaces::action::defer_emit
866 : VlanIfaces::action::emit_no_signals),
867 parentIdx(*info.parent_idx), eth(eth)
868{
869 VlanIntf::id(*info.vlan_id);
870 if (emitSignal)
871 {
872 this->emit_object_added();
873 }
874}
875
876void EthernetInterface::VlanProperties::delete_()
877{
878 auto intf = eth.interfaceName();
879
880 // Remove all configs for the current interface
881 const auto& confDir = eth.manager.getConfDir();
882 std::error_code ec;
883 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
884 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
885
886 // Write an updated parent interface since it has a VLAN entry
887 for (const auto& [_, intf] : eth.manager.interfaces)
888 {
889 if (intf->ifIdx == parentIdx)
890 {
891 intf->writeConfigurationFile();
892 }
893 }
894
895 // We need to forcibly delete the interface as systemd does not
896 deleteInterface(intf);
897
William A. Kennington III67b09da2022-10-31 14:09:53 -0700898 if (eth.ifIdx > 0)
899 {
900 eth.manager.interfacesByIdx.erase(eth.ifIdx);
901 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700902 eth.manager.interfaces.erase(intf);
903}
904
Gunnar Mills57d9c502018-09-14 14:42:34 -0500905} // namespace network
906} // namespace phosphor