blob: cd0600392060dc3f8e576f295a8e4a3473a9f076 [file] [log] [blame]
Patrick Rudolph9caa64d2023-09-04 11:22:31 +02001#include "config.h"
Gunnar Mills57d9c502018-09-14 14:42:34 -05002
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 IIId7946a72019-04-19 14:24:09 -070010#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070011#include <net/if.h>
William A. Kennington III9c441fd2023-02-24 13:40:01 -080012#include <net/if_arp.h>
Yuxiao Zhang46938072023-09-26 17:59:14 -070013#include <sys/stat.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014
Patrick Venture189d44e2018-07-09 12:30:59 -070015#include <phosphor-logging/elog-errors.hpp>
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -070016#include <phosphor-logging/lg2.hpp>
William A. Kennington III945878a2024-04-17 01:05:27 -070017#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070018#include <stdplus/raw.hpp>
William A. Kennington III86642522023-07-24 17:55:55 -070019#include <stdplus/str/cat.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070020#include <stdplus/zstring.hpp>
Patrick Williams89d734b2023-05-10 07:50:25 -050021#include <xyz/openbmc_project/Common/error.hpp>
22
23#include <algorithm>
24#include <filesystem>
William A. Kennington IIIcafc1512023-07-25 02:22:32 -070025#include <format>
Ratan Gupta2b106532017-07-25 16:05:02 +053026#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070027#include <unordered_map>
28#include <variant>
Ratan Gupta82549cc2017-04-21 08:45:23 +053029
Ratan Gupta91a99cc2017-04-14 16:32:09 +053030namespace phosphor
31{
32namespace network
33{
34
35using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053036using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053037using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
38using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050039using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070040using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053041constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
42constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
43constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
44constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060045
46constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
47constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
48constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
49
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053050constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053051
William A. Kennington III2e09d272022-10-14 17:15:00 -070052template <typename Func>
53inline decltype(std::declval<Func>()())
54 ignoreError(std::string_view msg, stdplus::zstring_view intf,
55 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080056{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070057 try
58 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070059 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070060 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070061 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070062 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -070063 lg2::error("{MSG} failed on {NET_INTF}: {ERROR}", "MSG", msg,
64 "NET_INTF", intf, "ERROR", e);
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070065 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070066 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070067}
William A. Kennington IIId298f932022-10-17 14:31:38 -070068
William A. Kennington IIId298f932022-10-17 14:31:38 -070069static std::string makeObjPath(std::string_view root, std::string_view intf)
70{
William A. Kennington III86642522023-07-24 17:55:55 -070071 auto ret = stdplus::strCat(root, "/"sv, intf);
William A. Kennington IIId298f932022-10-17 14:31:38 -070072 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
73 return ret;
74}
75
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -080076template <typename Addr>
77static bool validIntfIP(Addr a) noexcept
78{
79 return a.isUnicast() && !a.isLoopback();
80}
81
William A. Kennington III9ede1b72022-11-21 01:59:28 -080082EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
83 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080084 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070085 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070086 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080087 bool enabled) :
William A. Kennington III13d665c2022-11-15 20:34:40 -080088 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.intf.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080089 config, enabled)
Patrick Williams89d734b2023-05-10 07:50:25 -050090{}
William A. Kennington IIId298f932022-10-17 14:31:38 -070091
William A. Kennington III9ede1b72022-11-21 01:59:28 -080092EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
93 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080094 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070095 std::string&& objPath,
96 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080097 bool enabled) :
98 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit),
William A. Kennington III876927c2022-11-17 16:20:15 -080099 manager(manager), bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530100{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800101 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700102 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800103 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
104 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
105 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
106 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500107
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700108 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800109 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +0530110
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800111 updateInfo(info.intf, true);
112
113 if (info.defgw4)
114 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700115 EthernetInterface::defaultGateway(stdplus::toStr(*info.defgw4), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800116 }
117 if (info.defgw6)
118 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700119 EthernetInterface::defaultGateway6(stdplus::toStr(*info.defgw6), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800120 }
121 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700122
William A. Kennington III13d665c2022-11-15 20:34:40 -0800123 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700124 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800125 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700126 {
127 std::runtime_error("Missing parent link");
128 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800129 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
130 }
William A. Kennington IIIfad525c2024-04-17 00:51:59 -0700131 dhcp4Conf.emplace(bus, this->objPath + "/dhcp4", *this, DHCPType::v4);
132 dhcp6Conf.emplace(bus, this->objPath + "/dhcp6", *this, DHCPType::v6);
William A. Kennington III13d665c2022-11-15 20:34:40 -0800133 for (const auto& [_, addr] : info.addrs)
134 {
135 addAddr(addr);
136 }
137 for (const auto& [_, neigh] : info.staticNeighs)
138 {
139 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700140 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530141}
142
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800143void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700144{
William A. Kennington III876927c2022-11-17 16:20:15 -0800145 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800146 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700147 if (info.mac)
148 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700149 MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700150 }
151 if (info.mtu)
152 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800153 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700154 }
William A. Kennington III21539662022-11-15 14:53:11 -0800155 if (ifIdx > 0)
156 {
157 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
158 return system::getEthInfo(*info.name);
159 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800160 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
161 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800162 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700163}
164
Johnathan Mantey817012a2020-01-30 15:07:39 -0800165bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
166{
167 return (
168#ifdef LINK_LOCAL_AUTOCONFIGURATION
Johnathan Manteyfabe3952023-09-08 13:21:05 -0700169 (origin == IP::AddressOrigin::Static)
170#else
Johnathan Mantey817012a2020-01-30 15:07:39 -0800171 (origin == IP::AddressOrigin::Static ||
172 origin == IP::AddressOrigin::LinkLocal)
173#endif
174
175 );
176}
177
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800178void EthernetInterface::addAddr(const AddressInfo& info)
179{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800180 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ravi Teja86c4f442023-07-19 22:26:39 -0500181 if (dhcpIsEnabled(info.ifaddr.getAddr()))
182 {
183 origin = IP::AddressOrigin::DHCP;
184 }
185
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800186#ifdef LINK_LOCAL_AUTOCONFIGURATION
187 if (info.scope == RT_SCOPE_LINK)
188 {
189 origin = IP::AddressOrigin::LinkLocal;
190 }
191#endif
192
Ravi Tejac6201202023-03-28 21:29:58 -0500193 if ((info.scope == RT_SCOPE_UNIVERSE) && (info.flags & IFA_F_PERMANENT))
194 {
195 origin = IP::AddressOrigin::Static;
196 }
197 if ((info.scope == RT_SCOPE_UNIVERSE) &&
198 ((info.flags & IFA_F_NOPREFIXROUTE) &&
199 (info.flags & IFA_F_MANAGETEMPADDR)))
200 {
201 origin = IP::AddressOrigin::SLAAC;
202 }
203 else if ((info.scope == RT_SCOPE_UNIVERSE) &&
204 ((info.flags & IFA_F_NOPREFIXROUTE)))
205 {
206 origin = IP::AddressOrigin::DHCP;
207 }
208
William A. Kennington III77747f62022-11-07 23:11:15 -0800209 auto it = addrs.find(info.ifaddr);
210 if (it == addrs.end())
211 {
212 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
213 bus, std::string_view(objPath), *this,
214 info.ifaddr, origin));
215 }
216 else
217 {
218 it->second->IPIfaces::origin(origin);
219 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800220}
221
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800222void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
223{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800224 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800225 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700226 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700227 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800228 return;
229 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800230
231 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
232 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700233 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800234 }
235 else
236 {
237 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
238 bus, std::string_view(objPath),
239 *this, *info.addr, *info.mac,
240 Neighbor::State::Permanent));
241 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800242}
243
Patrick Williams6aef7692021-05-01 06:39:41 -0500244ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700245 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530246{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700247 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700248 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530249 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700250 switch (protType)
251 {
252 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700253 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700254 break;
255 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700256 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700257 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700258 default:
259 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700260 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700261 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
262 {
263 throw std::invalid_argument("not unicast");
264 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500265 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700266 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500267 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700268 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
269 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500270 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
271 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
272 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700273 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700274 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500275 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700276 if (prefixLength == 0)
277 {
278 throw std::invalid_argument("default route");
279 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700280 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700281 }
282 catch (const std::exception& e)
283 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700284 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
285 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500286 elog<InvalidArgument>(
287 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700288 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530289 }
290
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700291 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800292 if (it == addrs.end())
293 {
294 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700295 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800296 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700297 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800298 }
299 else
300 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800301 if (it->second->origin() == IP::AddressOrigin::Static)
302 {
303 return it->second->getObjPath();
304 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800305 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
306 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530307
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700308 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800309 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700310
William A. Kennington III434a9432022-11-04 18:38:46 -0700311 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530312}
313
Patrick Williams6aef7692021-05-01 06:39:41 -0500314ObjectPath EthernetInterface::neighbor(std::string ipAddress,
315 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800316{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700317 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700318 try
William A. Kennington III08505792019-01-30 16:00:04 -0800319 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700320 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700321 }
322 catch (const std::exception& e)
323 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700324 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700325 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500326 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
327 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800328 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700329
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700330 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700331 try
William A. Kennington III08505792019-01-30 16:00:04 -0800332 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700333 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700334 }
335 catch (const std::exception& e)
336 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700337 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
338 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500339 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
340 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800341 }
342
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700343 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800344 if (it == staticNeighbors.end())
345 {
346 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700347 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
348 *this, *addr, *lladdr,
349 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800350 }
351 else
352 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700353 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800354 if (it->second->macAddress() == str)
355 {
356 return it->second->getObjPath();
357 }
358 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800359 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700360
361 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800362 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700363
William A. Kennington III434a9432022-11-04 18:38:46 -0700364 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800365}
366
Patrick Williams6aef7692021-05-01 06:39:41 -0500367bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700368{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700369 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700370 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700371 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800372 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700373 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700374 return value;
375}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700376
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700377bool EthernetInterface::dhcp4(bool value)
378{
379 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
380 {
381 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800382 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700383 }
384 return value;
385}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700386
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700387bool EthernetInterface::dhcp6(bool value)
388{
389 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
390 {
391 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800392 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700393 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700394 return value;
395}
396
Patrick Williams6aef7692021-05-01 06:39:41 -0500397EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530398{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700399 auto old4 = EthernetInterfaceIntf::dhcp4();
400 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
401 value == DHCPConf::v4v6stateless ||
402 value == DHCPConf::both);
403 auto old6 = EthernetInterfaceIntf::dhcp6();
404 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
405 value == DHCPConf::both);
406 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
407 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
408 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
409 value == DHCPConf::v6 || value == DHCPConf::both);
410
411 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530412 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700413 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800414 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530415 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530416 return value;
417}
418
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700419EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
420{
421 if (dhcp6())
422 {
423 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
424 }
425 else if (dhcp4())
426 {
427 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
428 }
429 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
430}
431
Tejas Patil2c0fc562021-08-03 19:13:46 +0530432size_t EthernetInterface::mtu(size_t value)
433{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700434 const size_t old = EthernetInterfaceIntf::mtu();
435 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530436 {
437 return value;
438 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700439 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700440 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700441 system::setMTU(ifname, value);
442 return value;
443 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530444}
445
Patrick Williams6aef7692021-05-01 06:39:41 -0500446bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700447{
Patrick Williams6aef7692021-05-01 06:39:41 -0500448 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700449 {
450 return value;
451 }
452
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800453 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700454 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800455 if (!value)
456 {
457 // We only need to bring down the interface, networkd will always bring
458 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800459 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700460 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800461 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800462 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800463
464 return value;
465}
466
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530467ServerList EthernetInterface::staticNameServers(ServerList value)
468{
nitinkotania581cb0b2023-03-21 00:28:55 -0500469 std::vector<std::string> dnsUniqueValues;
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700470 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530471 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700472 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530473 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700474 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700475 }
476 catch (const std::exception& e)
477 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700478 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
479 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700480 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
481 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530482 }
nitinkotania581cb0b2023-03-21 00:28:55 -0500483 if (std::find(dnsUniqueValues.begin(), dnsUniqueValues.end(), ip) ==
484 dnsUniqueValues.end())
485 {
486 dnsUniqueValues.push_back(ip);
487 }
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530488 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700489
nitinkotania581cb0b2023-03-21 00:28:55 -0500490 value =
491 EthernetInterfaceIntf::staticNameServers(std::move(dnsUniqueValues));
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700492
493 writeConfigurationFile();
494 manager.get().reloadConfigs();
495
496 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530497}
498
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600499void EthernetInterface::loadNTPServers(const config::Parser& config)
500{
501 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
502 EthernetInterfaceIntf::staticNTPServers(
503 config.map.getValueStrings("Network", "NTP"));
504}
505
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700506void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530507{
508 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700509 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700510 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530511}
512
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600513ServerList EthernetInterface::getNTPServerFromTimeSyncd()
514{
515 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500516 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
517 TIMESYNCD_SERVICE_PATH,
518 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600519
520 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
521
522 try
523 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800524 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600525 std::variant<ServerList> response;
526 reply.read(response);
527 servers = std::get<ServerList>(response);
528 }
529 catch (const sdbusplus::exception::SdBusError& e)
530 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700531 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700532 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700533 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600534 }
535
536 return servers;
537}
538
Ravi Teja4f8b9a02023-09-06 13:41:52 -0500539ServerList EthernetInterface::nameservers() const
540{
541 return getNameServerFromResolvd();
542}
543
544ServerList EthernetInterface::getNameServerFromResolvd() const
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530545{
546 ServerList servers;
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700547 auto OBJ_PATH = std::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530548
549 /*
550 The DNS property under org.freedesktop.resolve1.Link interface contains
551 an array containing all DNS servers currently used by resolved. It
552 contains similar information as the DNS server data written to
553 /run/systemd/resolve/resolv.conf.
554
555 Each structure in the array consists of a numeric network interface index,
556 an address family, and a byte array containing the DNS server address
557 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
558 The array contains DNS servers configured system-wide, including those
559 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
560 /etc/systemd/resolved.conf, as well as per-interface DNS server
561 information either retrieved from systemd-networkd or configured by
562 external software via SetLinkDNS().
563 */
564
565 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
566 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800567 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
568 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530569
570 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530571
572 try
573 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800574 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530575 reply.read(name);
576 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500577 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530578 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700579 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700580 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700581 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530582 }
583 auto tupleVector = std::get_if<type>(&name);
584 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
585 {
Alexander Filippov983da552021-02-08 15:26:54 +0300586 int addressFamily = std::get<0>(*i);
587 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700588 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700589 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530590 }
591 return servers;
592}
593
William A. Kennington IIId298f932022-10-17 14:31:38 -0700594ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530595{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700596 auto idStr = stdplus::toStr(id);
William A. Kennington III86642522023-07-24 17:55:55 -0700597 auto intfName = stdplus::strCat(interfaceName(), "."sv, idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800598 if (manager.get().interfaces.find(intfName) !=
599 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800600 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700601 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700602 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
603 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800604 }
605
William A. Kennington IIId298f932022-10-17 14:31:38 -0700606 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700607 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700608 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700609 if (!macStr.empty())
610 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700611 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700612 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800613 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800614 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700615 .idx = 0, // TODO: Query the correct value after creation
616 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700617 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700618 .mac = std::move(mac),
619 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700620 .parent_idx = ifIdx,
621 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800622 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530623
Patrick Williams6aef7692021-05-01 06:39:41 -0500624 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530625 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700626 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800627 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700628 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530629
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800630 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530631
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700632 // write the device file for the vlan interface.
633 config::Parser config;
634 auto& netdev = config.map["NetDev"].emplace_back();
635 netdev["Name"].emplace_back(intfName);
636 netdev["Kind"].emplace_back("vlan");
637 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800638 config.writeFile(
639 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700640
641 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800642 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700643
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800644 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530645}
Ratan Gupta2b106532017-07-25 16:05:02 +0530646
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600647ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530648{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700649 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530650
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700651 writeConfigurationFile();
652 manager.get().reloadConfigs();
653
654 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600655}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700656
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600657ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
658{
659 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530660}
Ratan Gupta2b106532017-07-25 16:05:02 +0530661
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700662static constexpr std::string_view tfStr(bool value)
663{
664 return value ? "true"sv : "false"sv;
665}
666
William A. Kennington III945878a2024-04-17 01:05:27 -0700667static void writeUpdatedTime(const Manager& manager,
668 const std::filesystem::path& netFile)
669{
670 // JFFS2 doesn't have the time granularity to deal with sub-second
671 // updates. Since we can have multiple file updates within a second
672 // around a reload, we need a location which gives that precision for
673 // future networkd detected reloads. TMPFS gives us this property.
674 if (manager.getConfDir() == "/etc/systemd/network"sv)
675 {
676 auto dir = stdplus::strCat(netFile.native(), ".d");
677 dir.replace(1, 3, "run"); // Replace /etc with /run
678 auto file = dir + "/updated.conf";
679 try
680 {
681 std::filesystem::create_directories(dir);
682 using namespace stdplus::fd;
683 futimens(
684 open(file,
685 OpenFlags(OpenAccess::WriteOnly).set(OpenFlag::Create),
686 0644)
687 .get(),
688 nullptr);
689 }
690 catch (const std::exception& e)
691 {
692 lg2::error("Failed to write time updated file {FILE}: {ERROR}",
693 "FILE", file, "ERROR", e.what());
694 }
695 }
696}
697
Ratan Gupta2b106532017-07-25 16:05:02 +0530698void EthernetInterface::writeConfigurationFile()
699{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700700 config::Parser config;
701 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530702 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700703 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800704#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700705 auto mac = MacAddressIntf::macAddress();
706 if (!mac.empty())
707 {
708 link["MACAddress"].emplace_back(mac);
709 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800710#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700711 if (!EthernetInterfaceIntf::nicEnabled())
712 {
713 link["Unmanaged"].emplace_back("yes");
714 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700715 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 {
717 auto& network = config.map["Network"].emplace_back();
718 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400719#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700720 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400721#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700722 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400723#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700724 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
725 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
726 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600727 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700728 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800729 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700730 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700731 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
732 {
733 vlans.emplace_back(intf->interfaceName());
734 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700735 }
736 }
737 {
738 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600739 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700740 {
741 ntps.emplace_back(ntp);
742 }
743 }
744 {
745 auto& dnss = network["DNS"];
746 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
747 {
748 dnss.emplace_back(dns);
749 }
750 }
751 {
752 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700753 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700754 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700755 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700756 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700757 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700758 }
759 }
760 }
761 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700762 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700763 {
Ravi Teja91f60562024-04-17 06:26:43 -0500764 auto gateway4 = EthernetInterfaceIntf::defaultGateway();
765 if (!gateway4.empty())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700766 {
Ravi Teja91f60562024-04-17 06:26:43 -0500767 auto& gateway4route = config.map["Route"].emplace_back();
768 gateway4route["Gateway"].emplace_back(gateway4);
769 gateway4route["GatewayOnLink"].emplace_back("true");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700770 }
771 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530772
William A. Kennington III05cbc5b2023-07-20 19:37:30 -0700773 if (!ipv6AcceptRA())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700774 {
775 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
776 if (!gateway6.empty())
777 {
Ravi Teja91f60562024-04-17 06:26:43 -0500778 auto& gateway6route = config.map["Route"].emplace_back();
779 gateway6route["Gateway"].emplace_back(gateway6);
780 gateway6route["GatewayOnLink"].emplace_back("true");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700781 }
782 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600783 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800784 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700785 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700786 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500787 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700788 auto& neighbors = config.map["Neighbor"];
789 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800790 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700791 auto& neighbor = neighbors.emplace_back();
792 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
793 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800794 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500795 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500796 {
Jishnu CM57dfea92023-05-05 06:07:26 -0500797 auto& dhcp4 = config.map["DHCPv4"].emplace_back();
798 dhcp4["ClientIdentifier"].emplace_back("mac");
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700799 dhcp4["UseDNS"].emplace_back(tfStr(dhcp4Conf->dnsEnabled()));
800 dhcp4["UseDomains"].emplace_back(tfStr(dhcp4Conf->domainEnabled()));
801 dhcp4["UseNTP"].emplace_back(tfStr(dhcp4Conf->ntpEnabled()));
802 dhcp4["UseHostname"].emplace_back(tfStr(dhcp4Conf->hostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500803 dhcp4["SendHostname"].emplace_back(
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700804 tfStr(dhcp4Conf->sendHostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500805 }
806 {
807 auto& dhcp6 = config.map["DHCPv6"].emplace_back();
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700808 dhcp6["UseDNS"].emplace_back(tfStr(dhcp6Conf->dnsEnabled()));
809 dhcp6["UseDomains"].emplace_back(tfStr(dhcp6Conf->domainEnabled()));
810 dhcp6["UseNTP"].emplace_back(tfStr(dhcp6Conf->ntpEnabled()));
811 dhcp6["UseHostname"].emplace_back(tfStr(dhcp6Conf->hostNameEnabled()));
William A. Kennington III44937b12024-04-17 00:28:20 -0700812 dhcp6["SendHostname"].emplace_back(
813 tfStr(dhcp6Conf->sendHostNameEnabled()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500814 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500815 auto path = config::pathForIntfConf(manager.get().getConfDir(),
816 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700817 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700818 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
William A. Kennington III945878a2024-04-17 01:05:27 -0700819 writeUpdatedTime(manager, path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530820}
821
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800822std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530823{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700824 if (vlan)
825 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700826 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700827 elog<InternalFailure>();
828 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800829#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700830 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600831 try
832 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700833 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600834 }
Patrick Williams5758db32021-10-06 12:29:22 -0500835 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600836 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700837 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600838 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
839 Argument::ARGUMENT_VALUE(value.c_str()));
840 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700841 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530842 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700843 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500844 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
845 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530846 }
847
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300848 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700849 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300850
William A. Kennington III1137a972019-04-20 20:49:58 -0700851 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700852 auto oldMAC =
853 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700854 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530855 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700856 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800857 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530858 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700859 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
860 {
861 intf->MacAddressIntf::macAddress(validMAC);
862 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530863 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500864 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530865
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700866 writeConfigurationFile();
William A. Kennington III945878a2024-04-17 01:05:27 -0700867 manager.get().addReloadPreHook([interface, manager = manager]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800868 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700869 system::setNICUp(interface, false);
William A. Kennington III945878a2024-04-17 01:05:27 -0700870 writeUpdatedTime(
871 manager,
872 config::pathForIntfConf(manager.get().getConfDir(), interface));
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800873 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800874 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530875 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700876
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300877#ifdef HAVE_UBOOT_ENV
878 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700879 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300880 if (envVar)
881 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500882 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
883 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
884 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
885 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300886 }
887#endif // HAVE_UBOOT_ENV
888
William A. Kennington III1137a972019-04-20 20:49:58 -0700889 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800890#else
891 elog<NotAllowed>(
892 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
893#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530894}
895
Ratan Guptae9c9b812017-09-22 17:15:37 +0530896void EthernetInterface::deleteAll()
897{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530898 // clear all the ip on the interface
899 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700900
901 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800902 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530903}
904
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800905template <typename Addr>
906static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500907{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800908 if (gw.empty())
909 {
910 return;
911 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700912 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500913 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800914 auto ip = stdplus::fromStr<Addr>(gw);
915 if (ip == Addr{})
916 {
917 gw.clear();
918 return;
919 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800920 if (!validIntfIP(ip))
921 {
922 throw std::invalid_argument("Invalid unicast");
923 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800924 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500925 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700926 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500927 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800928 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500929 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800930 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500931 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800932}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700933
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800934std::string EthernetInterface::defaultGateway(std::string gateway)
935{
936 normalizeGateway<stdplus::In4Addr>(gateway);
937 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700938 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800939 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700940 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800941 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700942 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700943 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500944}
945
946std::string EthernetInterface::defaultGateway6(std::string gateway)
947{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800948 normalizeGateway<stdplus::In6Addr>(gateway);
949 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500950 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800951 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700952 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800953 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500954 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700955 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500956}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700957
958EthernetInterface::VlanProperties::VlanProperties(
959 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800960 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800961 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700962 parentIdx(*info.parent_idx), eth(eth)
963{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800964 VlanIntf::id(*info.vlan_id, true);
965 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700966}
967
968void EthernetInterface::VlanProperties::delete_()
969{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800970 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700971
972 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800973 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700974 std::error_code ec;
975 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
976 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
977
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800978 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800979 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800980 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800981 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800982 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800983 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800984 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800985
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700986 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800987 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700988 {
989 if (intf->ifIdx == parentIdx)
990 {
991 intf->writeConfigurationFile();
992 }
993 }
994
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800995 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700996 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800997 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800998 eth.get().manager.get().addReloadPostHook(
999 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -08001000
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001001 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001002 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -07001003 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001004
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001005 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001006}
1007
Jishnu CM57dfea92023-05-05 06:07:26 -05001008void EthernetInterface::reloadConfigs()
1009{
1010 manager.get().reloadConfigs();
1011}
1012
Gunnar Mills57d9c502018-09-14 14:42:34 -05001013} // namespace network
1014} // namespace phosphor