blob: 102173f586496b456b98468ac69337e8aef6cd5d [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 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800265 if (it->second->origin() == IP::AddressOrigin::Static)
266 {
267 return it->second->getObjPath();
268 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800269 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
270 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530271
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700272 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800273 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700274
William A. Kennington III434a9432022-11-04 18:38:46 -0700275 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530276}
277
Patrick Williams6aef7692021-05-01 06:39:41 -0500278ObjectPath EthernetInterface::neighbor(std::string ipAddress,
279 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800280{
William A. Kennington III434a9432022-11-04 18:38:46 -0700281 InAddrAny addr;
282 try
William A. Kennington III08505792019-01-30 16:00:04 -0800283 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700284 addr = ToAddr<InAddrAny>{}(ipAddress);
285 }
286 catch (const std::exception& e)
287 {
288 auto msg =
289 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
290 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500291 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
292 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800293 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700294
295 ether_addr lladdr;
296 try
William A. Kennington III08505792019-01-30 16:00:04 -0800297 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700298 lladdr = ToAddr<ether_addr>{}(macAddress);
299 }
300 catch (const std::exception& e)
301 {
302 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
303 e.what());
304 log<level::ERR>(msg.c_str(),
305 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500306 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
307 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800308 }
309
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800310 auto it = staticNeighbors.find(addr);
311 if (it == staticNeighbors.end())
312 {
313 it = std::get<0>(staticNeighbors.emplace(
314 addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
315 *this, addr, lladdr,
316 Neighbor::State::Permanent)));
317 }
318 else
319 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800320 auto str = std::to_string(lladdr);
321 if (it->second->macAddress() == str)
322 {
323 return it->second->getObjPath();
324 }
325 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800326 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700327
328 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800329 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700330
William A. Kennington III434a9432022-11-04 18:38:46 -0700331 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800332}
333
Patrick Williams6aef7692021-05-01 06:39:41 -0500334bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700335{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700336 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700337 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700338 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800339 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700340 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700341 return value;
342}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700343
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700344bool EthernetInterface::dhcp4(bool value)
345{
346 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
347 {
348 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800349 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700350 }
351 return value;
352}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700353
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700354bool EthernetInterface::dhcp6(bool value)
355{
356 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
357 {
358 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800359 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700360 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700361 return value;
362}
363
Patrick Williams6aef7692021-05-01 06:39:41 -0500364EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530365{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700366 auto old4 = EthernetInterfaceIntf::dhcp4();
367 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
368 value == DHCPConf::v4v6stateless ||
369 value == DHCPConf::both);
370 auto old6 = EthernetInterfaceIntf::dhcp6();
371 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
372 value == DHCPConf::both);
373 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
374 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
375 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
376 value == DHCPConf::v6 || value == DHCPConf::both);
377
378 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530379 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700380 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800381 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530382 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530383 return value;
384}
385
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700386EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
387{
388 if (dhcp6())
389 {
390 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
391 }
392 else if (dhcp4())
393 {
394 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
395 }
396 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
397}
398
Tejas Patil2c0fc562021-08-03 19:13:46 +0530399size_t EthernetInterface::mtu(size_t value)
400{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700401 const size_t old = EthernetInterfaceIntf::mtu();
402 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530403 {
404 return value;
405 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700406 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700407 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700408 system::setMTU(ifname, value);
409 return value;
410 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530411}
412
Patrick Williams6aef7692021-05-01 06:39:41 -0500413bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700414{
Patrick Williams6aef7692021-05-01 06:39:41 -0500415 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700416 {
417 return value;
418 }
419
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800420 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700421 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800422 if (!value)
423 {
424 // We only need to bring down the interface, networkd will always bring
425 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700426 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700427 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800428 }
William A. Kennington III5b179382022-11-15 15:23:26 -0800429 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800430
431 return value;
432}
433
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530434ServerList EthernetInterface::staticNameServers(ServerList value)
435{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700436 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530437 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700438 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530439 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700440 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
441 }
442 catch (const std::exception& e)
443 {
444 auto msg =
445 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
446 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
447 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
448 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530449 }
450 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530451 try
452 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530453 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700454
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530455 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800456 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530457 }
Patrick Williams5758db32021-10-06 12:29:22 -0500458 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530459 {
460 log<level::ERR>("Exception processing DNS entries");
461 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530462 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530463}
464
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600465void EthernetInterface::loadNTPServers(const config::Parser& config)
466{
467 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
468 EthernetInterfaceIntf::staticNTPServers(
469 config.map.getValueStrings("Network", "NTP"));
470}
471
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700472void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530473{
474 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700475 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700476 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530477}
478
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600479ServerList EthernetInterface::getNTPServerFromTimeSyncd()
480{
481 ServerList servers; // Variable to capture the NTP Server IPs
482 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
483 PROPERTY_INTERFACE, METHOD_GET);
484
485 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
486
487 try
488 {
489 auto reply = bus.call(method);
490 std::variant<ServerList> response;
491 reply.read(response);
492 servers = std::get<ServerList>(response);
493 }
494 catch (const sdbusplus::exception::SdBusError& e)
495 {
496 log<level::ERR>(
497 "Failed to get NTP server information from Systemd-Timesyncd");
498 }
499
500 return servers;
501}
502
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530503ServerList EthernetInterface::getNameServerFromResolvd()
504{
505 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700506 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530507
508 /*
509 The DNS property under org.freedesktop.resolve1.Link interface contains
510 an array containing all DNS servers currently used by resolved. It
511 contains similar information as the DNS server data written to
512 /run/systemd/resolve/resolv.conf.
513
514 Each structure in the array consists of a numeric network interface index,
515 an address family, and a byte array containing the DNS server address
516 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
517 The array contains DNS servers configured system-wide, including those
518 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
519 /etc/systemd/resolved.conf, as well as per-interface DNS server
520 information either retrieved from systemd-networkd or configured by
521 external software via SetLinkDNS().
522 */
523
524 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
525 std::variant<type> name; // Variable to capture the DNS property
526 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
527 PROPERTY_INTERFACE, METHOD_GET);
528
529 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530530
531 try
532 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500533 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530534 reply.read(name);
535 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500536 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530537 {
538 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
539 }
540 auto tupleVector = std::get_if<type>(&name);
541 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
542 {
Alexander Filippov983da552021-02-08 15:26:54 +0300543 int addressFamily = std::get<0>(*i);
544 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700545 servers.push_back(std::to_string(
546 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530547 }
548 return servers;
549}
550
William A. Kennington IIId298f932022-10-17 14:31:38 -0700551ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530552{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700553 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
554 auto idStr = std::to_string(id);
555 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800556 {
557 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700558 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
559 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800560 }
561
William A. Kennington IIId298f932022-10-17 14:31:38 -0700562 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700563 auto macStr = MacAddressIntf::macAddress();
564 std::optional<ether_addr> mac;
565 if (!macStr.empty())
566 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700567 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700568 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800569 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700570 .idx = 0, // TODO: Query the correct value after creation
571 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700572 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700573 .mac = std::move(mac),
574 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700575 .parent_idx = ifIdx,
576 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800577 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530578
Patrick Williams6aef7692021-05-01 06:39:41 -0500579 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530580 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700581 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800582 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700583 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530584
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700585 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530586
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700587 // write the device file for the vlan interface.
588 config::Parser config;
589 auto& netdev = config.map["NetDev"].emplace_back();
590 netdev["Name"].emplace_back(intfName);
591 netdev["Kind"].emplace_back("vlan");
592 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
593 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700594
595 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800596 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700597
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800598 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530599}
Ratan Gupta2b106532017-07-25 16:05:02 +0530600
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600601ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530602{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600603 try
604 {
605 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530606
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600607 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800608 manager.reloadConfigs();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600609 }
610 catch (InternalFailure& e)
611 {
612 log<level::ERR>("Exception processing NTP entries");
613 }
614 return EthernetInterfaceIntf::staticNTPServers();
615}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700616
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600617ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
618{
619 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530620}
Ratan Gupta2b106532017-07-25 16:05:02 +0530621// Need to merge the below function with the code which writes the
622// config file during factory reset.
623// TODO openbmc/openbmc#1751
624
625void EthernetInterface::writeConfigurationFile()
626{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700627 config::Parser config;
628 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530629 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700630 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800631#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700632 auto mac = MacAddressIntf::macAddress();
633 if (!mac.empty())
634 {
635 link["MACAddress"].emplace_back(mac);
636 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800637#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700638 if (!EthernetInterfaceIntf::nicEnabled())
639 {
640 link["Unmanaged"].emplace_back("yes");
641 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700642 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700643 {
644 auto& network = config.map["Network"].emplace_back();
645 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400646#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700647 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400648#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700649 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400650#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700651 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
652 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
653 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600654 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700655 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700656 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700657 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700658 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
659 {
660 vlans.emplace_back(intf->interfaceName());
661 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700662 }
663 }
664 {
665 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600666 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700667 {
668 ntps.emplace_back(ntp);
669 }
670 }
671 {
672 auto& dnss = network["DNS"];
673 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
674 {
675 dnss.emplace_back(dns);
676 }
677 }
678 {
679 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700680 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700681 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700682 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700683 {
684 address.emplace_back(
685 fmt::format("{}/{}", addr.second->address(),
686 addr.second->prefixLength()));
687 }
688 }
689 }
690 {
691 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700692 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700693 {
694 auto gateway = EthernetInterfaceIntf::defaultGateway();
695 if (!gateway.empty())
696 {
697 gateways.emplace_back(gateway);
698 }
699 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530700
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700701 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700702 {
703 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
704 if (!gateway6.empty())
705 {
706 gateways.emplace_back(gateway6);
707 }
708 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600709 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800710 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700711 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700712 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500713 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700714 auto& neighbors = config.map["Neighbor"];
715 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800716 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700717 auto& neighbor = neighbors.emplace_back();
718 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
719 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800720 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500721 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500722 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700723 auto& dhcp = config.map["DHCP"].emplace_back();
724 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III5b179382022-11-15 15:23:26 -0800725 const auto& conf = manager.getDHCPConf();
726 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
727 dhcp["UseDNS"].emplace_back(dns_enabled);
728 dhcp["UseDomains"].emplace_back(dns_enabled);
729 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
730 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
731 : "false");
732 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
733 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500734 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700735 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
736 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700737 auto msg = fmt::format("Wrote networkd file: {}", path.native());
738 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530739}
740
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800741std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530742{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700743 if (vlan)
744 {
745 log<level::ERR>("Tried to set MAC address on VLAN");
746 elog<InternalFailure>();
747 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800748#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600749 ether_addr newMAC;
750 try
751 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700752 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600753 }
Patrick Williams5758db32021-10-06 12:29:22 -0500754 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600755 {
756 log<level::ERR>("MACAddress is not valid.",
757 entry("MAC=%s", value.c_str()));
758 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
759 Argument::ARGUMENT_VALUE(value.c_str()));
760 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700761 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530762 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500763 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500764 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500765 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
766 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530767 }
768
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300769 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700770 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300771
William A. Kennington III1137a972019-04-20 20:49:58 -0700772 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700773 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700774 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530775 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700776 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700777 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530778 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700779 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
780 {
781 intf->MacAddressIntf::macAddress(validMAC);
782 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530783 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500784 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530785
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700786 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800787 manager.addReloadPreHook([interface]() {
788 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700789 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800790 });
William A. Kennington III5b179382022-11-15 15:23:26 -0800791 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530792 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700793
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300794#ifdef HAVE_UBOOT_ENV
795 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700796 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300797 if (envVar)
798 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500799 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
800 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
801 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
802 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300803 }
804#endif // HAVE_UBOOT_ENV
805
William A. Kennington III1137a972019-04-20 20:49:58 -0700806 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800807#else
808 elog<NotAllowed>(
809 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
810#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530811}
812
Ratan Guptae9c9b812017-09-22 17:15:37 +0530813void EthernetInterface::deleteAll()
814{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530815 // clear all the ip on the interface
816 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700817
818 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800819 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530820}
821
Ravi Tejaa5a09442020-07-17 00:57:33 -0500822std::string EthernetInterface::defaultGateway(std::string gateway)
823{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700824 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500825 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700826 if (!gateway.empty())
827 {
828 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
829 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500830 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700831 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500832 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700833 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
834 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500835 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
836 Argument::ARGUMENT_VALUE(gateway.c_str()));
837 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700838
839 if (EthernetInterfaceIntf::defaultGateway() == gateway)
840 {
841 return gateway;
842 }
843 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700844
845 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800846 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700847
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700848 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500849}
850
851std::string EthernetInterface::defaultGateway6(std::string gateway)
852{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700853 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500854 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700855 if (!gateway.empty())
856 {
857 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
858 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500859 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700860 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500861 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700862 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
863 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500864 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
865 Argument::ARGUMENT_VALUE(gateway.c_str()));
866 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700867
868 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
869 {
870 return gateway;
871 }
872 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700873
874 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800875 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700876
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700877 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500878}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700879
880EthernetInterface::VlanProperties::VlanProperties(
881 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800882 const InterfaceInfo& info, EthernetInterface& eth) :
883 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700884 parentIdx(*info.parent_idx), eth(eth)
885{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800886 VlanIntf::id(*info.vlan_id, true);
887 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700888}
889
890void EthernetInterface::VlanProperties::delete_()
891{
892 auto intf = eth.interfaceName();
893
894 // Remove all configs for the current interface
895 const auto& confDir = eth.manager.getConfDir();
896 std::error_code ec;
897 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
898 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
899
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800900 if (eth.ifIdx > 0)
901 {
902 eth.manager.interfacesByIdx.erase(eth.ifIdx);
903 }
904 auto it = eth.manager.interfaces.find(intf);
905 auto obj = std::move(it->second);
906 eth.manager.interfaces.erase(it);
907
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700908 // Write an updated parent interface since it has a VLAN entry
909 for (const auto& [_, intf] : eth.manager.interfaces)
910 {
911 if (intf->ifIdx == parentIdx)
912 {
913 intf->writeConfigurationFile();
914 }
915 }
916
William A. Kennington III67b09da2022-10-31 14:09:53 -0700917 if (eth.ifIdx > 0)
918 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800919 // We need to forcibly delete the interface as systemd does not
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800920 eth.manager.addReloadPostHook(
921 [idx = eth.ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800922
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800923 // Ignore the interface so the reload doesn't re-query it
924 eth.manager.ignoredIntf.emplace(eth.ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700925 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800926
927 eth.manager.reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700928}
929
Gunnar Mills57d9c502018-09-14 14:42:34 -0500930} // namespace network
931} // namespace phosphor