blob: 10229ac4cdc2d2cf1930c2700b2ec211d45a624a [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
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800161void EthernetInterface::addAddr(const AddressInfo& info)
162{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800163 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ravi Teja86c4f442023-07-19 22:26:39 -0500164 if (dhcpIsEnabled(info.ifaddr.getAddr()))
165 {
166 origin = IP::AddressOrigin::DHCP;
167 }
168
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800169#ifdef LINK_LOCAL_AUTOCONFIGURATION
170 if (info.scope == RT_SCOPE_LINK)
171 {
172 origin = IP::AddressOrigin::LinkLocal;
173 }
174#endif
175
Ravi Tejac6201202023-03-28 21:29:58 -0500176 if ((info.scope == RT_SCOPE_UNIVERSE) && (info.flags & IFA_F_PERMANENT))
177 {
178 origin = IP::AddressOrigin::Static;
179 }
180 if ((info.scope == RT_SCOPE_UNIVERSE) &&
181 ((info.flags & IFA_F_NOPREFIXROUTE) &&
182 (info.flags & IFA_F_MANAGETEMPADDR)))
183 {
184 origin = IP::AddressOrigin::SLAAC;
185 }
186 else if ((info.scope == RT_SCOPE_UNIVERSE) &&
187 ((info.flags & IFA_F_NOPREFIXROUTE)))
188 {
189 origin = IP::AddressOrigin::DHCP;
190 }
191
William A. Kennington III77747f62022-11-07 23:11:15 -0800192 auto it = addrs.find(info.ifaddr);
193 if (it == addrs.end())
194 {
195 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
196 bus, std::string_view(objPath), *this,
197 info.ifaddr, origin));
198 }
199 else
200 {
201 it->second->IPIfaces::origin(origin);
202 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800203}
204
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800205void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
206{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800207 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800208 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700209 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700210 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800211 return;
212 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800213
214 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
215 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700216 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800217 }
218 else
219 {
Patrick Williamsad205022024-08-16 15:20:07 -0400220 staticNeighbors.emplace(
221 *info.addr, std::make_unique<Neighbor>(
222 bus, std::string_view(objPath), *this, *info.addr,
223 *info.mac, Neighbor::State::Permanent));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800224 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800225}
226
Patrick Williams6aef7692021-05-01 06:39:41 -0500227ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700228 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530229{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700230 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700231 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530232 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700233 switch (protType)
234 {
235 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700236 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700237 break;
238 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700239 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700240 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700241 default:
242 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700243 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700244 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
245 {
246 throw std::invalid_argument("not unicast");
247 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500248 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700249 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500250 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700251 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
252 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500253 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
254 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
255 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700256 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700257 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500258 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700259 if (prefixLength == 0)
260 {
261 throw std::invalid_argument("default route");
262 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700263 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700264 }
265 catch (const std::exception& e)
266 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700267 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
268 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500269 elog<InvalidArgument>(
270 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700271 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530272 }
273
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700274 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800275 if (it == addrs.end())
276 {
277 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700278 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800279 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700280 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800281 }
282 else
283 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800284 if (it->second->origin() == IP::AddressOrigin::Static)
285 {
286 return it->second->getObjPath();
287 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800288 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
289 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530290
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700291 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800292 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700293
William A. Kennington III434a9432022-11-04 18:38:46 -0700294 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530295}
296
Patrick Williams6aef7692021-05-01 06:39:41 -0500297ObjectPath EthernetInterface::neighbor(std::string ipAddress,
298 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800299{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700300 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700301 try
William A. Kennington III08505792019-01-30 16:00:04 -0800302 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700303 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700304 }
305 catch (const std::exception& e)
306 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700307 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700308 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500309 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
310 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800311 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700312
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700313 std::optional<stdplus::EtherAddr> lladdr;
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 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
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 MAC address {NET_MAC}: {ERROR}", "NET_MAC",
321 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500322 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
323 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800324 }
325
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700326 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800327 if (it == staticNeighbors.end())
328 {
329 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700330 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
331 *this, *addr, *lladdr,
332 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800333 }
334 else
335 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700336 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800337 if (it->second->macAddress() == str)
338 {
339 return it->second->getObjPath();
340 }
341 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800342 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700343
344 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800345 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700346
William A. Kennington III434a9432022-11-04 18:38:46 -0700347 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800348}
349
Patrick Williams6aef7692021-05-01 06:39:41 -0500350bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700351{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700352 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700353 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700354 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800355 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700356 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700357 return value;
358}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700359
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700360bool EthernetInterface::dhcp4(bool value)
361{
362 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
363 {
364 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800365 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700366 }
367 return value;
368}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700369
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700370bool EthernetInterface::dhcp6(bool value)
371{
372 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
373 {
374 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800375 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700376 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700377 return value;
378}
379
Patrick Williams6aef7692021-05-01 06:39:41 -0500380EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530381{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700382 auto old4 = EthernetInterfaceIntf::dhcp4();
Patrick Williamsad205022024-08-16 15:20:07 -0400383 auto new4 = EthernetInterfaceIntf::dhcp4(
384 value == DHCPConf::v4 || value == DHCPConf::v4v6stateless ||
385 value == DHCPConf::both);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700386 auto old6 = EthernetInterfaceIntf::dhcp6();
Patrick Williamsad205022024-08-16 15:20:07 -0400387 auto new6 = EthernetInterfaceIntf::dhcp6(
388 value == DHCPConf::v6 || value == DHCPConf::both);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700389 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
390 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
391 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
392 value == DHCPConf::v6 || value == DHCPConf::both);
393
394 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530395 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700396 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800397 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530398 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530399 return value;
400}
401
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700402EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
403{
404 if (dhcp6())
405 {
406 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
407 }
408 else if (dhcp4())
409 {
410 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
411 }
412 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
413}
414
Tejas Patil2c0fc562021-08-03 19:13:46 +0530415size_t EthernetInterface::mtu(size_t value)
416{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700417 const size_t old = EthernetInterfaceIntf::mtu();
418 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530419 {
420 return value;
421 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700422 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700423 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700424 system::setMTU(ifname, value);
425 return value;
426 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530427}
428
Patrick Williams6aef7692021-05-01 06:39:41 -0500429bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700430{
Patrick Williams6aef7692021-05-01 06:39:41 -0500431 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700432 {
433 return value;
434 }
435
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800436 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700437 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800438 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800439
440 return value;
441}
442
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530443ServerList EthernetInterface::staticNameServers(ServerList value)
444{
nitinkotania581cb0b2023-03-21 00:28:55 -0500445 std::vector<std::string> dnsUniqueValues;
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700446 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530447 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700448 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530449 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700450 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700451 }
452 catch (const std::exception& e)
453 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700454 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
455 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700456 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
457 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530458 }
nitinkotania581cb0b2023-03-21 00:28:55 -0500459 if (std::find(dnsUniqueValues.begin(), dnsUniqueValues.end(), ip) ==
460 dnsUniqueValues.end())
461 {
462 dnsUniqueValues.push_back(ip);
463 }
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530464 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700465
nitinkotania581cb0b2023-03-21 00:28:55 -0500466 value =
467 EthernetInterfaceIntf::staticNameServers(std::move(dnsUniqueValues));
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700468
469 writeConfigurationFile();
470 manager.get().reloadConfigs();
471
472 return value;
Ratan Gupta6dec3902017-08-20 15:28:12 +0530473}
474
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600475void EthernetInterface::loadNTPServers(const config::Parser& config)
476{
477 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
478 EthernetInterfaceIntf::staticNTPServers(
479 config.map.getValueStrings("Network", "NTP"));
480}
481
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700482void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530483{
484 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700485 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700486 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec3902017-08-20 15:28:12 +0530487}
488
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600489ServerList EthernetInterface::getNTPServerFromTimeSyncd()
490{
491 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williamsad205022024-08-16 15:20:07 -0400492 auto method =
493 bus.get().new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
494 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600495
496 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
497
498 try
499 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800500 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600501 std::variant<ServerList> response;
502 reply.read(response);
503 servers = std::get<ServerList>(response);
504 }
505 catch (const sdbusplus::exception::SdBusError& e)
506 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700507 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700508 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700509 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600510 }
511
512 return servers;
513}
514
Ravi Teja4f8b9a02023-09-06 13:41:52 -0500515ServerList EthernetInterface::nameservers() const
516{
517 return getNameServerFromResolvd();
518}
519
520ServerList EthernetInterface::getNameServerFromResolvd() const
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530521{
522 ServerList servers;
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700523 auto OBJ_PATH = std::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530524
525 /*
526 The DNS property under org.freedesktop.resolve1.Link interface contains
527 an array containing all DNS servers currently used by resolved. It
528 contains similar information as the DNS server data written to
529 /run/systemd/resolve/resolv.conf.
530
531 Each structure in the array consists of a numeric network interface index,
532 an address family, and a byte array containing the DNS server address
533 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
534 The array contains DNS servers configured system-wide, including those
535 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
536 /etc/systemd/resolved.conf, as well as per-interface DNS server
537 information either retrieved from systemd-networkd or configured by
538 external software via SetLinkDNS().
539 */
540
541 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
542 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800543 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
544 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530545
546 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530547
548 try
549 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800550 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530551 reply.read(name);
552 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500553 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530554 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700555 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700556 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700557 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530558 }
559 auto tupleVector = std::get_if<type>(&name);
560 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
561 {
Alexander Filippov983da552021-02-08 15:26:54 +0300562 int addressFamily = std::get<0>(*i);
563 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700564 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700565 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530566 }
567 return servers;
568}
569
William A. Kennington IIId298f932022-10-17 14:31:38 -0700570ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530571{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700572 auto idStr = stdplus::toStr(id);
William A. Kennington III86642522023-07-24 17:55:55 -0700573 auto intfName = stdplus::strCat(interfaceName(), "."sv, idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800574 if (manager.get().interfaces.find(intfName) !=
575 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800576 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700577 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700578 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
579 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800580 }
581
William A. Kennington IIId298f932022-10-17 14:31:38 -0700582 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700583 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700584 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700585 if (!macStr.empty())
586 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700587 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700588 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800589 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800590 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700591 .idx = 0, // TODO: Query the correct value after creation
592 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700593 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700594 .mac = std::move(mac),
595 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700596 .parent_idx = ifIdx,
597 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800598 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530599
Patrick Williams6aef7692021-05-01 06:39:41 -0500600 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530601 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700602 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800603 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700604 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530605
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800606 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530607
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700608 // write the device file for the vlan interface.
609 config::Parser config;
610 auto& netdev = config.map["NetDev"].emplace_back();
611 netdev["Name"].emplace_back(intfName);
612 netdev["Kind"].emplace_back("vlan");
613 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800614 config.writeFile(
615 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700616
617 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800618 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700619
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800620 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530621}
Ratan Gupta2b106532017-07-25 16:05:02 +0530622
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600623ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530624{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700625 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530626
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700627 writeConfigurationFile();
628 manager.get().reloadConfigs();
629
630 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600631}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700632
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600633ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
634{
635 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530636}
Ratan Gupta2b106532017-07-25 16:05:02 +0530637
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700638static constexpr std::string_view tfStr(bool value)
639{
640 return value ? "true"sv : "false"sv;
641}
642
William A. Kennington III945878a2024-04-17 01:05:27 -0700643static void writeUpdatedTime(const Manager& manager,
644 const std::filesystem::path& netFile)
645{
646 // JFFS2 doesn't have the time granularity to deal with sub-second
647 // updates. Since we can have multiple file updates within a second
648 // around a reload, we need a location which gives that precision for
649 // future networkd detected reloads. TMPFS gives us this property.
650 if (manager.getConfDir() == "/etc/systemd/network"sv)
651 {
652 auto dir = stdplus::strCat(netFile.native(), ".d");
653 dir.replace(1, 3, "run"); // Replace /etc with /run
654 auto file = dir + "/updated.conf";
655 try
656 {
657 std::filesystem::create_directories(dir);
658 using namespace stdplus::fd;
659 futimens(
660 open(file,
661 OpenFlags(OpenAccess::WriteOnly).set(OpenFlag::Create),
662 0644)
663 .get(),
664 nullptr);
665 }
666 catch (const std::exception& e)
667 {
668 lg2::error("Failed to write time updated file {FILE}: {ERROR}",
669 "FILE", file, "ERROR", e.what());
670 }
671 }
672}
673
Ratan Gupta2b106532017-07-25 16:05:02 +0530674void EthernetInterface::writeConfigurationFile()
675{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700676 config::Parser config;
677 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530678 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700679 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800680#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700681 auto mac = MacAddressIntf::macAddress();
682 if (!mac.empty())
683 {
684 link["MACAddress"].emplace_back(mac);
685 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800686#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700687 if (!EthernetInterfaceIntf::nicEnabled())
688 {
Johnathan Mantey8e3c1fb2024-03-12 13:07:50 -0700689 link["ActivationPolicy"].emplace_back("down");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700690 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700691 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700692 {
693 auto& network = config.map["Network"].emplace_back();
694 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400695#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700696 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400697#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700698 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400699#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700700 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
701 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
702 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600703 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700704 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800705 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700706 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700707 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
708 {
709 vlans.emplace_back(intf->interfaceName());
710 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700711 }
712 }
713 {
714 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600715 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 {
717 ntps.emplace_back(ntp);
718 }
719 }
720 {
721 auto& dnss = network["DNS"];
722 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
723 {
724 dnss.emplace_back(dns);
725 }
726 }
727 {
728 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700729 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700730 {
Johnathan Mantey3865db22023-09-27 12:39:16 -0700731 if (addr.second->origin() == IP::AddressOrigin::Static)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700732 {
William A. Kennington IIIcafc1512023-07-25 02:22:32 -0700733 address.emplace_back(stdplus::toStr(addr.first));
William A. Kennington III95a49a22022-08-18 17:50:05 -0700734 }
735 }
736 }
737 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700738 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700739 {
Ravi Teja91f60562024-04-17 06:26:43 -0500740 auto gateway4 = EthernetInterfaceIntf::defaultGateway();
741 if (!gateway4.empty())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700742 {
Ravi Teja91f60562024-04-17 06:26:43 -0500743 auto& gateway4route = config.map["Route"].emplace_back();
744 gateway4route["Gateway"].emplace_back(gateway4);
745 gateway4route["GatewayOnLink"].emplace_back("true");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700746 }
747 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530748
William A. Kennington III05cbc5b2023-07-20 19:37:30 -0700749 if (!ipv6AcceptRA())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700750 {
751 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
752 if (!gateway6.empty())
753 {
Ravi Teja91f60562024-04-17 06:26:43 -0500754 auto& gateway6route = config.map["Route"].emplace_back();
755 gateway6route["Gateway"].emplace_back(gateway6);
756 gateway6route["GatewayOnLink"].emplace_back("true");
William A. Kennington III95a49a22022-08-18 17:50:05 -0700757 }
758 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600759 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800760 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700761 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700762 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500763 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700764 auto& neighbors = config.map["Neighbor"];
765 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800766 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700767 auto& neighbor = neighbors.emplace_back();
768 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
769 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800770 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500771 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500772 {
Jishnu CM57dfea92023-05-05 06:07:26 -0500773 auto& dhcp4 = config.map["DHCPv4"].emplace_back();
774 dhcp4["ClientIdentifier"].emplace_back("mac");
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700775 dhcp4["UseDNS"].emplace_back(tfStr(dhcp4Conf->dnsEnabled()));
776 dhcp4["UseDomains"].emplace_back(tfStr(dhcp4Conf->domainEnabled()));
777 dhcp4["UseNTP"].emplace_back(tfStr(dhcp4Conf->ntpEnabled()));
778 dhcp4["UseHostname"].emplace_back(tfStr(dhcp4Conf->hostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500779 dhcp4["SendHostname"].emplace_back(
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700780 tfStr(dhcp4Conf->sendHostNameEnabled()));
Jishnu CM57dfea92023-05-05 06:07:26 -0500781 }
782 {
783 auto& dhcp6 = config.map["DHCPv6"].emplace_back();
William A. Kennington IIIf179e702024-04-17 00:50:28 -0700784 dhcp6["UseDNS"].emplace_back(tfStr(dhcp6Conf->dnsEnabled()));
785 dhcp6["UseDomains"].emplace_back(tfStr(dhcp6Conf->domainEnabled()));
786 dhcp6["UseNTP"].emplace_back(tfStr(dhcp6Conf->ntpEnabled()));
787 dhcp6["UseHostname"].emplace_back(tfStr(dhcp6Conf->hostNameEnabled()));
William A. Kennington III44937b12024-04-17 00:28:20 -0700788 dhcp6["SendHostname"].emplace_back(
789 tfStr(dhcp6Conf->sendHostNameEnabled()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500790 }
Patrick Williamsad205022024-08-16 15:20:07 -0400791 auto path =
792 config::pathForIntfConf(manager.get().getConfDir(), interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700793 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700794 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
William A. Kennington III945878a2024-04-17 01:05:27 -0700795 writeUpdatedTime(manager, path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530796}
797
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800798std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530799{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700800 if (vlan)
801 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700802 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700803 elog<InternalFailure>();
804 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800805#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700806 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600807 try
808 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700809 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600810 }
Patrick Williams5758db32021-10-06 12:29:22 -0500811 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600812 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700813 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600814 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
815 Argument::ARGUMENT_VALUE(value.c_str()));
816 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700817 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530818 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700819 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500820 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
821 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530822 }
823
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300824 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700825 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300826
William A. Kennington III1137a972019-04-20 20:49:58 -0700827 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700828 auto oldMAC =
829 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700830 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530831 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700832 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800833 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530834 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700835 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
836 {
837 intf->MacAddressIntf::macAddress(validMAC);
838 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530839 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500840 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530841
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700842 writeConfigurationFile();
William A. Kennington III945878a2024-04-17 01:05:27 -0700843 manager.get().addReloadPreHook([interface, manager = manager]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800844 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700845 system::setNICUp(interface, false);
William A. Kennington III945878a2024-04-17 01:05:27 -0700846 writeUpdatedTime(
847 manager,
848 config::pathForIntfConf(manager.get().getConfDir(), interface));
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800849 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800850 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530851 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700852
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300853#ifdef HAVE_UBOOT_ENV
854 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700855 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300856 if (envVar)
857 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500858 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
859 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
860 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
861 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300862 }
863#endif // HAVE_UBOOT_ENV
864
William A. Kennington III1137a972019-04-20 20:49:58 -0700865 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800866#else
867 elog<NotAllowed>(
868 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
869#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530870}
871
Ratan Guptae9c9b812017-09-22 17:15:37 +0530872void EthernetInterface::deleteAll()
873{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530874 // clear all the ip on the interface
875 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700876
877 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800878 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530879}
880
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800881template <typename Addr>
882static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500883{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800884 if (gw.empty())
885 {
886 return;
887 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700888 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500889 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800890 auto ip = stdplus::fromStr<Addr>(gw);
891 if (ip == Addr{})
892 {
893 gw.clear();
894 return;
895 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800896 if (!validIntfIP(ip))
897 {
898 throw std::invalid_argument("Invalid unicast");
899 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800900 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500901 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700902 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500903 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800904 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500905 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800906 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500907 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800908}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700909
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800910std::string EthernetInterface::defaultGateway(std::string gateway)
911{
912 normalizeGateway<stdplus::In4Addr>(gateway);
913 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700914 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800915 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700916 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800917 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700918 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700919 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500920}
921
922std::string EthernetInterface::defaultGateway6(std::string gateway)
923{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800924 normalizeGateway<stdplus::In6Addr>(gateway);
925 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500926 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800927 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
Yuxiao Zhangaf38fe92023-10-12 13:50:50 -0700928 writeConfigurationFile();
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800929 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500930 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700931 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500932}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700933
934EthernetInterface::VlanProperties::VlanProperties(
935 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800936 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800937 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700938 parentIdx(*info.parent_idx), eth(eth)
939{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800940 VlanIntf::id(*info.vlan_id, true);
941 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700942}
943
944void EthernetInterface::VlanProperties::delete_()
945{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800946 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700947
948 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800949 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700950 std::error_code ec;
951 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
952 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
953
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800954 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800955 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800956 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800957 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800958 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800959 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800960 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800961
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700962 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800963 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700964 {
965 if (intf->ifIdx == parentIdx)
966 {
967 intf->writeConfigurationFile();
968 }
969 }
970
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800971 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700972 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800973 // We need to forcibly delete the interface as systemd does not
Patrick Williamsad205022024-08-16 15:20:07 -0400974 eth.get().manager.get().addReloadPostHook([idx = eth.get().ifIdx]() {
975 system::deleteIntf(idx);
976 });
William A. Kennington III6d217512022-11-17 16:18:01 -0800977
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800978 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800979 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700980 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800981
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800982 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700983}
984
Jishnu CM57dfea92023-05-05 06:07:26 -0500985void EthernetInterface::reloadConfigs()
986{
987 manager.get().reloadConfigs();
988}
989
Gunnar Mills57d9c502018-09-14 14:42:34 -0500990} // namespace network
991} // namespace phosphor