blob: a2739347c4e8ae894ddcff75b139e83b39a56f6e [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 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530447 try
448 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530449 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700450
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530451 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800452 manager.get().reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530453 }
Patrick Williams5758db32021-10-06 12:29:22 -0500454 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530455 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700456 lg2::error("Exception processing DNS entries: {ERROR}", "ERROR", e);
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530457 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530458 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530459}
460
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600461void EthernetInterface::loadNTPServers(const config::Parser& config)
462{
463 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
464 EthernetInterfaceIntf::staticNTPServers(
465 config.map.getValueStrings("Network", "NTP"));
466}
467
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700468void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530469{
470 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700471 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700472 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530473}
474
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600475ServerList EthernetInterface::getNTPServerFromTimeSyncd()
476{
477 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500478 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
479 TIMESYNCD_SERVICE_PATH,
480 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600481
482 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
483
484 try
485 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800486 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600487 std::variant<ServerList> response;
488 reply.read(response);
489 servers = std::get<ServerList>(response);
490 }
491 catch (const sdbusplus::exception::SdBusError& e)
492 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700493 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700494 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700495 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600496 }
497
498 return servers;
499}
500
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530501ServerList EthernetInterface::getNameServerFromResolvd()
502{
503 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700504 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530505
506 /*
507 The DNS property under org.freedesktop.resolve1.Link interface contains
508 an array containing all DNS servers currently used by resolved. It
509 contains similar information as the DNS server data written to
510 /run/systemd/resolve/resolv.conf.
511
512 Each structure in the array consists of a numeric network interface index,
513 an address family, and a byte array containing the DNS server address
514 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
515 The array contains DNS servers configured system-wide, including those
516 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
517 /etc/systemd/resolved.conf, as well as per-interface DNS server
518 information either retrieved from systemd-networkd or configured by
519 external software via SetLinkDNS().
520 */
521
522 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
523 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800524 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
525 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530526
527 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530528
529 try
530 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800531 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530532 reply.read(name);
533 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500534 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530535 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700536 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700537 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700538 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530539 }
540 auto tupleVector = std::get_if<type>(&name);
541 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
542 {
Alexander Filippov983da552021-02-08 15:26:54 +0300543 int addressFamily = std::get<0>(*i);
544 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700545 servers.push_back(std::to_string(
546 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530547 }
548 return servers;
549}
550
William A. Kennington IIId298f932022-10-17 14:31:38 -0700551ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530552{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700553 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
554 auto idStr = std::to_string(id);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800555 if (manager.get().interfaces.find(intfName) !=
556 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800557 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700558 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700559 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
560 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800561 }
562
William A. Kennington IIId298f932022-10-17 14:31:38 -0700563 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700564 auto macStr = MacAddressIntf::macAddress();
565 std::optional<ether_addr> mac;
566 if (!macStr.empty())
567 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700568 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700569 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800570 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700571 .idx = 0, // TODO: Query the correct value after creation
572 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700573 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700574 .mac = std::move(mac),
575 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700576 .parent_idx = ifIdx,
577 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800578 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530579
Patrick Williams6aef7692021-05-01 06:39:41 -0500580 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530581 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700582 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800583 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700584 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530585
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800586 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530587
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700588 // write the device file for the vlan interface.
589 config::Parser config;
590 auto& netdev = config.map["NetDev"].emplace_back();
591 netdev["Name"].emplace_back(intfName);
592 netdev["Kind"].emplace_back("vlan");
593 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800594 config.writeFile(
595 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700596
597 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800598 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700599
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800600 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530601}
Ratan Gupta2b106532017-07-25 16:05:02 +0530602
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600603ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530604{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600605 try
606 {
607 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530608
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600609 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800610 manager.get().reloadConfigs();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600611 }
612 catch (InternalFailure& e)
613 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700614 lg2::error("Exception processing NTP entries: {ERROR}", "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600615 }
616 return EthernetInterfaceIntf::staticNTPServers();
617}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700618
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600619ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
620{
621 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530622}
Ratan Gupta2b106532017-07-25 16:05:02 +0530623// Need to merge the below function with the code which writes the
624// config file during factory reset.
625// TODO openbmc/openbmc#1751
626
627void EthernetInterface::writeConfigurationFile()
628{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700629 config::Parser config;
630 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530631 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700632 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800633#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700634 auto mac = MacAddressIntf::macAddress();
635 if (!mac.empty())
636 {
637 link["MACAddress"].emplace_back(mac);
638 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800639#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700640 if (!EthernetInterfaceIntf::nicEnabled())
641 {
642 link["Unmanaged"].emplace_back("yes");
643 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700644 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700645 {
646 auto& network = config.map["Network"].emplace_back();
647 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400648#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700649 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400650#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700651 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400652#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700653 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
654 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
655 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600656 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700657 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800658 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700659 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700660 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
661 {
662 vlans.emplace_back(intf->interfaceName());
663 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700664 }
665 }
666 {
667 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600668 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700669 {
670 ntps.emplace_back(ntp);
671 }
672 }
673 {
674 auto& dnss = network["DNS"];
675 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
676 {
677 dnss.emplace_back(dns);
678 }
679 }
680 {
681 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700682 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700683 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700684 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700685 {
686 address.emplace_back(
687 fmt::format("{}/{}", addr.second->address(),
688 addr.second->prefixLength()));
689 }
690 }
691 }
692 {
693 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700694 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700695 {
696 auto gateway = EthernetInterfaceIntf::defaultGateway();
697 if (!gateway.empty())
698 {
699 gateways.emplace_back(gateway);
700 }
701 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530702
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700703 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700704 {
705 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
706 if (!gateway6.empty())
707 {
708 gateways.emplace_back(gateway6);
709 }
710 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600711 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800712 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700713 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700714 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500715 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 auto& neighbors = config.map["Neighbor"];
717 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800718 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700719 auto& neighbor = neighbors.emplace_back();
720 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
721 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800722 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500723 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500724 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700725 auto& dhcp = config.map["DHCP"].emplace_back();
726 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800727 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800728 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
729 dhcp["UseDNS"].emplace_back(dns_enabled);
730 dhcp["UseDomains"].emplace_back(dns_enabled);
731 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
732 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
733 : "false");
734 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
735 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500736 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500737 auto path = config::pathForIntfConf(manager.get().getConfDir(),
738 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700739 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700740 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530741}
742
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800743std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530744{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700745 if (vlan)
746 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700747 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700748 elog<InternalFailure>();
749 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800750#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600751 ether_addr newMAC;
752 try
753 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700754 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600755 }
Patrick Williams5758db32021-10-06 12:29:22 -0500756 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600757 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700758 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600759 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
760 Argument::ARGUMENT_VALUE(value.c_str()));
761 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700762 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530763 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700764 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500765 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
766 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530767 }
768
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300769 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700770 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300771
William A. Kennington III1137a972019-04-20 20:49:58 -0700772 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700773 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700774 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530775 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700776 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800777 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530778 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700779 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
780 {
781 intf->MacAddressIntf::macAddress(validMAC);
782 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530783 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500784 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530785
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700786 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800787 manager.get().addReloadPreHook([interface]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800788 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700789 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800790 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800791 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530792 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700793
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300794#ifdef HAVE_UBOOT_ENV
795 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700796 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300797 if (envVar)
798 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500799 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
800 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
801 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
802 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300803 }
804#endif // HAVE_UBOOT_ENV
805
William A. Kennington III1137a972019-04-20 20:49:58 -0700806 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800807#else
808 elog<NotAllowed>(
809 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
810#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530811}
812
Ratan Guptae9c9b812017-09-22 17:15:37 +0530813void EthernetInterface::deleteAll()
814{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530815 // clear all the ip on the interface
816 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700817
818 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800819 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530820}
821
Ravi Tejaa5a09442020-07-17 00:57:33 -0500822std::string EthernetInterface::defaultGateway(std::string gateway)
823{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700824 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500825 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700826 if (!gateway.empty())
827 {
828 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
829 }
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 III1d25ca42023-05-30 16:55:28 -0700833 lg2::error("Invalid v4 GW {NET_GW}: {ERROR}", "NET_GW", gateway,
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700834 "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500835 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
836 Argument::ARGUMENT_VALUE(gateway.c_str()));
837 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700838
839 if (EthernetInterfaceIntf::defaultGateway() == gateway)
840 {
841 return gateway;
842 }
843 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700844
845 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800846 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700847
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700848 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500849}
850
851std::string EthernetInterface::defaultGateway6(std::string gateway)
852{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700853 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500854 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700855 if (!gateway.empty())
856 {
857 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
858 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500859 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700860 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500861 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700862 lg2::error("Invalid v6 GW {NET_GW}: {ERROR}", "NET_GW", gateway,
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700863 "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500864 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
865 Argument::ARGUMENT_VALUE(gateway.c_str()));
866 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700867
868 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
869 {
870 return gateway;
871 }
872 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700873
874 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800875 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700876
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700877 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500878}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700879
880EthernetInterface::VlanProperties::VlanProperties(
881 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800882 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800883 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700884 parentIdx(*info.parent_idx), eth(eth)
885{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800886 VlanIntf::id(*info.vlan_id, true);
887 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700888}
889
890void EthernetInterface::VlanProperties::delete_()
891{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800892 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700893
894 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800895 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700896 std::error_code ec;
897 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
898 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
899
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800900 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800901 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800902 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800903 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800904 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800905 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800906 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800907
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700908 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800909 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700910 {
911 if (intf->ifIdx == parentIdx)
912 {
913 intf->writeConfigurationFile();
914 }
915 }
916
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800917 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700918 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800919 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800920 eth.get().manager.get().addReloadPostHook(
921 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800922
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800923 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800924 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700925 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800926
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800927 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700928}
929
Gunnar Mills57d9c502018-09-14 14:42:34 -0500930} // namespace network
931} // namespace phosphor