blob: fffb53a1608dd7a8f3f42a80ab0584d3673550ee [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 }
Jishnu CM57dfea92023-05-05 06:07:26 -0500121 addDHCPConfigurations();
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800122 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700123
William A. Kennington III13d665c2022-11-15 20:34:40 -0800124 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700125 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800126 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700127 {
128 std::runtime_error("Missing parent link");
129 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800130 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
131 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800132 for (const auto& [_, addr] : info.addrs)
133 {
134 addAddr(addr);
135 }
136 for (const auto& [_, neigh] : info.staticNeighs)
137 {
138 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700139 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530140}
141
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800142void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700143{
William A. Kennington III876927c2022-11-17 16:20:15 -0800144 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800145 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700146 if (info.mac)
147 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700148 MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700149 }
150 if (info.mtu)
151 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800152 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700153 }
William A. Kennington III21539662022-11-15 14:53:11 -0800154 if (ifIdx > 0)
155 {
156 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
157 return system::getEthInfo(*info.name);
158 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800159 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
160 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800161 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700162}
163
Johnathan Mantey817012a2020-01-30 15:07:39 -0800164bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
165{
166 return (
167#ifdef LINK_LOCAL_AUTOCONFIGURATION
Johnathan Manteyfabe3952023-09-08 13:21:05 -0700168 (origin == IP::AddressOrigin::Static)
169#else
Johnathan Mantey817012a2020-01-30 15:07:39 -0800170 (origin == IP::AddressOrigin::Static ||
171 origin == IP::AddressOrigin::LinkLocal)
172#endif
173
174 );
175}
176
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800177void EthernetInterface::addAddr(const AddressInfo& info)
178{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800179 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ravi Teja86c4f442023-07-19 22:26:39 -0500180 if (dhcpIsEnabled(info.ifaddr.getAddr()))
181 {
182 origin = IP::AddressOrigin::DHCP;
183 }
184
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800185#ifdef LINK_LOCAL_AUTOCONFIGURATION
186 if (info.scope == RT_SCOPE_LINK)
187 {
188 origin = IP::AddressOrigin::LinkLocal;
189 }
190#endif
191
Ravi Tejac6201202023-03-28 21:29:58 -0500192 if ((info.scope == RT_SCOPE_UNIVERSE) && (info.flags & IFA_F_PERMANENT))
193 {
194 origin = IP::AddressOrigin::Static;
195 }
196 if ((info.scope == RT_SCOPE_UNIVERSE) &&
197 ((info.flags & IFA_F_NOPREFIXROUTE) &&
198 (info.flags & IFA_F_MANAGETEMPADDR)))
199 {
200 origin = IP::AddressOrigin::SLAAC;
201 }
202 else if ((info.scope == RT_SCOPE_UNIVERSE) &&
203 ((info.flags & IFA_F_NOPREFIXROUTE)))
204 {
205 origin = IP::AddressOrigin::DHCP;
206 }
207
William A. Kennington III77747f62022-11-07 23:11:15 -0800208 auto it = addrs.find(info.ifaddr);
209 if (it == addrs.end())
210 {
211 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
212 bus, std::string_view(objPath), *this,
213 info.ifaddr, origin));
214 }
215 else
216 {
217 it->second->IPIfaces::origin(origin);
218 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800219}
220
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800221void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
222{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800223 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800224 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700225 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700226 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800227 return;
228 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800229
230 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
231 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700232 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800233 }
234 else
235 {
236 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
237 bus, std::string_view(objPath),
238 *this, *info.addr, *info.mac,
239 Neighbor::State::Permanent));
240 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800241}
242
Patrick Williams6aef7692021-05-01 06:39:41 -0500243ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700244 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530245{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700246 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700247 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530248 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700249 switch (protType)
250 {
251 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700252 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700253 break;
254 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700255 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700256 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700257 default:
258 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700259 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700260 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
261 {
262 throw std::invalid_argument("not unicast");
263 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500264 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700265 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500266 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700267 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
268 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500269 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
270 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
271 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700272 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700273 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500274 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700275 if (prefixLength == 0)
276 {
277 throw std::invalid_argument("default route");
278 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700279 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700280 }
281 catch (const std::exception& e)
282 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700283 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
284 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500285 elog<InvalidArgument>(
286 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700287 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530288 }
289
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700290 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800291 if (it == addrs.end())
292 {
293 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700294 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800295 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700296 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800297 }
298 else
299 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800300 if (it->second->origin() == IP::AddressOrigin::Static)
301 {
302 return it->second->getObjPath();
303 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800304 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
305 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530306
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700307 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800308 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700309
William A. Kennington III434a9432022-11-04 18:38:46 -0700310 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530311}
312
Patrick Williams6aef7692021-05-01 06:39:41 -0500313ObjectPath EthernetInterface::neighbor(std::string ipAddress,
314 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800315{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700316 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700317 try
William A. Kennington III08505792019-01-30 16:00:04 -0800318 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700319 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700320 }
321 catch (const std::exception& e)
322 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700323 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700324 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500325 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
326 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800327 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700328
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700329 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700330 try
William A. Kennington III08505792019-01-30 16:00:04 -0800331 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700332 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700333 }
334 catch (const std::exception& e)
335 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700336 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
337 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500338 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
339 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800340 }
341
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700342 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800343 if (it == staticNeighbors.end())
344 {
345 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700346 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
347 *this, *addr, *lladdr,
348 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800349 }
350 else
351 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700352 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800353 if (it->second->macAddress() == str)
354 {
355 return it->second->getObjPath();
356 }
357 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800358 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700359
360 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800361 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700362
William A. Kennington III434a9432022-11-04 18:38:46 -0700363 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800364}
365
Patrick Williams6aef7692021-05-01 06:39:41 -0500366bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700367{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700368 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700369 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700370 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800371 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700372 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700373 return value;
374}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700375
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700376bool EthernetInterface::dhcp4(bool value)
377{
378 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
379 {
380 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800381 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700382 }
383 return value;
384}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700385
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700386bool EthernetInterface::dhcp6(bool value)
387{
388 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
389 {
390 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800391 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700392 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700393 return value;
394}
395
Patrick Williams6aef7692021-05-01 06:39:41 -0500396EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530397{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700398 auto old4 = EthernetInterfaceIntf::dhcp4();
399 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
400 value == DHCPConf::v4v6stateless ||
401 value == DHCPConf::both);
402 auto old6 = EthernetInterfaceIntf::dhcp6();
403 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
404 value == DHCPConf::both);
405 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
406 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
407 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
408 value == DHCPConf::v6 || value == DHCPConf::both);
409
410 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530411 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700412 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800413 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530414 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530415 return value;
416}
417
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700418EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
419{
420 if (dhcp6())
421 {
422 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
423 }
424 else if (dhcp4())
425 {
426 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
427 }
428 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
429}
430
Tejas Patil2c0fc562021-08-03 19:13:46 +0530431size_t EthernetInterface::mtu(size_t value)
432{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700433 const size_t old = EthernetInterfaceIntf::mtu();
434 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530435 {
436 return value;
437 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700438 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700439 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700440 system::setMTU(ifname, value);
441 return value;
442 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530443}
444
Patrick Williams6aef7692021-05-01 06:39:41 -0500445bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700446{
Patrick Williams6aef7692021-05-01 06:39:41 -0500447 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700448 {
449 return value;
450 }
451
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800452 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700453 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800454 if (!value)
455 {
456 // We only need to bring down the interface, networkd will always bring
457 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800458 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700459 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800460 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800461 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800462
463 return value;
464}
465
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530466ServerList EthernetInterface::staticNameServers(ServerList value)
467{
nitinkotania581cb0b2023-03-21 00:28:55 -0500468 std::vector<std::string> dnsUniqueValues;
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700469 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530470 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700471 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530472 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700473 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700474 }
475 catch (const std::exception& e)
476 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700477 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
478 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700479 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
480 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530481 }
nitinkotania581cb0b2023-03-21 00:28:55 -0500482 if (std::find(dnsUniqueValues.begin(), dnsUniqueValues.end(), ip) ==
483 dnsUniqueValues.end())
484 {
485 dnsUniqueValues.push_back(ip);
486 }
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530487 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700488
nitinkotania581cb0b2023-03-21 00:28:55 -0500489 value =
490 EthernetInterfaceIntf::staticNameServers(std::move(dnsUniqueValues));
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700491
492 writeConfigurationFile();
493 manager.get().reloadConfigs();
494
495 return value;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530496}
497
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600498void EthernetInterface::loadNTPServers(const config::Parser& config)
499{
500 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
501 EthernetInterfaceIntf::staticNTPServers(
502 config.map.getValueStrings("Network", "NTP"));
503}
504
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700505void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530506{
507 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700508 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700509 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530510}
511
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600512ServerList EthernetInterface::getNTPServerFromTimeSyncd()
513{
514 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500515 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
516 TIMESYNCD_SERVICE_PATH,
517 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600518
519 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
520
521 try
522 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800523 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600524 std::variant<ServerList> response;
525 reply.read(response);
526 servers = std::get<ServerList>(response);
527 }
528 catch (const sdbusplus::exception::SdBusError& e)
529 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700530 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700531 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700532 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600533 }
534
535 return servers;
536}
537
Ravi Teja4f8b9a02023-09-06 13:41:52 -0500538ServerList EthernetInterface::nameservers() const
539{
540 return getNameServerFromResolvd();
541}
542
543ServerList EthernetInterface::getNameServerFromResolvd() const
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530544{
545 ServerList servers;
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700546 auto OBJ_PATH = std::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530547
548 /*
549 The DNS property under org.freedesktop.resolve1.Link interface contains
550 an array containing all DNS servers currently used by resolved. It
551 contains similar information as the DNS server data written to
552 /run/systemd/resolve/resolv.conf.
553
554 Each structure in the array consists of a numeric network interface index,
555 an address family, and a byte array containing the DNS server address
556 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
557 The array contains DNS servers configured system-wide, including those
558 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
559 /etc/systemd/resolved.conf, as well as per-interface DNS server
560 information either retrieved from systemd-networkd or configured by
561 external software via SetLinkDNS().
562 */
563
564 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
565 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800566 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
567 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530568
569 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530570
571 try
572 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800573 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530574 reply.read(name);
575 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500576 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530577 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700578 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700579 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700580 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530581 }
582 auto tupleVector = std::get_if<type>(&name);
583 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
584 {
Alexander Filippov983da552021-02-08 15:26:54 +0300585 int addressFamily = std::get<0>(*i);
586 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700587 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700588 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530589 }
590 return servers;
591}
592
William A. Kennington IIId298f932022-10-17 14:31:38 -0700593ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530594{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700595 auto idStr = stdplus::toStr(id);
William A. Kennington III86642522023-07-24 17:55:55 -0700596 auto intfName = stdplus::strCat(interfaceName(), "."sv, idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800597 if (manager.get().interfaces.find(intfName) !=
598 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800599 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700600 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700601 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
602 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800603 }
604
William A. Kennington IIId298f932022-10-17 14:31:38 -0700605 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700606 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700607 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700608 if (!macStr.empty())
609 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700610 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700611 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800612 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800613 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700614 .idx = 0, // TODO: Query the correct value after creation
615 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700616 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700617 .mac = std::move(mac),
618 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700619 .parent_idx = ifIdx,
620 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800621 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530622
Patrick Williams6aef7692021-05-01 06:39:41 -0500623 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530624 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700625 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800626 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700627 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530628
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800629 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530630
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700631 // write the device file for the vlan interface.
632 config::Parser config;
633 auto& netdev = config.map["NetDev"].emplace_back();
634 netdev["Name"].emplace_back(intfName);
635 netdev["Kind"].emplace_back("vlan");
636 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800637 config.writeFile(
638 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700639
640 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800641 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700642
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800643 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530644}
Ratan Gupta2b106532017-07-25 16:05:02 +0530645
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600646ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530647{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700648 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530649
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700650 writeConfigurationFile();
651 manager.get().reloadConfigs();
652
653 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600654}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700655
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600656ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
657{
658 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530659}
Ratan Gupta2b106532017-07-25 16:05:02 +0530660
661void EthernetInterface::writeConfigurationFile()
662{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700663 config::Parser config;
664 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530665 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700666 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800667#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700668 auto mac = MacAddressIntf::macAddress();
669 if (!mac.empty())
670 {
671 link["MACAddress"].emplace_back(mac);
672 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800673#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700674 if (!EthernetInterfaceIntf::nicEnabled())
675 {
676 link["Unmanaged"].emplace_back("yes");
677 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700678 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700679 {
680 auto& network = config.map["Network"].emplace_back();
681 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400682#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700683 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400684#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700685 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400686#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700687 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
688 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
689 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600690 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700691 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800692 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700693 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700694 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
695 {
696 vlans.emplace_back(intf->interfaceName());
697 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700698 }
699 }
700 {
701 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600702 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700703 {
704 ntps.emplace_back(ntp);
705 }
706 }
707 {
708 auto& dnss = network["DNS"];
709 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
710 {
711 dnss.emplace_back(dns);
712 }
713 }
714 {
715 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700716 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700717 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700718 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700719 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700720 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700721 }
722 }
723 }
724 {
725 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700726 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700727 {
728 auto gateway = EthernetInterfaceIntf::defaultGateway();
729 if (!gateway.empty())
730 {
731 gateways.emplace_back(gateway);
732 }
733 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530734
William A. Kennington III05cbc5b2023-07-20 19:37:30 -0700735 if (!ipv6AcceptRA())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700736 {
737 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
738 if (!gateway6.empty())
739 {
740 gateways.emplace_back(gateway6);
741 }
742 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600743 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800744 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700745 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700746 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500747 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700748 auto& neighbors = config.map["Neighbor"];
749 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800750 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700751 auto& neighbor = neighbors.emplace_back();
752 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
753 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800754 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500755 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500756 {
Jishnu CM57dfea92023-05-05 06:07:26 -0500757 auto& dhcp4 = config.map["DHCPv4"].emplace_back();
758 dhcp4["ClientIdentifier"].emplace_back("mac");
759 const auto& conf = *dhcpConfigs[static_cast<int>(DHCPType::v4)];
William A. Kennington III5b179382022-11-15 15:23:26 -0800760 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
Ravi Tejab6595b22024-02-23 05:00:23 -0600761 auto domain_enabled = conf.domainEnabled() ? "true" : "false";
Jishnu CM57dfea92023-05-05 06:07:26 -0500762 dhcp4["UseDNS"].emplace_back(dns_enabled);
Ravi Tejab6595b22024-02-23 05:00:23 -0600763 dhcp4["UseDomains"].emplace_back(domain_enabled);
Jishnu CM57dfea92023-05-05 06:07:26 -0500764 dhcp4["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
765 dhcp4["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
766 : "false");
767 dhcp4["SendHostname"].emplace_back(
768 conf.sendHostNameEnabled() ? "true" : "false");
769 }
770 {
771 auto& dhcp6 = config.map["DHCPv6"].emplace_back();
772 const auto& conf = *dhcpConfigs[static_cast<int>(DHCPType::v6)];
773 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
Ravi Tejab6595b22024-02-23 05:00:23 -0600774 auto domain_enabled = conf.domainEnabled() ? "true" : "false";
Jishnu CM57dfea92023-05-05 06:07:26 -0500775 dhcp6["UseDNS"].emplace_back(dns_enabled);
Ravi Tejab6595b22024-02-23 05:00:23 -0600776 dhcp6["UseDomains"].emplace_back(domain_enabled);
Jishnu CM57dfea92023-05-05 06:07:26 -0500777 dhcp6["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
778 dhcp6["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
779 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500780 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500781 auto path = config::pathForIntfConf(manager.get().getConfDir(),
782 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700783 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700784 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530785}
786
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800787std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530788{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700789 if (vlan)
790 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700791 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700792 elog<InternalFailure>();
793 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800794#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700795 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600796 try
797 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700798 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600799 }
Patrick Williams5758db32021-10-06 12:29:22 -0500800 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600801 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700802 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600803 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
804 Argument::ARGUMENT_VALUE(value.c_str()));
805 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700806 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530807 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700808 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500809 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
810 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530811 }
812
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300813 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700814 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300815
William A. Kennington III1137a972019-04-20 20:49:58 -0700816 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700817 auto oldMAC =
818 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700819 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530820 {
Yuxiao Zhang46938072023-09-26 17:59:14 -0700821 auto path = config::pathForIntfConf(manager.get().getConfDir(),
822 interface);
William A. Kennington III1137a972019-04-20 20:49:58 -0700823 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800824 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530825 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700826 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
827 {
828 intf->MacAddressIntf::macAddress(validMAC);
829 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530830 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500831 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530832
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700833 writeConfigurationFile();
Yuxiao Zhang46938072023-09-26 17:59:14 -0700834 manager.get().addReloadPreHook([interface, path]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800835 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700836 system::setNICUp(interface, false);
Yuxiao Zhang46938072023-09-26 17:59:14 -0700837 utimensat(AT_FDCWD, path.c_str(), NULL, 0);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800838 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800839 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530840 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700841
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300842#ifdef HAVE_UBOOT_ENV
843 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700844 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300845 if (envVar)
846 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500847 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
848 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
849 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
850 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300851 }
852#endif // HAVE_UBOOT_ENV
853
William A. Kennington III1137a972019-04-20 20:49:58 -0700854 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800855#else
856 elog<NotAllowed>(
857 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
858#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530859}
860
Ratan Guptae9c9b812017-09-22 17:15:37 +0530861void EthernetInterface::deleteAll()
862{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530863 // clear all the ip on the interface
864 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700865
866 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800867 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530868}
869
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800870template <typename Addr>
871static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500872{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800873 if (gw.empty())
874 {
875 return;
876 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700877 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500878 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800879 auto ip = stdplus::fromStr<Addr>(gw);
880 if (ip == Addr{})
881 {
882 gw.clear();
883 return;
884 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800885 if (!validIntfIP(ip))
886 {
887 throw std::invalid_argument("Invalid unicast");
888 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800889 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500890 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700891 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500892 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800893 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500894 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800895 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500896 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800897}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700898
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800899std::string EthernetInterface::defaultGateway(std::string gateway)
900{
901 normalizeGateway<stdplus::In4Addr>(gateway);
902 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700903 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800904 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700905 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800906 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700907 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700908 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500909}
910
911std::string EthernetInterface::defaultGateway6(std::string gateway)
912{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800913 normalizeGateway<stdplus::In6Addr>(gateway);
914 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500915 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800916 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700917 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800918 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500919 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700920 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500921}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700922
923EthernetInterface::VlanProperties::VlanProperties(
924 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800925 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800926 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700927 parentIdx(*info.parent_idx), eth(eth)
928{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800929 VlanIntf::id(*info.vlan_id, true);
930 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700931}
932
933void EthernetInterface::VlanProperties::delete_()
934{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800935 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700936
937 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800938 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700939 std::error_code ec;
940 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
941 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
942
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800943 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800944 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800945 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800946 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800947 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800948 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800949 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800950
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700951 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800952 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700953 {
954 if (intf->ifIdx == parentIdx)
955 {
956 intf->writeConfigurationFile();
957 }
958 }
959
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800960 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700961 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800962 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800963 eth.get().manager.get().addReloadPostHook(
964 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800965
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800966 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800967 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700968 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800969
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800970 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700971}
972
Jishnu CM57dfea92023-05-05 06:07:26 -0500973void EthernetInterface::addDHCPConfigurations()
974{
975 this->dhcpConfigs.emplace_back(std::make_unique<dhcp::Configuration>(
976 bus, objPath + "/dhcp4", *this, DHCPType::v4));
977 this->dhcpConfigs.emplace_back(std::make_unique<dhcp::Configuration>(
978 bus, objPath + "/dhcp6", *this, DHCPType::v6));
979}
980
981void EthernetInterface::reloadConfigs()
982{
983 manager.get().reloadConfigs();
984}
985
Gunnar Mills57d9c502018-09-14 14:42:34 -0500986} // namespace network
987} // namespace phosphor