blob: e7a2c29f2dde15f994aa8f086d27fe0842ffff78 [file] [log] [blame]
Gunnar Mills57d9c502018-09-14 14:42:34 -05001#include "config.h"
2
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 IIIa520a392022-08-08 12:17:34 -070010#include <fmt/compile.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070011#include <fmt/format.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070012#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070013#include <net/if.h>
William A. Kennington III9c441fd2023-02-24 13:40:01 -080014#include <net/if_arp.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015
Patrick Venture189d44e2018-07-09 12:30:59 -070016#include <phosphor-logging/elog-errors.hpp>
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -070017#include <phosphor-logging/lg2.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070018#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070019#include <stdplus/zstring.hpp>
Patrick Williams89d734b2023-05-10 07:50:25 -050020#include <xyz/openbmc_project/Common/error.hpp>
21
22#include <algorithm>
23#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053024#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070025#include <unordered_map>
26#include <variant>
Ratan Gupta82549cc2017-04-21 08:45:23 +053027
Ratan Gupta91a99cc2017-04-14 16:32:09 +053028namespace phosphor
29{
30namespace network
31{
32
33using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053034using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053035using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
36using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050037using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070038using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053039constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
40constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
41constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
42constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060043
44constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
45constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
46constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
47
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053048constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053049
William A. Kennington III2e09d272022-10-14 17:15:00 -070050template <typename Func>
51inline decltype(std::declval<Func>()())
52 ignoreError(std::string_view msg, stdplus::zstring_view intf,
53 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080054{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070055 try
56 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070057 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070058 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070059 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070060 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -070061 lg2::error("{MSG} failed on {NET_INTF}: {ERROR}", "MSG", msg,
62 "NET_INTF", intf, "ERROR", e);
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070063 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070064 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070065}
William A. Kennington IIId298f932022-10-17 14:31:38 -070066
William A. Kennington IIId298f932022-10-17 14:31:38 -070067static std::string makeObjPath(std::string_view root, std::string_view intf)
68{
69 auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
70 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
71 return ret;
72}
73
William A. Kennington III9ede1b72022-11-21 01:59:28 -080074EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
75 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080076 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070077 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070078 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080079 bool enabled) :
William A. Kennington III13d665c2022-11-15 20:34:40 -080080 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.intf.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080081 config, enabled)
Patrick Williams89d734b2023-05-10 07:50:25 -050082{}
William A. Kennington IIId298f932022-10-17 14:31:38 -070083
William A. Kennington III9ede1b72022-11-21 01:59:28 -080084EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
85 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080086 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070087 std::string&& objPath,
88 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080089 bool enabled) :
90 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit),
William A. Kennington III876927c2022-11-17 16:20:15 -080091 manager(manager), bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +053092{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080093 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070094 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080095 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
96 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
97 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
98 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaa5a09442020-07-17 00:57:33 -050099
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700100 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800101 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +0530102
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800103 updateInfo(info.intf, true);
104
105 if (info.defgw4)
106 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700107 EthernetInterface::defaultGateway(stdplus::toStr(*info.defgw4), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800108 }
109 if (info.defgw6)
110 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700111 EthernetInterface::defaultGateway6(stdplus::toStr(*info.defgw6), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800112 }
113 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700114
William A. Kennington III13d665c2022-11-15 20:34:40 -0800115 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700116 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800117 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700118 {
119 std::runtime_error("Missing parent link");
120 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800121 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
122 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800123 for (const auto& [_, addr] : info.addrs)
124 {
125 addAddr(addr);
126 }
127 for (const auto& [_, neigh] : info.staticNeighs)
128 {
129 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700130 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530131}
132
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800133void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700134{
William A. Kennington III876927c2022-11-17 16:20:15 -0800135 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800136 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700137 if (info.mac)
138 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700139 MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700140 }
141 if (info.mtu)
142 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800143 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700144 }
William A. Kennington III21539662022-11-15 14:53:11 -0800145 if (ifIdx > 0)
146 {
147 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
148 return system::getEthInfo(*info.name);
149 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800150 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
151 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800152 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700153}
154
Johnathan Mantey817012a2020-01-30 15:07:39 -0800155bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
156{
157 return (
158#ifdef LINK_LOCAL_AUTOCONFIGURATION
159 (origin == IP::AddressOrigin::Static)
160#else
161 (origin == IP::AddressOrigin::Static ||
162 origin == IP::AddressOrigin::LinkLocal)
163#endif
164
165 );
166}
167
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800168void EthernetInterface::addAddr(const AddressInfo& info)
169{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800170 IP::AddressOrigin origin = IP::AddressOrigin::Static;
171 if (dhcpIsEnabled(info.ifaddr.getAddr()))
172 {
173 origin = IP::AddressOrigin::DHCP;
174 }
175#ifdef LINK_LOCAL_AUTOCONFIGURATION
176 if (info.scope == RT_SCOPE_LINK)
177 {
178 origin = IP::AddressOrigin::LinkLocal;
179 }
180#endif
181
William A. Kennington III77747f62022-11-07 23:11:15 -0800182 auto it = addrs.find(info.ifaddr);
183 if (it == addrs.end())
184 {
185 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
186 bus, std::string_view(objPath), *this,
187 info.ifaddr, origin));
188 }
189 else
190 {
191 it->second->IPIfaces::origin(origin);
192 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800193}
194
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800195void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
196{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800197 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800198 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700199 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700200 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800201 return;
202 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800203
204 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
205 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700206 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800207 }
208 else
209 {
210 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
211 bus, std::string_view(objPath),
212 *this, *info.addr, *info.mac,
213 Neighbor::State::Permanent));
214 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800215}
216
Patrick Williams6aef7692021-05-01 06:39:41 -0500217ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700218 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530219{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700220 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700221 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530222 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700223 switch (protType)
224 {
225 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700226 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700227 break;
228 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700229 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700230 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700231 default:
232 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700233 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500234 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700235 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500236 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700237 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
238 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500239 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
240 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
241 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700242 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700243 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500244 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700245 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700246 }
247 catch (const std::exception& e)
248 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700249 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
250 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500251 elog<InvalidArgument>(
252 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700253 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530254 }
255
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700256 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800257 if (it == addrs.end())
258 {
259 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700260 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800261 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700262 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800263 }
264 else
265 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800266 if (it->second->origin() == IP::AddressOrigin::Static)
267 {
268 return it->second->getObjPath();
269 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800270 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
271 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530272
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700273 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800274 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700275
William A. Kennington III434a9432022-11-04 18:38:46 -0700276 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530277}
278
Patrick Williams6aef7692021-05-01 06:39:41 -0500279ObjectPath EthernetInterface::neighbor(std::string ipAddress,
280 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800281{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700282 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700283 try
William A. Kennington III08505792019-01-30 16:00:04 -0800284 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700285 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700286 }
287 catch (const std::exception& e)
288 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700289 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700290 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500291 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
292 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800293 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700294
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700295 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700296 try
William A. Kennington III08505792019-01-30 16:00:04 -0800297 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700298 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700299 }
300 catch (const std::exception& e)
301 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700302 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
303 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500304 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
305 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800306 }
307
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700308 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800309 if (it == staticNeighbors.end())
310 {
311 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700312 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
313 *this, *addr, *lladdr,
314 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800315 }
316 else
317 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700318 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800319 if (it->second->macAddress() == str)
320 {
321 return it->second->getObjPath();
322 }
323 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800324 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700325
326 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800327 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700328
William A. Kennington III434a9432022-11-04 18:38:46 -0700329 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800330}
331
Patrick Williams6aef7692021-05-01 06:39:41 -0500332bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700333{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700334 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700335 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700336 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800337 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700338 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700339 return value;
340}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700341
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700342bool EthernetInterface::dhcp4(bool value)
343{
344 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
345 {
346 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800347 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700348 }
349 return value;
350}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700351
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700352bool EthernetInterface::dhcp6(bool value)
353{
354 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
355 {
356 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800357 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700358 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700359 return value;
360}
361
Patrick Williams6aef7692021-05-01 06:39:41 -0500362EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530363{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700364 auto old4 = EthernetInterfaceIntf::dhcp4();
365 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
366 value == DHCPConf::v4v6stateless ||
367 value == DHCPConf::both);
368 auto old6 = EthernetInterfaceIntf::dhcp6();
369 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
370 value == DHCPConf::both);
371 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
372 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
373 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
374 value == DHCPConf::v6 || value == DHCPConf::both);
375
376 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530377 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700378 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800379 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530380 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530381 return value;
382}
383
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700384EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
385{
386 if (dhcp6())
387 {
388 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
389 }
390 else if (dhcp4())
391 {
392 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
393 }
394 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
395}
396
Tejas Patil2c0fc562021-08-03 19:13:46 +0530397size_t EthernetInterface::mtu(size_t value)
398{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700399 const size_t old = EthernetInterfaceIntf::mtu();
400 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530401 {
402 return value;
403 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700404 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700405 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700406 system::setMTU(ifname, value);
407 return value;
408 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530409}
410
Patrick Williams6aef7692021-05-01 06:39:41 -0500411bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700412{
Patrick Williams6aef7692021-05-01 06:39:41 -0500413 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700414 {
415 return value;
416 }
417
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800418 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700419 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800420 if (!value)
421 {
422 // We only need to bring down the interface, networkd will always bring
423 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800424 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700425 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800426 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800427 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800428
429 return value;
430}
431
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530432ServerList EthernetInterface::staticNameServers(ServerList value)
433{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700434 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530435 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700436 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530437 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700438 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700439 }
440 catch (const std::exception& e)
441 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700442 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
443 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700444 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
445 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530446 }
447 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700448
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700449 value = EthernetInterfaceIntf::staticNameServers(std::move(value));
450
451 writeConfigurationFile();
452 manager.get().reloadConfigs();
453
454 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530455}
456
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600457void EthernetInterface::loadNTPServers(const config::Parser& config)
458{
459 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
460 EthernetInterfaceIntf::staticNTPServers(
461 config.map.getValueStrings("Network", "NTP"));
462}
463
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700464void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530465{
466 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700467 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700468 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530469}
470
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600471ServerList EthernetInterface::getNTPServerFromTimeSyncd()
472{
473 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500474 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
475 TIMESYNCD_SERVICE_PATH,
476 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600477
478 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
479
480 try
481 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800482 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600483 std::variant<ServerList> response;
484 reply.read(response);
485 servers = std::get<ServerList>(response);
486 }
487 catch (const sdbusplus::exception::SdBusError& e)
488 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700489 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700490 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700491 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600492 }
493
494 return servers;
495}
496
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530497ServerList EthernetInterface::getNameServerFromResolvd()
498{
499 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700500 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530501
502 /*
503 The DNS property under org.freedesktop.resolve1.Link interface contains
504 an array containing all DNS servers currently used by resolved. It
505 contains similar information as the DNS server data written to
506 /run/systemd/resolve/resolv.conf.
507
508 Each structure in the array consists of a numeric network interface index,
509 an address family, and a byte array containing the DNS server address
510 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
511 The array contains DNS servers configured system-wide, including those
512 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
513 /etc/systemd/resolved.conf, as well as per-interface DNS server
514 information either retrieved from systemd-networkd or configured by
515 external software via SetLinkDNS().
516 */
517
518 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
519 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800520 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
521 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530522
523 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530524
525 try
526 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800527 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530528 reply.read(name);
529 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500530 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530531 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700532 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700533 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700534 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530535 }
536 auto tupleVector = std::get_if<type>(&name);
537 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
538 {
Alexander Filippov983da552021-02-08 15:26:54 +0300539 int addressFamily = std::get<0>(*i);
540 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700541 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700542 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530543 }
544 return servers;
545}
546
William A. Kennington IIId298f932022-10-17 14:31:38 -0700547ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530548{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700549 auto idStr = stdplus::toStr(id);
550 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800551 if (manager.get().interfaces.find(intfName) !=
552 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800553 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700554 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700555 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
556 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800557 }
558
William A. Kennington IIId298f932022-10-17 14:31:38 -0700559 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700560 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700561 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700562 if (!macStr.empty())
563 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700564 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700565 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800566 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800567 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700568 .idx = 0, // TODO: Query the correct value after creation
569 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700570 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700571 .mac = std::move(mac),
572 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700573 .parent_idx = ifIdx,
574 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800575 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530576
Patrick Williams6aef7692021-05-01 06:39:41 -0500577 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530578 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700579 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800580 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700581 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530582
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800583 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530584
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700585 // write the device file for the vlan interface.
586 config::Parser config;
587 auto& netdev = config.map["NetDev"].emplace_back();
588 netdev["Name"].emplace_back(intfName);
589 netdev["Kind"].emplace_back("vlan");
590 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800591 config.writeFile(
592 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700593
594 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800595 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700596
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800597 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530598}
Ratan Gupta2b106532017-07-25 16:05:02 +0530599
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600600ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530601{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700602 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530603
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700604 writeConfigurationFile();
605 manager.get().reloadConfigs();
606
607 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600608}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700609
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600610ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
611{
612 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530613}
Ratan Gupta2b106532017-07-25 16:05:02 +0530614// Need to merge the below function with the code which writes the
615// config file during factory reset.
616// TODO openbmc/openbmc#1751
617
618void EthernetInterface::writeConfigurationFile()
619{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700620 config::Parser config;
621 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530622 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700623 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800624#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700625 auto mac = MacAddressIntf::macAddress();
626 if (!mac.empty())
627 {
628 link["MACAddress"].emplace_back(mac);
629 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800630#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700631 if (!EthernetInterfaceIntf::nicEnabled())
632 {
633 link["Unmanaged"].emplace_back("yes");
634 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700635 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700636 {
637 auto& network = config.map["Network"].emplace_back();
638 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400639#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700640 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400641#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700642 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400643#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700644 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
645 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
646 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600647 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800649 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700650 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700651 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
652 {
653 vlans.emplace_back(intf->interfaceName());
654 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700655 }
656 }
657 {
658 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600659 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700660 {
661 ntps.emplace_back(ntp);
662 }
663 }
664 {
665 auto& dnss = network["DNS"];
666 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
667 {
668 dnss.emplace_back(dns);
669 }
670 }
671 {
672 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700673 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700674 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700675 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700676 {
677 address.emplace_back(
678 fmt::format("{}/{}", addr.second->address(),
679 addr.second->prefixLength()));
680 }
681 }
682 }
683 {
684 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700685 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700686 {
687 auto gateway = EthernetInterfaceIntf::defaultGateway();
688 if (!gateway.empty())
689 {
690 gateways.emplace_back(gateway);
691 }
692 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530693
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700694 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700695 {
696 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
697 if (!gateway6.empty())
698 {
699 gateways.emplace_back(gateway6);
700 }
701 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600702 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800703 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700704 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700705 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500706 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700707 auto& neighbors = config.map["Neighbor"];
708 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800709 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700710 auto& neighbor = neighbors.emplace_back();
711 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
712 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800713 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500714 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500715 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 auto& dhcp = config.map["DHCP"].emplace_back();
717 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800718 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800719 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
720 dhcp["UseDNS"].emplace_back(dns_enabled);
721 dhcp["UseDomains"].emplace_back(dns_enabled);
722 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
723 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
724 : "false");
725 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
726 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500727 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500728 auto path = config::pathForIntfConf(manager.get().getConfDir(),
729 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700730 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700731 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530732}
733
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800734std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530735{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700736 if (vlan)
737 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700738 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700739 elog<InternalFailure>();
740 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800741#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700742 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600743 try
744 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700745 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600746 }
Patrick Williams5758db32021-10-06 12:29:22 -0500747 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600748 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700749 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600750 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
751 Argument::ARGUMENT_VALUE(value.c_str()));
752 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700753 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530754 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700755 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500756 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
757 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530758 }
759
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300760 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700761 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300762
William A. Kennington III1137a972019-04-20 20:49:58 -0700763 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700764 auto oldMAC =
765 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700766 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530767 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700768 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800769 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530770 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700771 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
772 {
773 intf->MacAddressIntf::macAddress(validMAC);
774 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530775 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500776 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530777
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700778 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800779 manager.get().addReloadPreHook([interface]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800780 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700781 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800782 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800783 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530784 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700785
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300786#ifdef HAVE_UBOOT_ENV
787 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700788 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300789 if (envVar)
790 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500791 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
792 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
793 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
794 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300795 }
796#endif // HAVE_UBOOT_ENV
797
William A. Kennington III1137a972019-04-20 20:49:58 -0700798 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800799#else
800 elog<NotAllowed>(
801 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
802#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530803}
804
Ratan Guptae9c9b812017-09-22 17:15:37 +0530805void EthernetInterface::deleteAll()
806{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530807 // clear all the ip on the interface
808 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700809
810 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800811 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530812}
813
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800814template <typename Addr>
815static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500816{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800817 if (gw.empty())
818 {
819 return;
820 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700821 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500822 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800823 auto ip = stdplus::fromStr<Addr>(gw);
824 if (ip == Addr{})
825 {
826 gw.clear();
827 return;
828 }
829 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500830 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700831 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500832 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800833 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500834 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800835 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500836 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800837}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700838
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800839std::string EthernetInterface::defaultGateway(std::string gateway)
840{
841 normalizeGateway<stdplus::In4Addr>(gateway);
842 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700843 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800844 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
845 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700846 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700847 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500848}
849
850std::string EthernetInterface::defaultGateway6(std::string gateway)
851{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800852 normalizeGateway<stdplus::In6Addr>(gateway);
853 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500854 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800855 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
856 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500857 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700858 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500859}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700860
861EthernetInterface::VlanProperties::VlanProperties(
862 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800863 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800864 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700865 parentIdx(*info.parent_idx), eth(eth)
866{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800867 VlanIntf::id(*info.vlan_id, true);
868 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700869}
870
871void EthernetInterface::VlanProperties::delete_()
872{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800873 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700874
875 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800876 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700877 std::error_code ec;
878 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
879 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
880
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800881 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800882 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800883 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800884 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800885 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800886 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800887 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800888
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700889 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800890 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700891 {
892 if (intf->ifIdx == parentIdx)
893 {
894 intf->writeConfigurationFile();
895 }
896 }
897
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800898 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700899 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800900 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800901 eth.get().manager.get().addReloadPostHook(
902 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800903
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800904 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800905 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700906 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800907
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800908 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700909}
910
Gunnar Mills57d9c502018-09-14 14:42:34 -0500911} // namespace network
912} // namespace phosphor