blob: a2d123dce910b7fa97c6faba500695760eda9ef5 [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>
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 III12beaad2020-06-13 19:30:41 -070017#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070018#include <stdplus/zstring.hpp>
Patrick Williams89d734b2023-05-10 07:50:25 -050019#include <xyz/openbmc_project/Common/error.hpp>
20
21#include <algorithm>
22#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053023#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070024#include <unordered_map>
25#include <variant>
Ratan Gupta82549cc2017-04-21 08:45:23 +053026
Ratan Gupta91a99cc2017-04-14 16:32:09 +053027namespace phosphor
28{
29namespace network
30{
31
32using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053033using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053034using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
35using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050036using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070037using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053038constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
39constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
40constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
41constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060042
43constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
44constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
45constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
46
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053047constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053048
William A. Kennington III2e09d272022-10-14 17:15:00 -070049template <typename Func>
50inline decltype(std::declval<Func>()())
51 ignoreError(std::string_view msg, stdplus::zstring_view intf,
52 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080053{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070054 try
55 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070056 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070057 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070058 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070059 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -070060 lg2::error("{MSG} failed on {NET_INTF}: {ERROR}", "MSG", msg,
61 "NET_INTF", intf, "ERROR", e);
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070062 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070063 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070064}
William A. Kennington IIId298f932022-10-17 14:31:38 -070065
William A. Kennington IIId298f932022-10-17 14:31:38 -070066static std::string makeObjPath(std::string_view root, std::string_view intf)
67{
68 auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
69 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
70 return ret;
71}
72
William A. Kennington III9ede1b72022-11-21 01:59:28 -080073EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
74 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080075 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070076 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070077 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080078 bool enabled) :
William A. Kennington III13d665c2022-11-15 20:34:40 -080079 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.intf.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080080 config, enabled)
Patrick Williams89d734b2023-05-10 07:50:25 -050081{}
William A. Kennington IIId298f932022-10-17 14:31:38 -070082
William A. Kennington III9ede1b72022-11-21 01:59:28 -080083EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
84 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080085 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070086 std::string&& objPath,
87 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080088 bool enabled) :
89 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit),
William A. Kennington III876927c2022-11-17 16:20:15 -080090 manager(manager), bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +053091{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080092 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070093 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080094 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
95 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
96 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
97 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaa5a09442020-07-17 00:57:33 -050098
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -070099 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800100 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +0530101
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800102 updateInfo(info.intf, true);
103
104 if (info.defgw4)
105 {
106 EthernetInterface::defaultGateway(std::to_string(*info.defgw4), true);
107 }
108 if (info.defgw6)
109 {
110 EthernetInterface::defaultGateway6(std::to_string(*info.defgw6), true);
111 }
112 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700113
William A. Kennington III13d665c2022-11-15 20:34:40 -0800114 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700115 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800116 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700117 {
118 std::runtime_error("Missing parent link");
119 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800120 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
121 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800122 for (const auto& [_, addr] : info.addrs)
123 {
124 addAddr(addr);
125 }
126 for (const auto& [_, neigh] : info.staticNeighs)
127 {
128 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700129 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530130}
131
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800132void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700133{
William A. Kennington III876927c2022-11-17 16:20:15 -0800134 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800135 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700136 if (info.mac)
137 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800138 MacAddressIntf::macAddress(std::to_string(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700139 }
140 if (info.mtu)
141 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800142 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700143 }
William A. Kennington III21539662022-11-15 14:53:11 -0800144 if (ifIdx > 0)
145 {
146 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
147 return system::getEthInfo(*info.name);
148 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800149 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
150 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800151 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700152}
153
Johnathan Mantey817012a2020-01-30 15:07:39 -0800154bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
155{
156 return (
157#ifdef LINK_LOCAL_AUTOCONFIGURATION
158 (origin == IP::AddressOrigin::Static)
159#else
160 (origin == IP::AddressOrigin::Static ||
161 origin == IP::AddressOrigin::LinkLocal)
162#endif
163
164 );
165}
166
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800167void EthernetInterface::addAddr(const AddressInfo& info)
168{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800169 IP::AddressOrigin origin = IP::AddressOrigin::Static;
170 if (dhcpIsEnabled(info.ifaddr.getAddr()))
171 {
172 origin = IP::AddressOrigin::DHCP;
173 }
174#ifdef LINK_LOCAL_AUTOCONFIGURATION
175 if (info.scope == RT_SCOPE_LINK)
176 {
177 origin = IP::AddressOrigin::LinkLocal;
178 }
179#endif
180
William A. Kennington III77747f62022-11-07 23:11:15 -0800181 auto it = addrs.find(info.ifaddr);
182 if (it == addrs.end())
183 {
184 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
185 bus, std::string_view(objPath), *this,
186 info.ifaddr, origin));
187 }
188 else
189 {
190 it->second->IPIfaces::origin(origin);
191 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800192}
193
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800194void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
195{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800196 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800197 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700198 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700199 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800200 return;
201 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800202
203 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
204 {
205 it->second->NeighborObj::macAddress(std::to_string(*info.mac));
206 }
207 else
208 {
209 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
210 bus, std::string_view(objPath),
211 *this, *info.addr, *info.mac,
212 Neighbor::State::Permanent));
213 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800214}
215
Patrick Williams6aef7692021-05-01 06:39:41 -0500216ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700217 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530218{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700219 InAddrAny addr;
220 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530221 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700222 switch (protType)
223 {
224 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700225 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700226 break;
227 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700228 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700229 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700230 default:
231 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700232 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500233 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700234 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500235 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700236 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
237 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500238 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
239 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
240 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700241 IfAddr ifaddr;
242 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500243 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700244 ifaddr = {addr, prefixLength};
245 }
246 catch (const std::exception& e)
247 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700248 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
249 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500250 elog<InvalidArgument>(
251 Argument::ARGUMENT_NAME("prefixLength"),
252 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530253 }
254
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800255 auto it = addrs.find(ifaddr);
256 if (it == addrs.end())
257 {
258 it = std::get<0>(addrs.emplace(
259 ifaddr,
260 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
261 ifaddr, IP::AddressOrigin::Static)));
262 }
263 else
264 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800265 if (it->second->origin() == IP::AddressOrigin::Static)
266 {
267 return it->second->getObjPath();
268 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800269 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
270 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530271
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700272 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800273 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700274
William A. Kennington III434a9432022-11-04 18:38:46 -0700275 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530276}
277
Patrick Williams6aef7692021-05-01 06:39:41 -0500278ObjectPath EthernetInterface::neighbor(std::string ipAddress,
279 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800280{
William A. Kennington III434a9432022-11-04 18:38:46 -0700281 InAddrAny addr;
282 try
William A. Kennington III08505792019-01-30 16:00:04 -0800283 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700284 addr = ToAddr<InAddrAny>{}(ipAddress);
285 }
286 catch (const std::exception& e)
287 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700288 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700289 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500290 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
291 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800292 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700293
294 ether_addr lladdr;
295 try
William A. Kennington III08505792019-01-30 16:00:04 -0800296 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700297 lladdr = ToAddr<ether_addr>{}(macAddress);
298 }
299 catch (const std::exception& e)
300 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700301 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
302 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500303 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
304 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800305 }
306
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800307 auto it = staticNeighbors.find(addr);
308 if (it == staticNeighbors.end())
309 {
310 it = std::get<0>(staticNeighbors.emplace(
311 addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
312 *this, addr, lladdr,
313 Neighbor::State::Permanent)));
314 }
315 else
316 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800317 auto str = std::to_string(lladdr);
318 if (it->second->macAddress() == str)
319 {
320 return it->second->getObjPath();
321 }
322 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800323 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700324
325 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800326 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700327
William A. Kennington III434a9432022-11-04 18:38:46 -0700328 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800329}
330
Patrick Williams6aef7692021-05-01 06:39:41 -0500331bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700332{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700333 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700334 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700335 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800336 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700337 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700338 return value;
339}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700340
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700341bool EthernetInterface::dhcp4(bool value)
342{
343 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
344 {
345 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800346 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700347 }
348 return value;
349}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700350
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700351bool EthernetInterface::dhcp6(bool value)
352{
353 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
354 {
355 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800356 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700357 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700358 return value;
359}
360
Patrick Williams6aef7692021-05-01 06:39:41 -0500361EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530362{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700363 auto old4 = EthernetInterfaceIntf::dhcp4();
364 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
365 value == DHCPConf::v4v6stateless ||
366 value == DHCPConf::both);
367 auto old6 = EthernetInterfaceIntf::dhcp6();
368 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
369 value == DHCPConf::both);
370 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
371 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
372 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
373 value == DHCPConf::v6 || value == DHCPConf::both);
374
375 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530376 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700377 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800378 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530379 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530380 return value;
381}
382
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700383EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
384{
385 if (dhcp6())
386 {
387 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
388 }
389 else if (dhcp4())
390 {
391 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
392 }
393 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
394}
395
Tejas Patil2c0fc562021-08-03 19:13:46 +0530396size_t EthernetInterface::mtu(size_t value)
397{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700398 const size_t old = EthernetInterfaceIntf::mtu();
399 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530400 {
401 return value;
402 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700403 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700404 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700405 system::setMTU(ifname, value);
406 return value;
407 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530408}
409
Patrick Williams6aef7692021-05-01 06:39:41 -0500410bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700411{
Patrick Williams6aef7692021-05-01 06:39:41 -0500412 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700413 {
414 return value;
415 }
416
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800417 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700418 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800419 if (!value)
420 {
421 // We only need to bring down the interface, networkd will always bring
422 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800423 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700424 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800425 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800426 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800427
428 return value;
429}
430
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530431ServerList EthernetInterface::staticNameServers(ServerList value)
432{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700433 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530434 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700435 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530436 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700437 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
438 }
439 catch (const std::exception& e)
440 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700441 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
442 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700443 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
444 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530445 }
446 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700447
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700448 value = EthernetInterfaceIntf::staticNameServers(std::move(value));
449
450 writeConfigurationFile();
451 manager.get().reloadConfigs();
452
453 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530454}
455
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600456void EthernetInterface::loadNTPServers(const config::Parser& config)
457{
458 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
459 EthernetInterfaceIntf::staticNTPServers(
460 config.map.getValueStrings("Network", "NTP"));
461}
462
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700463void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530464{
465 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700466 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700467 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530468}
469
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600470ServerList EthernetInterface::getNTPServerFromTimeSyncd()
471{
472 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500473 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
474 TIMESYNCD_SERVICE_PATH,
475 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600476
477 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
478
479 try
480 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800481 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600482 std::variant<ServerList> response;
483 reply.read(response);
484 servers = std::get<ServerList>(response);
485 }
486 catch (const sdbusplus::exception::SdBusError& e)
487 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700488 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700489 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700490 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600491 }
492
493 return servers;
494}
495
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530496ServerList EthernetInterface::getNameServerFromResolvd()
497{
498 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700499 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530500
501 /*
502 The DNS property under org.freedesktop.resolve1.Link interface contains
503 an array containing all DNS servers currently used by resolved. It
504 contains similar information as the DNS server data written to
505 /run/systemd/resolve/resolv.conf.
506
507 Each structure in the array consists of a numeric network interface index,
508 an address family, and a byte array containing the DNS server address
509 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
510 The array contains DNS servers configured system-wide, including those
511 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
512 /etc/systemd/resolved.conf, as well as per-interface DNS server
513 information either retrieved from systemd-networkd or configured by
514 external software via SetLinkDNS().
515 */
516
517 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
518 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800519 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
520 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530521
522 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530523
524 try
525 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800526 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530527 reply.read(name);
528 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500529 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530530 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700531 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700532 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700533 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530534 }
535 auto tupleVector = std::get_if<type>(&name);
536 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
537 {
Alexander Filippov983da552021-02-08 15:26:54 +0300538 int addressFamily = std::get<0>(*i);
539 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700540 servers.push_back(std::to_string(
541 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530542 }
543 return servers;
544}
545
William A. Kennington IIId298f932022-10-17 14:31:38 -0700546ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530547{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700548 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
549 auto idStr = std::to_string(id);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800550 if (manager.get().interfaces.find(intfName) !=
551 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800552 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700553 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700554 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
555 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800556 }
557
William A. Kennington IIId298f932022-10-17 14:31:38 -0700558 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700559 auto macStr = MacAddressIntf::macAddress();
560 std::optional<ether_addr> mac;
561 if (!macStr.empty())
562 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700563 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700564 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800565 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700566 .idx = 0, // TODO: Query the correct value after creation
567 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700568 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700569 .mac = std::move(mac),
570 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700571 .parent_idx = ifIdx,
572 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800573 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530574
Patrick Williams6aef7692021-05-01 06:39:41 -0500575 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530576 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700577 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800578 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700579 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530580
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800581 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530582
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700583 // write the device file for the vlan interface.
584 config::Parser config;
585 auto& netdev = config.map["NetDev"].emplace_back();
586 netdev["Name"].emplace_back(intfName);
587 netdev["Kind"].emplace_back("vlan");
588 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800589 config.writeFile(
590 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700591
592 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800593 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700594
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800595 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530596}
Ratan Gupta2b106532017-07-25 16:05:02 +0530597
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600598ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530599{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700600 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530601
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700602 writeConfigurationFile();
603 manager.get().reloadConfigs();
604
605 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600606}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700607
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600608ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
609{
610 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530611}
Ratan Gupta2b106532017-07-25 16:05:02 +0530612// Need to merge the below function with the code which writes the
613// config file during factory reset.
614// TODO openbmc/openbmc#1751
615
616void EthernetInterface::writeConfigurationFile()
617{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700618 config::Parser config;
619 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530620 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700621 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800622#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700623 auto mac = MacAddressIntf::macAddress();
624 if (!mac.empty())
625 {
626 link["MACAddress"].emplace_back(mac);
627 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800628#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700629 if (!EthernetInterfaceIntf::nicEnabled())
630 {
631 link["Unmanaged"].emplace_back("yes");
632 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700633 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700634 {
635 auto& network = config.map["Network"].emplace_back();
636 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400637#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700638 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400639#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700640 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400641#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700642 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
643 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
644 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600645 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700646 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800647 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700649 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
650 {
651 vlans.emplace_back(intf->interfaceName());
652 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700653 }
654 }
655 {
656 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600657 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700658 {
659 ntps.emplace_back(ntp);
660 }
661 }
662 {
663 auto& dnss = network["DNS"];
664 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
665 {
666 dnss.emplace_back(dns);
667 }
668 }
669 {
670 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700671 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700672 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700673 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700674 {
675 address.emplace_back(
676 fmt::format("{}/{}", addr.second->address(),
677 addr.second->prefixLength()));
678 }
679 }
680 }
681 {
682 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700683 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700684 {
685 auto gateway = EthernetInterfaceIntf::defaultGateway();
686 if (!gateway.empty())
687 {
688 gateways.emplace_back(gateway);
689 }
690 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530691
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700692 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700693 {
694 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
695 if (!gateway6.empty())
696 {
697 gateways.emplace_back(gateway6);
698 }
699 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600700 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800701 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700702 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700703 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500704 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700705 auto& neighbors = config.map["Neighbor"];
706 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800707 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700708 auto& neighbor = neighbors.emplace_back();
709 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
710 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800711 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500712 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500713 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700714 auto& dhcp = config.map["DHCP"].emplace_back();
715 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800716 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800717 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
718 dhcp["UseDNS"].emplace_back(dns_enabled);
719 dhcp["UseDomains"].emplace_back(dns_enabled);
720 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
721 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
722 : "false");
723 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
724 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500725 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500726 auto path = config::pathForIntfConf(manager.get().getConfDir(),
727 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700728 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700729 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530730}
731
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800732std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530733{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700734 if (vlan)
735 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700736 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700737 elog<InternalFailure>();
738 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800739#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600740 ether_addr newMAC;
741 try
742 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700743 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600744 }
Patrick Williams5758db32021-10-06 12:29:22 -0500745 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600746 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700747 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600748 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
749 Argument::ARGUMENT_VALUE(value.c_str()));
750 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700751 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530752 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700753 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500754 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
755 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530756 }
757
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300758 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700759 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300760
William A. Kennington III1137a972019-04-20 20:49:58 -0700761 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700762 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700763 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530764 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700765 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800766 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530767 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700768 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
769 {
770 intf->MacAddressIntf::macAddress(validMAC);
771 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530772 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500773 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530774
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700775 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800776 manager.get().addReloadPreHook([interface]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800777 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700778 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800779 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800780 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530781 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700782
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300783#ifdef HAVE_UBOOT_ENV
784 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700785 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300786 if (envVar)
787 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500788 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
789 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
790 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
791 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300792 }
793#endif // HAVE_UBOOT_ENV
794
William A. Kennington III1137a972019-04-20 20:49:58 -0700795 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800796#else
797 elog<NotAllowed>(
798 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
799#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530800}
801
Ratan Guptae9c9b812017-09-22 17:15:37 +0530802void EthernetInterface::deleteAll()
803{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530804 // clear all the ip on the interface
805 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700806
807 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800808 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530809}
810
Ravi Tejaa5a09442020-07-17 00:57:33 -0500811std::string EthernetInterface::defaultGateway(std::string gateway)
812{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700813 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500814 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700815 if (!gateway.empty())
816 {
817 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
818 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500819 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700820 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500821 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700822 lg2::error("Invalid v4 GW {NET_GW}: {ERROR}", "NET_GW", gateway,
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700823 "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500824 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
825 Argument::ARGUMENT_VALUE(gateway.c_str()));
826 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700827
828 if (EthernetInterfaceIntf::defaultGateway() == gateway)
829 {
830 return gateway;
831 }
832 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700833
834 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800835 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700836
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700837 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500838}
839
840std::string EthernetInterface::defaultGateway6(std::string gateway)
841{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700842 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500843 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700844 if (!gateway.empty())
845 {
846 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
847 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500848 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700849 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500850 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700851 lg2::error("Invalid v6 GW {NET_GW}: {ERROR}", "NET_GW", gateway,
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700852 "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500853 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
854 Argument::ARGUMENT_VALUE(gateway.c_str()));
855 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700856
857 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
858 {
859 return gateway;
860 }
861 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700862
863 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800864 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700865
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700866 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500867}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700868
869EthernetInterface::VlanProperties::VlanProperties(
870 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800871 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800872 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700873 parentIdx(*info.parent_idx), eth(eth)
874{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800875 VlanIntf::id(*info.vlan_id, true);
876 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700877}
878
879void EthernetInterface::VlanProperties::delete_()
880{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800881 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700882
883 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800884 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700885 std::error_code ec;
886 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
887 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
888
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800889 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800890 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800891 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800892 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800893 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800894 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800895 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800896
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700897 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800898 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700899 {
900 if (intf->ifIdx == parentIdx)
901 {
902 intf->writeConfigurationFile();
903 }
904 }
905
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800906 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700907 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800908 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800909 eth.get().manager.get().addReloadPostHook(
910 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800911
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800912 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800913 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700914 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800915
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800916 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700917}
918
Gunnar Mills57d9c502018-09-14 14:42:34 -0500919} // namespace network
920} // namespace phosphor