blob: 6a34492ce12dc54c79043e09af25395ce89900f4 [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
William A. Kennington IIId7946a72019-04-19 14:24:09 -070010#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070011#include <net/if.h>
William A. Kennington III9c441fd2023-02-24 13:40:01 -080012#include <net/if_arp.h>
Yuxiao Zhang46938072023-09-26 17:59:14 -070013#include <sys/stat.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014
Patrick Venture189d44e2018-07-09 12:30:59 -070015#include <phosphor-logging/elog-errors.hpp>
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -070016#include <phosphor-logging/lg2.hpp>
William A. Kennington III945878a2024-04-17 01:05:27 -070017#include <stdplus/fd/create.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
Patrick Williamsad205022024-08-16 15:20:07 -040082EthernetInterface::EthernetInterface(
83 stdplus::PinnedRef<sdbusplus::bus_t> bus,
84 stdplus::PinnedRef<Manager> manager, const AllIntfInfo& info,
85 std::string_view objRoot, const config::Parser& config, bool enabled) :
William A. Kennington III13d665c2022-11-15 20:34:40 -080086 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.intf.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080087 config, enabled)
Patrick Williams89d734b2023-05-10 07:50:25 -050088{}
William A. Kennington IIId298f932022-10-17 14:31:38 -070089
Patrick Williamsad205022024-08-16 15:20:07 -040090EthernetInterface::EthernetInterface(
91 stdplus::PinnedRef<sdbusplus::bus_t> bus,
92 stdplus::PinnedRef<Manager> manager, const AllIntfInfo& info,
93 std::string&& objPath, const config::Parser& config, bool enabled) :
94 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit), manager(manager),
95 bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +053096{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080097 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070098 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080099 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
100 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
101 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
102 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500103
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700104 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800105 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +0530106
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800107 updateInfo(info.intf, true);
108
109 if (info.defgw4)
110 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700111 EthernetInterface::defaultGateway(stdplus::toStr(*info.defgw4), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800112 }
113 if (info.defgw6)
114 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700115 EthernetInterface::defaultGateway6(stdplus::toStr(*info.defgw6), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800116 }
117 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700118
William A. Kennington III13d665c2022-11-15 20:34:40 -0800119 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700120 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800121 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700122 {
123 std::runtime_error("Missing parent link");
124 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800125 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
126 }
William A. Kennington IIIfad525c2024-04-17 00:51:59 -0700127 dhcp4Conf.emplace(bus, this->objPath + "/dhcp4", *this, DHCPType::v4);
128 dhcp6Conf.emplace(bus, this->objPath + "/dhcp6", *this, DHCPType::v6);
William A. Kennington III13d665c2022-11-15 20:34:40 -0800129 for (const auto& [_, addr] : info.addrs)
130 {
131 addAddr(addr);
132 }
133 for (const auto& [_, neigh] : info.staticNeighs)
134 {
135 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700136 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530137}
138
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800139void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700140{
William A. Kennington III876927c2022-11-17 16:20:15 -0800141 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800142 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700143 if (info.mac)
144 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700145 MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700146 }
147 if (info.mtu)
148 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800149 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700150 }
William A. Kennington III21539662022-11-15 14:53:11 -0800151 if (ifIdx > 0)
152 {
153 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
154 return system::getEthInfo(*info.name);
155 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800156 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
157 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800158 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700159}
160
Johnathan Mantey817012a2020-01-30 15:07:39 -0800161bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
162{
163 return (
164#ifdef LINK_LOCAL_AUTOCONFIGURATION
Johnathan Manteyfabe3952023-09-08 13:21:05 -0700165 (origin == IP::AddressOrigin::Static)
166#else
Johnathan Mantey817012a2020-01-30 15:07:39 -0800167 (origin == IP::AddressOrigin::Static ||
168 origin == IP::AddressOrigin::LinkLocal)
169#endif
170
171 );
172}
173
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800174void EthernetInterface::addAddr(const AddressInfo& info)
175{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800176 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ravi Teja86c4f442023-07-19 22:26:39 -0500177 if (dhcpIsEnabled(info.ifaddr.getAddr()))
178 {
179 origin = IP::AddressOrigin::DHCP;
180 }
181
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800182#ifdef LINK_LOCAL_AUTOCONFIGURATION
183 if (info.scope == RT_SCOPE_LINK)
184 {
185 origin = IP::AddressOrigin::LinkLocal;
186 }
187#endif
188
Ravi Tejac6201202023-03-28 21:29:58 -0500189 if ((info.scope == RT_SCOPE_UNIVERSE) && (info.flags & IFA_F_PERMANENT))
190 {
191 origin = IP::AddressOrigin::Static;
192 }
193 if ((info.scope == RT_SCOPE_UNIVERSE) &&
194 ((info.flags & IFA_F_NOPREFIXROUTE) &&
195 (info.flags & IFA_F_MANAGETEMPADDR)))
196 {
197 origin = IP::AddressOrigin::SLAAC;
198 }
199 else if ((info.scope == RT_SCOPE_UNIVERSE) &&
200 ((info.flags & IFA_F_NOPREFIXROUTE)))
201 {
202 origin = IP::AddressOrigin::DHCP;
203 }
204
William A. Kennington III77747f62022-11-07 23:11:15 -0800205 auto it = addrs.find(info.ifaddr);
206 if (it == addrs.end())
207 {
208 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
209 bus, std::string_view(objPath), *this,
210 info.ifaddr, origin));
211 }
212 else
213 {
214 it->second->IPIfaces::origin(origin);
215 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800216}
217
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800218void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
219{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800220 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800221 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700222 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700223 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800224 return;
225 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800226
227 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
228 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700229 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800230 }
231 else
232 {
Patrick Williamsad205022024-08-16 15:20:07 -0400233 staticNeighbors.emplace(
234 *info.addr, std::make_unique<Neighbor>(
235 bus, std::string_view(objPath), *this, *info.addr,
236 *info.mac, Neighbor::State::Permanent));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800237 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800238}
239
Patrick Williams6aef7692021-05-01 06:39:41 -0500240ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700241 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530242{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700243 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700244 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530245 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700246 switch (protType)
247 {
248 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700249 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700250 break;
251 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700252 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700253 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700254 default:
255 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700256 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700257 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
258 {
259 throw std::invalid_argument("not unicast");
260 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500261 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700262 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500263 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700264 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
265 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500266 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
267 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
268 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700269 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700270 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500271 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700272 if (prefixLength == 0)
273 {
274 throw std::invalid_argument("default route");
275 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700276 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700277 }
278 catch (const std::exception& e)
279 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700280 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
281 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500282 elog<InvalidArgument>(
283 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700284 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530285 }
286
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700287 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800288 if (it == addrs.end())
289 {
290 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700291 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800292 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700293 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800294 }
295 else
296 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800297 if (it->second->origin() == IP::AddressOrigin::Static)
298 {
299 return it->second->getObjPath();
300 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800301 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
302 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530303
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700304 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800305 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700306
William A. Kennington III434a9432022-11-04 18:38:46 -0700307 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530308}
309
Patrick Williams6aef7692021-05-01 06:39:41 -0500310ObjectPath EthernetInterface::neighbor(std::string ipAddress,
311 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800312{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700313 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700314 try
William A. Kennington III08505792019-01-30 16:00:04 -0800315 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700316 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700317 }
318 catch (const std::exception& e)
319 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700320 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700321 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500322 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
323 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800324 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700325
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700326 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700327 try
William A. Kennington III08505792019-01-30 16:00:04 -0800328 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700329 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700330 }
331 catch (const std::exception& e)
332 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700333 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
334 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500335 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
336 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800337 }
338
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700339 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800340 if (it == staticNeighbors.end())
341 {
342 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700343 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
344 *this, *addr, *lladdr,
345 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800346 }
347 else
348 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700349 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800350 if (it->second->macAddress() == str)
351 {
352 return it->second->getObjPath();
353 }
354 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800355 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700356
357 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800358 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700359
William A. Kennington III434a9432022-11-04 18:38:46 -0700360 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800361}
362
Patrick Williams6aef7692021-05-01 06:39:41 -0500363bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700364{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700365 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700366 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700367 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800368 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700369 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700370 return value;
371}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700372
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700373bool EthernetInterface::dhcp4(bool value)
374{
375 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
376 {
377 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800378 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700379 }
380 return value;
381}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700382
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700383bool EthernetInterface::dhcp6(bool value)
384{
385 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
386 {
387 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800388 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700389 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700390 return value;
391}
392
Patrick Williams6aef7692021-05-01 06:39:41 -0500393EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530394{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700395 auto old4 = EthernetInterfaceIntf::dhcp4();
Patrick Williamsad205022024-08-16 15:20:07 -0400396 auto new4 = EthernetInterfaceIntf::dhcp4(
397 value == DHCPConf::v4 || value == DHCPConf::v4v6stateless ||
398 value == DHCPConf::both);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700399 auto old6 = EthernetInterfaceIntf::dhcp6();
Patrick Williamsad205022024-08-16 15:20:07 -0400400 auto new6 = EthernetInterfaceIntf::dhcp6(
401 value == DHCPConf::v6 || value == DHCPConf::both);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700402 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
403 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
404 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
405 value == DHCPConf::v6 || value == DHCPConf::both);
406
407 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530408 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700409 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800410 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530411 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530412 return value;
413}
414
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700415EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
416{
417 if (dhcp6())
418 {
419 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
420 }
421 else if (dhcp4())
422 {
423 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
424 }
425 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
426}
427
Tejas Patil2c0fc562021-08-03 19:13:46 +0530428size_t EthernetInterface::mtu(size_t value)
429{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700430 const size_t old = EthernetInterfaceIntf::mtu();
431 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530432 {
433 return value;
434 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700435 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700436 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700437 system::setMTU(ifname, value);
438 return value;
439 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530440}
441
Patrick Williams6aef7692021-05-01 06:39:41 -0500442bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700443{
Patrick Williams6aef7692021-05-01 06:39:41 -0500444 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700445 {
446 return value;
447 }
448
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800449 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700450 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800451 if (!value)
452 {
453 // We only need to bring down the interface, networkd will always bring
454 // up managed interfaces
Patrick Williamsad205022024-08-16 15:20:07 -0400455 manager.get().addReloadPreHook([ifname = interfaceName()]() {
456 system::setNICUp(ifname, false);
457 });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800458 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800459 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800460
461 return value;
462}
463
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530464ServerList EthernetInterface::staticNameServers(ServerList value)
465{
nitinkotania581cb0b2023-03-21 00:28:55 -0500466 std::vector<std::string> dnsUniqueValues;
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 }
nitinkotania581cb0b2023-03-21 00:28:55 -0500480 if (std::find(dnsUniqueValues.begin(), dnsUniqueValues.end(), ip) ==
481 dnsUniqueValues.end())
482 {
483 dnsUniqueValues.push_back(ip);
484 }
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530485 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700486
nitinkotania581cb0b2023-03-21 00:28:55 -0500487 value =
488 EthernetInterfaceIntf::staticNameServers(std::move(dnsUniqueValues));
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700489
490 writeConfigurationFile();
491 manager.get().reloadConfigs();
492
493 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530494}
495
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600496void EthernetInterface::loadNTPServers(const config::Parser& config)
497{
498 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
499 EthernetInterfaceIntf::staticNTPServers(
500 config.map.getValueStrings("Network", "NTP"));
501}
502
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700503void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530504{
505 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700506 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700507 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530508}
509
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600510ServerList EthernetInterface::getNTPServerFromTimeSyncd()
511{
512 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williamsad205022024-08-16 15:20:07 -0400513 auto method =
514 bus.get().new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
515 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600516
517 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
518
519 try
520 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800521 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600522 std::variant<ServerList> response;
523 reply.read(response);
524 servers = std::get<ServerList>(response);
525 }
526 catch (const sdbusplus::exception::SdBusError& e)
527 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700528 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700529 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700530 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600531 }
532
533 return servers;
534}
535
Ravi Teja4f8b9a02023-09-06 13:41:52 -0500536ServerList EthernetInterface::nameservers() const
537{
538 return getNameServerFromResolvd();
539}
540
541ServerList EthernetInterface::getNameServerFromResolvd() const
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530542{
543 ServerList servers;
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700544 auto OBJ_PATH = std::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530545
546 /*
547 The DNS property under org.freedesktop.resolve1.Link interface contains
548 an array containing all DNS servers currently used by resolved. It
549 contains similar information as the DNS server data written to
550 /run/systemd/resolve/resolv.conf.
551
552 Each structure in the array consists of a numeric network interface index,
553 an address family, and a byte array containing the DNS server address
554 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
555 The array contains DNS servers configured system-wide, including those
556 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
557 /etc/systemd/resolved.conf, as well as per-interface DNS server
558 information either retrieved from systemd-networkd or configured by
559 external software via SetLinkDNS().
560 */
561
562 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
563 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800564 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
565 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530566
567 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530568
569 try
570 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800571 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530572 reply.read(name);
573 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500574 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530575 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700576 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700577 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700578 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530579 }
580 auto tupleVector = std::get_if<type>(&name);
581 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
582 {
Alexander Filippov983da552021-02-08 15:26:54 +0300583 int addressFamily = std::get<0>(*i);
584 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700585 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700586 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530587 }
588 return servers;
589}
590
William A. Kennington IIId298f932022-10-17 14:31:38 -0700591ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530592{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700593 auto idStr = stdplus::toStr(id);
William A. Kennington III86642522023-07-24 17:55:55 -0700594 auto intfName = stdplus::strCat(interfaceName(), "."sv, idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800595 if (manager.get().interfaces.find(intfName) !=
596 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800597 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700598 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700599 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
600 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800601 }
602
William A. Kennington IIId298f932022-10-17 14:31:38 -0700603 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700604 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700605 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700606 if (!macStr.empty())
607 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700608 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700609 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800610 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800611 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700612 .idx = 0, // TODO: Query the correct value after creation
613 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700614 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700615 .mac = std::move(mac),
616 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700617 .parent_idx = ifIdx,
618 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800619 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530620
Patrick Williams6aef7692021-05-01 06:39:41 -0500621 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530622 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700623 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800624 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700625 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530626
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800627 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530628
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700629 // write the device file for the vlan interface.
630 config::Parser config;
631 auto& netdev = config.map["NetDev"].emplace_back();
632 netdev["Name"].emplace_back(intfName);
633 netdev["Kind"].emplace_back("vlan");
634 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800635 config.writeFile(
636 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700637
638 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800639 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700640
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800641 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530642}
Ratan Gupta2b106532017-07-25 16:05:02 +0530643
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600644ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530645{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700646 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530647
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700648 writeConfigurationFile();
649 manager.get().reloadConfigs();
650
651 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600652}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700653
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600654ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
655{
656 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530657}
Ratan Gupta2b106532017-07-25 16:05:02 +0530658
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700659static constexpr std::string_view tfStr(bool value)
660{
661 return value ? "true"sv : "false"sv;
662}
663
William A. Kennington III945878a2024-04-17 01:05:27 -0700664static void writeUpdatedTime(const Manager& manager,
665 const std::filesystem::path& netFile)
666{
667 // JFFS2 doesn't have the time granularity to deal with sub-second
668 // updates. Since we can have multiple file updates within a second
669 // around a reload, we need a location which gives that precision for
670 // future networkd detected reloads. TMPFS gives us this property.
671 if (manager.getConfDir() == "/etc/systemd/network"sv)
672 {
673 auto dir = stdplus::strCat(netFile.native(), ".d");
674 dir.replace(1, 3, "run"); // Replace /etc with /run
675 auto file = dir + "/updated.conf";
676 try
677 {
678 std::filesystem::create_directories(dir);
679 using namespace stdplus::fd;
680 futimens(
681 open(file,
682 OpenFlags(OpenAccess::WriteOnly).set(OpenFlag::Create),
683 0644)
684 .get(),
685 nullptr);
686 }
687 catch (const std::exception& e)
688 {
689 lg2::error("Failed to write time updated file {FILE}: {ERROR}",
690 "FILE", file, "ERROR", e.what());
691 }
692 }
693}
694
Ratan Gupta2b106532017-07-25 16:05:02 +0530695void EthernetInterface::writeConfigurationFile()
696{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700697 config::Parser config;
698 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530699 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700700 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800701#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700702 auto mac = MacAddressIntf::macAddress();
703 if (!mac.empty())
704 {
705 link["MACAddress"].emplace_back(mac);
706 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800707#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700708 if (!EthernetInterfaceIntf::nicEnabled())
709 {
710 link["Unmanaged"].emplace_back("yes");
711 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700712 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700713 {
714 auto& network = config.map["Network"].emplace_back();
715 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400716#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700717 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400718#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700719 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400720#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700721 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
722 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
723 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600724 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700725 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800726 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700727 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700728 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
729 {
730 vlans.emplace_back(intf->interfaceName());
731 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700732 }
733 }
734 {
735 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600736 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700737 {
738 ntps.emplace_back(ntp);
739 }
740 }
741 {
742 auto& dnss = network["DNS"];
743 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
744 {
745 dnss.emplace_back(dns);
746 }
747 }
748 {
749 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700750 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700751 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700752 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700753 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700754 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700755 }
756 }
757 }
758 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700759 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700760 {
Ravi Teja91f60562024-04-17 06:26:43 -0500761 auto gateway4 = EthernetInterfaceIntf::defaultGateway();
762 if (!gateway4.empty())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700763 {
Ravi Teja91f60562024-04-17 06:26:43 -0500764 auto& gateway4route = config.map["Route"].emplace_back();
765 gateway4route["Gateway"].emplace_back(gateway4);
766 gateway4route["GatewayOnLink"].emplace_back("true");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700767 }
768 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530769
William A. Kennington III05cbc5b2023-07-20 19:37:30 -0700770 if (!ipv6AcceptRA())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700771 {
772 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
773 if (!gateway6.empty())
774 {
Ravi Teja91f60562024-04-17 06:26:43 -0500775 auto& gateway6route = config.map["Route"].emplace_back();
776 gateway6route["Gateway"].emplace_back(gateway6);
777 gateway6route["GatewayOnLink"].emplace_back("true");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700778 }
779 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600780 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800781 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700782 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700783 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500784 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700785 auto& neighbors = config.map["Neighbor"];
786 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800787 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700788 auto& neighbor = neighbors.emplace_back();
789 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
790 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800791 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500792 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500793 {
Jishnu CM57dfea92023-05-05 06:07:26 -0500794 auto& dhcp4 = config.map["DHCPv4"].emplace_back();
795 dhcp4["ClientIdentifier"].emplace_back("mac");
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700796 dhcp4["UseDNS"].emplace_back(tfStr(dhcp4Conf->dnsEnabled()));
797 dhcp4["UseDomains"].emplace_back(tfStr(dhcp4Conf->domainEnabled()));
798 dhcp4["UseNTP"].emplace_back(tfStr(dhcp4Conf->ntpEnabled()));
799 dhcp4["UseHostname"].emplace_back(tfStr(dhcp4Conf->hostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500800 dhcp4["SendHostname"].emplace_back(
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700801 tfStr(dhcp4Conf->sendHostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500802 }
803 {
804 auto& dhcp6 = config.map["DHCPv6"].emplace_back();
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700805 dhcp6["UseDNS"].emplace_back(tfStr(dhcp6Conf->dnsEnabled()));
806 dhcp6["UseDomains"].emplace_back(tfStr(dhcp6Conf->domainEnabled()));
807 dhcp6["UseNTP"].emplace_back(tfStr(dhcp6Conf->ntpEnabled()));
808 dhcp6["UseHostname"].emplace_back(tfStr(dhcp6Conf->hostNameEnabled()));
William A. Kennington III44937b12024-04-17 00:28:20 -0700809 dhcp6["SendHostname"].emplace_back(
810 tfStr(dhcp6Conf->sendHostNameEnabled()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500811 }
Patrick Williamsad205022024-08-16 15:20:07 -0400812 auto path =
813 config::pathForIntfConf(manager.get().getConfDir(), interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700814 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700815 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
William A. Kennington III945878a2024-04-17 01:05:27 -0700816 writeUpdatedTime(manager, path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530817}
818
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800819std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530820{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700821 if (vlan)
822 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700823 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700824 elog<InternalFailure>();
825 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800826#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700827 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600828 try
829 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700830 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600831 }
Patrick Williams5758db32021-10-06 12:29:22 -0500832 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600833 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700834 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600835 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
836 Argument::ARGUMENT_VALUE(value.c_str()));
837 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700838 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530839 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700840 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500841 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
842 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530843 }
844
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300845 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700846 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300847
William A. Kennington III1137a972019-04-20 20:49:58 -0700848 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700849 auto oldMAC =
850 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700851 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530852 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700853 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800854 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530855 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700856 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
857 {
858 intf->MacAddressIntf::macAddress(validMAC);
859 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530860 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500861 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530862
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700863 writeConfigurationFile();
William A. Kennington III945878a2024-04-17 01:05:27 -0700864 manager.get().addReloadPreHook([interface, manager = manager]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800865 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700866 system::setNICUp(interface, false);
William A. Kennington III945878a2024-04-17 01:05:27 -0700867 writeUpdatedTime(
868 manager,
869 config::pathForIntfConf(manager.get().getConfDir(), interface));
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800870 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800871 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530872 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700873
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300874#ifdef HAVE_UBOOT_ENV
875 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700876 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300877 if (envVar)
878 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500879 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
880 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
881 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
882 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300883 }
884#endif // HAVE_UBOOT_ENV
885
William A. Kennington III1137a972019-04-20 20:49:58 -0700886 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800887#else
888 elog<NotAllowed>(
889 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
890#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530891}
892
Ratan Guptae9c9b812017-09-22 17:15:37 +0530893void EthernetInterface::deleteAll()
894{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530895 // clear all the ip on the interface
896 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700897
898 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800899 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530900}
901
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800902template <typename Addr>
903static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500904{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800905 if (gw.empty())
906 {
907 return;
908 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700909 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500910 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800911 auto ip = stdplus::fromStr<Addr>(gw);
912 if (ip == Addr{})
913 {
914 gw.clear();
915 return;
916 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800917 if (!validIntfIP(ip))
918 {
919 throw std::invalid_argument("Invalid unicast");
920 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800921 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500922 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700923 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500924 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800925 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500926 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800927 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500928 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800929}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700930
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800931std::string EthernetInterface::defaultGateway(std::string gateway)
932{
933 normalizeGateway<stdplus::In4Addr>(gateway);
934 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700935 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800936 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700937 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800938 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700939 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700940 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500941}
942
943std::string EthernetInterface::defaultGateway6(std::string gateway)
944{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800945 normalizeGateway<stdplus::In6Addr>(gateway);
946 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500947 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800948 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700949 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800950 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500951 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700952 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500953}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700954
955EthernetInterface::VlanProperties::VlanProperties(
956 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800957 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800958 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700959 parentIdx(*info.parent_idx), eth(eth)
960{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800961 VlanIntf::id(*info.vlan_id, true);
962 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700963}
964
965void EthernetInterface::VlanProperties::delete_()
966{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800967 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700968
969 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800970 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700971 std::error_code ec;
972 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
973 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
974
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800975 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800976 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800977 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800978 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800979 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800980 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800981 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800982
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700983 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800984 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700985 {
986 if (intf->ifIdx == parentIdx)
987 {
988 intf->writeConfigurationFile();
989 }
990 }
991
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800992 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700993 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800994 // We need to forcibly delete the interface as systemd does not
Patrick Williamsad205022024-08-16 15:20:07 -0400995 eth.get().manager.get().addReloadPostHook([idx = eth.get().ifIdx]() {
996 system::deleteIntf(idx);
997 });
William A. Kennington III6d217512022-11-17 16:18:01 -0800998
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800999 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001000 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -07001001 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -08001002
William A. Kennington III9ede1b72022-11-21 01:59:28 -08001003 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001004}
1005
Jishnu CM57dfea92023-05-05 06:07:26 -05001006void EthernetInterface::reloadConfigs()
1007{
1008 manager.get().reloadConfigs();
1009}
1010
Gunnar Mills57d9c502018-09-14 14:42:34 -05001011} // namespace network
1012} // namespace phosphor