blob: 4f71a4632a3e646c1d22804af36a629e6d7cd027 [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 III2e09d272022-10-14 17:15:00 -070012#include <linux/if_addr.h>
13#include <linux/neighbour.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070014#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070015#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053016
Ratan Gupta82549cc2017-04-21 08:45:23 +053017#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053018#include <filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070019#include <phosphor-logging/elog-errors.hpp>
20#include <phosphor-logging/log.hpp>
William A. Kennington III26275a32021-07-13 20:32:42 -070021#include <sdbusplus/bus/match.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070022#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070023#include <stdplus/zstring.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053024#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070025#include <unordered_map>
26#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070027#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053028
Ratan Gupta91a99cc2017-04-14 16:32:09 +053029namespace phosphor
30{
31namespace network
32{
33
34using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053035using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053036using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
37using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050038using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070039using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053040constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
41constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
42constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
43constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060044
45constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
46constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
47constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
48
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053049constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053050
William A. Kennington III2e09d272022-10-14 17:15:00 -070051template <typename Func>
52inline decltype(std::declval<Func>()())
53 ignoreError(std::string_view msg, stdplus::zstring_view intf,
54 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080055{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070056 try
57 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070058 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070059 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070060 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070061 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070062 auto err = fmt::format("{} failed on {}: {}", msg, intf, e.what());
63 log<level::ERR>(err.c_str(), entry("INTERFACE=%s", intf.c_str()));
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070064 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070065 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070066}
William A. Kennington IIId298f932022-10-17 14:31:38 -070067
William A. Kennington IIId298f932022-10-17 14:31:38 -070068static std::string makeObjPath(std::string_view root, std::string_view intf)
69{
70 auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
71 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
72 return ret;
73}
74
75EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080076 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070077 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070078 const config::Parser& config,
William A. Kennington IIId298f932022-10-17 14:31:38 -070079 bool emitSignal,
80 std::optional<bool> enabled) :
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070081 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.name),
William A. Kennington IIId298f932022-10-17 14:31:38 -070082 config, emitSignal, enabled)
83{
84}
85
86EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080087 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070088 std::string&& objPath,
89 const config::Parser& config,
90 bool emitSignal,
William A. Kennington III26275a32021-07-13 20:32:42 -070091 std::optional<bool> enabled) :
Patrick Williams166b9592022-03-30 16:09:16 -050092 Ifaces(bus, objPath.c_str(),
93 emitSignal ? Ifaces::action::defer_emit
94 : Ifaces::action::emit_no_signals),
William A. Kennington III59e5b912022-11-02 02:49:46 -070095 manager(manager), bus(bus), objPath(std::move(objPath)), ifIdx(info.idx)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053096{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070097 interfaceName(*info.name);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070098 auto dhcpVal = getDHCPValue(config);
99 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
100 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700101 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III26275a32021-07-13 20:32:42 -0700102 EthernetInterfaceIntf::nicEnabled(enabled ? *enabled : queryNicEnabled());
Ravi Tejaa5a09442020-07-17 00:57:33 -0500103 {
William A. Kennington III2bd35d62022-10-26 19:20:29 -0700104 const auto& gws = manager.getRouteTable().getDefaultGateway();
105 auto it = gws.find(ifIdx);
106 if (it != gws.end())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500107 {
William A. Kennington III2bd35d62022-10-26 19:20:29 -0700108 EthernetInterfaceIntf::defaultGateway(std::to_string(it->second));
109 }
110 }
111 {
112 const auto& gws = manager.getRouteTable().getDefaultGateway6();
113 auto it = gws.find(ifIdx);
114 if (it != gws.end())
115 {
116 EthernetInterfaceIntf::defaultGateway6(std::to_string(it->second));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500117 }
118 }
119
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700120 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700121 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +0530122
William A. Kennington III3e471c52022-10-27 19:46:07 -0700123 if (ifIdx > 0)
124 {
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700125 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
126 return system::getEthInfo(*info.name);
William A. Kennington III3e471c52022-10-27 19:46:07 -0700127 });
128 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg);
129 EthernetInterfaceIntf::speed(ethInfo.speed);
130 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530131
William A. Kennington IIId298f932022-10-17 14:31:38 -0700132 updateInfo(info);
133
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700134 if (info.vlan_id)
135 {
136 if (!info.parent_idx)
137 {
138 std::runtime_error("Missing parent link");
139 }
140 vlan.emplace(bus, this->objPath.c_str(), info, *this, emitSignal);
141 }
142
Ratan Gupta29b0e432017-05-25 12:51:40 +0530143 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +0530144 if (emitSignal)
145 {
146 this->emit_object_added();
147 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530148}
149
William A. Kennington III454a0de2022-11-12 01:01:04 -0800150void EthernetInterface::updateInfo(const InterfaceInfo& info)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700151{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700152 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700153 if (info.mac)
154 {
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700155 MacAddressIntf::macAddress(std::to_string(*info.mac));
William A. Kennington IIId298f932022-10-17 14:31:38 -0700156 }
157 if (info.mtu)
158 {
159 EthernetInterfaceIntf::mtu(*info.mtu);
160 }
161}
162
Johnathan Mantey817012a2020-01-30 15:07:39 -0800163bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
164{
165 return (
166#ifdef LINK_LOCAL_AUTOCONFIGURATION
167 (origin == IP::AddressOrigin::Static)
168#else
169 (origin == IP::AddressOrigin::Static ||
170 origin == IP::AddressOrigin::LinkLocal)
171#endif
172
173 );
174}
175
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800176void EthernetInterface::addAddr(const AddressInfo& info)
177{
178 if (info.flags & IFA_F_DEPRECATED)
179 {
180 return;
181 }
182 IP::AddressOrigin origin = IP::AddressOrigin::Static;
183 if (dhcpIsEnabled(info.ifaddr.getAddr()))
184 {
185 origin = IP::AddressOrigin::DHCP;
186 }
187#ifdef LINK_LOCAL_AUTOCONFIGURATION
188 if (info.scope == RT_SCOPE_LINK)
189 {
190 origin = IP::AddressOrigin::LinkLocal;
191 }
192#endif
193
William A. Kennington III77747f62022-11-07 23:11:15 -0800194 auto it = addrs.find(info.ifaddr);
195 if (it == addrs.end())
196 {
197 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
198 bus, std::string_view(objPath), *this,
199 info.ifaddr, origin));
200 }
201 else
202 {
203 it->second->IPIfaces::origin(origin);
204 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800205}
206
Ratan Gupta87c13982017-06-15 09:27:27 +0530207void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530208{
Ratan Gupta87c13982017-06-15 09:27:27 +0530209 addrs.clear();
William A. Kennington III6a923632022-11-06 18:17:33 -0800210 for (const auto& addr : system::getAddresses({.ifidx = ifIdx}))
Ratan Gupta82549cc2017-04-21 08:45:23 +0530211 {
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800212 addAddr(addr);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530213 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530214}
215
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800216void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
217{
218 if ((info.state & NUD_PERMANENT) == 0)
219 {
220 return;
221 }
William A. Kennington IIId3615142022-11-12 01:28:33 -0800222 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800223 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800224 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800225 log<level::ERR>(msg.c_str());
226 return;
227 }
228 staticNeighbors.emplace(
William A. Kennington IIId3615142022-11-12 01:28:33 -0800229 *info.addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
230 *this, *info.addr, *info.mac,
231 Neighbor::State::Permanent));
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800232}
233
William A. Kennington III08505792019-01-30 16:00:04 -0800234void EthernetInterface::createStaticNeighborObjects()
235{
236 staticNeighbors.clear();
William A. Kennington IIIa8426902022-11-07 15:37:41 -0800237 for (const auto& neighbor : system::getNeighbors({.ifidx = ifIdx}))
William A. Kennington III08505792019-01-30 16:00:04 -0800238 {
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800239 addStaticNeigh(neighbor);
William A. Kennington III08505792019-01-30 16:00:04 -0800240 }
241}
242
Patrick Williams6aef7692021-05-01 06:39:41 -0500243ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700244 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530245{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700246 InAddrAny addr;
247 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530248 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700249 switch (protType)
250 {
251 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700252 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700253 break;
254 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700255 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700256 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700257 default:
258 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700259 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500260 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700261 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500262 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700263 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
264 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500265 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
266 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
267 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700268 IfAddr ifaddr;
269 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500270 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700271 ifaddr = {addr, prefixLength};
272 }
273 catch (const std::exception& e)
274 {
275 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
276 e.what());
277 log<level::ERR>(msg.c_str(),
278 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500279 elog<InvalidArgument>(
280 Argument::ARGUMENT_NAME("prefixLength"),
281 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530282 }
283
William A. Kennington III434a9432022-11-04 18:38:46 -0700284 auto [it, _] = this->addrs.insert_or_assign(
285 ifaddr,
William A. Kennington III59e5b912022-11-02 02:49:46 -0700286 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III434a9432022-11-04 18:38:46 -0700287 ifaddr, IP::AddressOrigin::Static));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530288
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700289 writeConfigurationFile();
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800290 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700291
William A. Kennington III434a9432022-11-04 18:38:46 -0700292 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530293}
294
Patrick Williams6aef7692021-05-01 06:39:41 -0500295ObjectPath EthernetInterface::neighbor(std::string ipAddress,
296 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800297{
William A. Kennington III434a9432022-11-04 18:38:46 -0700298 InAddrAny addr;
299 try
William A. Kennington III08505792019-01-30 16:00:04 -0800300 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700301 addr = ToAddr<InAddrAny>{}(ipAddress);
302 }
303 catch (const std::exception& e)
304 {
305 auto msg =
306 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
307 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500308 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
309 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800310 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700311
312 ether_addr lladdr;
313 try
William A. Kennington III08505792019-01-30 16:00:04 -0800314 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700315 lladdr = ToAddr<ether_addr>{}(macAddress);
316 }
317 catch (const std::exception& e)
318 {
319 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
320 e.what());
321 log<level::ERR>(msg.c_str(),
322 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500323 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
324 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800325 }
326
William A. Kennington III434a9432022-11-04 18:38:46 -0700327 auto [it, _] = staticNeighbors.emplace(
328 addr,
329 std::make_unique<Neighbor>(bus, std::string_view(objPath), *this, addr,
330 lladdr, Neighbor::State::Permanent));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700331
332 writeConfigurationFile();
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800333 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700334
William A. Kennington III434a9432022-11-04 18:38:46 -0700335 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800336}
337
Patrick Williams6aef7692021-05-01 06:39:41 -0500338bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700339{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700340 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700341 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700342 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800343 manager.reloadConfigsNoRefresh();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700344 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700345 return value;
346}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700347
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700348bool EthernetInterface::dhcp4(bool value)
349{
350 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
351 {
352 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800353 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700354 }
355 return value;
356}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700357
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700358bool EthernetInterface::dhcp6(bool value)
359{
360 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
361 {
362 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800363 manager.reloadConfigsNoRefresh();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700364 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700365 return value;
366}
367
Patrick Williams6aef7692021-05-01 06:39:41 -0500368EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530369{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700370 auto old4 = EthernetInterfaceIntf::dhcp4();
371 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
372 value == DHCPConf::v4v6stateless ||
373 value == DHCPConf::both);
374 auto old6 = EthernetInterfaceIntf::dhcp6();
375 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
376 value == DHCPConf::both);
377 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
378 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
379 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
380 value == DHCPConf::v6 || value == DHCPConf::both);
381
382 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530383 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700384 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800385 manager.reloadConfigsNoRefresh();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530386 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530387 return value;
388}
389
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700390EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
391{
392 if (dhcp6())
393 {
394 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
395 }
396 else if (dhcp4())
397 {
398 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
399 }
400 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
401}
402
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800403bool EthernetInterface::linkUp() const
404{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700405 if (ifIdx == 0)
406 {
407 return EthernetInterfaceIntf::linkUp();
408 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700409 return system::intfIsRunning(interfaceName());
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700410}
411
Tejas Patil2c0fc562021-08-03 19:13:46 +0530412size_t EthernetInterface::mtu() const
413{
William A. Kennington III3e471c52022-10-27 19:46:07 -0700414 if (ifIdx == 0)
415 {
416 return EthernetInterfaceIntf::mtu();
417 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700418 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700419 return ignoreError("GetMTU", ifname, std::nullopt,
William A. Kennington III2e09d272022-10-14 17:15:00 -0700420 [&] { return system::getMTU(ifname); })
421 .value_or(EthernetInterfaceIntf::mtu());
Tejas Patil2c0fc562021-08-03 19:13:46 +0530422}
423
424size_t EthernetInterface::mtu(size_t value)
425{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700426 const size_t old = EthernetInterfaceIntf::mtu();
427 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530428 {
429 return value;
430 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700431 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700432 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700433 system::setMTU(ifname, value);
434 return value;
435 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530436}
437
William A. Kennington III26275a32021-07-13 20:32:42 -0700438bool EthernetInterface::queryNicEnabled() const
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700439{
William A. Kennington III26275a32021-07-13 20:32:42 -0700440 constexpr auto svc = "org.freedesktop.network1";
441 constexpr auto intf = "org.freedesktop.network1.Link";
442 constexpr auto prop = "AdministrativeState";
443 char* rpath;
444 sd_bus_path_encode("/org/freedesktop/network1/link",
William A. Kennington III2e09d272022-10-14 17:15:00 -0700445 std::to_string(ifIdx).c_str(), &rpath);
William A. Kennington III26275a32021-07-13 20:32:42 -0700446 std::string path(rpath);
447 free(rpath);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700448
William A. Kennington III26275a32021-07-13 20:32:42 -0700449 // Store / Parser for the AdministrativeState return value
450 std::optional<bool> ret;
William A. Kennington IIIbe3bd2f2022-10-11 14:11:27 -0700451 auto cb = [&](std::string_view state) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700452 if (state != "initialized")
453 {
454 ret = state != "unmanaged";
455 }
456 };
457
458 // Build a matcher before making the property call to ensure we
459 // can eventually get the value.
Patrick Williamsc38b0712022-07-22 19:26:54 -0500460 sdbusplus::bus::match_t match(
William A. Kennington III26275a32021-07-13 20:32:42 -0700461 bus,
462 fmt::format("type='signal',sender='{}',path='{}',interface='{}',member="
463 "'PropertiesChanged',arg0='{}',",
464 svc, path, PROPERTY_INTERFACE, intf)
465 .c_str(),
Patrick Williamsc38b0712022-07-22 19:26:54 -0500466 [&](sdbusplus::message_t& m) {
William A. Kennington III26275a32021-07-13 20:32:42 -0700467 std::string intf;
468 std::unordered_map<std::string, std::variant<std::string>> values;
469 try
470 {
471 m.read(intf, values);
472 auto it = values.find(prop);
473 // Ignore properties that aren't AdministrativeState
474 if (it != values.end())
475 {
476 cb(std::get<std::string>(it->second));
477 }
478 }
479 catch (const std::exception& e)
480 {
481 log<level::ERR>(
482 fmt::format(
483 "AdministrativeState match parsing failed on {}: {}",
484 interfaceName(), e.what())
485 .c_str(),
486 entry("INTERFACE=%s", interfaceName().c_str()),
487 entry("ERROR=%s", e.what()));
488 }
489 });
490
491 // Actively call for the value in case the interface is already configured
492 auto method =
493 bus.new_method_call(svc, path.c_str(), PROPERTY_INTERFACE, METHOD_GET);
494 method.append(intf, prop);
495 try
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700496 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700497 auto reply = bus.call(method);
498 std::variant<std::string> state;
499 reply.read(state);
500 cb(std::get<std::string>(state));
501 }
502 catch (const std::exception& e)
503 {
504 log<level::ERR>(
505 fmt::format("Failed to get AdministrativeState on {}: {}",
506 interfaceName(), e.what())
507 .c_str(),
508 entry("INTERFACE=%s", interfaceName().c_str()),
509 entry("ERROR=%s", e.what()));
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700510 }
511
William A. Kennington III26275a32021-07-13 20:32:42 -0700512 // The interface is not yet configured by systemd-networkd, wait until it
513 // signals us a valid state.
514 while (!ret)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700515 {
William A. Kennington III26275a32021-07-13 20:32:42 -0700516 bus.wait();
517 bus.process_discard();
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700518 }
William A. Kennington III26275a32021-07-13 20:32:42 -0700519
520 return *ret;
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700521}
522
Patrick Williams6aef7692021-05-01 06:39:41 -0500523bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700524{
Patrick Williams6aef7692021-05-01 06:39:41 -0500525 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700526 {
527 return value;
528 }
529
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800530 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700531 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800532 if (!value)
533 {
534 // We only need to bring down the interface, networkd will always bring
535 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700536 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700537 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800538 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700539 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800540
541 return value;
542}
543
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530544ServerList EthernetInterface::staticNameServers(ServerList value)
545{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700546 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530547 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700548 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530549 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700550 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
551 }
552 catch (const std::exception& e)
553 {
554 auto msg =
555 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
556 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
557 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
558 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530559 }
560 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530561 try
562 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530563 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700564
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530565 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800566 manager.reloadConfigsNoRefresh();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530567 }
Patrick Williams5758db32021-10-06 12:29:22 -0500568 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530569 {
570 log<level::ERR>("Exception processing DNS entries");
571 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530572 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530573}
574
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600575void EthernetInterface::loadNTPServers(const config::Parser& config)
576{
577 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
578 EthernetInterfaceIntf::staticNTPServers(
579 config.map.getValueStrings("Network", "NTP"));
580}
581
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700582void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530583{
584 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700585 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700586 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530587}
588
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600589ServerList EthernetInterface::getNTPServerFromTimeSyncd()
590{
591 ServerList servers; // Variable to capture the NTP Server IPs
592 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
593 PROPERTY_INTERFACE, METHOD_GET);
594
595 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
596
597 try
598 {
599 auto reply = bus.call(method);
600 std::variant<ServerList> response;
601 reply.read(response);
602 servers = std::get<ServerList>(response);
603 }
604 catch (const sdbusplus::exception::SdBusError& e)
605 {
606 log<level::ERR>(
607 "Failed to get NTP server information from Systemd-Timesyncd");
608 }
609
610 return servers;
611}
612
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530613ServerList EthernetInterface::getNameServerFromResolvd()
614{
615 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700616 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530617
618 /*
619 The DNS property under org.freedesktop.resolve1.Link interface contains
620 an array containing all DNS servers currently used by resolved. It
621 contains similar information as the DNS server data written to
622 /run/systemd/resolve/resolv.conf.
623
624 Each structure in the array consists of a numeric network interface index,
625 an address family, and a byte array containing the DNS server address
626 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
627 The array contains DNS servers configured system-wide, including those
628 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
629 /etc/systemd/resolved.conf, as well as per-interface DNS server
630 information either retrieved from systemd-networkd or configured by
631 external software via SetLinkDNS().
632 */
633
634 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
635 std::variant<type> name; // Variable to capture the DNS property
636 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
637 PROPERTY_INTERFACE, METHOD_GET);
638
639 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530640
641 try
642 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500643 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530644 reply.read(name);
645 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500646 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530647 {
648 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
649 }
650 auto tupleVector = std::get_if<type>(&name);
651 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
652 {
Alexander Filippov983da552021-02-08 15:26:54 +0300653 int addressFamily = std::get<0>(*i);
654 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700655 servers.push_back(std::to_string(
656 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530657 }
658 return servers;
659}
660
William A. Kennington IIId298f932022-10-17 14:31:38 -0700661ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530662{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700663 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
664 auto idStr = std::to_string(id);
665 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800666 {
667 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700668 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
669 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800670 }
671
William A. Kennington IIId298f932022-10-17 14:31:38 -0700672 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700673 auto macStr = MacAddressIntf::macAddress();
674 std::optional<ether_addr> mac;
675 if (!macStr.empty())
676 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700677 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700678 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800679 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700680 .idx = 0, // TODO: Query the correct value after creation
681 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700682 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700683 .mac = std::move(mac),
684 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700685 .parent_idx = ifIdx,
686 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700687 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530688
Patrick Williams6aef7692021-05-01 06:39:41 -0500689 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530690 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700691 auto vlanIntf = std::make_unique<EthernetInterface>(
692 bus, manager, info, objRoot, config::Parser(), /*emit=*/true,
William A. Kennington IIId298f932022-10-17 14:31:38 -0700693 nicEnabled());
694 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530695
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700696 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530697
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700698 // write the device file for the vlan interface.
699 config::Parser config;
700 auto& netdev = config.map["NetDev"].emplace_back();
701 netdev["Name"].emplace_back(intfName);
702 netdev["Kind"].emplace_back("vlan");
703 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
704 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700705
706 writeConfigurationFile();
707 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700708
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800709 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530710}
Ratan Gupta2b106532017-07-25 16:05:02 +0530711
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600712ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530713{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600714 try
715 {
716 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530717
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600718 writeConfigurationFile();
William A. Kennington IIIffab00d2022-11-07 16:58:36 -0800719 manager.reloadConfigsNoRefresh();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600720 }
721 catch (InternalFailure& e)
722 {
723 log<level::ERR>("Exception processing NTP entries");
724 }
725 return EthernetInterfaceIntf::staticNTPServers();
726}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700727
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600728ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
729{
730 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530731}
Ratan Gupta2b106532017-07-25 16:05:02 +0530732// Need to merge the below function with the code which writes the
733// config file during factory reset.
734// TODO openbmc/openbmc#1751
735
736void EthernetInterface::writeConfigurationFile()
737{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700738 config::Parser config;
739 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530740 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700741 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800742#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700743 auto mac = MacAddressIntf::macAddress();
744 if (!mac.empty())
745 {
746 link["MACAddress"].emplace_back(mac);
747 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800748#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700749 if (!EthernetInterfaceIntf::nicEnabled())
750 {
751 link["Unmanaged"].emplace_back("yes");
752 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700753 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700754 {
755 auto& network = config.map["Network"].emplace_back();
756 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400757#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700758 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400759#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700760 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400761#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700762 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
763 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
764 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600765 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700766 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700767 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700768 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700769 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
770 {
771 vlans.emplace_back(intf->interfaceName());
772 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700773 }
774 }
775 {
776 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600777 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700778 {
779 ntps.emplace_back(ntp);
780 }
781 }
782 {
783 auto& dnss = network["DNS"];
784 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
785 {
786 dnss.emplace_back(dns);
787 }
788 }
789 {
790 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700791 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700792 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700793 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700794 {
795 address.emplace_back(
796 fmt::format("{}/{}", addr.second->address(),
797 addr.second->prefixLength()));
798 }
799 }
800 }
801 {
802 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700803 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700804 {
805 auto gateway = EthernetInterfaceIntf::defaultGateway();
806 if (!gateway.empty())
807 {
808 gateways.emplace_back(gateway);
809 }
810 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530811
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700812 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700813 {
814 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
815 if (!gateway6.empty())
816 {
817 gateways.emplace_back(gateway6);
818 }
819 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600820 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800821 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700822 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700823 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500824 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700825 auto& neighbors = config.map["Neighbor"];
826 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800827 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700828 auto& neighbor = neighbors.emplace_back();
829 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
830 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800831 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500832 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500833 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700834 auto& dhcp = config.map["DHCP"].emplace_back();
835 dhcp["ClientIdentifier"].emplace_back("mac");
836 if (manager.getDHCPConf())
Lei YUcb2d4082021-08-12 15:26:49 +0800837 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700838 const auto& conf = *manager.getDHCPConf();
839 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
840 dhcp["UseDNS"].emplace_back(dns_enabled);
841 dhcp["UseDomains"].emplace_back(dns_enabled);
842 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
843 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
844 : "false");
845 dhcp["SendHostname"].emplace_back(
846 conf.sendHostNameEnabled() ? "true" : "false");
Lei YUcb2d4082021-08-12 15:26:49 +0800847 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500848 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700849 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
850 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700851 auto msg = fmt::format("Wrote networkd file: {}", path.native());
852 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530853}
854
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800855std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530856{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700857 if (vlan)
858 {
859 log<level::ERR>("Tried to set MAC address on VLAN");
860 elog<InternalFailure>();
861 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800862#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600863 ether_addr newMAC;
864 try
865 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700866 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600867 }
Patrick Williams5758db32021-10-06 12:29:22 -0500868 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600869 {
870 log<level::ERR>("MACAddress is not valid.",
871 entry("MAC=%s", value.c_str()));
872 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
873 Argument::ARGUMENT_VALUE(value.c_str()));
874 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700875 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530876 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500877 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500878 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500879 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
880 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530881 }
882
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300883 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700884 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300885
William A. Kennington III1137a972019-04-20 20:49:58 -0700886 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700887 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700888 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530889 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700890 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700891 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530892 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700893 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
894 {
895 intf->MacAddressIntf::macAddress(validMAC);
896 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530897 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500898 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530899
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700900 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800901 manager.addReloadPreHook([interface]() {
902 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700903 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800904 });
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700905 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530906 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700907
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300908#ifdef HAVE_UBOOT_ENV
909 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700910 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300911 if (envVar)
912 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500913 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
914 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
915 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
916 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300917 }
918#endif // HAVE_UBOOT_ENV
919
William A. Kennington III1137a972019-04-20 20:49:58 -0700920 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800921#else
922 elog<NotAllowed>(
923 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
924#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530925}
926
Ratan Guptae9c9b812017-09-22 17:15:37 +0530927void EthernetInterface::deleteAll()
928{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530929 // clear all the ip on the interface
930 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700931
932 writeConfigurationFile();
933 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530934}
935
Ravi Tejaa5a09442020-07-17 00:57:33 -0500936std::string EthernetInterface::defaultGateway(std::string gateway)
937{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700938 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500939 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700940 if (!gateway.empty())
941 {
942 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
943 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500944 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700945 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500946 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700947 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
948 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500949 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
950 Argument::ARGUMENT_VALUE(gateway.c_str()));
951 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700952
953 if (EthernetInterfaceIntf::defaultGateway() == gateway)
954 {
955 return gateway;
956 }
957 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700958
959 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700960 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700961
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700962 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500963}
964
965std::string EthernetInterface::defaultGateway6(std::string gateway)
966{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700967 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500968 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700969 if (!gateway.empty())
970 {
971 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
972 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500973 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700974 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500975 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700976 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
977 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500978 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
979 Argument::ARGUMENT_VALUE(gateway.c_str()));
980 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700981
982 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
983 {
984 return gateway;
985 }
986 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700987
988 writeConfigurationFile();
William A. Kennington III71590bf2022-10-31 14:14:16 -0700989 manager.reloadConfigsNoRefresh();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700990
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700991 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500992}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700993
994EthernetInterface::VlanProperties::VlanProperties(
995 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III454a0de2022-11-12 01:01:04 -0800996 const InterfaceInfo& info, EthernetInterface& eth, bool emitSignal) :
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700997 VlanIfaces(bus, objPath.c_str(),
998 emitSignal ? VlanIfaces::action::defer_emit
999 : VlanIfaces::action::emit_no_signals),
1000 parentIdx(*info.parent_idx), eth(eth)
1001{
1002 VlanIntf::id(*info.vlan_id);
1003 if (emitSignal)
1004 {
1005 this->emit_object_added();
1006 }
1007}
1008
1009void EthernetInterface::VlanProperties::delete_()
1010{
1011 auto intf = eth.interfaceName();
1012
1013 // Remove all configs for the current interface
1014 const auto& confDir = eth.manager.getConfDir();
1015 std::error_code ec;
1016 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
1017 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
1018
1019 // Write an updated parent interface since it has a VLAN entry
1020 for (const auto& [_, intf] : eth.manager.interfaces)
1021 {
1022 if (intf->ifIdx == parentIdx)
1023 {
1024 intf->writeConfigurationFile();
1025 }
1026 }
1027
1028 // We need to forcibly delete the interface as systemd does not
1029 deleteInterface(intf);
1030
William A. Kennington III67b09da2022-10-31 14:09:53 -07001031 if (eth.ifIdx > 0)
1032 {
1033 eth.manager.interfacesByIdx.erase(eth.ifIdx);
1034 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -07001035 eth.manager.interfaces.erase(intf);
1036}
1037
Gunnar Mills57d9c502018-09-14 14:42:34 -05001038} // namespace network
1039} // namespace phosphor