blob: 7a17208324d54933e66b26b56008f3dfb95bb7c8 [file] [log] [blame]
Gunnar Mills57d9c502018-09-14 14:42:34 -05001#include "config.h"
2
Patrick Venture189d44e2018-07-09 12:30:59 -07003#include "ethernet_interface.hpp"
4
Ratan Gupta497c0c92017-08-22 19:15:59 +05305#include "config_parser.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05306#include "network_manager.hpp"
William A. Kennington III2e09d272022-10-14 17:15:00 -07007#include "system_queries.hpp"
William A. Kennington III95530ec2022-08-19 01:44:39 -07008#include "util.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05309
William A. Kennington IIIa520a392022-08-08 12:17:34 -070010#include <fmt/compile.h>
William A. Kennington III26275a32021-07-13 20:32:42 -070011#include <fmt/format.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070012#include <linux/rtnetlink.h>
William A. Kennington IIIfd862be2022-10-09 18:40:55 -070013#include <net/if.h>
William A. Kennington III9c441fd2023-02-24 13:40:01 -080014#include <net/if_arp.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053015
Patrick Venture189d44e2018-07-09 12:30:59 -070016#include <phosphor-logging/elog-errors.hpp>
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -070017#include <phosphor-logging/lg2.hpp>
William A. Kennington III12beaad2020-06-13 19:30:41 -070018#include <stdplus/raw.hpp>
William A. Kennington III69f45542022-09-24 23:28:14 -070019#include <stdplus/zstring.hpp>
Patrick Williams89d734b2023-05-10 07:50:25 -050020#include <xyz/openbmc_project/Common/error.hpp>
21
22#include <algorithm>
23#include <filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053024#include <string>
William A. Kennington III26275a32021-07-13 20:32:42 -070025#include <unordered_map>
26#include <variant>
Ratan Gupta82549cc2017-04-21 08:45:23 +053027
Ratan Gupta91a99cc2017-04-14 16:32:09 +053028namespace phosphor
29{
30namespace network
31{
32
33using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053034using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053035using NotAllowed = sdbusplus::xyz::openbmc_project::Common::Error::NotAllowed;
36using NotAllowedArgument = xyz::openbmc_project::Common::NotAllowed;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050037using Argument = xyz::openbmc_project::Common::InvalidArgument;
William A. Kennington III991a8e82022-10-11 15:02:47 -070038using std::literals::string_view_literals::operator""sv;
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053039constexpr auto RESOLVED_SERVICE = "org.freedesktop.resolve1";
40constexpr auto RESOLVED_INTERFACE = "org.freedesktop.resolve1.Link";
41constexpr auto PROPERTY_INTERFACE = "org.freedesktop.DBus.Properties";
42constexpr auto RESOLVED_SERVICE_PATH = "/org/freedesktop/resolve1/link/";
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -060043
44constexpr auto TIMESYNCD_SERVICE = "org.freedesktop.timesync1";
45constexpr auto TIMESYNCD_INTERFACE = "org.freedesktop.timesync1.Manager";
46constexpr auto TIMESYNCD_SERVICE_PATH = "/org/freedesktop/timesync1";
47
Manojkiran Edaacd6dd52019-10-15 15:00:51 +053048constexpr auto METHOD_GET = "Get";
Ratan Gupta2b106532017-07-25 16:05:02 +053049
William A. Kennington III2e09d272022-10-14 17:15:00 -070050template <typename Func>
51inline decltype(std::declval<Func>()())
52 ignoreError(std::string_view msg, stdplus::zstring_view intf,
53 decltype(std::declval<Func>()()) fallback, Func&& func) noexcept
William A. Kennington III5dad2aa2022-01-21 16:00:17 -080054{
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070055 try
56 {
William A. Kennington III2e09d272022-10-14 17:15:00 -070057 return func();
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070058 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070059 catch (const std::exception& e)
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070060 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -070061 lg2::error("{MSG} failed on {NET_INTF}: {ERROR}", "MSG", msg,
62 "NET_INTF", intf, "ERROR", e);
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070063 }
William A. Kennington III2e09d272022-10-14 17:15:00 -070064 return fallback;
William A. Kennington III4ee7a7e2022-10-11 16:37:22 -070065}
William A. Kennington IIId298f932022-10-17 14:31:38 -070066
William A. Kennington IIId298f932022-10-17 14:31:38 -070067static std::string makeObjPath(std::string_view root, std::string_view intf)
68{
69 auto ret = fmt::format(FMT_COMPILE("{}/{}"), root, intf);
70 std::replace(ret.begin() + ret.size() - intf.size(), ret.end(), '.', '_');
71 return ret;
72}
73
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -080074template <typename Addr>
75static bool validIntfIP(Addr a) noexcept
76{
77 return a.isUnicast() && !a.isLoopback();
78}
79
William A. Kennington III9ede1b72022-11-21 01:59:28 -080080EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
81 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080082 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070083 std::string_view objRoot,
William A. Kennington IIIa520a392022-08-08 12:17:34 -070084 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080085 bool enabled) :
William A. Kennington III13d665c2022-11-15 20:34:40 -080086 EthernetInterface(bus, manager, info, makeObjPath(objRoot, *info.intf.name),
William A. Kennington IIIb6452542022-11-15 18:09:12 -080087 config, enabled)
Patrick Williams89d734b2023-05-10 07:50:25 -050088{}
William A. Kennington IIId298f932022-10-17 14:31:38 -070089
William A. Kennington III9ede1b72022-11-21 01:59:28 -080090EthernetInterface::EthernetInterface(stdplus::PinnedRef<sdbusplus::bus_t> bus,
91 stdplus::PinnedRef<Manager> manager,
William A. Kennington III13d665c2022-11-15 20:34:40 -080092 const AllIntfInfo& info,
William A. Kennington IIId298f932022-10-17 14:31:38 -070093 std::string&& objPath,
94 const config::Parser& config,
William A. Kennington IIIb6452542022-11-15 18:09:12 -080095 bool enabled) :
96 Ifaces(bus, objPath.c_str(), Ifaces::action::defer_emit),
William A. Kennington III876927c2022-11-17 16:20:15 -080097 manager(manager), bus(bus), objPath(std::move(objPath))
Ratan Gupta91a99cc2017-04-14 16:32:09 +053098{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -080099 interfaceName(*info.intf.name, true);
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700100 auto dhcpVal = getDHCPValue(config);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800101 EthernetInterfaceIntf::dhcp4(dhcpVal.v4, true);
102 EthernetInterfaceIntf::dhcp6(dhcpVal.v6, true);
103 EthernetInterfaceIntf::ipv6AcceptRA(getIPv6AcceptRA(config), true);
104 EthernetInterfaceIntf::nicEnabled(enabled, true);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500105
William A. Kennington IIIe21a5cf2022-08-09 12:19:14 -0700106 EthernetInterfaceIntf::ntpServers(
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800107 config.map.getValueStrings("Network", "NTP"), true);
Ratan Gupta613a0122020-04-24 15:18:53 +0530108
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800109 updateInfo(info.intf, true);
110
111 if (info.defgw4)
112 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700113 EthernetInterface::defaultGateway(stdplus::toStr(*info.defgw4), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800114 }
115 if (info.defgw6)
116 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700117 EthernetInterface::defaultGateway6(stdplus::toStr(*info.defgw6), true);
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800118 }
119 emit_object_added();
William A. Kennington IIId298f932022-10-17 14:31:38 -0700120
William A. Kennington III13d665c2022-11-15 20:34:40 -0800121 if (info.intf.vlan_id)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700122 {
William A. Kennington III13d665c2022-11-15 20:34:40 -0800123 if (!info.intf.parent_idx)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700124 {
125 std::runtime_error("Missing parent link");
126 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800127 vlan.emplace(bus, this->objPath.c_str(), info.intf, *this);
128 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800129 for (const auto& [_, addr] : info.addrs)
130 {
131 addAddr(addr);
132 }
133 for (const auto& [_, neigh] : info.staticNeighs)
134 {
135 addStaticNeigh(neigh);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700136 }
Ratan Gupta29b0e432017-05-25 12:51:40 +0530137}
138
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800139void EthernetInterface::updateInfo(const InterfaceInfo& info, bool skipSignal)
William A. Kennington IIId298f932022-10-17 14:31:38 -0700140{
William A. Kennington III876927c2022-11-17 16:20:15 -0800141 ifIdx = info.idx;
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800142 EthernetInterfaceIntf::linkUp(info.flags & IFF_RUNNING, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700143 if (info.mac)
144 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700145 MacAddressIntf::macAddress(stdplus::toStr(*info.mac), skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700146 }
147 if (info.mtu)
148 {
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800149 EthernetInterfaceIntf::mtu(*info.mtu, skipSignal);
William A. Kennington IIId298f932022-10-17 14:31:38 -0700150 }
William A. Kennington III21539662022-11-15 14:53:11 -0800151 if (ifIdx > 0)
152 {
153 auto ethInfo = ignoreError("GetEthInfo", *info.name, {}, [&] {
154 return system::getEthInfo(*info.name);
155 });
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800156 EthernetInterfaceIntf::autoNeg(ethInfo.autoneg, skipSignal);
157 EthernetInterfaceIntf::speed(ethInfo.speed, skipSignal);
William A. Kennington III21539662022-11-15 14:53:11 -0800158 }
William A. Kennington IIId298f932022-10-17 14:31:38 -0700159}
160
Johnathan Mantey817012a2020-01-30 15:07:39 -0800161bool EthernetInterface::originIsManuallyAssigned(IP::AddressOrigin origin)
162{
163 return (
164#ifdef LINK_LOCAL_AUTOCONFIGURATION
Johnathan Mantey817012a2020-01-30 15:07:39 -0800165 (origin == IP::AddressOrigin::Static ||
166 origin == IP::AddressOrigin::LinkLocal)
Tim Lee721d8f752023-07-08 00:26:27 +0800167#else
168 (origin == IP::AddressOrigin::Static)
Johnathan Mantey817012a2020-01-30 15:07:39 -0800169#endif
170
171 );
172}
173
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800174void EthernetInterface::addAddr(const AddressInfo& info)
175{
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800176 IP::AddressOrigin origin = IP::AddressOrigin::Static;
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800177#ifdef LINK_LOCAL_AUTOCONFIGURATION
178 if (info.scope == RT_SCOPE_LINK)
179 {
180 origin = IP::AddressOrigin::LinkLocal;
181 }
182#endif
183
Ravi Tejac6201202023-03-28 21:29:58 -0500184 if ((info.scope == RT_SCOPE_UNIVERSE) && (info.flags & IFA_F_PERMANENT))
185 {
186 origin = IP::AddressOrigin::Static;
187 }
188 if ((info.scope == RT_SCOPE_UNIVERSE) &&
189 ((info.flags & IFA_F_NOPREFIXROUTE) &&
190 (info.flags & IFA_F_MANAGETEMPADDR)))
191 {
192 origin = IP::AddressOrigin::SLAAC;
193 }
194 else if ((info.scope == RT_SCOPE_UNIVERSE) &&
195 ((info.flags & IFA_F_NOPREFIXROUTE)))
196 {
197 origin = IP::AddressOrigin::DHCP;
198 }
199
William A. Kennington III77747f62022-11-07 23:11:15 -0800200 auto it = addrs.find(info.ifaddr);
201 if (it == addrs.end())
202 {
203 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
204 bus, std::string_view(objPath), *this,
205 info.ifaddr, origin));
206 }
207 else
208 {
209 it->second->IPIfaces::origin(origin);
210 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800211}
212
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800213void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
214{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800215 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800216 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700217 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700218 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800219 return;
220 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800221
222 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
223 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700224 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800225 }
226 else
227 {
228 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
229 bus, std::string_view(objPath),
230 *this, *info.addr, *info.mac,
231 Neighbor::State::Permanent));
232 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800233}
234
Patrick Williams6aef7692021-05-01 06:39:41 -0500235ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700236 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530237{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700238 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700239 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530240 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700241 switch (protType)
242 {
243 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700244 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700245 break;
246 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700247 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700248 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700249 default:
250 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700251 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700252 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
253 {
254 throw std::invalid_argument("not unicast");
255 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500256 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700257 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500258 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700259 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
260 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500261 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
262 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
263 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700264 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700265 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500266 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700267 if (prefixLength == 0)
268 {
269 throw std::invalid_argument("default route");
270 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700271 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700272 }
273 catch (const std::exception& e)
274 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700275 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
276 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500277 elog<InvalidArgument>(
278 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700279 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530280 }
281
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700282 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800283 if (it == addrs.end())
284 {
285 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700286 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800287 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700288 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800289 }
290 else
291 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800292 if (it->second->origin() == IP::AddressOrigin::Static)
293 {
294 return it->second->getObjPath();
295 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800296 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
297 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530298
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700299 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800300 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700301
William A. Kennington III434a9432022-11-04 18:38:46 -0700302 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530303}
304
Patrick Williams6aef7692021-05-01 06:39:41 -0500305ObjectPath EthernetInterface::neighbor(std::string ipAddress,
306 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800307{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700308 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700309 try
William A. Kennington III08505792019-01-30 16:00:04 -0800310 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700311 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700312 }
313 catch (const std::exception& e)
314 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700315 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700316 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500317 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
318 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800319 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700320
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700321 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700322 try
William A. Kennington III08505792019-01-30 16:00:04 -0800323 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700324 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700325 }
326 catch (const std::exception& e)
327 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700328 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
329 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500330 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
331 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800332 }
333
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700334 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800335 if (it == staticNeighbors.end())
336 {
337 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700338 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
339 *this, *addr, *lladdr,
340 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800341 }
342 else
343 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700344 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800345 if (it->second->macAddress() == str)
346 {
347 return it->second->getObjPath();
348 }
349 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800350 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700351
352 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800353 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700354
William A. Kennington III434a9432022-11-04 18:38:46 -0700355 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800356}
357
Patrick Williams6aef7692021-05-01 06:39:41 -0500358bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700359{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700360 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700361 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700362 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800363 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700364 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700365 return value;
366}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700367
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700368bool EthernetInterface::dhcp4(bool value)
369{
370 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
371 {
372 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800373 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700374 }
375 return value;
376}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700377
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700378bool EthernetInterface::dhcp6(bool value)
379{
380 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
381 {
382 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800383 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700384 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700385 return value;
386}
387
Patrick Williams6aef7692021-05-01 06:39:41 -0500388EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530389{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700390 auto old4 = EthernetInterfaceIntf::dhcp4();
391 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
392 value == DHCPConf::v4v6stateless ||
393 value == DHCPConf::both);
394 auto old6 = EthernetInterfaceIntf::dhcp6();
395 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
396 value == DHCPConf::both);
397 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
398 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
399 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
400 value == DHCPConf::v6 || value == DHCPConf::both);
401
402 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530403 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700404 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800405 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530406 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530407 return value;
408}
409
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700410EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
411{
412 if (dhcp6())
413 {
414 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
415 }
416 else if (dhcp4())
417 {
418 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
419 }
420 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
421}
422
Tejas Patil2c0fc562021-08-03 19:13:46 +0530423size_t EthernetInterface::mtu(size_t value)
424{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700425 const size_t old = EthernetInterfaceIntf::mtu();
426 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530427 {
428 return value;
429 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700430 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700431 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700432 system::setMTU(ifname, value);
433 return value;
434 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530435}
436
Patrick Williams6aef7692021-05-01 06:39:41 -0500437bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700438{
Patrick Williams6aef7692021-05-01 06:39:41 -0500439 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700440 {
441 return value;
442 }
443
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800444 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700445 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800446 if (!value)
447 {
448 // We only need to bring down the interface, networkd will always bring
449 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800450 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700451 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800452 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800453 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800454
455 return value;
456}
457
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530458ServerList EthernetInterface::staticNameServers(ServerList value)
459{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700460 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530461 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700462 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530463 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700464 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700465 }
466 catch (const std::exception& e)
467 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700468 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
469 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700470 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
471 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530472 }
473 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700474
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700475 value = EthernetInterfaceIntf::staticNameServers(std::move(value));
476
477 writeConfigurationFile();
478 manager.get().reloadConfigs();
479
480 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530481}
482
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600483void EthernetInterface::loadNTPServers(const config::Parser& config)
484{
485 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
486 EthernetInterfaceIntf::staticNTPServers(
487 config.map.getValueStrings("Network", "NTP"));
488}
489
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700490void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530491{
492 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700493 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700494 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530495}
496
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600497ServerList EthernetInterface::getNTPServerFromTimeSyncd()
498{
499 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500500 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
501 TIMESYNCD_SERVICE_PATH,
502 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600503
504 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
505
506 try
507 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800508 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600509 std::variant<ServerList> response;
510 reply.read(response);
511 servers = std::get<ServerList>(response);
512 }
513 catch (const sdbusplus::exception::SdBusError& e)
514 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700515 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700516 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700517 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600518 }
519
520 return servers;
521}
522
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530523ServerList EthernetInterface::getNameServerFromResolvd()
524{
525 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700526 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530527
528 /*
529 The DNS property under org.freedesktop.resolve1.Link interface contains
530 an array containing all DNS servers currently used by resolved. It
531 contains similar information as the DNS server data written to
532 /run/systemd/resolve/resolv.conf.
533
534 Each structure in the array consists of a numeric network interface index,
535 an address family, and a byte array containing the DNS server address
536 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
537 The array contains DNS servers configured system-wide, including those
538 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
539 /etc/systemd/resolved.conf, as well as per-interface DNS server
540 information either retrieved from systemd-networkd or configured by
541 external software via SetLinkDNS().
542 */
543
544 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
545 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800546 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
547 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530548
549 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530550
551 try
552 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800553 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530554 reply.read(name);
555 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500556 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530557 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700558 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700559 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700560 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530561 }
562 auto tupleVector = std::get_if<type>(&name);
563 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
564 {
Alexander Filippov983da552021-02-08 15:26:54 +0300565 int addressFamily = std::get<0>(*i);
566 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700567 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700568 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530569 }
570 return servers;
571}
572
William A. Kennington IIId298f932022-10-17 14:31:38 -0700573ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530574{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700575 auto idStr = stdplus::toStr(id);
576 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800577 if (manager.get().interfaces.find(intfName) !=
578 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800579 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700580 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700581 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
582 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800583 }
584
William A. Kennington IIId298f932022-10-17 14:31:38 -0700585 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700586 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700587 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700588 if (!macStr.empty())
589 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700590 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700591 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800592 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800593 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700594 .idx = 0, // TODO: Query the correct value after creation
595 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700596 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700597 .mac = std::move(mac),
598 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700599 .parent_idx = ifIdx,
600 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800601 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530602
Patrick Williams6aef7692021-05-01 06:39:41 -0500603 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530604 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700605 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800606 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700607 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530608
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800609 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530610
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700611 // write the device file for the vlan interface.
612 config::Parser config;
613 auto& netdev = config.map["NetDev"].emplace_back();
614 netdev["Name"].emplace_back(intfName);
615 netdev["Kind"].emplace_back("vlan");
616 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800617 config.writeFile(
618 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700619
620 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800621 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700622
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800623 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530624}
Ratan Gupta2b106532017-07-25 16:05:02 +0530625
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600626ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530627{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700628 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530629
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700630 writeConfigurationFile();
631 manager.get().reloadConfigs();
632
633 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600634}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700635
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600636ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
637{
638 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530639}
Ratan Gupta2b106532017-07-25 16:05:02 +0530640// Need to merge the below function with the code which writes the
641// config file during factory reset.
642// TODO openbmc/openbmc#1751
643
644void EthernetInterface::writeConfigurationFile()
645{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700646 config::Parser config;
647 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530648 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700649 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800650#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700651 auto mac = MacAddressIntf::macAddress();
652 if (!mac.empty())
653 {
654 link["MACAddress"].emplace_back(mac);
655 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800656#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700657 if (!EthernetInterfaceIntf::nicEnabled())
658 {
659 link["Unmanaged"].emplace_back("yes");
660 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700661 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700662 {
663 auto& network = config.map["Network"].emplace_back();
664 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400665#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700666 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400667#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700668 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400669#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700670 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
671 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
672 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600673 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700674 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800675 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700676 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700677 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
678 {
679 vlans.emplace_back(intf->interfaceName());
680 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700681 }
682 }
683 {
684 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600685 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700686 {
687 ntps.emplace_back(ntp);
688 }
689 }
690 {
691 auto& dnss = network["DNS"];
692 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
693 {
694 dnss.emplace_back(dns);
695 }
696 }
697 {
698 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700699 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700700 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700701 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700702 {
703 address.emplace_back(
704 fmt::format("{}/{}", addr.second->address(),
705 addr.second->prefixLength()));
706 }
707 }
708 }
709 {
710 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700711 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700712 {
713 auto gateway = EthernetInterfaceIntf::defaultGateway();
714 if (!gateway.empty())
715 {
716 gateways.emplace_back(gateway);
717 }
718 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530719
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700720 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700721 {
722 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
723 if (!gateway6.empty())
724 {
725 gateways.emplace_back(gateway6);
726 }
727 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600728 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800729 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700730 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700731 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500732 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700733 auto& neighbors = config.map["Neighbor"];
734 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800735 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700736 auto& neighbor = neighbors.emplace_back();
737 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
738 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800739 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500740 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500741 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700742 auto& dhcp = config.map["DHCP"].emplace_back();
743 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800744 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800745 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
746 dhcp["UseDNS"].emplace_back(dns_enabled);
747 dhcp["UseDomains"].emplace_back(dns_enabled);
748 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
749 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
750 : "false");
751 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
752 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500753 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500754 auto path = config::pathForIntfConf(manager.get().getConfDir(),
755 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700756 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700757 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530758}
759
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800760std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530761{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700762 if (vlan)
763 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700764 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700765 elog<InternalFailure>();
766 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800767#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700768 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600769 try
770 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700771 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600772 }
Patrick Williams5758db32021-10-06 12:29:22 -0500773 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600774 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700775 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600776 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
777 Argument::ARGUMENT_VALUE(value.c_str()));
778 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700779 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530780 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700781 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500782 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
783 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530784 }
785
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300786 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700787 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300788
William A. Kennington III1137a972019-04-20 20:49:58 -0700789 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700790 auto oldMAC =
791 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700792 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530793 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700794 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800795 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530796 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700797 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
798 {
799 intf->MacAddressIntf::macAddress(validMAC);
800 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530801 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500802 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530803
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700804 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800805 manager.get().addReloadPreHook([interface]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800806 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700807 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800808 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800809 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530810 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700811
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300812#ifdef HAVE_UBOOT_ENV
813 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700814 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300815 if (envVar)
816 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500817 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
818 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
819 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
820 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300821 }
822#endif // HAVE_UBOOT_ENV
823
William A. Kennington III1137a972019-04-20 20:49:58 -0700824 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800825#else
826 elog<NotAllowed>(
827 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
828#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530829}
830
Ratan Guptae9c9b812017-09-22 17:15:37 +0530831void EthernetInterface::deleteAll()
832{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530833 // clear all the ip on the interface
834 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700835
836 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800837 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530838}
839
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800840template <typename Addr>
841static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500842{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800843 if (gw.empty())
844 {
845 return;
846 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700847 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500848 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800849 auto ip = stdplus::fromStr<Addr>(gw);
850 if (ip == Addr{})
851 {
852 gw.clear();
853 return;
854 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800855 if (!validIntfIP(ip))
856 {
857 throw std::invalid_argument("Invalid unicast");
858 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800859 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500860 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700861 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500862 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800863 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500864 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800865 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500866 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800867}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700868
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800869std::string EthernetInterface::defaultGateway(std::string gateway)
870{
871 normalizeGateway<stdplus::In4Addr>(gateway);
872 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700873 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800874 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
875 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700876 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700877 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500878}
879
880std::string EthernetInterface::defaultGateway6(std::string gateway)
881{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800882 normalizeGateway<stdplus::In6Addr>(gateway);
883 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500884 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800885 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
886 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500887 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700888 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500889}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700890
891EthernetInterface::VlanProperties::VlanProperties(
892 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800893 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800894 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700895 parentIdx(*info.parent_idx), eth(eth)
896{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800897 VlanIntf::id(*info.vlan_id, true);
898 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700899}
900
901void EthernetInterface::VlanProperties::delete_()
902{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800903 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700904
905 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800906 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700907 std::error_code ec;
908 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
909 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
910
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800911 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800912 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800913 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800914 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800915 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800916 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800917 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800918
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700919 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800920 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700921 {
922 if (intf->ifIdx == parentIdx)
923 {
924 intf->writeConfigurationFile();
925 }
926 }
927
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800928 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700929 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800930 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800931 eth.get().manager.get().addReloadPostHook(
932 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800933
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800934 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800935 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700936 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800937
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800938 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700939}
940
Gunnar Mills57d9c502018-09-14 14:42:34 -0500941} // namespace network
942} // namespace phosphor