blob: 2e42e7f8b56e1a3ebedc21de497813763a876e4b [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 III13d665c2022-11-15 20:34:40 -080073 const AllIntfInfo& 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 IIIb6452542022-11-15 18:09:12 -080076 bool enabled) :
William A. Kennington III13d665c2022-11-15 20:34:40 -080077 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.intf.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080078 config, enabled)
William A. Kennington IIId298f932022-10-17 14:31:38 -070079{
80}
81
82EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080083 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070084 std::string&& objPath,
85 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080086 bool enabled) :
87 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit),
William A. Kennington III876927c2022-11-17 16:20:15 -080088 manager(manager), bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +053089{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080090 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070091 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080092 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
93 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
94 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
95 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaa5a09442020-07-17 00:57:33 -050096
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -070097 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080098 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +053099
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800100 updateInfo(info.intf, true);
101
102 if (info.defgw4)
103 {
104 EthernetInterface::defaultGateway(std::to_string(*info.defgw4), true);
105 }
106 if (info.defgw6)
107 {
108 EthernetInterface::defaultGateway6(std::to_string(*info.defgw6), true);
109 }
110 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700111
William A. Kennington III13d665c2022-11-15 20:34:40 -0800112 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700113 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800114 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700115 {
116 std::runtime_error("Missing parent link");
117 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800118 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
119 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800120 for (const auto& [_, addr] : info.addrs)
121 {
122 addAddr(addr);
123 }
124 for (const auto& [_, neigh] : info.staticNeighs)
125 {
126 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700127 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530128}
129
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800130void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700131{
William A. Kennington III876927c2022-11-17 16:20:15 -0800132 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800133 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700134 if (info.mac)
135 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800136 MacAddressIntf::macAddress(std::to_string(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700137 }
138 if (info.mtu)
139 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800140 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700141 }
William A. Kennington III21539662022-11-15 14:53:11 -0800142 if (ifIdx > 0)
143 {
144 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
145 return system::getEthInfo(*info.name);
146 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800147 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
148 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800149 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700150}
151
Johnathan Mantey817012a2020-01-30 15:07:39 -0800152bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
153{
154 return (
155#ifdef LINK_LOCAL_AUTOCONFIGURATION
156 (origin == IP::AddressOrigin::Static)
157#else
158 (origin == IP::AddressOrigin::Static ||
159 origin == IP::AddressOrigin::LinkLocal)
160#endif
161
162 );
163}
164
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800165void EthernetInterface::addAddr(const AddressInfo& info)
166{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800167 IP::AddressOrigin origin = IP::AddressOrigin::Static;
168 if (dhcpIsEnabled(info.ifaddr.getAddr()))
169 {
170 origin = IP::AddressOrigin::DHCP;
171 }
172#ifdef LINK_LOCAL_AUTOCONFIGURATION
173 if (info.scope == RT_SCOPE_LINK)
174 {
175 origin = IP::AddressOrigin::LinkLocal;
176 }
177#endif
178
William A. Kennington III77747f62022-11-07 23:11:15 -0800179 auto it = addrs.find(info.ifaddr);
180 if (it == addrs.end())
181 {
182 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
183 bus, std::string_view(objPath), *this,
184 info.ifaddr, origin));
185 }
186 else
187 {
188 it->second->IPIfaces::origin(origin);
189 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800190}
191
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800192void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
193{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800194 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800195 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800196 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800197 log<level::ERR>(msg.c_str());
198 return;
199 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800200
201 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
202 {
203 it->second->NeighborObj::macAddress(std::to_string(*info.mac));
204 }
205 else
206 {
207 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
208 bus, std::string_view(objPath),
209 *this, *info.addr, *info.mac,
210 Neighbor::State::Permanent));
211 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800212}
213
Patrick Williams6aef7692021-05-01 06:39:41 -0500214ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700215 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530216{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700217 InAddrAny addr;
218 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530219 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700220 switch (protType)
221 {
222 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700223 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700224 break;
225 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700226 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700227 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700228 default:
229 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700230 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500231 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700232 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500233 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700234 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
235 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500236 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
237 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
238 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700239 IfAddr ifaddr;
240 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500241 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700242 ifaddr = {addr, prefixLength};
243 }
244 catch (const std::exception& e)
245 {
246 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
247 e.what());
248 log<level::ERR>(msg.c_str(),
249 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500250 elog<InvalidArgument>(
251 Argument::ARGUMENT_NAME("prefixLength"),
252 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530253 }
254
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800255 auto it = addrs.find(ifaddr);
256 if (it == addrs.end())
257 {
258 it = std::get<0>(addrs.emplace(
259 ifaddr,
260 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
261 ifaddr, IP::AddressOrigin::Static)));
262 }
263 else
264 {
265 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
266 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530267
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700268 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800269 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700270
William A. Kennington III434a9432022-11-04 18:38:46 -0700271 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530272}
273
Patrick Williams6aef7692021-05-01 06:39:41 -0500274ObjectPath EthernetInterface::neighbor(std::string ipAddress,
275 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800276{
William A. Kennington III434a9432022-11-04 18:38:46 -0700277 InAddrAny addr;
278 try
William A. Kennington III08505792019-01-30 16:00:04 -0800279 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700280 addr = ToAddr<InAddrAny>{}(ipAddress);
281 }
282 catch (const std::exception& e)
283 {
284 auto msg =
285 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
286 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500287 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
288 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800289 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700290
291 ether_addr lladdr;
292 try
William A. Kennington III08505792019-01-30 16:00:04 -0800293 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700294 lladdr = ToAddr<ether_addr>{}(macAddress);
295 }
296 catch (const std::exception& e)
297 {
298 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
299 e.what());
300 log<level::ERR>(msg.c_str(),
301 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500302 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
303 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800304 }
305
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800306 auto it = staticNeighbors.find(addr);
307 if (it == staticNeighbors.end())
308 {
309 it = std::get<0>(staticNeighbors.emplace(
310 addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
311 *this, addr, lladdr,
312 Neighbor::State::Permanent)));
313 }
314 else
315 {
316 it->second->NeighborObj::macAddress(std::to_string(lladdr));
317 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700318
319 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800320 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700321
William A. Kennington III434a9432022-11-04 18:38:46 -0700322 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800323}
324
Patrick Williams6aef7692021-05-01 06:39:41 -0500325bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700326{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700327 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700328 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700329 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800330 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700331 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700332 return value;
333}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700334
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700335bool EthernetInterface::dhcp4(bool value)
336{
337 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
338 {
339 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800340 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700341 }
342 return value;
343}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700344
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700345bool EthernetInterface::dhcp6(bool value)
346{
347 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
348 {
349 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800350 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700351 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700352 return value;
353}
354
Patrick Williams6aef7692021-05-01 06:39:41 -0500355EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530356{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700357 auto old4 = EthernetInterfaceIntf::dhcp4();
358 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
359 value == DHCPConf::v4v6stateless ||
360 value == DHCPConf::both);
361 auto old6 = EthernetInterfaceIntf::dhcp6();
362 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
363 value == DHCPConf::both);
364 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
365 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
366 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
367 value == DHCPConf::v6 || value == DHCPConf::both);
368
369 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530370 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700371 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800372 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530373 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530374 return value;
375}
376
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700377EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
378{
379 if (dhcp6())
380 {
381 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
382 }
383 else if (dhcp4())
384 {
385 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
386 }
387 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
388}
389
Tejas Patil2c0fc562021-08-03 19:13:46 +0530390size_t EthernetInterface::mtu(size_t value)
391{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700392 const size_t old = EthernetInterfaceIntf::mtu();
393 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530394 {
395 return value;
396 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700397 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700398 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700399 system::setMTU(ifname, value);
400 return value;
401 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530402}
403
Patrick Williams6aef7692021-05-01 06:39:41 -0500404bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700405{
Patrick Williams6aef7692021-05-01 06:39:41 -0500406 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700407 {
408 return value;
409 }
410
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800411 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700412 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800413 if (!value)
414 {
415 // We only need to bring down the interface, networkd will always bring
416 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700417 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700418 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800419 }
William A. Kennington III5b179382022-11-15 15:23:26 -0800420 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800421
422 return value;
423}
424
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530425ServerList EthernetInterface::staticNameServers(ServerList value)
426{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700427 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530428 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700429 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530430 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700431 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
432 }
433 catch (const std::exception& e)
434 {
435 auto msg =
436 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
437 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
438 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
439 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530440 }
441 }
Ratan Gupta6dec3902017-08-20 15:28:12 +0530442 try
443 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530444 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700445
Ratan Gupta6dec3902017-08-20 15:28:12 +0530446 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800447 manager.reloadConfigs();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530448 }
Patrick Williams5758db32021-10-06 12:29:22 -0500449 catch (const InternalFailure& e)
Ratan Gupta6dec3902017-08-20 15:28:12 +0530450 {
451 log<level::ERR>("Exception processing DNS entries");
452 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530453 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec3902017-08-20 15:28:12 +0530454}
455
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600456void EthernetInterface::loadNTPServers(const config::Parser& config)
457{
458 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
459 EthernetInterfaceIntf::staticNTPServers(
460 config.map.getValueStrings("Network", "NTP"));
461}
462
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700463void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530464{
465 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700466 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700467 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530468}
469
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600470ServerList EthernetInterface::getNTPServerFromTimeSyncd()
471{
472 ServerList servers; // Variable to capture the NTP Server IPs
473 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
474 PROPERTY_INTERFACE, METHOD_GET);
475
476 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
477
478 try
479 {
480 auto reply = bus.call(method);
481 std::variant<ServerList> response;
482 reply.read(response);
483 servers = std::get<ServerList>(response);
484 }
485 catch (const sdbusplus::exception::SdBusError& e)
486 {
487 log<level::ERR>(
488 "Failed to get NTP server information from Systemd-Timesyncd");
489 }
490
491 return servers;
492}
493
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530494ServerList EthernetInterface::getNameServerFromResolvd()
495{
496 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700497 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530498
499 /*
500 The DNS property under org.freedesktop.resolve1.Link interface contains
501 an array containing all DNS servers currently used by resolved. It
502 contains similar information as the DNS server data written to
503 /run/systemd/resolve/resolv.conf.
504
505 Each structure in the array consists of a numeric network interface index,
506 an address family, and a byte array containing the DNS server address
507 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
508 The array contains DNS servers configured system-wide, including those
509 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
510 /etc/systemd/resolved.conf, as well as per-interface DNS server
511 information either retrieved from systemd-networkd or configured by
512 external software via SetLinkDNS().
513 */
514
515 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
516 std::variant<type> name; // Variable to capture the DNS property
517 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
518 PROPERTY_INTERFACE, METHOD_GET);
519
520 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530521
522 try
523 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500524 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530525 reply.read(name);
526 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500527 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530528 {
529 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
530 }
531 auto tupleVector = std::get_if<type>(&name);
532 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
533 {
Alexander Filippov983da552021-02-08 15:26:54 +0300534 int addressFamily = std::get<0>(*i);
535 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700536 servers.push_back(std::to_string(
537 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530538 }
539 return servers;
540}
541
William A. Kennington IIId298f932022-10-17 14:31:38 -0700542ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530543{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700544 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
545 auto idStr = std::to_string(id);
546 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800547 {
548 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700549 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
550 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800551 }
552
William A. Kennington IIId298f932022-10-17 14:31:38 -0700553 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700554 auto macStr = MacAddressIntf::macAddress();
555 std::optional<ether_addr> mac;
556 if (!macStr.empty())
557 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700558 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700559 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800560 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700561 .idx = 0, // TODO: Query the correct value after creation
562 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700563 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700564 .mac = std::move(mac),
565 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700566 .parent_idx = ifIdx,
567 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800568 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530569
Patrick Williams6aef7692021-05-01 06:39:41 -0500570 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530571 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700572 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800573 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700574 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530575
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700576 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530577
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700578 // write the device file for the vlan interface.
579 config::Parser config;
580 auto& netdev = config.map["NetDev"].emplace_back();
581 netdev["Name"].emplace_back(intfName);
582 netdev["Kind"].emplace_back("vlan");
583 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
584 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700585
586 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800587 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700588
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800589 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530590}
Ratan Gupta2b106532017-07-25 16:05:02 +0530591
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600592ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530593{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600594 try
595 {
596 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530597
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600598 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800599 manager.reloadConfigs();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600600 }
601 catch (InternalFailure& e)
602 {
603 log<level::ERR>("Exception processing NTP entries");
604 }
605 return EthernetInterfaceIntf::staticNTPServers();
606}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700607
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600608ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
609{
610 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530611}
Ratan Gupta2b106532017-07-25 16:05:02 +0530612// Need to merge the below function with the code which writes the
613// config file during factory reset.
614// TODO openbmc/openbmc#1751
615
616void EthernetInterface::writeConfigurationFile()
617{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700618 config::Parser config;
619 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530620 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700621 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800622#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700623 auto mac = MacAddressIntf::macAddress();
624 if (!mac.empty())
625 {
626 link["MACAddress"].emplace_back(mac);
627 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800628#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700629 if (!EthernetInterfaceIntf::nicEnabled())
630 {
631 link["Unmanaged"].emplace_back("yes");
632 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700633 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700634 {
635 auto& network = config.map["Network"].emplace_back();
636 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400637#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700638 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400639#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700640 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400641#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700642 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
643 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
644 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600645 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700646 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700647 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700649 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
650 {
651 vlans.emplace_back(intf->interfaceName());
652 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700653 }
654 }
655 {
656 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600657 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700658 {
659 ntps.emplace_back(ntp);
660 }
661 }
662 {
663 auto& dnss = network["DNS"];
664 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
665 {
666 dnss.emplace_back(dns);
667 }
668 }
669 {
670 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700671 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700672 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700673 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700674 {
675 address.emplace_back(
676 fmt::format("{}/{}", addr.second->address(),
677 addr.second->prefixLength()));
678 }
679 }
680 }
681 {
682 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700683 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700684 {
685 auto gateway = EthernetInterfaceIntf::defaultGateway();
686 if (!gateway.empty())
687 {
688 gateways.emplace_back(gateway);
689 }
690 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530691
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700692 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700693 {
694 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
695 if (!gateway6.empty())
696 {
697 gateways.emplace_back(gateway6);
698 }
699 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600700 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800701 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700702 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700703 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500704 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700705 auto& neighbors = config.map["Neighbor"];
706 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800707 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700708 auto& neighbor = neighbors.emplace_back();
709 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
710 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800711 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500712 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500713 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700714 auto& dhcp = config.map["DHCP"].emplace_back();
715 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III5b179382022-11-15 15:23:26 -0800716 const auto& conf = manager.getDHCPConf();
717 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
718 dhcp["UseDNS"].emplace_back(dns_enabled);
719 dhcp["UseDomains"].emplace_back(dns_enabled);
720 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
721 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
722 : "false");
723 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
724 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500725 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700726 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
727 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700728 auto msg = fmt::format("Wrote networkd file: {}", path.native());
729 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530730}
731
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800732std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530733{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700734 if (vlan)
735 {
736 log<level::ERR>("Tried to set MAC address on VLAN");
737 elog<InternalFailure>();
738 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800739#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600740 ether_addr newMAC;
741 try
742 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700743 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600744 }
Patrick Williams5758db32021-10-06 12:29:22 -0500745 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600746 {
747 log<level::ERR>("MACAddress is not valid.",
748 entry("MAC=%s", value.c_str()));
749 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
750 Argument::ARGUMENT_VALUE(value.c_str()));
751 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700752 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530753 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500754 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500755 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500756 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
757 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530758 }
759
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300760 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700761 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300762
William A. Kennington III1137a972019-04-20 20:49:58 -0700763 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700764 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700765 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530766 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700767 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700768 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530769 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700770 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
771 {
772 intf->MacAddressIntf::macAddress(validMAC);
773 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530774 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500775 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530776
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700777 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800778 manager.addReloadPreHook([interface]() {
779 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700780 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800781 });
William A. Kennington III5b179382022-11-15 15:23:26 -0800782 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530783 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700784
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300785#ifdef HAVE_UBOOT_ENV
786 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700787 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300788 if (envVar)
789 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500790 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
791 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
792 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
793 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300794 }
795#endif // HAVE_UBOOT_ENV
796
William A. Kennington III1137a972019-04-20 20:49:58 -0700797 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800798#else
799 elog<NotAllowed>(
800 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
801#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530802}
803
Ratan Guptae9c9b812017-09-22 17:15:37 +0530804void EthernetInterface::deleteAll()
805{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530806 // clear all the ip on the interface
807 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700808
809 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800810 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530811}
812
Ravi Tejaa5a09442020-07-17 00:57:33 -0500813std::string EthernetInterface::defaultGateway(std::string gateway)
814{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700815 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500816 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700817 if (!gateway.empty())
818 {
819 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
820 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500821 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700822 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500823 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700824 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
825 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500826 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
827 Argument::ARGUMENT_VALUE(gateway.c_str()));
828 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700829
830 if (EthernetInterfaceIntf::defaultGateway() == gateway)
831 {
832 return gateway;
833 }
834 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700835
836 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800837 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700838
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700839 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500840}
841
842std::string EthernetInterface::defaultGateway6(std::string gateway)
843{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700844 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500845 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700846 if (!gateway.empty())
847 {
848 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
849 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500850 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700851 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500852 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700853 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
854 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500855 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
856 Argument::ARGUMENT_VALUE(gateway.c_str()));
857 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700858
859 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
860 {
861 return gateway;
862 }
863 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700864
865 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800866 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700867
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700868 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500869}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700870
871EthernetInterface::VlanProperties::VlanProperties(
872 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800873 const InterfaceInfo& info, EthernetInterface& eth) :
874 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700875 parentIdx(*info.parent_idx), eth(eth)
876{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800877 VlanIntf::id(*info.vlan_id, true);
878 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700879}
880
881void EthernetInterface::VlanProperties::delete_()
882{
883 auto intf = eth.interfaceName();
884
885 // Remove all configs for the current interface
886 const auto& confDir = eth.manager.getConfDir();
887 std::error_code ec;
888 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
889 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
890
891 // Write an updated parent interface since it has a VLAN entry
892 for (const auto& [_, intf] : eth.manager.interfaces)
893 {
894 if (intf->ifIdx == parentIdx)
895 {
896 intf->writeConfigurationFile();
897 }
898 }
899
William A. Kennington III67b09da2022-10-31 14:09:53 -0700900 if (eth.ifIdx > 0)
901 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800902 // We need to forcibly delete the interface as systemd does not
903 system::deleteIntf(eth.ifIdx);
904
William A. Kennington III67b09da2022-10-31 14:09:53 -0700905 eth.manager.interfacesByIdx.erase(eth.ifIdx);
906 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700907 eth.manager.interfaces.erase(intf);
908}
909
Gunnar Mills57d9c502018-09-14 14:42:34 -0500910} // namespace network
911} // namespace phosphor