blob: f92c31cf79b62fbd7a4ae14afe992ddda54cf734 [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{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700467 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530468 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700469 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530470 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700471 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700472 }
473 catch (const std::exception& e)
474 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700475 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
476 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700477 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
478 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530479 }
480 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700481
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700482 value = EthernetInterfaceIntf::staticNameServers(std::move(value));
483
484 writeConfigurationFile();
485 manager.get().reloadConfigs();
486
487 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530488}
489
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600490void EthernetInterface::loadNTPServers(const config::Parser& config)
491{
492 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
493 EthernetInterfaceIntf::staticNTPServers(
494 config.map.getValueStrings("Network", "NTP"));
495}
496
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700497void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530498{
499 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700500 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700501 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530502}
503
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600504ServerList EthernetInterface::getNTPServerFromTimeSyncd()
505{
506 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500507 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
508 TIMESYNCD_SERVICE_PATH,
509 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600510
511 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
512
513 try
514 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800515 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600516 std::variant<ServerList> response;
517 reply.read(response);
518 servers = std::get<ServerList>(response);
519 }
520 catch (const sdbusplus::exception::SdBusError& e)
521 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700522 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700523 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700524 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600525 }
526
527 return servers;
528}
529
Ravi Teja4f8b9a02023-09-06 13:41:52 -0500530ServerList EthernetInterface::nameservers() const
531{
532 return getNameServerFromResolvd();
533}
534
535ServerList EthernetInterface::getNameServerFromResolvd() const
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530536{
537 ServerList servers;
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700538 auto OBJ_PATH = std::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530539
540 /*
541 The DNS property under org.freedesktop.resolve1.Link interface contains
542 an array containing all DNS servers currently used by resolved. It
543 contains similar information as the DNS server data written to
544 /run/systemd/resolve/resolv.conf.
545
546 Each structure in the array consists of a numeric network interface index,
547 an address family, and a byte array containing the DNS server address
548 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
549 The array contains DNS servers configured system-wide, including those
550 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
551 /etc/systemd/resolved.conf, as well as per-interface DNS server
552 information either retrieved from systemd-networkd or configured by
553 external software via SetLinkDNS().
554 */
555
556 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
557 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800558 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
559 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530560
561 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530562
563 try
564 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800565 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530566 reply.read(name);
567 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500568 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530569 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700570 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700571 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700572 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530573 }
574 auto tupleVector = std::get_if<type>(&name);
575 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
576 {
Alexander Filippov983da552021-02-08 15:26:54 +0300577 int addressFamily = std::get<0>(*i);
578 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700579 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700580 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530581 }
582 return servers;
583}
584
William A. Kennington IIId298f932022-10-17 14:31:38 -0700585ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530586{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700587 auto idStr = stdplus::toStr(id);
William A. Kennington III86642522023-07-24 17:55:55 -0700588 auto intfName = stdplus::strCat(interfaceName(), "."sv, idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800589 if (manager.get().interfaces.find(intfName) !=
590 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800591 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700592 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700593 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
594 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800595 }
596
William A. Kennington IIId298f932022-10-17 14:31:38 -0700597 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700598 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700599 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700600 if (!macStr.empty())
601 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700602 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700603 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800604 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800605 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700606 .idx = 0, // TODO: Query the correct value after creation
607 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700608 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700609 .mac = std::move(mac),
610 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700611 .parent_idx = ifIdx,
612 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800613 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530614
Patrick Williams6aef7692021-05-01 06:39:41 -0500615 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530616 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700617 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800618 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700619 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530620
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800621 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530622
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700623 // write the device file for the vlan interface.
624 config::Parser config;
625 auto& netdev = config.map["NetDev"].emplace_back();
626 netdev["Name"].emplace_back(intfName);
627 netdev["Kind"].emplace_back("vlan");
628 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800629 config.writeFile(
630 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700631
632 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800633 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700634
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800635 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530636}
Ratan Gupta2b106532017-07-25 16:05:02 +0530637
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600638ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530639{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700640 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530641
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700642 writeConfigurationFile();
643 manager.get().reloadConfigs();
644
645 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600646}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700647
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600648ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
649{
650 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530651}
Ratan Gupta2b106532017-07-25 16:05:02 +0530652
653void EthernetInterface::writeConfigurationFile()
654{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700655 config::Parser config;
656 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530657 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700658 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800659#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700660 auto mac = MacAddressIntf::macAddress();
661 if (!mac.empty())
662 {
663 link["MACAddress"].emplace_back(mac);
664 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800665#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700666 if (!EthernetInterfaceIntf::nicEnabled())
667 {
668 link["Unmanaged"].emplace_back("yes");
669 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700670 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700671 {
672 auto& network = config.map["Network"].emplace_back();
673 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400674#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700675 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400676#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700677 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400678#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700679 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
680 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
681 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600682 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700683 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800684 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700685 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700686 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
687 {
688 vlans.emplace_back(intf->interfaceName());
689 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700690 }
691 }
692 {
693 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600694 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700695 {
696 ntps.emplace_back(ntp);
697 }
698 }
699 {
700 auto& dnss = network["DNS"];
701 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
702 {
703 dnss.emplace_back(dns);
704 }
705 }
706 {
707 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700708 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700709 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700710 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700711 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700712 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700713 }
714 }
715 }
716 {
717 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700718 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700719 {
720 auto gateway = EthernetInterfaceIntf::defaultGateway();
721 if (!gateway.empty())
722 {
723 gateways.emplace_back(gateway);
724 }
725 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530726
William A. Kennington III05cbc5b2023-07-20 19:37:30 -0700727 if (!ipv6AcceptRA())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700728 {
729 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
730 if (!gateway6.empty())
731 {
732 gateways.emplace_back(gateway6);
733 }
734 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600735 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800736 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700737 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700738 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500739 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700740 auto& neighbors = config.map["Neighbor"];
741 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800742 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700743 auto& neighbor = neighbors.emplace_back();
744 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
745 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800746 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500747 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500748 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700749 auto& dhcp = config.map["DHCP"].emplace_back();
750 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800751 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800752 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
753 dhcp["UseDNS"].emplace_back(dns_enabled);
754 dhcp["UseDomains"].emplace_back(dns_enabled);
755 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
756 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
757 : "false");
758 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
759 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500760 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500761 auto path = config::pathForIntfConf(manager.get().getConfDir(),
762 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700763 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700764 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530765}
766
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800767std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530768{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700769 if (vlan)
770 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700771 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700772 elog<InternalFailure>();
773 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800774#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700775 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600776 try
777 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700778 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600779 }
Patrick Williams5758db32021-10-06 12:29:22 -0500780 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600781 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700782 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600783 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
784 Argument::ARGUMENT_VALUE(value.c_str()));
785 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700786 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530787 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700788 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500789 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
790 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530791 }
792
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300793 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700794 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300795
William A. Kennington III1137a972019-04-20 20:49:58 -0700796 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700797 auto oldMAC =
798 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700799 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530800 {
Yuxiao Zhang46938072023-09-26 17:59:14 -0700801 auto path = config::pathForIntfConf(manager.get().getConfDir(),
802 interface);
William A. Kennington III1137a972019-04-20 20:49:58 -0700803 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800804 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530805 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700806 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
807 {
808 intf->MacAddressIntf::macAddress(validMAC);
809 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530810 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500811 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530812
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700813 writeConfigurationFile();
Yuxiao Zhang46938072023-09-26 17:59:14 -0700814 manager.get().addReloadPreHook([interface, path]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800815 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700816 system::setNICUp(interface, false);
Yuxiao Zhang46938072023-09-26 17:59:14 -0700817 utimensat(AT_FDCWD, path.c_str(), NULL, 0);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800818 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800819 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530820 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700821
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300822#ifdef HAVE_UBOOT_ENV
823 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700824 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300825 if (envVar)
826 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500827 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
828 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
829 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
830 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300831 }
832#endif // HAVE_UBOOT_ENV
833
William A. Kennington III1137a972019-04-20 20:49:58 -0700834 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800835#else
836 elog<NotAllowed>(
837 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
838#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530839}
840
Ratan Guptae9c9b812017-09-22 17:15:37 +0530841void EthernetInterface::deleteAll()
842{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530843 // clear all the ip on the interface
844 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700845
846 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800847 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530848}
849
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800850template <typename Addr>
851static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500852{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800853 if (gw.empty())
854 {
855 return;
856 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700857 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500858 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800859 auto ip = stdplus::fromStr<Addr>(gw);
860 if (ip == Addr{})
861 {
862 gw.clear();
863 return;
864 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800865 if (!validIntfIP(ip))
866 {
867 throw std::invalid_argument("Invalid unicast");
868 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800869 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500870 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700871 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500872 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800873 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500874 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800875 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500876 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800877}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700878
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800879std::string EthernetInterface::defaultGateway(std::string gateway)
880{
881 normalizeGateway<stdplus::In4Addr>(gateway);
882 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700883 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800884 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
885 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700886 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700887 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500888}
889
890std::string EthernetInterface::defaultGateway6(std::string gateway)
891{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800892 normalizeGateway<stdplus::In6Addr>(gateway);
893 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500894 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800895 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
896 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500897 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700898 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500899}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700900
901EthernetInterface::VlanProperties::VlanProperties(
902 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800903 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800904 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700905 parentIdx(*info.parent_idx), eth(eth)
906{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800907 VlanIntf::id(*info.vlan_id, true);
908 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700909}
910
911void EthernetInterface::VlanProperties::delete_()
912{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800913 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700914
915 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800916 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700917 std::error_code ec;
918 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
919 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
920
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800921 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800922 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800923 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800924 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800925 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800926 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800927 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800928
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700929 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800930 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700931 {
932 if (intf->ifIdx == parentIdx)
933 {
934 intf->writeConfigurationFile();
935 }
936 }
937
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800938 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700939 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800940 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800941 eth.get().manager.get().addReloadPostHook(
942 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800943
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800944 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800945 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700946 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800947
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800948 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700949}
950
Gunnar Mills57d9c502018-09-14 14:42:34 -0500951} // namespace network
952} // namespace phosphor