blob: 40fda8ce48013ee8c8cc67915333b037bee70753 [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
Ravi Tejaab27a812023-05-02 10:01:53 -050010#include <arpa/inet.h>
11#include <fcntl.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>
William A. Kennington III9c441fd2023-02-24 13:40:01 -080014#include <net/if_arp.h>
Yuxiao Zhang46938072023-09-26 17:59:14 -070015#include <sys/stat.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053016
Patrick Venture189d44e2018-07-09 12:30:59 -070017#include <phosphor-logging/elog-errors.hpp>
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -070018#include <phosphor-logging/lg2.hpp>
William A. Kennington III945878a2024-04-17 01:05:27 -070019#include <stdplus/fd/create.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070020#include <stdplus/raw.hpp>
William A. Kennington III86642522023-07-24 17:55:55 -070021#include <stdplus/str/cat.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070022#include <stdplus/zstring.hpp>
Patrick Williams89d734b2023-05-10 07:50:25 -050023#include <xyz/openbmc_project/Common/error.hpp>
24
25#include <algorithm>
26#include <filesystem>
William A. Kennington IIIcafc1512023-07-25 02:22:32 -070027#include <format>
Ratan Gupta2b106532017-07-25 16:05:02 +053028#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070029#include <unordered_map>
30#include <variant>
Ratan Gupta82549cc2017-04-21 08:45:23 +053031
Ratan Gupta91a99cc2017-04-14 16:32:09 +053032namespace phosphor
33{
34namespace network
35{
36
37using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053038using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053039using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
40using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050041using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070042using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053043constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
44constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
45constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
46constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060047
48constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
49constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
50constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
51
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053052constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053053
William A. Kennington III2e09d272022-10-14 17:15:00 -070054template <typename Func>
Patrick Williams618ac412025-04-27 02:31:49 -040055inline decltype(std::declval<Func>()()) ignoreError(
56 std::string_view msg, stdplus::zstring_view intf,
57 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080058{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070059 try
60 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070061 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070062 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070063 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070064 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -070065 lg2::error("{MSG} failed on {NET_INTF}: {ERROR}", "MSG", msg,
66 "NET_INTF", intf, "ERROR", e);
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070067 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070068 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070069}
William A. Kennington IIId298f932022-10-17 14:31:38 -070070
William A. Kennington IIId298f932022-10-17 14:31:38 -070071static std::string makeObjPath(std::string_view root, std::string_view intf)
72{
William A. Kennington III86642522023-07-24 17:55:55 -070073 auto ret = stdplus::strCat(root, "/"sv, intf);
William A. Kennington IIId298f932022-10-17 14:31:38 -070074 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
75 return ret;
76}
77
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -080078template <typename Addr>
79static bool validIntfIP(Addr a) noexcept
80{
81 return a.isUnicast() && !a.isLoopback();
82}
83
Patrick Williamsad205022024-08-16 15:20:07 -040084EthernetInterface::EthernetInterface(
85 stdplus::PinnedRef<sdbusplus::bus_t> bus,
86 stdplus::PinnedRef<Manager> manager, const AllIntfInfo& info,
87 std::string_view objRoot, const config::Parser& config, 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
Patrick Williamsad205022024-08-16 15:20:07 -040092EthernetInterface::EthernetInterface(
93 stdplus::PinnedRef<sdbusplus::bus_t> bus,
94 stdplus::PinnedRef<Manager> manager, const AllIntfInfo& info,
95 std::string&& objPath, const config::Parser& config, bool enabled) :
96 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit), manager(manager),
97 bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +053098{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080099 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700100 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800101 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
102 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
103 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
104 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaf7116de2024-12-08 22:48:21 -0600105 auto lldpVal = parseLLDPConf();
106 if (!lldpVal.empty())
107 {
108 EthernetInterfaceIntf::emitLLDP(lldpVal[interfaceName()], true);
109 }
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700110 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800111 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +0530112
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800113 updateInfo(info.intf, true);
114
115 if (info.defgw4)
116 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700117 EthernetInterface::defaultGateway(stdplus::toStr(*info.defgw4), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800118 }
119 if (info.defgw6)
120 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700121 EthernetInterface::defaultGateway6(stdplus::toStr(*info.defgw6), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800122 }
123 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700124
William A. Kennington III13d665c2022-11-15 20:34:40 -0800125 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700126 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800127 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700128 {
129 std::runtime_error("Missing parent link");
130 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800131 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
132 }
William A. Kennington IIIfad525c2024-04-17 00:51:59 -0700133 dhcp4Conf.emplace(bus, this->objPath + "/dhcp4", *this, DHCPType::v4);
134 dhcp6Conf.emplace(bus, this->objPath + "/dhcp6", *this, DHCPType::v6);
William A. Kennington III13d665c2022-11-15 20:34:40 -0800135 for (const auto& [_, addr] : info.addrs)
136 {
137 addAddr(addr);
138 }
139 for (const auto& [_, neigh] : info.staticNeighs)
140 {
141 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700142 }
Ravi Tejaab27a812023-05-02 10:01:53 -0500143 for (const auto& [_, staticGateway] : info.staticGateways)
144 {
145 addStaticGateway(staticGateway);
146 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530147}
148
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800149void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700150{
William A. Kennington III876927c2022-11-17 16:20:15 -0800151 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800152 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700153 if (info.mac)
154 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700155 MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700156 }
157 if (info.mtu)
158 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800159 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700160 }
William A. Kennington III21539662022-11-15 14:53:11 -0800161 if (ifIdx > 0)
162 {
163 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
164 return system::getEthInfo(*info.name);
165 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800166 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
167 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
Ravi Teja970c7b62026-01-05 11:53:40 -0600168 EthernetInterfaceIntf::fullDuplex(ethInfo.fullDuplex, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800169 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700170}
171
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800172void EthernetInterface::addAddr(const AddressInfo& info)
173{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800174 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ravi Teja86c4f442023-07-19 22:26:39 -0500175 if (dhcpIsEnabled(info.ifaddr.getAddr()))
176 {
177 origin = IP::AddressOrigin::DHCP;
178 }
179
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800180#ifdef LINK_LOCAL_AUTOCONFIGURATION
Ravi Tejaf02fc4a2025-12-17 00:59:21 -0600181 if (info.scope == RT_SCOPE_LINK &&
182 std::holds_alternative<stdplus::In6Addr>(info.ifaddr.getAddr()))
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800183 {
184 origin = IP::AddressOrigin::LinkLocal;
185 }
Ravi Tejaf02fc4a2025-12-17 00:59:21 -0600186 else if (info.scope == RT_SCOPE_LINK &&
187 std::holds_alternative<stdplus::In4Addr>(info.ifaddr.getAddr()))
188 {
189 try
190 {
191 stdplus::ToStrHandle<stdplus::IntToStr<10, unsigned>> tsh;
192 auto obj = stdplus::strCat("/org/freedesktop/network1/link/_3"sv,
193 tsh(info.ifidx));
194 auto req = bus.get().new_method_call(
195 "org.freedesktop.network1", obj.c_str(),
196 "org.freedesktop.DBus.Properties", "GetAll");
197 req.append("org.freedesktop.network1.Link");
198 auto rsp = req.call();
199 std::map<std::string, std::variant<std::string>> props;
200 rsp.read(props);
201 auto operationalStateIt = props.find("OperationalState");
202 auto ipv4addressStateIt = props.find("IPv4AddressState");
203
204 if ((operationalStateIt != props.end()) &&
205 (ipv4addressStateIt != props.end()))
206 {
207 const std::string& opState =
208 std::get<std::string>(operationalStateIt->second);
209 const std::string& ipv4State =
210 std::get<std::string>(ipv4addressStateIt->second);
211 if ((opState == "routable") && (ipv4State == "routable"))
212 {
213 bool status = system::deleteLinkLocalIPv4ViaNetlink(
214 info.ifidx, info.ifaddr);
215 if (status)
216 {
217 lg2::info("Deleted IPv4 linklocal address");
218 }
219 else
220 {
221 lg2::error("Failed to delete IPv4 Linklocal address");
222 }
223 }
224 else
225 {
226 origin = IP::AddressOrigin::LinkLocal;
227 }
228 }
229 }
230 catch (const std::exception& e)
231 {
232 lg2::error(
233 "Failed to read link OperationalState and IPv4AddressState : {ERROR}",
234 "ERROR", e);
235 }
236 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800237#endif
238
Ravi Tejac6201202023-03-28 21:29:58 -0500239 if ((info.scope == RT_SCOPE_UNIVERSE) && (info.flags & IFA_F_PERMANENT))
240 {
241 origin = IP::AddressOrigin::Static;
242 }
243 if ((info.scope == RT_SCOPE_UNIVERSE) &&
244 ((info.flags & IFA_F_NOPREFIXROUTE) &&
245 (info.flags & IFA_F_MANAGETEMPADDR)))
246 {
247 origin = IP::AddressOrigin::SLAAC;
248 }
249 else if ((info.scope == RT_SCOPE_UNIVERSE) &&
250 ((info.flags & IFA_F_NOPREFIXROUTE)))
251 {
252 origin = IP::AddressOrigin::DHCP;
253 }
254
William A. Kennington III77747f62022-11-07 23:11:15 -0800255 auto it = addrs.find(info.ifaddr);
256 if (it == addrs.end())
257 {
258 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
259 bus, std::string_view(objPath), *this,
260 info.ifaddr, origin));
261 }
262 else
263 {
264 it->second->IPIfaces::origin(origin);
265 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800266}
267
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800268void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
269{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800270 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800271 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700272 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700273 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800274 return;
275 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800276
277 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
278 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700279 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800280 }
281 else
282 {
Patrick Williamsad205022024-08-16 15:20:07 -0400283 staticNeighbors.emplace(
284 *info.addr, std::make_unique<Neighbor>(
285 bus, std::string_view(objPath), *this, *info.addr,
286 *info.mac, Neighbor::State::Permanent));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800287 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800288}
289
Ravi Tejaab27a812023-05-02 10:01:53 -0500290void EthernetInterface::addStaticGateway(const StaticGatewayInfo& info)
291{
292 if (!info.gateway)
293 {
294 lg2::error("Missing static gateway on {NET_INTF}", "NET_INTF",
295 interfaceName());
296 return;
297 }
298
299 IP::Protocol protocolType;
300 if (*info.protocol == "IPv4")
301 {
302 protocolType = IP::Protocol::IPv4;
303 }
304 else if (*info.protocol == "IPv6")
305 {
306 protocolType = IP::Protocol::IPv6;
307 }
308
309 if (auto it = staticGateways.find(*info.gateway);
310 it != staticGateways.end())
311 {
312 it->second->StaticGatewayObj::gateway(*info.gateway);
313 }
314 else
315 {
316 staticGateways.emplace(*info.gateway,
317 std::make_unique<StaticGateway>(
318 bus, std::string_view(objPath), *this,
319 *info.gateway, protocolType));
320 }
321}
322
Patrick Williams6aef7692021-05-01 06:39:41 -0500323ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700324 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530325{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700326 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700327 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530328 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700329 switch (protType)
330 {
331 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700332 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700333 break;
334 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700335 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700336 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700337 default:
338 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700339 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700340 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
341 {
342 throw std::invalid_argument("not unicast");
343 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500344 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700345 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500346 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700347 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
348 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500349 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
350 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
351 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700352 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700353 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500354 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700355 if (prefixLength == 0)
356 {
357 throw std::invalid_argument("default route");
358 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700359 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700360 }
361 catch (const std::exception& e)
362 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700363 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
364 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500365 elog<InvalidArgument>(
366 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700367 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530368 }
369
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700370 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800371 if (it == addrs.end())
372 {
373 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700374 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800375 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700376 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800377 }
378 else
379 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800380 if (it->second->origin() == IP::AddressOrigin::Static)
381 {
382 return it->second->getObjPath();
383 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800384 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
385 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530386
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700387 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800388 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700389
William A. Kennington III434a9432022-11-04 18:38:46 -0700390 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530391}
392
Patrick Williams6aef7692021-05-01 06:39:41 -0500393ObjectPath EthernetInterface::neighbor(std::string ipAddress,
394 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800395{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700396 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700397 try
William A. Kennington III08505792019-01-30 16:00:04 -0800398 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700399 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700400 }
401 catch (const std::exception& e)
402 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700403 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700404 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500405 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
406 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800407 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700408
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700409 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700410 try
William A. Kennington III08505792019-01-30 16:00:04 -0800411 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700412 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700413 }
414 catch (const std::exception& e)
415 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700416 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
417 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500418 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
419 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800420 }
421
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700422 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800423 if (it == staticNeighbors.end())
424 {
425 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700426 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
427 *this, *addr, *lladdr,
428 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800429 }
430 else
431 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700432 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800433 if (it->second->macAddress() == str)
434 {
435 return it->second->getObjPath();
436 }
437 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800438 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700439
440 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800441 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700442
William A. Kennington III434a9432022-11-04 18:38:46 -0700443 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800444}
445
Ravi Tejaab27a812023-05-02 10:01:53 -0500446ObjectPath EthernetInterface::staticGateway(std::string gateway,
447 IP::Protocol protocolType)
448{
449 std::optional<stdplus::InAnyAddr> addr;
450 std::string route;
451 try
452 {
kokilav0779db72025-01-07 10:21:51 -0600453 switch (protocolType)
454 {
455 case IP::Protocol::IPv4:
456 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(gateway));
457 break;
458 case IP::Protocol::IPv6:
459 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(gateway));
460 break;
461 default:
462 throw std::logic_error("Exhausted protocols");
463 }
Ravi Tejaab27a812023-05-02 10:01:53 -0500464 route = gateway;
465 }
466 catch (const std::exception& e)
467 {
468 lg2::error("Not a valid IP address {GATEWAY}: {ERROR}", "GATEWAY",
469 gateway, "ERROR", e);
470 elog<InvalidArgument>(Argument::ARGUMENT_NAME("gateway"),
471 Argument::ARGUMENT_VALUE(gateway.c_str()));
472 }
473
474 auto it = staticGateways.find(route);
475 if (it == staticGateways.end())
476 {
477 it = std::get<0>(staticGateways.emplace(
478 route,
479 std::make_unique<StaticGateway>(bus, std::string_view(objPath),
480 *this, gateway, protocolType)));
481 }
482 else
483 {
484 it->second->StaticGatewayObj::gateway(gateway);
485 }
486
487 writeConfigurationFile();
488 manager.get().reloadConfigs();
489
490 return it->second->getObjPath();
491}
492
Patrick Williams6aef7692021-05-01 06:39:41 -0500493bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700494{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700495 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700496 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700497 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800498 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700499 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700500 return value;
501}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700502
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700503bool EthernetInterface::dhcp4(bool value)
504{
505 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
506 {
507 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800508 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700509 }
510 return value;
511}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700512
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700513bool EthernetInterface::dhcp6(bool value)
514{
515 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
516 {
517 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800518 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700519 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700520 return value;
521}
522
Patrick Williams6aef7692021-05-01 06:39:41 -0500523EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530524{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700525 auto old4 = EthernetInterfaceIntf::dhcp4();
Patrick Williamsad205022024-08-16 15:20:07 -0400526 auto new4 = EthernetInterfaceIntf::dhcp4(
527 value == DHCPConf::v4 || value == DHCPConf::v4v6stateless ||
528 value == DHCPConf::both);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700529 auto old6 = EthernetInterfaceIntf::dhcp6();
Patrick Williamsad205022024-08-16 15:20:07 -0400530 auto new6 = EthernetInterfaceIntf::dhcp6(
531 value == DHCPConf::v6 || value == DHCPConf::both);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700532 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
533 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
534 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
535 value == DHCPConf::v6 || value == DHCPConf::both);
536
537 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530538 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700539 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800540 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530541 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530542 return value;
543}
544
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700545EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
546{
547 if (dhcp6())
548 {
549 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
550 }
551 else if (dhcp4())
552 {
553 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
554 }
555 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
556}
557
Tejas Patil2c0fc562021-08-03 19:13:46 +0530558size_t EthernetInterface::mtu(size_t value)
559{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700560 const size_t old = EthernetInterfaceIntf::mtu();
561 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530562 {
563 return value;
564 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700565 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700566 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700567 system::setMTU(ifname, value);
568 return value;
569 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530570}
571
Patrick Williams6aef7692021-05-01 06:39:41 -0500572bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700573{
Patrick Williams6aef7692021-05-01 06:39:41 -0500574 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700575 {
576 return value;
577 }
578
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800579 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700580 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800581 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800582
583 return value;
584}
585
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530586ServerList EthernetInterface::staticNameServers(ServerList value)
587{
nitinkotania581cb0b2023-03-21 00:28:55 -0500588 std::vector<std::string> dnsUniqueValues;
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700589 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530590 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700591 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530592 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700593 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700594 }
595 catch (const std::exception& e)
596 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700597 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
598 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700599 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
600 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530601 }
nitinkotania581cb0b2023-03-21 00:28:55 -0500602 if (std::find(dnsUniqueValues.begin(), dnsUniqueValues.end(), ip) ==
603 dnsUniqueValues.end())
604 {
605 dnsUniqueValues.push_back(ip);
606 }
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530607 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700608
nitinkotania581cb0b2023-03-21 00:28:55 -0500609 value =
610 EthernetInterfaceIntf::staticNameServers(std::move(dnsUniqueValues));
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700611
612 writeConfigurationFile();
613 manager.get().reloadConfigs();
614
615 return value;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530616}
617
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600618void EthernetInterface::loadNTPServers(const config::Parser& config)
619{
Jishnu CM4fe86132024-09-15 12:02:56 -0500620 ServerList ntpServerList = getNTPServerFromTimeSyncd();
621 ServerList staticNTPServers = config.map.getValueStrings("Network", "NTP");
622
623 std::unordered_set<std::string> staticNTPServersSet(
624 staticNTPServers.begin(), staticNTPServers.end());
625 ServerList networkSuppliedServers;
626
627 std::copy_if(ntpServerList.begin(), ntpServerList.end(),
628 std::back_inserter(networkSuppliedServers),
629 [&staticNTPServersSet](const std::string& server) {
630 return staticNTPServersSet.find(server) ==
631 staticNTPServersSet.end();
632 });
633
634 EthernetInterfaceIntf::ntpServers(networkSuppliedServers);
635 EthernetInterfaceIntf::staticNTPServers(staticNTPServers);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600636}
637
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700638void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530639{
640 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700641 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700642 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530643}
644
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600645ServerList EthernetInterface::getNTPServerFromTimeSyncd()
646{
647 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williamsad205022024-08-16 15:20:07 -0400648 auto method =
649 bus.get().new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
650 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600651
652 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
653
654 try
655 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800656 auto reply = bus.get().call(method);
Patrick Williams137d9442025-11-05 00:17:55 -0500657 auto response = reply.unpack<std::variant<ServerList>>();
658
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600659 servers = std::get<ServerList>(response);
660 }
661 catch (const sdbusplus::exception::SdBusError& e)
662 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700663 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700664 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700665 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600666 }
667
668 return servers;
669}
670
Ravi Teja4f8b9a02023-09-06 13:41:52 -0500671ServerList EthernetInterface::nameservers() const
672{
673 return getNameServerFromResolvd();
674}
675
676ServerList EthernetInterface::getNameServerFromResolvd() const
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530677{
678 ServerList servers;
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700679 auto OBJ_PATH = std::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530680
681 /*
682 The DNS property under org.freedesktop.resolve1.Link interface contains
683 an array containing all DNS servers currently used by resolved. It
684 contains similar information as the DNS server data written to
685 /run/systemd/resolve/resolv.conf.
686
687 Each structure in the array consists of a numeric network interface index,
688 an address family, and a byte array containing the DNS server address
689 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
690 The array contains DNS servers configured system-wide, including those
691 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
692 /etc/systemd/resolved.conf, as well as per-interface DNS server
693 information either retrieved from systemd-networkd or configured by
694 external software via SetLinkDNS().
695 */
696
697 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
698 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800699 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
700 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530701
702 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530703
704 try
705 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800706 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530707 reply.read(name);
708 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500709 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530710 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700711 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700712 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700713 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530714 }
715 auto tupleVector = std::get_if<type>(&name);
716 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
717 {
Alexander Filippov983da552021-02-08 15:26:54 +0300718 int addressFamily = std::get<0>(*i);
719 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700720 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700721 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530722 }
723 return servers;
724}
725
William A. Kennington IIId298f932022-10-17 14:31:38 -0700726ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530727{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700728 auto idStr = stdplus::toStr(id);
William A. Kennington III86642522023-07-24 17:55:55 -0700729 auto intfName = stdplus::strCat(interfaceName(), "."sv, idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800730 if (manager.get().interfaces.find(intfName) !=
731 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800732 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700733 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700734 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
735 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800736 }
737
William A. Kennington IIId298f932022-10-17 14:31:38 -0700738 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700739 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700740 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700741 if (!macStr.empty())
742 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700743 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700744 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800745 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800746 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700747 .idx = 0, // TODO: Query the correct value after creation
748 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700749 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700750 .mac = std::move(mac),
751 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700752 .parent_idx = ifIdx,
753 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800754 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530755
Patrick Williams6aef7692021-05-01 06:39:41 -0500756 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530757 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700758 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800759 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700760 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530761
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800762 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530763
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700764 // write the device file for the vlan interface.
765 config::Parser config;
766 auto& netdev = config.map["NetDev"].emplace_back();
767 netdev["Name"].emplace_back(intfName);
768 netdev["Kind"].emplace_back("vlan");
769 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800770 config.writeFile(
771 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700772
773 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800774 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700775
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800776 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530777}
Ratan Gupta2b106532017-07-25 16:05:02 +0530778
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600779ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530780{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700781 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530782
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700783 writeConfigurationFile();
784 manager.get().reloadConfigs();
785
786 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600787}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700788
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600789ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
790{
791 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530792}
Ratan Gupta2b106532017-07-25 16:05:02 +0530793
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700794static constexpr std::string_view tfStr(bool value)
795{
796 return value ? "true"sv : "false"sv;
797}
798
William A. Kennington III945878a2024-04-17 01:05:27 -0700799static void writeUpdatedTime(const Manager& manager,
800 const std::filesystem::path& netFile)
801{
802 // JFFS2 doesn't have the time granularity to deal with sub-second
803 // updates. Since we can have multiple file updates within a second
804 // around a reload, we need a location which gives that precision for
805 // future networkd detected reloads. TMPFS gives us this property.
806 if (manager.getConfDir() == "/etc/systemd/network"sv)
807 {
808 auto dir = stdplus::strCat(netFile.native(), ".d");
809 dir.replace(1, 3, "run"); // Replace /etc with /run
810 auto file = dir + "/updated.conf";
811 try
812 {
813 std::filesystem::create_directories(dir);
814 using namespace stdplus::fd;
815 futimens(
816 open(file,
817 OpenFlags(OpenAccess::WriteOnly).set(OpenFlag::Create),
818 0644)
819 .get(),
820 nullptr);
821 }
822 catch (const std::exception& e)
823 {
824 lg2::error("Failed to write time updated file {FILE}: {ERROR}",
825 "FILE", file, "ERROR", e.what());
826 }
827 }
828}
829
Ratan Gupta2b106532017-07-25 16:05:02 +0530830void EthernetInterface::writeConfigurationFile()
831{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700832 config::Parser config;
833 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530834 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700835 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800836#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700837 auto mac = MacAddressIntf::macAddress();
838 if (!mac.empty())
839 {
840 link["MACAddress"].emplace_back(mac);
841 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800842#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700843 if (!EthernetInterfaceIntf::nicEnabled())
844 {
Johnathan Mantey8e3c1fb2024-03-12 13:07:50 -0700845 link["ActivationPolicy"].emplace_back("down");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700846 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700847 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700848 {
849 auto& network = config.map["Network"].emplace_back();
850 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400851#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700852 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400853#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700854 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400855#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700856 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
857 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
858 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600859 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700860 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800861 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700862 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700863 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
864 {
865 vlans.emplace_back(intf->interfaceName());
866 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700867 }
868 }
869 {
870 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600871 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700872 {
873 ntps.emplace_back(ntp);
874 }
875 }
876 {
877 auto& dnss = network["DNS"];
878 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
879 {
880 dnss.emplace_back(dns);
881 }
882 }
883 {
884 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700885 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700886 {
Johnathan Mantey3865db22023-09-27 12:39:16 -0700887 if (addr.second->origin() == IP::AddressOrigin::Static)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700888 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700889 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700890 }
891 }
892 }
893 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700894 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700895 {
Ravi Teja91f60562024-04-17 06:26:43 -0500896 auto gateway4 = EthernetInterfaceIntf::defaultGateway();
897 if (!gateway4.empty())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700898 {
Ravi Teja91f60562024-04-17 06:26:43 -0500899 auto& gateway4route = config.map["Route"].emplace_back();
900 gateway4route["Gateway"].emplace_back(gateway4);
901 gateway4route["GatewayOnLink"].emplace_back("true");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700902 }
903 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530904
William A. Kennington III05cbc5b2023-07-20 19:37:30 -0700905 if (!ipv6AcceptRA())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700906 {
907 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
908 if (!gateway6.empty())
909 {
Ravi Teja91f60562024-04-17 06:26:43 -0500910 auto& gateway6route = config.map["Route"].emplace_back();
911 gateway6route["Gateway"].emplace_back(gateway6);
912 gateway6route["GatewayOnLink"].emplace_back("true");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700913 }
914 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600915 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800916 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700917 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700918 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500919 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700920 auto& neighbors = config.map["Neighbor"];
921 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800922 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700923 auto& neighbor = neighbors.emplace_back();
924 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
925 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800926 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500927 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500928 {
Jishnu CM57dfea92023-05-05 06:07:26 -0500929 auto& dhcp4 = config.map["DHCPv4"].emplace_back();
930 dhcp4["ClientIdentifier"].emplace_back("mac");
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700931 dhcp4["UseDNS"].emplace_back(tfStr(dhcp4Conf->dnsEnabled()));
932 dhcp4["UseDomains"].emplace_back(tfStr(dhcp4Conf->domainEnabled()));
933 dhcp4["UseNTP"].emplace_back(tfStr(dhcp4Conf->ntpEnabled()));
934 dhcp4["UseHostname"].emplace_back(tfStr(dhcp4Conf->hostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500935 dhcp4["SendHostname"].emplace_back(
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700936 tfStr(dhcp4Conf->sendHostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500937 }
938 {
939 auto& dhcp6 = config.map["DHCPv6"].emplace_back();
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700940 dhcp6["UseDNS"].emplace_back(tfStr(dhcp6Conf->dnsEnabled()));
941 dhcp6["UseDomains"].emplace_back(tfStr(dhcp6Conf->domainEnabled()));
942 dhcp6["UseNTP"].emplace_back(tfStr(dhcp6Conf->ntpEnabled()));
943 dhcp6["UseHostname"].emplace_back(tfStr(dhcp6Conf->hostNameEnabled()));
William A. Kennington III44937b12024-04-17 00:28:20 -0700944 dhcp6["SendHostname"].emplace_back(
945 tfStr(dhcp6Conf->sendHostNameEnabled()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500946 }
Ravi Tejaab27a812023-05-02 10:01:53 -0500947
948 {
949 auto& sroutes = config.map["Route"];
950 for (const auto& temp : staticGateways)
951 {
952 auto& staticGateway = sroutes.emplace_back();
953 staticGateway["Gateway"].emplace_back(temp.second->gateway());
954 staticGateway["GatewayOnLink"].emplace_back("true");
955 }
956 }
957
Patrick Williamsad205022024-08-16 15:20:07 -0400958 auto path =
959 config::pathForIntfConf(manager.get().getConfDir(), interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700960 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700961 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
William A. Kennington III945878a2024-04-17 01:05:27 -0700962 writeUpdatedTime(manager, path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530963}
964
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800965std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530966{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700967 if (vlan)
968 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700969 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700970 elog<InternalFailure>();
971 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800972#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700973 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600974 try
975 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700976 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600977 }
kokilavf51a2c62024-12-12 02:18:34 -0600978 catch (const std::exception& e)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600979 {
Milton D. Miller IIe0349902025-04-12 23:23:04 +0000980 lg2::error("Invalid MAC address {NET_MAC}: {ERROR}", "NET_MAC", value,
kokilavf51a2c62024-12-12 02:18:34 -0600981 "ERROR", e);
982 elog<InvalidArgument>(Argument::ARGUMENT_NAME("netmac"),
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600983 Argument::ARGUMENT_VALUE(value.c_str()));
984 }
kokilavf51a2c62024-12-12 02:18:34 -0600985
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700986 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530987 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700988 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500989 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
990 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530991 }
992
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300993 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700994 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300995
William A. Kennington III1137a972019-04-20 20:49:58 -0700996 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700997 auto oldMAC =
998 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700999 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +05301000 {
William A. Kennington III1137a972019-04-20 20:49:58 -07001001 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001002 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +05301003 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001004 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
1005 {
1006 intf->MacAddressIntf::macAddress(validMAC);
1007 }
Ratan Guptabd303b12017-08-18 17:10:07 +05301008 }
Patrick Williams6aef7692021-05-01 06:39:41 -05001009 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +05301010
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001011 writeConfigurationFile();
William A. Kennington III945878a2024-04-17 01:05:27 -07001012 manager.get().addReloadPreHook([interface, manager = manager]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001013 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -07001014 system::setNICUp(interface, false);
William A. Kennington III945878a2024-04-17 01:05:27 -07001015 writeUpdatedTime(
1016 manager,
1017 config::pathForIntfConf(manager.get().getConfDir(), interface));
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -08001018 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001019 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +05301020 }
William A. Kennington III1137a972019-04-20 20:49:58 -07001021
William A. Kennington III64f61262022-11-06 16:59:41 -08001022 std::error_code ec;
1023 const auto fw_setenv = std::filesystem::path("/sbin/fw_setenv");
1024 if (std::filesystem::exists(fw_setenv, ec))
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001025 {
William A. Kennington III64f61262022-11-06 16:59:41 -08001026 // Ensure that the valid address is stored in the u-boot-env
1027 auto envVar = interfaceToUbootEthAddr(interface);
1028 if (envVar)
1029 {
1030 execute(fw_setenv.native(), "fw_setenv", envVar->c_str(),
1031 validMAC.c_str());
1032 }
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001033 }
Alexander Filippov76b2aa32020-07-10 13:28:55 +03001034
William A. Kennington III1137a972019-04-20 20:49:58 -07001035 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +08001036#else
1037 elog<NotAllowed>(
1038 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
1039#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +05301040}
1041
Ratan Guptae9c9b812017-09-22 17:15:37 +05301042void EthernetInterface::deleteAll()
1043{
Ratan Guptae9c9b812017-09-22 17:15:37 +05301044 // clear all the ip on the interface
1045 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -07001046
1047 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001048 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +05301049}
1050
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001051template <typename Addr>
1052static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -05001053{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001054 if (gw.empty())
1055 {
1056 return;
1057 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -07001058 try
Ravi Tejaa5a09442020-07-17 00:57:33 -05001059 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -08001060 auto ip = stdplus::fromStr<Addr>(gw);
1061 if (ip == Addr{})
1062 {
1063 gw.clear();
1064 return;
1065 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -08001066 if (!validIntfIP(ip))
1067 {
1068 throw std::invalid_argument("Invalid unicast");
1069 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -08001070 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -05001071 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -07001072 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -05001073 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001074 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -05001075 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001076 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -05001077 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001078}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -07001079
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001080std::string EthernetInterface::defaultGateway(std::string gateway)
1081{
1082 normalizeGateway<stdplus::In4Addr>(gateway);
1083 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -07001084 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001085 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -07001086 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001087 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -07001088 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -07001089 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -05001090}
1091
1092std::string EthernetInterface::defaultGateway6(std::string gateway)
1093{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001094 normalizeGateway<stdplus::In6Addr>(gateway);
1095 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -05001096 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001097 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -07001098 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -08001099 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -05001100 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -07001101 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -05001102}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001103
1104EthernetInterface::VlanProperties::VlanProperties(
1105 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001106 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -08001107 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001108 parentIdx(*info.parent_idx), eth(eth)
1109{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -08001110 VlanIntf::id(*info.vlan_id, true);
1111 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001112}
1113
1114void EthernetInterface::VlanProperties::delete_()
1115{
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001116 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001117
1118 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001119 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001120 std::error_code ec;
1121 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
1122 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
1123
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001124 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001125 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001126 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001127 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001128 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001129 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001130 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001131
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001132 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001133 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001134 {
1135 if (intf->ifIdx == parentIdx)
1136 {
1137 intf->writeConfigurationFile();
1138 }
1139 }
1140
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001141 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -07001142 {
William A. Kennington III6d217512022-11-17 16:18:01 -08001143 // We need to forcibly delete the interface as systemd does not
Patrick Williamsad205022024-08-16 15:20:07 -04001144 eth.get().manager.get().addReloadPostHook([idx = eth.get().ifIdx]() {
1145 system::deleteIntf(idx);
1146 });
William A. Kennington III6d217512022-11-17 16:18:01 -08001147
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001148 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001149 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -07001150 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001151
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001152 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001153}
1154
Ravi Tejaf7116de2024-12-08 22:48:21 -06001155bool EthernetInterface::emitLLDP(bool value)
1156{
1157 if (emitLLDP() != EthernetInterfaceIntf::emitLLDP(value))
1158 {
1159 manager.get().writeLLDPDConfigurationFile();
1160 manager.get().reloadLLDPService();
1161 }
1162 return value;
1163}
1164
Jishnu CM57dfea92023-05-05 06:07:26 -05001165void EthernetInterface::reloadConfigs()
1166{
1167 manager.get().reloadConfigs();
1168}
1169
Gunnar Mills57d9c502018-09-14 14:42:34 -05001170} // namespace network
1171} // namespace phosphor