blob: 4b50894cad38ef1d755dc37aeff42091ca7aef27 [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
Yuxiao Zhang46938072023-09-26 17:59:14 -070010#include <fcntl.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070011#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070012#include <net/if.h>
William A. Kennington III9c441fd2023-02-24 13:40:01 -080013#include <net/if_arp.h>
Yuxiao Zhang46938072023-09-26 17:59:14 -070014#include <sys/stat.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015
Patrick Venture189d44e2018-07-09 12:30:59 -070016#include <phosphor-logging/elog-errors.hpp>
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -070017#include <phosphor-logging/lg2.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
Ratan Gupta2b106532017-07-25 16:05:02 +0530667void EthernetInterface::writeConfigurationFile()
668{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700669 config::Parser config;
670 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530671 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700672 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800673#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700674 auto mac = MacAddressIntf::macAddress();
675 if (!mac.empty())
676 {
677 link["MACAddress"].emplace_back(mac);
678 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800679#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700680 if (!EthernetInterfaceIntf::nicEnabled())
681 {
682 link["Unmanaged"].emplace_back("yes");
683 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700684 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700685 {
686 auto& network = config.map["Network"].emplace_back();
687 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400688#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700689 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400690#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700691 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400692#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700693 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
694 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
695 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600696 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700697 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800698 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700699 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700700 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
701 {
702 vlans.emplace_back(intf->interfaceName());
703 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700704 }
705 }
706 {
707 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600708 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700709 {
710 ntps.emplace_back(ntp);
711 }
712 }
713 {
714 auto& dnss = network["DNS"];
715 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
716 {
717 dnss.emplace_back(dns);
718 }
719 }
720 {
721 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700722 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700723 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700724 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700725 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700726 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700727 }
728 }
729 }
730 {
731 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700732 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700733 {
734 auto gateway = EthernetInterfaceIntf::defaultGateway();
735 if (!gateway.empty())
736 {
737 gateways.emplace_back(gateway);
738 }
739 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530740
William A. Kennington III05cbc5b2023-07-20 19:37:30 -0700741 if (!ipv6AcceptRA())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700742 {
743 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
744 if (!gateway6.empty())
745 {
746 gateways.emplace_back(gateway6);
747 }
748 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600749 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800750 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700751 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700752 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500753 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700754 auto& neighbors = config.map["Neighbor"];
755 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800756 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700757 auto& neighbor = neighbors.emplace_back();
758 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
759 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800760 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500761 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500762 {
Jishnu CM57dfea92023-05-05 06:07:26 -0500763 auto& dhcp4 = config.map["DHCPv4"].emplace_back();
764 dhcp4["ClientIdentifier"].emplace_back("mac");
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700765 dhcp4["UseDNS"].emplace_back(tfStr(dhcp4Conf->dnsEnabled()));
766 dhcp4["UseDomains"].emplace_back(tfStr(dhcp4Conf->domainEnabled()));
767 dhcp4["UseNTP"].emplace_back(tfStr(dhcp4Conf->ntpEnabled()));
768 dhcp4["UseHostname"].emplace_back(tfStr(dhcp4Conf->hostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500769 dhcp4["SendHostname"].emplace_back(
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700770 tfStr(dhcp4Conf->sendHostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500771 }
772 {
773 auto& dhcp6 = config.map["DHCPv6"].emplace_back();
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700774 dhcp6["UseDNS"].emplace_back(tfStr(dhcp6Conf->dnsEnabled()));
775 dhcp6["UseDomains"].emplace_back(tfStr(dhcp6Conf->domainEnabled()));
776 dhcp6["UseNTP"].emplace_back(tfStr(dhcp6Conf->ntpEnabled()));
777 dhcp6["UseHostname"].emplace_back(tfStr(dhcp6Conf->hostNameEnabled()));
William A. Kennington III44937b12024-04-17 00:28:20 -0700778 dhcp6["SendHostname"].emplace_back(
779 tfStr(dhcp6Conf->sendHostNameEnabled()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500780 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500781 auto path = config::pathForIntfConf(manager.get().getConfDir(),
782 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700783 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700784 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530785}
786
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800787std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530788{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700789 if (vlan)
790 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700791 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700792 elog<InternalFailure>();
793 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800794#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700795 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600796 try
797 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700798 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600799 }
Patrick Williams5758db32021-10-06 12:29:22 -0500800 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600801 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700802 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600803 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
804 Argument::ARGUMENT_VALUE(value.c_str()));
805 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700806 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530807 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700808 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500809 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
810 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530811 }
812
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300813 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700814 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300815
William A. Kennington III1137a972019-04-20 20:49:58 -0700816 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700817 auto oldMAC =
818 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700819 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530820 {
Yuxiao Zhang46938072023-09-26 17:59:14 -0700821 auto path = config::pathForIntfConf(manager.get().getConfDir(),
822 interface);
William A. Kennington III1137a972019-04-20 20:49:58 -0700823 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800824 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530825 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700826 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
827 {
828 intf->MacAddressIntf::macAddress(validMAC);
829 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530830 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500831 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530832
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700833 writeConfigurationFile();
Yuxiao Zhang46938072023-09-26 17:59:14 -0700834 manager.get().addReloadPreHook([interface, path]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800835 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700836 system::setNICUp(interface, false);
Yuxiao Zhang46938072023-09-26 17:59:14 -0700837 utimensat(AT_FDCWD, path.c_str(), NULL, 0);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800838 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800839 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530840 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700841
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300842#ifdef HAVE_UBOOT_ENV
843 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700844 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300845 if (envVar)
846 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500847 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
848 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
849 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
850 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300851 }
852#endif // HAVE_UBOOT_ENV
853
William A. Kennington III1137a972019-04-20 20:49:58 -0700854 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800855#else
856 elog<NotAllowed>(
857 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
858#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530859}
860
Ratan Guptae9c9b812017-09-22 17:15:37 +0530861void EthernetInterface::deleteAll()
862{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530863 // clear all the ip on the interface
864 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700865
866 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800867 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530868}
869
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800870template <typename Addr>
871static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500872{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800873 if (gw.empty())
874 {
875 return;
876 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700877 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500878 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800879 auto ip = stdplus::fromStr<Addr>(gw);
880 if (ip == Addr{})
881 {
882 gw.clear();
883 return;
884 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800885 if (!validIntfIP(ip))
886 {
887 throw std::invalid_argument("Invalid unicast");
888 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800889 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500890 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700891 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500892 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800893 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500894 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800895 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500896 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800897}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700898
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800899std::string EthernetInterface::defaultGateway(std::string gateway)
900{
901 normalizeGateway<stdplus::In4Addr>(gateway);
902 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700903 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800904 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700905 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800906 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700907 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700908 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500909}
910
911std::string EthernetInterface::defaultGateway6(std::string gateway)
912{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800913 normalizeGateway<stdplus::In6Addr>(gateway);
914 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500915 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800916 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700917 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800918 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500919 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700920 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500921}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700922
923EthernetInterface::VlanProperties::VlanProperties(
924 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800925 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800926 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700927 parentIdx(*info.parent_idx), eth(eth)
928{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800929 VlanIntf::id(*info.vlan_id, true);
930 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700931}
932
933void EthernetInterface::VlanProperties::delete_()
934{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800935 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700936
937 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800938 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700939 std::error_code ec;
940 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
941 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
942
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800943 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800944 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800945 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800946 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800947 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800948 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800949 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800950
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700951 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800952 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700953 {
954 if (intf->ifIdx == parentIdx)
955 {
956 intf->writeConfigurationFile();
957 }
958 }
959
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800960 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700961 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800962 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800963 eth.get().manager.get().addReloadPostHook(
964 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800965
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800966 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800967 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700968 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800969
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800970 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700971}
972
Jishnu CM57dfea92023-05-05 06:07:26 -0500973void EthernetInterface::reloadConfigs()
974{
975 manager.get().reloadConfigs();
976}
977
Gunnar Mills57d9c502018-09-14 14:42:34 -0500978} // namespace network
979} // namespace phosphor