blob: fdd01c22d22bbc31458513885b75020468338311 [file] [log] [blame]
Gunnar Mills57d9c502018-09-14 14:42:34 -05001
Patrick Venture189d44e2018-07-09 12:30:59 -07002#include "ethernet_interface.hpp"
3
Ratan Gupta497c0c92017-08-22 19:15:59 +05304#include "config_parser.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05305#include "network_manager.hpp"
William A. Kennington III2e09d272022-10-14 17:15:00 -07006#include "system_queries.hpp"
William A. Kennington III95530ec2022-08-19 01:44:39 -07007#include "util.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05308
William A. Kennington IIId7946a72019-04-19 14:24:09 -07009#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070010#include <net/if.h>
William A. Kennington III9c441fd2023-02-24 13:40:01 -080011#include <net/if_arp.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053012
Patrick Venture189d44e2018-07-09 12:30:59 -070013#include <phosphor-logging/elog-errors.hpp>
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -070014#include <phosphor-logging/lg2.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070015#include <stdplus/raw.hpp>
William A. Kennington III86642522023-07-24 17:55:55 -070016#include <stdplus/str/cat.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070017#include <stdplus/zstring.hpp>
Patrick Williams89d734b2023-05-10 07:50:25 -050018#include <xyz/openbmc_project/Common/error.hpp>
19
20#include <algorithm>
21#include <filesystem>
William A. Kennington IIIcafc1512023-07-25 02:22:32 -070022#include <format>
Ratan Gupta2b106532017-07-25 16:05:02 +053023#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070024#include <unordered_map>
25#include <variant>
Ratan Gupta82549cc2017-04-21 08:45:23 +053026
Ratan Gupta91a99cc2017-04-14 16:32:09 +053027namespace phosphor
28{
29namespace network
30{
31
32using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053033using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053034using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
35using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050036using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070037using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053038constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
39constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
40constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
41constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060042
43constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
44constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
45constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
46
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053047constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053048
William A. Kennington III2e09d272022-10-14 17:15:00 -070049template <typename Func>
50inline decltype(std::declval<Func>()())
51 ignoreError(std::string_view msg, stdplus::zstring_view intf,
52 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080053{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070054 try
55 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070056 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070057 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070058 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070059 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -070060 lg2::error("{MSG} failed on {NET_INTF}: {ERROR}", "MSG", msg,
61 "NET_INTF", intf, "ERROR", e);
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070062 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070063 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070064}
William A. Kennington IIId298f932022-10-17 14:31:38 -070065
William A. Kennington IIId298f932022-10-17 14:31:38 -070066static std::string makeObjPath(std::string_view root, std::string_view intf)
67{
William A. Kennington III86642522023-07-24 17:55:55 -070068 auto ret = stdplus::strCat(root, "/"sv, intf);
William A. Kennington IIId298f932022-10-17 14:31:38 -070069 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
70 return ret;
71}
72
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -080073template <typename Addr>
74static bool validIntfIP(Addr a) noexcept
75{
76 return a.isUnicast() && !a.isLoopback();
77}
78
William A. Kennington III9ede1b72022-11-21 01:59:28 -080079EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
80 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080081 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070082 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070083 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080084 bool enabled) :
William A. Kennington III13d665c2022-11-15 20:34:40 -080085 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.intf.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080086 config, enabled)
Patrick Williams89d734b2023-05-10 07:50:25 -050087{}
William A. Kennington IIId298f932022-10-17 14:31:38 -070088
William A. Kennington III9ede1b72022-11-21 01:59:28 -080089EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
90 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080091 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070092 std::string&& objPath,
93 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080094 bool enabled) :
95 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit),
William A. Kennington III876927c2022-11-17 16:20:15 -080096 manager(manager), bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +053097{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080098 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070099 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800100 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
101 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
102 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
103 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500104
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700105 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800106 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +0530107
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800108 updateInfo(info.intf, true);
109
110 if (info.defgw4)
111 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700112 EthernetInterface::defaultGateway(stdplus::toStr(*info.defgw4), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800113 }
114 if (info.defgw6)
115 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700116 EthernetInterface::defaultGateway6(stdplus::toStr(*info.defgw6), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800117 }
118 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700119
William A. Kennington III13d665c2022-11-15 20:34:40 -0800120 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700121 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800122 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700123 {
124 std::runtime_error("Missing parent link");
125 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800126 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
127 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800128 for (const auto& [_, addr] : info.addrs)
129 {
130 addAddr(addr);
131 }
132 for (const auto& [_, neigh] : info.staticNeighs)
133 {
134 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700135 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530136}
137
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800138void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700139{
William A. Kennington III876927c2022-11-17 16:20:15 -0800140 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800141 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700142 if (info.mac)
143 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700144 MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700145 }
146 if (info.mtu)
147 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800148 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700149 }
William A. Kennington III21539662022-11-15 14:53:11 -0800150 if (ifIdx > 0)
151 {
152 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
153 return system::getEthInfo(*info.name);
154 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800155 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
156 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800157 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700158}
159
Johnathan Mantey817012a2020-01-30 15:07:39 -0800160bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
161{
162 return (
163#ifdef LINK_LOCAL_AUTOCONFIGURATION
Johnathan Mantey817012a2020-01-30 15:07:39 -0800164 (origin == IP::AddressOrigin::Static ||
165 origin == IP::AddressOrigin::LinkLocal)
Tim Lee721d8f752023-07-08 00:26:27 +0800166#else
167 (origin == IP::AddressOrigin::Static)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800168#endif
169
170 );
171}
172
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800173void EthernetInterface::addAddr(const AddressInfo& info)
174{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800175 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ravi Teja86c4f442023-07-19 22:26:39 -0500176 if (dhcpIsEnabled(info.ifaddr.getAddr()))
177 {
178 origin = IP::AddressOrigin::DHCP;
179 }
180
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800181#ifdef LINK_LOCAL_AUTOCONFIGURATION
182 if (info.scope == RT_SCOPE_LINK)
183 {
184 origin = IP::AddressOrigin::LinkLocal;
185 }
186#endif
187
Ravi Tejac6201202023-03-28 21:29:58 -0500188 if ((info.scope == RT_SCOPE_UNIVERSE) && (info.flags & IFA_F_PERMANENT))
189 {
190 origin = IP::AddressOrigin::Static;
191 }
192 if ((info.scope == RT_SCOPE_UNIVERSE) &&
193 ((info.flags & IFA_F_NOPREFIXROUTE) &&
194 (info.flags & IFA_F_MANAGETEMPADDR)))
195 {
196 origin = IP::AddressOrigin::SLAAC;
197 }
198 else if ((info.scope == RT_SCOPE_UNIVERSE) &&
199 ((info.flags & IFA_F_NOPREFIXROUTE)))
200 {
201 origin = IP::AddressOrigin::DHCP;
202 }
203
William A. Kennington III77747f62022-11-07 23:11:15 -0800204 auto it = addrs.find(info.ifaddr);
205 if (it == addrs.end())
206 {
207 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
208 bus, std::string_view(objPath), *this,
209 info.ifaddr, origin));
210 }
211 else
212 {
213 it->second->IPIfaces::origin(origin);
214 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800215}
216
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800217void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
218{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800219 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800220 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700221 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700222 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800223 return;
224 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800225
226 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
227 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700228 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800229 }
230 else
231 {
232 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
233 bus, std::string_view(objPath),
234 *this, *info.addr, *info.mac,
235 Neighbor::State::Permanent));
236 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800237}
238
Patrick Williams6aef7692021-05-01 06:39:41 -0500239ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700240 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530241{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700242 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700243 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530244 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700245 switch (protType)
246 {
247 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700248 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700249 break;
250 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700251 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700252 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700253 default:
254 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700255 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700256 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
257 {
258 throw std::invalid_argument("not unicast");
259 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500260 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700261 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500262 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700263 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
264 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500265 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
266 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
267 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700268 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700269 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500270 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700271 if (prefixLength == 0)
272 {
273 throw std::invalid_argument("default route");
274 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700275 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700276 }
277 catch (const std::exception& e)
278 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700279 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
280 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500281 elog<InvalidArgument>(
282 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700283 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530284 }
285
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700286 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800287 if (it == addrs.end())
288 {
289 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700290 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800291 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700292 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800293 }
294 else
295 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800296 if (it->second->origin() == IP::AddressOrigin::Static)
297 {
298 return it->second->getObjPath();
299 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800300 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
301 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530302
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700303 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800304 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700305
William A. Kennington III434a9432022-11-04 18:38:46 -0700306 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530307}
308
Patrick Williams6aef7692021-05-01 06:39:41 -0500309ObjectPath EthernetInterface::neighbor(std::string ipAddress,
310 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800311{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700312 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700313 try
William A. Kennington III08505792019-01-30 16:00:04 -0800314 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700315 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700316 }
317 catch (const std::exception& e)
318 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700319 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700320 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500321 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
322 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800323 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700324
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700325 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700326 try
William A. Kennington III08505792019-01-30 16:00:04 -0800327 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700328 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700329 }
330 catch (const std::exception& e)
331 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700332 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
333 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500334 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
335 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800336 }
337
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700338 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800339 if (it == staticNeighbors.end())
340 {
341 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700342 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
343 *this, *addr, *lladdr,
344 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800345 }
346 else
347 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700348 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800349 if (it->second->macAddress() == str)
350 {
351 return it->second->getObjPath();
352 }
353 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800354 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700355
356 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800357 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700358
William A. Kennington III434a9432022-11-04 18:38:46 -0700359 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800360}
361
Patrick Williams6aef7692021-05-01 06:39:41 -0500362bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700363{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700364 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700365 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700366 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800367 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700368 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700369 return value;
370}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700371
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700372bool EthernetInterface::dhcp4(bool value)
373{
374 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
375 {
376 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800377 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700378 }
379 return value;
380}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700381
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700382bool EthernetInterface::dhcp6(bool value)
383{
384 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
385 {
386 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800387 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700388 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700389 return value;
390}
391
Patrick Williams6aef7692021-05-01 06:39:41 -0500392EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530393{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700394 auto old4 = EthernetInterfaceIntf::dhcp4();
395 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
396 value == DHCPConf::v4v6stateless ||
397 value == DHCPConf::both);
398 auto old6 = EthernetInterfaceIntf::dhcp6();
399 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
400 value == DHCPConf::both);
401 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
402 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
403 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
404 value == DHCPConf::v6 || value == DHCPConf::both);
405
406 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530407 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700408 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800409 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530410 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530411 return value;
412}
413
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700414EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
415{
416 if (dhcp6())
417 {
418 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
419 }
420 else if (dhcp4())
421 {
422 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
423 }
424 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
425}
426
Tejas Patil2c0fc562021-08-03 19:13:46 +0530427size_t EthernetInterface::mtu(size_t value)
428{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700429 const size_t old = EthernetInterfaceIntf::mtu();
430 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530431 {
432 return value;
433 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700434 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700435 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700436 system::setMTU(ifname, value);
437 return value;
438 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530439}
440
Patrick Williams6aef7692021-05-01 06:39:41 -0500441bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700442{
Patrick Williams6aef7692021-05-01 06:39:41 -0500443 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700444 {
445 return value;
446 }
447
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800448 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700449 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800450 if (!value)
451 {
452 // We only need to bring down the interface, networkd will always bring
453 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800454 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700455 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800456 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800457 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800458
459 return value;
460}
461
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530462ServerList EthernetInterface::staticNameServers(ServerList value)
463{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700464 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530465 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700466 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530467 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700468 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700469 }
470 catch (const std::exception& e)
471 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700472 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
473 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700474 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
475 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530476 }
477 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700478
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700479 value = EthernetInterfaceIntf::staticNameServers(std::move(value));
480
481 writeConfigurationFile();
482 manager.get().reloadConfigs();
483
484 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530485}
486
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600487void EthernetInterface::loadNTPServers(const config::Parser& config)
488{
489 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
490 EthernetInterfaceIntf::staticNTPServers(
491 config.map.getValueStrings("Network", "NTP"));
492}
493
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700494void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530495{
496 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700497 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700498 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530499}
500
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600501ServerList EthernetInterface::getNTPServerFromTimeSyncd()
502{
503 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500504 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
505 TIMESYNCD_SERVICE_PATH,
506 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600507
508 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
509
510 try
511 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800512 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600513 std::variant<ServerList> response;
514 reply.read(response);
515 servers = std::get<ServerList>(response);
516 }
517 catch (const sdbusplus::exception::SdBusError& e)
518 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700519 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700520 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700521 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600522 }
523
524 return servers;
525}
526
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530527ServerList EthernetInterface::getNameServerFromResolvd()
528{
529 ServerList servers;
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700530 auto OBJ_PATH = std::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530531
532 /*
533 The DNS property under org.freedesktop.resolve1.Link interface contains
534 an array containing all DNS servers currently used by resolved. It
535 contains similar information as the DNS server data written to
536 /run/systemd/resolve/resolv.conf.
537
538 Each structure in the array consists of a numeric network interface index,
539 an address family, and a byte array containing the DNS server address
540 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
541 The array contains DNS servers configured system-wide, including those
542 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
543 /etc/systemd/resolved.conf, as well as per-interface DNS server
544 information either retrieved from systemd-networkd or configured by
545 external software via SetLinkDNS().
546 */
547
548 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
549 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800550 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
551 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530552
553 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530554
555 try
556 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800557 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530558 reply.read(name);
559 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500560 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530561 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700562 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700563 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700564 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530565 }
566 auto tupleVector = std::get_if<type>(&name);
567 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
568 {
Alexander Filippov983da552021-02-08 15:26:54 +0300569 int addressFamily = std::get<0>(*i);
570 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700571 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700572 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530573 }
574 return servers;
575}
576
William A. Kennington IIId298f932022-10-17 14:31:38 -0700577ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530578{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700579 auto idStr = stdplus::toStr(id);
William A. Kennington III86642522023-07-24 17:55:55 -0700580 auto intfName = stdplus::strCat(interfaceName(), "."sv, idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800581 if (manager.get().interfaces.find(intfName) !=
582 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800583 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700584 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700585 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
586 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800587 }
588
William A. Kennington IIId298f932022-10-17 14:31:38 -0700589 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700590 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700591 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700592 if (!macStr.empty())
593 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700594 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700595 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800596 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800597 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700598 .idx = 0, // TODO: Query the correct value after creation
599 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700600 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700601 .mac = std::move(mac),
602 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700603 .parent_idx = ifIdx,
604 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800605 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530606
Patrick Williams6aef7692021-05-01 06:39:41 -0500607 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530608 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700609 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800610 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700611 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530612
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800613 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530614
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700615 // write the device file for the vlan interface.
616 config::Parser config;
617 auto& netdev = config.map["NetDev"].emplace_back();
618 netdev["Name"].emplace_back(intfName);
619 netdev["Kind"].emplace_back("vlan");
620 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800621 config.writeFile(
622 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700623
624 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800625 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700626
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800627 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530628}
Ratan Gupta2b106532017-07-25 16:05:02 +0530629
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600630ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530631{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700632 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530633
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700634 writeConfigurationFile();
635 manager.get().reloadConfigs();
636
637 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600638}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700639
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600640ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
641{
642 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530643}
Ratan Gupta2b106532017-07-25 16:05:02 +0530644// Need to merge the below function with the code which writes the
645// config file during factory reset.
646// TODO openbmc/openbmc#1751
647
648void EthernetInterface::writeConfigurationFile()
649{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700650 config::Parser config;
651 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530652 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700653 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800654#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700655 auto mac = MacAddressIntf::macAddress();
656 if (!mac.empty())
657 {
658 link["MACAddress"].emplace_back(mac);
659 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800660#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700661 if (!EthernetInterfaceIntf::nicEnabled())
662 {
663 link["Unmanaged"].emplace_back("yes");
664 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700665 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700666 {
667 auto& network = config.map["Network"].emplace_back();
668 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400669#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700670 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400671#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700672 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400673#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700674 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
675 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
676 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600677 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700678 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800679 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700680 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700681 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
682 {
683 vlans.emplace_back(intf->interfaceName());
684 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700685 }
686 }
687 {
688 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600689 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700690 {
691 ntps.emplace_back(ntp);
692 }
693 }
694 {
695 auto& dnss = network["DNS"];
696 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
697 {
698 dnss.emplace_back(dns);
699 }
700 }
701 {
702 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700703 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700704 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700705 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700706 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700707 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700708 }
709 }
710 }
711 {
712 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700713 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700714 {
715 auto gateway = EthernetInterfaceIntf::defaultGateway();
716 if (!gateway.empty())
717 {
718 gateways.emplace_back(gateway);
719 }
720 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530721
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700722 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700723 {
724 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
725 if (!gateway6.empty())
726 {
727 gateways.emplace_back(gateway6);
728 }
729 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600730 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800731 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700732 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700733 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500734 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700735 auto& neighbors = config.map["Neighbor"];
736 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800737 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700738 auto& neighbor = neighbors.emplace_back();
739 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
740 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800741 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500742 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500743 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700744 auto& dhcp = config.map["DHCP"].emplace_back();
745 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800746 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800747 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
748 dhcp["UseDNS"].emplace_back(dns_enabled);
749 dhcp["UseDomains"].emplace_back(dns_enabled);
750 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
751 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
752 : "false");
753 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
754 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500755 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500756 auto path = config::pathForIntfConf(manager.get().getConfDir(),
757 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700758 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700759 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530760}
761
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800762std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530763{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700764 if (vlan)
765 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700766 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700767 elog<InternalFailure>();
768 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800769#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700770 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600771 try
772 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700773 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600774 }
Patrick Williams5758db32021-10-06 12:29:22 -0500775 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600776 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700777 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600778 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
779 Argument::ARGUMENT_VALUE(value.c_str()));
780 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700781 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530782 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700783 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500784 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
785 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530786 }
787
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300788 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700789 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300790
William A. Kennington III1137a972019-04-20 20:49:58 -0700791 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700792 auto oldMAC =
793 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700794 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530795 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700796 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800797 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530798 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700799 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
800 {
801 intf->MacAddressIntf::macAddress(validMAC);
802 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530803 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500804 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530805
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700806 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800807 manager.get().addReloadPreHook([interface]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800808 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700809 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800810 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800811 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530812 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700813
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300814#ifdef HAVE_UBOOT_ENV
815 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700816 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300817 if (envVar)
818 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500819 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
820 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
821 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
822 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300823 }
824#endif // HAVE_UBOOT_ENV
825
William A. Kennington III1137a972019-04-20 20:49:58 -0700826 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800827#else
828 elog<NotAllowed>(
829 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
830#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530831}
832
Ratan Guptae9c9b812017-09-22 17:15:37 +0530833void EthernetInterface::deleteAll()
834{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530835 // clear all the ip on the interface
836 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700837
838 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800839 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530840}
841
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800842template <typename Addr>
843static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500844{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800845 if (gw.empty())
846 {
847 return;
848 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700849 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500850 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800851 auto ip = stdplus::fromStr<Addr>(gw);
852 if (ip == Addr{})
853 {
854 gw.clear();
855 return;
856 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800857 if (!validIntfIP(ip))
858 {
859 throw std::invalid_argument("Invalid unicast");
860 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800861 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500862 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700863 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500864 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800865 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500866 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800867 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500868 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800869}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700870
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800871std::string EthernetInterface::defaultGateway(std::string gateway)
872{
873 normalizeGateway<stdplus::In4Addr>(gateway);
874 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700875 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800876 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
877 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700878 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700879 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500880}
881
882std::string EthernetInterface::defaultGateway6(std::string gateway)
883{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800884 normalizeGateway<stdplus::In6Addr>(gateway);
885 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500886 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800887 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
888 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500889 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700890 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500891}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700892
893EthernetInterface::VlanProperties::VlanProperties(
894 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800895 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800896 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700897 parentIdx(*info.parent_idx), eth(eth)
898{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800899 VlanIntf::id(*info.vlan_id, true);
900 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700901}
902
903void EthernetInterface::VlanProperties::delete_()
904{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800905 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700906
907 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800908 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700909 std::error_code ec;
910 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
911 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
912
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800913 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800914 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800915 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800916 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800917 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800918 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800919 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800920
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700921 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800922 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700923 {
924 if (intf->ifIdx == parentIdx)
925 {
926 intf->writeConfigurationFile();
927 }
928 }
929
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800930 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700931 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800932 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800933 eth.get().manager.get().addReloadPostHook(
934 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800935
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800936 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800937 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700938 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800939
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800940 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700941}
942
Gunnar Mills57d9c502018-09-14 14:42:34 -0500943} // namespace network
944} // namespace phosphor