blob: 8476136c4dc7a94a62f4d48cd00671244870e70a [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
Ratan Gupta82549cc2017-04-21 08:45:23 +053015#include <algorithm>
Manojkiran Edaa879baa2020-06-13 14:39:08 +053016#include <filesystem>
Patrick Venture189d44e2018-07-09 12:30:59 -070017#include <phosphor-logging/elog-errors.hpp>
18#include <phosphor-logging/log.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070019#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070020#include <stdplus/zstring.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053021#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070022#include <unordered_map>
23#include <variant>
Patrick Venture189d44e2018-07-09 12:30:59 -070024#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053025
Ratan Gupta91a99cc2017-04-14 16:32:09 +053026namespace phosphor
27{
28namespace network
29{
30
31using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053032using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053033using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
34using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050035using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070036using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053037constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
38constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
39constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
40constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060041
42constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
43constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
44constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
45
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053046constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053047
William A. Kennington III2e09d272022-10-14 17:15:00 -070048template <typename Func>
49inline decltype(std::declval<Func>()())
50 ignoreError(std::string_view msg, stdplus::zstring_view intf,
51 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080052{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070053 try
54 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070055 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070056 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070057 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070058 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070059 auto err = fmt::format("{} failed on {}: {}", msg, intf, e.what());
60 log<level::ERR>(err.c_str(), entry("INTERFACE=%s", intf.c_str()));
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070061 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070062 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070063}
William A. Kennington IIId298f932022-10-17 14:31:38 -070064
William A. Kennington IIId298f932022-10-17 14:31:38 -070065static std::string makeObjPath(std::string_view root, std::string_view intf)
66{
67 auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
68 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
69 return ret;
70}
71
72EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080073 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070074 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070075 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080076 bool enabled) :
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070077 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080078 config, enabled)
William A. Kennington IIId298f932022-10-17 14:31:38 -070079{
80}
81
82EthernetInterface::EthernetInterface(sdbusplus::bus_t& bus, Manager& manager,
William A. Kennington III454a0de2022-11-12 01:01:04 -080083 const InterfaceInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070084 std::string&& objPath,
85 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080086 bool enabled) :
87 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit),
William A. Kennington III59e5b912022-11-02 02:49:46 -070088 manager(manager), bus(bus), objPath(std::move(objPath)), ifIdx(info.idx)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053089{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070090 interfaceName(*info.name);
William A. Kennington III8060c0d2022-08-18 19:19:34 -070091 auto dhcpVal = getDHCPValue(config);
92 EthernetInterfaceIntf::dhcp4(dhcpVal.v4);
93 EthernetInterfaceIntf::dhcp6(dhcpVal.v6);
William A. Kennington IIIa520a392022-08-08 12:17:34 -070094 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config));
William A. Kennington III80d29012022-11-12 02:31:40 -080095 EthernetInterfaceIntf::nicEnabled(enabled);
Ravi Tejaa5a09442020-07-17 00:57:33 -050096
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -070097 EthernetInterfaceIntf::ntpServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -070098 config.map.getValueStrings("Network", "NTP"));
Ratan Gupta613a0122020-04-24 15:18:53 +053099
William A. Kennington IIId298f932022-10-17 14:31:38 -0700100 updateInfo(info);
101
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700102 if (info.vlan_id)
103 {
104 if (!info.parent_idx)
105 {
106 std::runtime_error("Missing parent link");
107 }
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800108 vlan.emplace(bus, this->objPath.c_str(), info, *this);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700109 }
110
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800111 this->emit_object_added();
Ratan Gupta29b0e432017-05-25 12:51:40 +0530112}
113
William A. Kennington III454a0de2022-11-12 01:01:04 -0800114void EthernetInterface::updateInfo(const InterfaceInfo& info)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700115{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700116 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700117 if (info.mac)
118 {
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700119 MacAddressIntf::macAddress(std::to_string(*info.mac));
William A. Kennington IIId298f932022-10-17 14:31:38 -0700120 }
121 if (info.mtu)
122 {
123 EthernetInterfaceIntf::mtu(*info.mtu);
124 }
William A. Kennington III21539662022-11-15 14:53:11 -0800125 if (ifIdx > 0)
126 {
127 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
128 return system::getEthInfo(*info.name);
129 });
130 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg);
131 EthernetInterfaceIntf::speed(ethInfo.speed);
132 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700133}
134
Johnathan Mantey817012a2020-01-30 15:07:39 -0800135bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
136{
137 return (
138#ifdef LINK_LOCAL_AUTOCONFIGURATION
139 (origin == IP::AddressOrigin::Static)
140#else
141 (origin == IP::AddressOrigin::Static ||
142 origin == IP::AddressOrigin::LinkLocal)
143#endif
144
145 );
146}
147
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800148void EthernetInterface::addAddr(const AddressInfo& info)
149{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800150 IP::AddressOrigin origin = IP::AddressOrigin::Static;
151 if (dhcpIsEnabled(info.ifaddr.getAddr()))
152 {
153 origin = IP::AddressOrigin::DHCP;
154 }
155#ifdef LINK_LOCAL_AUTOCONFIGURATION
156 if (info.scope == RT_SCOPE_LINK)
157 {
158 origin = IP::AddressOrigin::LinkLocal;
159 }
160#endif
161
William A. Kennington III77747f62022-11-07 23:11:15 -0800162 auto it = addrs.find(info.ifaddr);
163 if (it == addrs.end())
164 {
165 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
166 bus, std::string_view(objPath), *this,
167 info.ifaddr, origin));
168 }
169 else
170 {
171 it->second->IPIfaces::origin(origin);
172 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800173}
174
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800175void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
176{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800177 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800178 {
William A. Kennington IIId3615142022-11-12 01:28:33 -0800179 auto msg = fmt::format("Missing neighbor mac on {}\n", interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800180 log<level::ERR>(msg.c_str());
181 return;
182 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800183
184 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
185 {
186 it->second->NeighborObj::macAddress(std::to_string(*info.mac));
187 }
188 else
189 {
190 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
191 bus, std::string_view(objPath),
192 *this, *info.addr, *info.mac,
193 Neighbor::State::Permanent));
194 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800195}
196
Patrick Williams6aef7692021-05-01 06:39:41 -0500197ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700198 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530199{
William A. Kennington III59e5b912022-11-02 02:49:46 -0700200 InAddrAny addr;
201 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530202 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700203 switch (protType)
204 {
205 case IP::Protocol::IPv4:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700206 addr = ToAddr<in_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700207 break;
208 case IP::Protocol::IPv6:
William A. Kennington III59e5b912022-11-02 02:49:46 -0700209 addr = ToAddr<in6_addr>{}(ipaddress);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700210 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700211 default:
212 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700213 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500214 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700215 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500216 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700217 auto msg = fmt::format("Invalid IP `{}`: {}\n", ipaddress, e.what());
218 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipaddress.c_str()));
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500219 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
220 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
221 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700222 IfAddr ifaddr;
223 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500224 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700225 ifaddr = {addr, prefixLength};
226 }
227 catch (const std::exception& e)
228 {
229 auto msg = fmt::format("Invalid prefix length `{}`: {}\n", prefixLength,
230 e.what());
231 log<level::ERR>(msg.c_str(),
232 entry("PREFIXLENGTH=%" PRIu8, prefixLength));
Gunnar Mills57d9c502018-09-14 14:42:34 -0500233 elog<InvalidArgument>(
234 Argument::ARGUMENT_NAME("prefixLength"),
235 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530236 }
237
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800238 auto it = addrs.find(ifaddr);
239 if (it == addrs.end())
240 {
241 it = std::get<0>(addrs.emplace(
242 ifaddr,
243 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
244 ifaddr, IP::AddressOrigin::Static)));
245 }
246 else
247 {
248 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
249 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530250
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700251 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800252 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700253
William A. Kennington III434a9432022-11-04 18:38:46 -0700254 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530255}
256
Patrick Williams6aef7692021-05-01 06:39:41 -0500257ObjectPath EthernetInterface::neighbor(std::string ipAddress,
258 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800259{
William A. Kennington III434a9432022-11-04 18:38:46 -0700260 InAddrAny addr;
261 try
William A. Kennington III08505792019-01-30 16:00:04 -0800262 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700263 addr = ToAddr<InAddrAny>{}(ipAddress);
264 }
265 catch (const std::exception& e)
266 {
267 auto msg =
268 fmt::format("Not a valid IP address `{}`: {}", ipAddress, e.what());
269 log<level::ERR>(msg.c_str(), entry("ADDRESS=%s", ipAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500270 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
271 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800272 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700273
274 ether_addr lladdr;
275 try
William A. Kennington III08505792019-01-30 16:00:04 -0800276 {
William A. Kennington III434a9432022-11-04 18:38:46 -0700277 lladdr = ToAddr<ether_addr>{}(macAddress);
278 }
279 catch (const std::exception& e)
280 {
281 auto msg = fmt::format("Not a valid MAC address `{}`: {}", macAddress,
282 e.what());
283 log<level::ERR>(msg.c_str(),
284 entry("MACADDRESS=%s", macAddress.c_str()));
Patrick Williams6aef7692021-05-01 06:39:41 -0500285 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
286 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800287 }
288
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800289 auto it = staticNeighbors.find(addr);
290 if (it == staticNeighbors.end())
291 {
292 it = std::get<0>(staticNeighbors.emplace(
293 addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
294 *this, addr, lladdr,
295 Neighbor::State::Permanent)));
296 }
297 else
298 {
299 it->second->NeighborObj::macAddress(std::to_string(lladdr));
300 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700301
302 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800303 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700304
William A. Kennington III434a9432022-11-04 18:38:46 -0700305 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800306}
307
Patrick Williams6aef7692021-05-01 06:39:41 -0500308bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700309{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700310 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700311 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700312 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800313 manager.reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700314 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700315 return value;
316}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700317
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700318bool EthernetInterface::dhcp4(bool value)
319{
320 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
321 {
322 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800323 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700324 }
325 return value;
326}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700327
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700328bool EthernetInterface::dhcp6(bool value)
329{
330 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
331 {
332 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800333 manager.reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700334 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700335 return value;
336}
337
Patrick Williams6aef7692021-05-01 06:39:41 -0500338EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530339{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700340 auto old4 = EthernetInterfaceIntf::dhcp4();
341 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
342 value == DHCPConf::v4v6stateless ||
343 value == DHCPConf::both);
344 auto old6 = EthernetInterfaceIntf::dhcp6();
345 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
346 value == DHCPConf::both);
347 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
348 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
349 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
350 value == DHCPConf::v6 || value == DHCPConf::both);
351
352 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530353 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700354 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800355 manager.reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530356 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530357 return value;
358}
359
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700360EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
361{
362 if (dhcp6())
363 {
364 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
365 }
366 else if (dhcp4())
367 {
368 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
369 }
370 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
371}
372
Tejas Patil2c0fc562021-08-03 19:13:46 +0530373size_t EthernetInterface::mtu(size_t value)
374{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700375 const size_t old = EthernetInterfaceIntf::mtu();
376 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530377 {
378 return value;
379 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700380 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700381 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700382 system::setMTU(ifname, value);
383 return value;
384 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530385}
386
Patrick Williams6aef7692021-05-01 06:39:41 -0500387bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700388{
Patrick Williams6aef7692021-05-01 06:39:41 -0500389 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700390 {
391 return value;
392 }
393
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800394 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700395 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800396 if (!value)
397 {
398 // We only need to bring down the interface, networkd will always bring
399 // up managed interfaces
William A. Kennington III69f45542022-09-24 23:28:14 -0700400 manager.addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700401 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800402 }
William A. Kennington III5b179382022-11-15 15:23:26 -0800403 manager.reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800404
405 return value;
406}
407
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530408ServerList EthernetInterface::staticNameServers(ServerList value)
409{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700410 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530411 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700412 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530413 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700414 ip = std::to_string(ToAddr<InAddrAny>{}(ip));
415 }
416 catch (const std::exception& e)
417 {
418 auto msg =
419 fmt::format("Not a valid IP address `{}`: {}", ip, e.what());
420 log<level::ERR>(msg.c_str()), entry("ADDRESS=%s", ip.c_str());
421 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
422 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530423 }
424 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530425 try
426 {
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530427 EthernetInterfaceIntf::staticNameServers(value);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700428
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530429 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800430 manager.reloadConfigs();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530431 }
Patrick Williams5758db32021-10-06 12:29:22 -0500432 catch (const InternalFailure& e)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530433 {
434 log<level::ERR>("Exception processing DNS entries");
435 }
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530436 return EthernetInterfaceIntf::staticNameServers();
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530437}
438
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600439void EthernetInterface::loadNTPServers(const config::Parser& config)
440{
441 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
442 EthernetInterfaceIntf::staticNTPServers(
443 config.map.getValueStrings("Network", "NTP"));
444}
445
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700446void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530447{
448 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700449 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700450 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530451}
452
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600453ServerList EthernetInterface::getNTPServerFromTimeSyncd()
454{
455 ServerList servers; // Variable to capture the NTP Server IPs
456 auto method = bus.new_method_call(TIMESYNCD_SERVICE, TIMESYNCD_SERVICE_PATH,
457 PROPERTY_INTERFACE, METHOD_GET);
458
459 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
460
461 try
462 {
463 auto reply = bus.call(method);
464 std::variant<ServerList> response;
465 reply.read(response);
466 servers = std::get<ServerList>(response);
467 }
468 catch (const sdbusplus::exception::SdBusError& e)
469 {
470 log<level::ERR>(
471 "Failed to get NTP server information from Systemd-Timesyncd");
472 }
473
474 return servers;
475}
476
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530477ServerList EthernetInterface::getNameServerFromResolvd()
478{
479 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700480 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530481
482 /*
483 The DNS property under org.freedesktop.resolve1.Link interface contains
484 an array containing all DNS servers currently used by resolved. It
485 contains similar information as the DNS server data written to
486 /run/systemd/resolve/resolv.conf.
487
488 Each structure in the array consists of a numeric network interface index,
489 an address family, and a byte array containing the DNS server address
490 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
491 The array contains DNS servers configured system-wide, including those
492 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
493 /etc/systemd/resolved.conf, as well as per-interface DNS server
494 information either retrieved from systemd-networkd or configured by
495 external software via SetLinkDNS().
496 */
497
498 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
499 std::variant<type> name; // Variable to capture the DNS property
500 auto method = bus.new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
501 PROPERTY_INTERFACE, METHOD_GET);
502
503 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530504
505 try
506 {
Asmitha Karunanithi97ddb8d2022-05-05 01:00:18 -0500507 auto reply = bus.call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530508 reply.read(name);
509 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500510 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530511 {
512 log<level::ERR>("Failed to get DNS information from Systemd-Resolved");
513 }
514 auto tupleVector = std::get_if<type>(&name);
515 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
516 {
Alexander Filippov983da552021-02-08 15:26:54 +0300517 int addressFamily = std::get<0>(*i);
518 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700519 servers.push_back(std::to_string(
520 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530521 }
522 return servers;
523}
524
William A. Kennington IIId298f932022-10-17 14:31:38 -0700525ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530526{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700527 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), id);
528 auto idStr = std::to_string(id);
529 if (manager.interfaces.find(intfName) != manager.interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800530 {
531 log<level::ERR>("VLAN already exists", entry("VLANID=%u", id));
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700532 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
533 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800534 }
535
William A. Kennington IIId298f932022-10-17 14:31:38 -0700536 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700537 auto macStr = MacAddressIntf::macAddress();
538 std::optional<ether_addr> mac;
539 if (!macStr.empty())
540 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700541 mac.emplace(ToAddr<ether_addr>{}(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700542 }
William A. Kennington III454a0de2022-11-12 01:01:04 -0800543 auto info = InterfaceInfo{
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700544 .idx = 0, // TODO: Query the correct value after creation
545 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700546 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700547 .mac = std::move(mac),
548 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700549 .parent_idx = ifIdx,
550 .vlan_id = id,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700551 };
Ratan Gupta5978dd12017-07-25 13:47:13 +0530552
Patrick Williams6aef7692021-05-01 06:39:41 -0500553 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530554 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700555 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800556 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700557 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530558
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700559 manager.interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530560
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700561 // write the device file for the vlan interface.
562 config::Parser config;
563 auto& netdev = config.map["NetDev"].emplace_back();
564 netdev["Name"].emplace_back(intfName);
565 netdev["Kind"].emplace_back("vlan");
566 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
567 config.writeFile(config::pathForIntfDev(manager.getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700568
569 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800570 manager.reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700571
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800572 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530573}
Ratan Gupta2b106532017-07-25 16:05:02 +0530574
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600575ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530576{
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600577 try
578 {
579 EthernetInterfaceIntf::staticNTPServers(value);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530580
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600581 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800582 manager.reloadConfigs();
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600583 }
584 catch (InternalFailure& e)
585 {
586 log<level::ERR>("Exception processing NTP entries");
587 }
588 return EthernetInterfaceIntf::staticNTPServers();
589}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700590
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600591ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
592{
593 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530594}
Ratan Gupta2b106532017-07-25 16:05:02 +0530595// Need to merge the below function with the code which writes the
596// config file during factory reset.
597// TODO openbmc/openbmc#1751
598
599void EthernetInterface::writeConfigurationFile()
600{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700601 config::Parser config;
602 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530603 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700604 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800605#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700606 auto mac = MacAddressIntf::macAddress();
607 if (!mac.empty())
608 {
609 link["MACAddress"].emplace_back(mac);
610 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800611#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700612 if (!EthernetInterfaceIntf::nicEnabled())
613 {
614 link["Unmanaged"].emplace_back("yes");
615 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700616 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700617 {
618 auto& network = config.map["Network"].emplace_back();
619 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400620#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700621 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400622#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700623 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400624#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700625 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
626 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
627 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600628 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700629 auto& vlans = network["VLAN"];
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700630 for (const auto& [_, intf] : manager.interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700631 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700632 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
633 {
634 vlans.emplace_back(intf->interfaceName());
635 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700636 }
637 }
638 {
639 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600640 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700641 {
642 ntps.emplace_back(ntp);
643 }
644 }
645 {
646 auto& dnss = network["DNS"];
647 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
648 {
649 dnss.emplace_back(dns);
650 }
651 }
652 {
653 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700654 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700655 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700656 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700657 {
658 address.emplace_back(
659 fmt::format("{}/{}", addr.second->address(),
660 addr.second->prefixLength()));
661 }
662 }
663 }
664 {
665 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700666 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700667 {
668 auto gateway = EthernetInterfaceIntf::defaultGateway();
669 if (!gateway.empty())
670 {
671 gateways.emplace_back(gateway);
672 }
673 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530674
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700675 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700676 {
677 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
678 if (!gateway6.empty())
679 {
680 gateways.emplace_back(gateway6);
681 }
682 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600683 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800684 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700685 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700686 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500687 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700688 auto& neighbors = config.map["Neighbor"];
689 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800690 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700691 auto& neighbor = neighbors.emplace_back();
692 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
693 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800694 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500695 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500696 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700697 auto& dhcp = config.map["DHCP"].emplace_back();
698 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III5b179382022-11-15 15:23:26 -0800699 const auto& conf = manager.getDHCPConf();
700 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
701 dhcp["UseDNS"].emplace_back(dns_enabled);
702 dhcp["UseDomains"].emplace_back(dns_enabled);
703 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
704 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
705 : "false");
706 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
707 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500708 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700709 auto path = config::pathForIntfConf(manager.getConfDir(), interfaceName());
710 config.writeFile(path);
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700711 auto msg = fmt::format("Wrote networkd file: {}", path.native());
712 log<level::INFO>(msg.c_str(), entry("FILE=%s", path.c_str()));
Ratan Gupta2b106532017-07-25 16:05:02 +0530713}
714
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800715std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530716{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700717 if (vlan)
718 {
719 log<level::ERR>("Tried to set MAC address on VLAN");
720 elog<InternalFailure>();
721 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800722#ifdef PERSIST_MAC
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600723 ether_addr newMAC;
724 try
725 {
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700726 newMAC = ToAddr<ether_addr>{}(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600727 }
Patrick Williams5758db32021-10-06 12:29:22 -0500728 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600729 {
730 log<level::ERR>("MACAddress is not valid.",
731 entry("MAC=%s", value.c_str()));
732 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
733 Argument::ARGUMENT_VALUE(value.c_str()));
734 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700735 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530736 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500737 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500738 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500739 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
740 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530741 }
742
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300743 auto interface = interfaceName();
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700744 auto validMAC = std::to_string(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300745
William A. Kennington III1137a972019-04-20 20:49:58 -0700746 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb01d08f2022-11-03 12:50:00 -0700747 ether_addr oldMAC = ToAddr<ether_addr>{}(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700748 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530749 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700750 // Update everything that depends on the MAC value
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700751 for (const auto& [_, intf] : manager.interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530752 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700753 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
754 {
755 intf->MacAddressIntf::macAddress(validMAC);
756 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530757 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500758 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530759
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700760 writeConfigurationFile();
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800761 manager.addReloadPreHook([interface]() {
762 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700763 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800764 });
William A. Kennington III5b179382022-11-15 15:23:26 -0800765 manager.reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530766 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700767
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300768#ifdef HAVE_UBOOT_ENV
769 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700770 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300771 if (envVar)
772 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500773 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
774 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
775 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
776 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300777 }
778#endif // HAVE_UBOOT_ENV
779
William A. Kennington III1137a972019-04-20 20:49:58 -0700780 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800781#else
782 elog<NotAllowed>(
783 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
784#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530785}
786
Ratan Guptae9c9b812017-09-22 17:15:37 +0530787void EthernetInterface::deleteAll()
788{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530789 // clear all the ip on the interface
790 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700791
792 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800793 manager.reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530794}
795
Ravi Tejaa5a09442020-07-17 00:57:33 -0500796std::string EthernetInterface::defaultGateway(std::string gateway)
797{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700798 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500799 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700800 if (!gateway.empty())
801 {
802 gateway = std::to_string(ToAddr<in_addr>{}(gateway));
803 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500804 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700805 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500806 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700807 auto msg = fmt::format("Invalid v4 GW `{}`: {}", gateway, e.what());
808 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500809 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
810 Argument::ARGUMENT_VALUE(gateway.c_str()));
811 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700812
813 if (EthernetInterfaceIntf::defaultGateway() == gateway)
814 {
815 return gateway;
816 }
817 EthernetInterfaceIntf::defaultGateway(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700818
819 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800820 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700821
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700822 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500823}
824
825std::string EthernetInterface::defaultGateway6(std::string gateway)
826{
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700827 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500828 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700829 if (!gateway.empty())
830 {
831 gateway = std::to_string(ToAddr<in6_addr>{}(gateway));
832 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500833 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700834 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500835 {
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700836 auto msg = fmt::format("Invalid v6 GW `{}`: {}", gateway, e.what());
837 log<level::ERR>(msg.c_str(), entry("GATEWAY=%s", gateway.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500838 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
839 Argument::ARGUMENT_VALUE(gateway.c_str()));
840 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700841
842 if (EthernetInterfaceIntf::defaultGateway6() == gateway)
843 {
844 return gateway;
845 }
846 EthernetInterfaceIntf::defaultGateway6(gateway);
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700847
848 writeConfigurationFile();
William A. Kennington III5b179382022-11-15 15:23:26 -0800849 manager.reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700850
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700851 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500852}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700853
854EthernetInterface::VlanProperties::VlanProperties(
855 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800856 const InterfaceInfo& info, EthernetInterface& eth) :
857 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700858 parentIdx(*info.parent_idx), eth(eth)
859{
860 VlanIntf::id(*info.vlan_id);
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800861 this->emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700862}
863
864void EthernetInterface::VlanProperties::delete_()
865{
866 auto intf = eth.interfaceName();
867
868 // Remove all configs for the current interface
869 const auto& confDir = eth.manager.getConfDir();
870 std::error_code ec;
871 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
872 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
873
874 // Write an updated parent interface since it has a VLAN entry
875 for (const auto& [_, intf] : eth.manager.interfaces)
876 {
877 if (intf->ifIdx == parentIdx)
878 {
879 intf->writeConfigurationFile();
880 }
881 }
882
883 // We need to forcibly delete the interface as systemd does not
884 deleteInterface(intf);
885
William A. Kennington III67b09da2022-10-31 14:09:53 -0700886 if (eth.ifIdx > 0)
887 {
888 eth.manager.interfacesByIdx.erase(eth.ifIdx);
889 }
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700890 eth.manager.interfaces.erase(intf);
891}
892
Gunnar Mills57d9c502018-09-14 14:42:34 -0500893} // namespace network
894} // namespace phosphor