blob: 5e61cbd6e2312b465bc62bb1326cdd0699776c36 [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
William A. Kennington III9ede1b72022-11-21 01:59:28 -080072EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
73 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080074 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070075 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070076 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080077 bool enabled) :
William A. Kennington III13d665c2022-11-15 20:34:40 -080078 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.intf.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080079 config, enabled)
William A. Kennington IIId298f932022-10-17 14:31:38 -070080{
81}
82
William A. Kennington III9ede1b72022-11-21 01:59:28 -080083EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
84 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080085 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070086 std::string&& objPath,
87 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080088 bool enabled) :
89 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit),
William A. Kennington III876927c2022-11-17 16:20:15 -080090 manager(manager), bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +053091{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080092 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070093 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080094 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
95 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
96 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
97 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaa5a09442020-07-17 00:57:33 -050098
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -070099 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800100 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +0530101
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800102 updateInfo(info.intf, true);
103
104 if (info.defgw4)
105 {
106 EthernetInterface::defaultGateway(std::to_string(*info.defgw4), true);
107 }
108 if (info.defgw6)
109 {
110 EthernetInterface::defaultGateway6(std::to_string(*info.defgw6), true);
111 }
112 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700113
William A. Kennington III13d665c2022-11-15 20:34:40 -0800114 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700115 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800116 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700117 {
118 std::runtime_error("Missing parent link");
119 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800120 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
121 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800122 for (const auto& [_, addr] : info.addrs)
123 {
124 addAddr(addr);
125 }
126 for (const auto& [_, neigh] : info.staticNeighs)
127 {
128 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700129 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530130}
131
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800132void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700133{
William A. Kennington III876927c2022-11-17 16:20:15 -0800134 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800135 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700136 if (info.mac)
137 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800138 MacAddressIntf::macAddress(std::to_string(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700139 }
140 if (info.mtu)
141 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800142 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700143 }
William A. Kennington III21539662022-11-15 14:53:11 -0800144 if (ifIdx > 0)
145 {
146 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
147 return system::getEthInfo(*info.name);
148 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800149 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
150 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800151 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700152}
153
Johnathan Mantey817012a2020-01-30 15:07:39 -0800154bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
155{
156 return (
157#ifdef LINK_LOCAL_AUTOCONFIGURATION
158 (origin == IP::AddressOrigin::Static)
159#else
160 (origin == IP::AddressOrigin::Static ||
161 origin == IP::AddressOrigin::LinkLocal)
162#endif
163
164 );
165}
166
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800167void EthernetInterface::addAddr(const AddressInfo& info)
168{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800169 IP::AddressOrigin origin = IP::AddressOrigin::Static;
170 if (dhcpIsEnabled(info.ifaddr.getAddr()))
171 {
172 origin = IP::AddressOrigin::DHCP;
173 }
174#ifdef LINK_LOCAL_AUTOCONFIGURATION
175 if (info.scope == RT_SCOPE_LINK)
176 {
177 origin = IP::AddressOrigin::LinkLocal;
178 }
179#endif
180
William A. Kennington III77747f62022-11-07 23:11:15 -0800181 auto it = addrs.find(info.ifaddr);
182 if (it == addrs.end())
183 {
184 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
185 bus, std::string_view(objPath), *this,
186 info.ifaddr, origin));
187 }
188 else
189 {
190 it->second->IPIfaces::origin(origin);
191 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800192}
193
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800194void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
195{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800196 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800197 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800198 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800199 log<level::ERR>(msg.c_str());
200 return;
201 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800202
203 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
204 {
205 it->second->NeighborObj::macAddress(std::to_string(*info.mac));
206 }
207 else
208 {
209 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
210 bus, std::string_view(objPath),
211 *this, *info.addr, *info.mac,
212 Neighbor::State::Permanent));
213 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800214}
215
Patrick Williams6aef7692021-05-01 06:39:41 -0500216ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700217 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530218{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700219 InAddrAny addr;
220 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530221 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700222 switch (protType)
223 {
224 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700225 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700226 break;
227 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700228 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700229 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700230 default:
231 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700232 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500233 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700234 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500235 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700236 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
237 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500238 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
239 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
240 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700241 IfAddr ifaddr;
242 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500243 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700244 ifaddr = {addr, prefixLength};
245 }
246 catch (const std::exception& e)
247 {
248 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
249 e.what());
250 log<level::ERR>(msg.c_str(),
251 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500252 elog<InvalidArgument>(
253 Argument::ARGUMENT_NAME("prefixLength"),
254 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530255 }
256
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800257 auto it = addrs.find(ifaddr);
258 if (it == addrs.end())
259 {
260 it = std::get<0>(addrs.emplace(
261 ifaddr,
262 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
263 ifaddr, IP::AddressOrigin::Static)));
264 }
265 else
266 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800267 if (it->second->origin() == IP::AddressOrigin::Static)
268 {
269 return it->second->getObjPath();
270 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800271 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
272 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530273
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700274 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800275 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700276
William A. Kennington III434a9432022-11-04 18:38:46 -0700277 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530278}
279
Patrick Williams6aef7692021-05-01 06:39:41 -0500280ObjectPath EthernetInterface::neighbor(std::string ipAddress,
281 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800282{
William A. Kennington III434a9432022-11-04 18:38:46 -0700283 InAddrAny addr;
284 try
William A. Kennington III08505792019-01-30 16:00:04 -0800285 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700286 addr = ToAddr<InAddrAny>{}(ipAddress);
287 }
288 catch (const std::exception& e)
289 {
290 auto msg =
291 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
292 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500293 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
294 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800295 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700296
297 ether_addr lladdr;
298 try
William A. Kennington III08505792019-01-30 16:00:04 -0800299 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700300 lladdr = ToAddr<ether_addr>{}(macAddress);
301 }
302 catch (const std::exception& e)
303 {
304 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
305 e.what());
306 log<level::ERR>(msg.c_str(),
307 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500308 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
309 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800310 }
311
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800312 auto it = staticNeighbors.find(addr);
313 if (it == staticNeighbors.end())
314 {
315 it = std::get<0>(staticNeighbors.emplace(
316 addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
317 *this, addr, lladdr,
318 Neighbor::State::Permanent)));
319 }
320 else
321 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800322 auto str = std::to_string(lladdr);
323 if (it->second->macAddress() == str)
324 {
325 return it->second->getObjPath();
326 }
327 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800328 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700329
330 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800331 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700332
William A. Kennington III434a9432022-11-04 18:38:46 -0700333 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800334}
335
Patrick Williams6aef7692021-05-01 06:39:41 -0500336bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700337{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700338 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700339 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700340 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800341 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700342 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700343 return value;
344}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700345
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700346bool EthernetInterface::dhcp4(bool value)
347{
348 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
349 {
350 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800351 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700352 }
353 return value;
354}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700355
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700356bool EthernetInterface::dhcp6(bool value)
357{
358 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
359 {
360 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800361 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700362 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700363 return value;
364}
365
Patrick Williams6aef7692021-05-01 06:39:41 -0500366EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530367{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700368 auto old4 = EthernetInterfaceIntf::dhcp4();
369 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
370 value == DHCPConf::v4v6stateless ||
371 value == DHCPConf::both);
372 auto old6 = EthernetInterfaceIntf::dhcp6();
373 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
374 value == DHCPConf::both);
375 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
376 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
377 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
378 value == DHCPConf::v6 || value == DHCPConf::both);
379
380 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530381 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700382 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800383 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530384 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530385 return value;
386}
387
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700388EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
389{
390 if (dhcp6())
391 {
392 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
393 }
394 else if (dhcp4())
395 {
396 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
397 }
398 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
399}
400
Tejas Patil2c0fc562021-08-03 19:13:46 +0530401size_t EthernetInterface::mtu(size_t value)
402{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700403 const size_t old = EthernetInterfaceIntf::mtu();
404 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530405 {
406 return value;
407 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700408 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700409 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700410 system::setMTU(ifname, value);
411 return value;
412 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530413}
414
Patrick Williams6aef7692021-05-01 06:39:41 -0500415bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700416{
Patrick Williams6aef7692021-05-01 06:39:41 -0500417 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700418 {
419 return value;
420 }
421
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800422 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700423 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800424 if (!value)
425 {
426 // We only need to bring down the interface, networkd will always bring
427 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800428 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700429 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800430 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800431 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800432
433 return value;
434}
435
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530436ServerList EthernetInterface::staticNameServers(ServerList value)
437{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700438 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530439 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700440 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530441 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700442 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
443 }
444 catch (const std::exception& e)
445 {
446 auto msg =
447 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
448 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
449 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
450 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530451 }
452 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530453 try
454 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530455 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700456
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530457 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800458 manager.get().reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530459 }
Patrick Williams5758db32021-10-06 12:29:22 -0500460 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530461 {
462 log<level::ERR>("Exception processing DNS entries");
463 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530464 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530465}
466
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600467void EthernetInterface::loadNTPServers(const config::Parser& config)
468{
469 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
470 EthernetInterfaceIntf::staticNTPServers(
471 config.map.getValueStrings("Network", "NTP"));
472}
473
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700474void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530475{
476 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700477 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700478 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530479}
480
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600481ServerList EthernetInterface::getNTPServerFromTimeSyncd()
482{
483 ServerList servers; // Variable to capture the NTP Server IPs
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800484 auto method =
485 bus.get().new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
486 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600487
488 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
489
490 try
491 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800492 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600493 std::variant<ServerList> response;
494 reply.read(response);
495 servers = std::get<ServerList>(response);
496 }
497 catch (const sdbusplus::exception::SdBusError& e)
498 {
499 log<level::ERR>(
500 "Failed to get NTP server information from Systemd-Timesyncd");
501 }
502
503 return servers;
504}
505
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530506ServerList EthernetInterface::getNameServerFromResolvd()
507{
508 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700509 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530510
511 /*
512 The DNS property under org.freedesktop.resolve1.Link interface contains
513 an array containing all DNS servers currently used by resolved. It
514 contains similar information as the DNS server data written to
515 /run/systemd/resolve/resolv.conf.
516
517 Each structure in the array consists of a numeric network interface index,
518 an address family, and a byte array containing the DNS server address
519 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
520 The array contains DNS servers configured system-wide, including those
521 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
522 /etc/systemd/resolved.conf, as well as per-interface DNS server
523 information either retrieved from systemd-networkd or configured by
524 external software via SetLinkDNS().
525 */
526
527 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
528 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800529 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
530 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530531
532 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530533
534 try
535 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800536 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530537 reply.read(name);
538 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500539 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530540 {
541 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
542 }
543 auto tupleVector = std::get_if<type>(&name);
544 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
545 {
Alexander Filippov983da552021-02-08 15:26:54 +0300546 int addressFamily = std::get<0>(*i);
547 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700548 servers.push_back(std::to_string(
549 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530550 }
551 return servers;
552}
553
William A. Kennington IIId298f932022-10-17 14:31:38 -0700554ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530555{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700556 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
557 auto idStr = std::to_string(id);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800558 if (manager.get().interfaces.find(intfName) !=
559 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800560 {
561 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700562 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
563 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800564 }
565
William A. Kennington IIId298f932022-10-17 14:31:38 -0700566 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700567 auto macStr = MacAddressIntf::macAddress();
568 std::optional<ether_addr> mac;
569 if (!macStr.empty())
570 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700571 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700572 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800573 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700574 .idx = 0, // TODO: Query the correct value after creation
575 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700576 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700577 .mac = std::move(mac),
578 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700579 .parent_idx = ifIdx,
580 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800581 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530582
Patrick Williams6aef7692021-05-01 06:39:41 -0500583 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530584 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700585 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800586 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700587 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530588
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800589 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530590
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700591 // write the device file for the vlan interface.
592 config::Parser config;
593 auto& netdev = config.map["NetDev"].emplace_back();
594 netdev["Name"].emplace_back(intfName);
595 netdev["Kind"].emplace_back("vlan");
596 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800597 config.writeFile(
598 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700599
600 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800601 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700602
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800603 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530604}
Ratan Gupta2b106532017-07-25 16:05:02 +0530605
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600606ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530607{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600608 try
609 {
610 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530611
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600612 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800613 manager.get().reloadConfigs();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600614 }
615 catch (InternalFailure& e)
616 {
617 log<level::ERR>("Exception processing NTP entries");
618 }
619 return EthernetInterfaceIntf::staticNTPServers();
620}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700621
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600622ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
623{
624 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530625}
Ratan Gupta2b106532017-07-25 16:05:02 +0530626// Need to merge the below function with the code which writes the
627// config file during factory reset.
628// TODO openbmc/openbmc#1751
629
630void EthernetInterface::writeConfigurationFile()
631{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700632 config::Parser config;
633 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530634 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700635 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800636#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700637 auto mac = MacAddressIntf::macAddress();
638 if (!mac.empty())
639 {
640 link["MACAddress"].emplace_back(mac);
641 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800642#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700643 if (!EthernetInterfaceIntf::nicEnabled())
644 {
645 link["Unmanaged"].emplace_back("yes");
646 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700647 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 {
649 auto& network = config.map["Network"].emplace_back();
650 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400651#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700652 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400653#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700654 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400655#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700656 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
657 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
658 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600659 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700660 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800661 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700662 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700663 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
664 {
665 vlans.emplace_back(intf->interfaceName());
666 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700667 }
668 }
669 {
670 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600671 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700672 {
673 ntps.emplace_back(ntp);
674 }
675 }
676 {
677 auto& dnss = network["DNS"];
678 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
679 {
680 dnss.emplace_back(dns);
681 }
682 }
683 {
684 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700685 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700686 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700687 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700688 {
689 address.emplace_back(
690 fmt::format("{}/{}", addr.second->address(),
691 addr.second->prefixLength()));
692 }
693 }
694 }
695 {
696 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700697 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700698 {
699 auto gateway = EthernetInterfaceIntf::defaultGateway();
700 if (!gateway.empty())
701 {
702 gateways.emplace_back(gateway);
703 }
704 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530705
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700706 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700707 {
708 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
709 if (!gateway6.empty())
710 {
711 gateways.emplace_back(gateway6);
712 }
713 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600714 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800715 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700717 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500718 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700719 auto& neighbors = config.map["Neighbor"];
720 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800721 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700722 auto& neighbor = neighbors.emplace_back();
723 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
724 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800725 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500726 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500727 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700728 auto& dhcp = config.map["DHCP"].emplace_back();
729 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800730 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800731 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
732 dhcp["UseDNS"].emplace_back(dns_enabled);
733 dhcp["UseDomains"].emplace_back(dns_enabled);
734 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
735 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
736 : "false");
737 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
738 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500739 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800740 auto path =
741 config::pathForIntfConf(manager.get().getConfDir(), interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700742 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700743 auto msg = fmt::format("Wrote networkd file: {}", path.native());
744 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530745}
746
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800747std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530748{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700749 if (vlan)
750 {
751 log<level::ERR>("Tried to set MAC address on VLAN");
752 elog<InternalFailure>();
753 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800754#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600755 ether_addr newMAC;
756 try
757 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700758 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600759 }
Patrick Williams5758db32021-10-06 12:29:22 -0500760 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600761 {
762 log<level::ERR>("MACAddress is not valid.",
763 entry("MAC=%s", value.c_str()));
764 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
765 Argument::ARGUMENT_VALUE(value.c_str()));
766 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700767 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530768 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500769 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500770 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500771 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
772 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530773 }
774
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300775 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700776 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300777
William A. Kennington III1137a972019-04-20 20:49:58 -0700778 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700779 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700780 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530781 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700782 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800783 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530784 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700785 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
786 {
787 intf->MacAddressIntf::macAddress(validMAC);
788 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530789 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500790 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530791
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700792 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800793 manager.get().addReloadPreHook([interface]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800794 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700795 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800796 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800797 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530798 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700799
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300800#ifdef HAVE_UBOOT_ENV
801 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700802 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300803 if (envVar)
804 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500805 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
806 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
807 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
808 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300809 }
810#endif // HAVE_UBOOT_ENV
811
William A. Kennington III1137a972019-04-20 20:49:58 -0700812 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800813#else
814 elog<NotAllowed>(
815 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
816#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530817}
818
Ratan Guptae9c9b812017-09-22 17:15:37 +0530819void EthernetInterface::deleteAll()
820{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530821 // clear all the ip on the interface
822 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700823
824 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800825 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530826}
827
Ravi Tejaa5a09442020-07-17 00:57:33 -0500828std::string EthernetInterface::defaultGateway(std::string gateway)
829{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700830 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500831 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700832 if (!gateway.empty())
833 {
834 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
835 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500836 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700837 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500838 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700839 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
840 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500841 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
842 Argument::ARGUMENT_VALUE(gateway.c_str()));
843 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700844
845 if (EthernetInterfaceIntf::defaultGateway() == gateway)
846 {
847 return gateway;
848 }
849 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700850
851 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800852 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700853
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700854 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500855}
856
857std::string EthernetInterface::defaultGateway6(std::string gateway)
858{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700859 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500860 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700861 if (!gateway.empty())
862 {
863 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
864 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500865 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700866 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500867 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700868 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
869 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500870 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
871 Argument::ARGUMENT_VALUE(gateway.c_str()));
872 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700873
874 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
875 {
876 return gateway;
877 }
878 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700879
880 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800881 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700882
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700883 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500884}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700885
886EthernetInterface::VlanProperties::VlanProperties(
887 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800888 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800889 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700890 parentIdx(*info.parent_idx), eth(eth)
891{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800892 VlanIntf::id(*info.vlan_id, true);
893 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700894}
895
896void EthernetInterface::VlanProperties::delete_()
897{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800898 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700899
900 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800901 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700902 std::error_code ec;
903 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
904 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
905
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800906 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800907 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800908 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800909 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800910 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800911 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800912 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800913
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700914 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800915 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700916 {
917 if (intf->ifIdx == parentIdx)
918 {
919 intf->writeConfigurationFile();
920 }
921 }
922
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800923 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700924 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800925 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800926 eth.get().manager.get().addReloadPostHook(
927 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800928
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800929 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800930 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700931 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800932
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800933 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700934}
935
Gunnar Mills57d9c502018-09-14 14:42:34 -0500936} // namespace network
937} // namespace phosphor