blob: bac778f705f20045b7a7a0c6a3e516e63efcefbd [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 III13d665c2022-11-15 20:34:40 -0800131 for (const auto& [_, addr] : info.addrs)
132 {
133 addAddr(addr);
134 }
135 for (const auto& [_, neigh] : info.staticNeighs)
136 {
137 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700138 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530139}
140
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800141void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700142{
William A. Kennington III876927c2022-11-17 16:20:15 -0800143 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800144 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700145 if (info.mac)
146 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700147 MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700148 }
149 if (info.mtu)
150 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800151 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700152 }
William A. Kennington III21539662022-11-15 14:53:11 -0800153 if (ifIdx > 0)
154 {
155 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
156 return system::getEthInfo(*info.name);
157 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800158 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
159 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800160 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700161}
162
Johnathan Mantey817012a2020-01-30 15:07:39 -0800163bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
164{
165 return (
166#ifdef LINK_LOCAL_AUTOCONFIGURATION
Johnathan Manteyfabe3952023-09-08 13:21:05 -0700167 (origin == IP::AddressOrigin::Static)
168#else
Johnathan Mantey817012a2020-01-30 15:07:39 -0800169 (origin == IP::AddressOrigin::Static ||
170 origin == IP::AddressOrigin::LinkLocal)
171#endif
172
173 );
174}
175
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800176void EthernetInterface::addAddr(const AddressInfo& info)
177{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800178 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ravi Teja86c4f442023-07-19 22:26:39 -0500179 if (dhcpIsEnabled(info.ifaddr.getAddr()))
180 {
181 origin = IP::AddressOrigin::DHCP;
182 }
183
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800184#ifdef LINK_LOCAL_AUTOCONFIGURATION
185 if (info.scope == RT_SCOPE_LINK)
186 {
187 origin = IP::AddressOrigin::LinkLocal;
188 }
189#endif
190
Ravi Tejac6201202023-03-28 21:29:58 -0500191 if ((info.scope == RT_SCOPE_UNIVERSE) && (info.flags & IFA_F_PERMANENT))
192 {
193 origin = IP::AddressOrigin::Static;
194 }
195 if ((info.scope == RT_SCOPE_UNIVERSE) &&
196 ((info.flags & IFA_F_NOPREFIXROUTE) &&
197 (info.flags & IFA_F_MANAGETEMPADDR)))
198 {
199 origin = IP::AddressOrigin::SLAAC;
200 }
201 else if ((info.scope == RT_SCOPE_UNIVERSE) &&
202 ((info.flags & IFA_F_NOPREFIXROUTE)))
203 {
204 origin = IP::AddressOrigin::DHCP;
205 }
206
William A. Kennington III77747f62022-11-07 23:11:15 -0800207 auto it = addrs.find(info.ifaddr);
208 if (it == addrs.end())
209 {
210 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
211 bus, std::string_view(objPath), *this,
212 info.ifaddr, origin));
213 }
214 else
215 {
216 it->second->IPIfaces::origin(origin);
217 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800218}
219
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800220void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
221{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800222 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800223 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700224 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700225 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800226 return;
227 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800228
229 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
230 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700231 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800232 }
233 else
234 {
235 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
236 bus, std::string_view(objPath),
237 *this, *info.addr, *info.mac,
238 Neighbor::State::Permanent));
239 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800240}
241
Patrick Williams6aef7692021-05-01 06:39:41 -0500242ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700243 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530244{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700245 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700246 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530247 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700248 switch (protType)
249 {
250 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700251 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700252 break;
253 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700254 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700255 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700256 default:
257 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700258 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700259 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
260 {
261 throw std::invalid_argument("not unicast");
262 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500263 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700264 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500265 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700266 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
267 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500268 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
269 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
270 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700271 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700272 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500273 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700274 if (prefixLength == 0)
275 {
276 throw std::invalid_argument("default route");
277 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700278 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700279 }
280 catch (const std::exception& e)
281 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700282 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
283 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500284 elog<InvalidArgument>(
285 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700286 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530287 }
288
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700289 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800290 if (it == addrs.end())
291 {
292 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700293 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800294 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700295 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800296 }
297 else
298 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800299 if (it->second->origin() == IP::AddressOrigin::Static)
300 {
301 return it->second->getObjPath();
302 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800303 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
304 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530305
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700306 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800307 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700308
William A. Kennington III434a9432022-11-04 18:38:46 -0700309 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530310}
311
Patrick Williams6aef7692021-05-01 06:39:41 -0500312ObjectPath EthernetInterface::neighbor(std::string ipAddress,
313 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800314{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700315 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700316 try
William A. Kennington III08505792019-01-30 16:00:04 -0800317 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700318 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700319 }
320 catch (const std::exception& e)
321 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700322 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700323 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500324 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
325 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800326 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700327
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700328 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700329 try
William A. Kennington III08505792019-01-30 16:00:04 -0800330 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700331 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700332 }
333 catch (const std::exception& e)
334 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700335 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
336 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500337 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
338 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800339 }
340
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700341 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800342 if (it == staticNeighbors.end())
343 {
344 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700345 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
346 *this, *addr, *lladdr,
347 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800348 }
349 else
350 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700351 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800352 if (it->second->macAddress() == str)
353 {
354 return it->second->getObjPath();
355 }
356 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800357 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700358
359 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800360 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700361
William A. Kennington III434a9432022-11-04 18:38:46 -0700362 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800363}
364
Patrick Williams6aef7692021-05-01 06:39:41 -0500365bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700366{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700367 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700368 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700369 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800370 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700371 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700372 return value;
373}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700374
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700375bool EthernetInterface::dhcp4(bool value)
376{
377 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
378 {
379 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800380 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700381 }
382 return value;
383}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700384
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700385bool EthernetInterface::dhcp6(bool value)
386{
387 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
388 {
389 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800390 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700391 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700392 return value;
393}
394
Patrick Williams6aef7692021-05-01 06:39:41 -0500395EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530396{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700397 auto old4 = EthernetInterfaceIntf::dhcp4();
398 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
399 value == DHCPConf::v4v6stateless ||
400 value == DHCPConf::both);
401 auto old6 = EthernetInterfaceIntf::dhcp6();
402 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
403 value == DHCPConf::both);
404 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
405 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
406 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
407 value == DHCPConf::v6 || value == DHCPConf::both);
408
409 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530410 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700411 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800412 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530413 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530414 return value;
415}
416
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700417EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
418{
419 if (dhcp6())
420 {
421 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
422 }
423 else if (dhcp4())
424 {
425 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
426 }
427 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
428}
429
Tejas Patil2c0fc562021-08-03 19:13:46 +0530430size_t EthernetInterface::mtu(size_t value)
431{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700432 const size_t old = EthernetInterfaceIntf::mtu();
433 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530434 {
435 return value;
436 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700437 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700438 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700439 system::setMTU(ifname, value);
440 return value;
441 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530442}
443
Patrick Williams6aef7692021-05-01 06:39:41 -0500444bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700445{
Patrick Williams6aef7692021-05-01 06:39:41 -0500446 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700447 {
448 return value;
449 }
450
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800451 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700452 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800453 if (!value)
454 {
455 // We only need to bring down the interface, networkd will always bring
456 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800457 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700458 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800459 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800460 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800461
462 return value;
463}
464
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530465ServerList EthernetInterface::staticNameServers(ServerList value)
466{
nitinkotania581cb0b2023-03-21 00:28:55 -0500467 std::vector<std::string> dnsUniqueValues;
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700468 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530469 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700470 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530471 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700472 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700473 }
474 catch (const std::exception& e)
475 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700476 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
477 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700478 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
479 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530480 }
nitinkotania581cb0b2023-03-21 00:28:55 -0500481 if (std::find(dnsUniqueValues.begin(), dnsUniqueValues.end(), ip) ==
482 dnsUniqueValues.end())
483 {
484 dnsUniqueValues.push_back(ip);
485 }
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530486 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700487
nitinkotania581cb0b2023-03-21 00:28:55 -0500488 value =
489 EthernetInterfaceIntf::staticNameServers(std::move(dnsUniqueValues));
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700490
491 writeConfigurationFile();
492 manager.get().reloadConfigs();
493
494 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530495}
496
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600497void EthernetInterface::loadNTPServers(const config::Parser& config)
498{
499 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
500 EthernetInterfaceIntf::staticNTPServers(
501 config.map.getValueStrings("Network", "NTP"));
502}
503
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700504void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530505{
506 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700507 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700508 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530509}
510
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600511ServerList EthernetInterface::getNTPServerFromTimeSyncd()
512{
513 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500514 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
515 TIMESYNCD_SERVICE_PATH,
516 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600517
518 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
519
520 try
521 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800522 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600523 std::variant<ServerList> response;
524 reply.read(response);
525 servers = std::get<ServerList>(response);
526 }
527 catch (const sdbusplus::exception::SdBusError& e)
528 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700529 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700530 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700531 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600532 }
533
534 return servers;
535}
536
Ravi Teja4f8b9a02023-09-06 13:41:52 -0500537ServerList EthernetInterface::nameservers() const
538{
539 return getNameServerFromResolvd();
540}
541
542ServerList EthernetInterface::getNameServerFromResolvd() const
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530543{
544 ServerList servers;
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700545 auto OBJ_PATH = std::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530546
547 /*
548 The DNS property under org.freedesktop.resolve1.Link interface contains
549 an array containing all DNS servers currently used by resolved. It
550 contains similar information as the DNS server data written to
551 /run/systemd/resolve/resolv.conf.
552
553 Each structure in the array consists of a numeric network interface index,
554 an address family, and a byte array containing the DNS server address
555 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
556 The array contains DNS servers configured system-wide, including those
557 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
558 /etc/systemd/resolved.conf, as well as per-interface DNS server
559 information either retrieved from systemd-networkd or configured by
560 external software via SetLinkDNS().
561 */
562
563 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
564 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800565 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
566 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530567
568 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530569
570 try
571 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800572 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530573 reply.read(name);
574 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500575 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530576 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700577 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700578 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700579 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530580 }
581 auto tupleVector = std::get_if<type>(&name);
582 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
583 {
Alexander Filippov983da552021-02-08 15:26:54 +0300584 int addressFamily = std::get<0>(*i);
585 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700586 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700587 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530588 }
589 return servers;
590}
591
William A. Kennington IIId298f932022-10-17 14:31:38 -0700592ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530593{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700594 auto idStr = stdplus::toStr(id);
William A. Kennington III86642522023-07-24 17:55:55 -0700595 auto intfName = stdplus::strCat(interfaceName(), "."sv, idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800596 if (manager.get().interfaces.find(intfName) !=
597 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800598 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700599 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700600 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
601 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800602 }
603
William A. Kennington IIId298f932022-10-17 14:31:38 -0700604 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700605 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700606 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700607 if (!macStr.empty())
608 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700609 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700610 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800611 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800612 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700613 .idx = 0, // TODO: Query the correct value after creation
614 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700615 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700616 .mac = std::move(mac),
617 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700618 .parent_idx = ifIdx,
619 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800620 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530621
Patrick Williams6aef7692021-05-01 06:39:41 -0500622 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530623 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700624 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800625 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700626 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530627
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800628 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530629
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700630 // write the device file for the vlan interface.
631 config::Parser config;
632 auto& netdev = config.map["NetDev"].emplace_back();
633 netdev["Name"].emplace_back(intfName);
634 netdev["Kind"].emplace_back("vlan");
635 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800636 config.writeFile(
637 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700638
639 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800640 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700641
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800642 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530643}
Ratan Gupta2b106532017-07-25 16:05:02 +0530644
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600645ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530646{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700647 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530648
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700649 writeConfigurationFile();
650 manager.get().reloadConfigs();
651
652 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600653}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700654
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600655ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
656{
657 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530658}
Ratan Gupta2b106532017-07-25 16:05:02 +0530659
660void EthernetInterface::writeConfigurationFile()
661{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700662 config::Parser config;
663 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530664 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700665 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800666#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700667 auto mac = MacAddressIntf::macAddress();
668 if (!mac.empty())
669 {
670 link["MACAddress"].emplace_back(mac);
671 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800672#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700673 if (!EthernetInterfaceIntf::nicEnabled())
674 {
675 link["Unmanaged"].emplace_back("yes");
676 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700677 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700678 {
679 auto& network = config.map["Network"].emplace_back();
680 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400681#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700682 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400683#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700684 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400685#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700686 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
687 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
688 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600689 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700690 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800691 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700692 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700693 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
694 {
695 vlans.emplace_back(intf->interfaceName());
696 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700697 }
698 }
699 {
700 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600701 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700702 {
703 ntps.emplace_back(ntp);
704 }
705 }
706 {
707 auto& dnss = network["DNS"];
708 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
709 {
710 dnss.emplace_back(dns);
711 }
712 }
713 {
714 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700715 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700717 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700718 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700719 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700720 }
721 }
722 }
723 {
724 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700725 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700726 {
727 auto gateway = EthernetInterfaceIntf::defaultGateway();
728 if (!gateway.empty())
729 {
730 gateways.emplace_back(gateway);
731 }
732 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530733
William A. Kennington III05cbc5b2023-07-20 19:37:30 -0700734 if (!ipv6AcceptRA())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700735 {
736 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
737 if (!gateway6.empty())
738 {
739 gateways.emplace_back(gateway6);
740 }
741 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600742 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800743 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700744 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700745 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500746 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700747 auto& neighbors = config.map["Neighbor"];
748 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800749 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700750 auto& neighbor = neighbors.emplace_back();
751 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
752 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800753 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500754 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500755 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700756 auto& dhcp = config.map["DHCP"].emplace_back();
757 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800758 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800759 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
760 dhcp["UseDNS"].emplace_back(dns_enabled);
761 dhcp["UseDomains"].emplace_back(dns_enabled);
762 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
763 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
764 : "false");
765 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
766 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500767 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500768 auto path = config::pathForIntfConf(manager.get().getConfDir(),
769 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700770 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700771 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530772}
773
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800774std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530775{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700776 if (vlan)
777 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700778 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700779 elog<InternalFailure>();
780 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800781#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700782 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600783 try
784 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700785 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600786 }
Patrick Williams5758db32021-10-06 12:29:22 -0500787 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600788 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700789 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600790 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
791 Argument::ARGUMENT_VALUE(value.c_str()));
792 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700793 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530794 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700795 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500796 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
797 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530798 }
799
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300800 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700801 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300802
William A. Kennington III1137a972019-04-20 20:49:58 -0700803 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700804 auto oldMAC =
805 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700806 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530807 {
Yuxiao Zhang46938072023-09-26 17:59:14 -0700808 auto path = config::pathForIntfConf(manager.get().getConfDir(),
809 interface);
William A. Kennington III1137a972019-04-20 20:49:58 -0700810 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800811 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530812 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700813 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
814 {
815 intf->MacAddressIntf::macAddress(validMAC);
816 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530817 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500818 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530819
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700820 writeConfigurationFile();
Yuxiao Zhang46938072023-09-26 17:59:14 -0700821 manager.get().addReloadPreHook([interface, path]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800822 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700823 system::setNICUp(interface, false);
Yuxiao Zhang46938072023-09-26 17:59:14 -0700824 utimensat(AT_FDCWD, path.c_str(), NULL, 0);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800825 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800826 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530827 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700828
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300829#ifdef HAVE_UBOOT_ENV
830 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700831 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300832 if (envVar)
833 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500834 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
835 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
836 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
837 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300838 }
839#endif // HAVE_UBOOT_ENV
840
William A. Kennington III1137a972019-04-20 20:49:58 -0700841 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800842#else
843 elog<NotAllowed>(
844 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
845#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530846}
847
Ratan Guptae9c9b812017-09-22 17:15:37 +0530848void EthernetInterface::deleteAll()
849{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530850 // clear all the ip on the interface
851 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700852
853 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800854 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530855}
856
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800857template <typename Addr>
858static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500859{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800860 if (gw.empty())
861 {
862 return;
863 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700864 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500865 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800866 auto ip = stdplus::fromStr<Addr>(gw);
867 if (ip == Addr{})
868 {
869 gw.clear();
870 return;
871 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800872 if (!validIntfIP(ip))
873 {
874 throw std::invalid_argument("Invalid unicast");
875 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800876 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500877 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700878 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500879 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800880 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500881 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800882 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500883 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800884}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700885
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800886std::string EthernetInterface::defaultGateway(std::string gateway)
887{
888 normalizeGateway<stdplus::In4Addr>(gateway);
889 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700890 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800891 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700892 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800893 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700894 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700895 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500896}
897
898std::string EthernetInterface::defaultGateway6(std::string gateway)
899{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800900 normalizeGateway<stdplus::In6Addr>(gateway);
901 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500902 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800903 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700904 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800905 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500906 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700907 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500908}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700909
910EthernetInterface::VlanProperties::VlanProperties(
911 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800912 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800913 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700914 parentIdx(*info.parent_idx), eth(eth)
915{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800916 VlanIntf::id(*info.vlan_id, true);
917 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700918}
919
920void EthernetInterface::VlanProperties::delete_()
921{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800922 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700923
924 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800925 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700926 std::error_code ec;
927 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
928 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
929
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800930 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800931 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800932 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800933 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800934 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800935 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800936 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800937
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700938 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800939 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700940 {
941 if (intf->ifIdx == parentIdx)
942 {
943 intf->writeConfigurationFile();
944 }
945 }
946
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800947 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700948 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800949 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800950 eth.get().manager.get().addReloadPostHook(
951 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800952
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800953 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800954 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700955 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800956
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800957 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700958}
959
Gunnar Mills57d9c502018-09-14 14:42:34 -0500960} // namespace network
961} // namespace phosphor