blob: a577c2a0fcb0aecd36cb977be3ead0092ce886cc [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
165 (origin == IP::AddressOrigin::Static)
166#else
167 (origin == IP::AddressOrigin::Static ||
168 origin == IP::AddressOrigin::LinkLocal)
169#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;
177 if (dhcpIsEnabled(info.ifaddr.getAddr()))
178 {
179 origin = IP::AddressOrigin::DHCP;
180 }
181#ifdef LINK_LOCAL_AUTOCONFIGURATION
182 if (info.scope == RT_SCOPE_LINK)
183 {
184 origin = IP::AddressOrigin::LinkLocal;
185 }
186#endif
187
William A. Kennington III77747f62022-11-07 23:11:15 -0800188 auto it = addrs.find(info.ifaddr);
189 if (it == addrs.end())
190 {
191 addrs.emplace(info.ifaddr, std::make_unique<IPAddress>(
192 bus, std::string_view(objPath), *this,
193 info.ifaddr, origin));
194 }
195 else
196 {
197 it->second->IPIfaces::origin(origin);
198 }
William A. Kennington IIId6f53402022-11-07 14:48:53 -0800199}
200
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800201void EthernetInterface::addStaticNeigh(const NeighborInfo& info)
202{
William A. Kennington IIId3615142022-11-12 01:28:33 -0800203 if (!info.mac || !info.addr)
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800204 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700205 lg2::error("Missing neighbor mac on {NET_INTF}", "NET_INTF",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700206 interfaceName());
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800207 return;
208 }
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800209
210 if (auto it = staticNeighbors.find(*info.addr); it != staticNeighbors.end())
211 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700212 it->second->NeighborObj::macAddress(stdplus::toStr(*info.mac));
William A. Kennington III4e75acc2022-11-14 19:13:31 -0800213 }
214 else
215 {
216 staticNeighbors.emplace(*info.addr, std::make_unique<Neighbor>(
217 bus, std::string_view(objPath),
218 *this, *info.addr, *info.mac,
219 Neighbor::State::Permanent));
220 }
William A. Kennington IIIbc2502c2022-11-07 16:31:54 -0800221}
222
Patrick Williams6aef7692021-05-01 06:39:41 -0500223ObjectPath EthernetInterface::ip(IP::Protocol protType, std::string ipaddress,
William A. Kennington IIIe25f8b42022-10-11 14:43:28 -0700224 uint8_t prefixLength, std::string)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530225{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700226 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700227 try
Ratan Guptafc2c7242017-05-29 08:46:06 +0530228 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700229 switch (protType)
230 {
231 case IP::Protocol::IPv4:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700232 addr.emplace(stdplus::fromStr<stdplus::In4Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700233 break;
234 case IP::Protocol::IPv6:
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700235 addr.emplace(stdplus::fromStr<stdplus::In6Addr>(ipaddress));
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700236 break;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700237 default:
238 throw std::logic_error("Exhausted protocols");
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700239 }
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700240 if (!std::visit([](auto ip) { return validIntfIP(ip); }, *addr))
241 {
242 throw std::invalid_argument("not unicast");
243 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500244 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700245 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500246 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700247 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
248 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500249 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
250 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
251 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700252 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700253 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500254 {
William A. Kennington III30f3ba22023-06-28 15:50:12 -0700255 if (prefixLength == 0)
256 {
257 throw std::invalid_argument("default route");
258 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700259 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700260 }
261 catch (const std::exception& e)
262 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700263 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
264 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500265 elog<InvalidArgument>(
266 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700267 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530268 }
269
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700270 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800271 if (it == addrs.end())
272 {
273 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700274 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800275 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700276 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800277 }
278 else
279 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800280 if (it->second->origin() == IP::AddressOrigin::Static)
281 {
282 return it->second->getObjPath();
283 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800284 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
285 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530286
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700287 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800288 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700289
William A. Kennington III434a9432022-11-04 18:38:46 -0700290 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530291}
292
Patrick Williams6aef7692021-05-01 06:39:41 -0500293ObjectPath EthernetInterface::neighbor(std::string ipAddress,
294 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800295{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700296 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700297 try
William A. Kennington III08505792019-01-30 16:00:04 -0800298 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700299 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700300 }
301 catch (const std::exception& e)
302 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700303 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700304 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500305 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
306 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800307 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700308
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700309 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700310 try
William A. Kennington III08505792019-01-30 16:00:04 -0800311 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700312 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700313 }
314 catch (const std::exception& e)
315 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700316 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
317 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500318 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
319 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800320 }
321
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700322 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800323 if (it == staticNeighbors.end())
324 {
325 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700326 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
327 *this, *addr, *lladdr,
328 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800329 }
330 else
331 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700332 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800333 if (it->second->macAddress() == str)
334 {
335 return it->second->getObjPath();
336 }
337 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800338 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700339
340 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800341 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700342
William A. Kennington III434a9432022-11-04 18:38:46 -0700343 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800344}
345
Patrick Williams6aef7692021-05-01 06:39:41 -0500346bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700347{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700348 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700349 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700350 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800351 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700352 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700353 return value;
354}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700355
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700356bool EthernetInterface::dhcp4(bool value)
357{
358 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
359 {
360 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800361 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700362 }
363 return value;
364}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700365
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700366bool EthernetInterface::dhcp6(bool value)
367{
368 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
369 {
370 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800371 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700372 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700373 return value;
374}
375
Patrick Williams6aef7692021-05-01 06:39:41 -0500376EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530377{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700378 auto old4 = EthernetInterfaceIntf::dhcp4();
379 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
380 value == DHCPConf::v4v6stateless ||
381 value == DHCPConf::both);
382 auto old6 = EthernetInterfaceIntf::dhcp6();
383 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
384 value == DHCPConf::both);
385 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
386 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
387 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
388 value == DHCPConf::v6 || value == DHCPConf::both);
389
390 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530391 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700392 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800393 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530394 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530395 return value;
396}
397
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700398EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
399{
400 if (dhcp6())
401 {
402 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
403 }
404 else if (dhcp4())
405 {
406 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
407 }
408 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
409}
410
Tejas Patil2c0fc562021-08-03 19:13:46 +0530411size_t EthernetInterface::mtu(size_t value)
412{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700413 const size_t old = EthernetInterfaceIntf::mtu();
414 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530415 {
416 return value;
417 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700418 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700419 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700420 system::setMTU(ifname, value);
421 return value;
422 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530423}
424
Patrick Williams6aef7692021-05-01 06:39:41 -0500425bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700426{
Patrick Williams6aef7692021-05-01 06:39:41 -0500427 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700428 {
429 return value;
430 }
431
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800432 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700433 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800434 if (!value)
435 {
436 // We only need to bring down the interface, networkd will always bring
437 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800438 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700439 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800440 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800441 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800442
443 return value;
444}
445
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530446ServerList EthernetInterface::staticNameServers(ServerList value)
447{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700448 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530449 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700450 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530451 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700452 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700453 }
454 catch (const std::exception& e)
455 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700456 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
457 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700458 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
459 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530460 }
461 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700462
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700463 value = EthernetInterfaceIntf::staticNameServers(std::move(value));
464
465 writeConfigurationFile();
466 manager.get().reloadConfigs();
467
468 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530469}
470
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600471void EthernetInterface::loadNTPServers(const config::Parser& config)
472{
473 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
474 EthernetInterfaceIntf::staticNTPServers(
475 config.map.getValueStrings("Network", "NTP"));
476}
477
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700478void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530479{
480 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700481 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700482 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530483}
484
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600485ServerList EthernetInterface::getNTPServerFromTimeSyncd()
486{
487 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500488 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
489 TIMESYNCD_SERVICE_PATH,
490 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600491
492 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
493
494 try
495 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800496 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600497 std::variant<ServerList> response;
498 reply.read(response);
499 servers = std::get<ServerList>(response);
500 }
501 catch (const sdbusplus::exception::SdBusError& e)
502 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700503 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700504 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700505 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600506 }
507
508 return servers;
509}
510
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530511ServerList EthernetInterface::getNameServerFromResolvd()
512{
513 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700514 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530515
516 /*
517 The DNS property under org.freedesktop.resolve1.Link interface contains
518 an array containing all DNS servers currently used by resolved. It
519 contains similar information as the DNS server data written to
520 /run/systemd/resolve/resolv.conf.
521
522 Each structure in the array consists of a numeric network interface index,
523 an address family, and a byte array containing the DNS server address
524 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
525 The array contains DNS servers configured system-wide, including those
526 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
527 /etc/systemd/resolved.conf, as well as per-interface DNS server
528 information either retrieved from systemd-networkd or configured by
529 external software via SetLinkDNS().
530 */
531
532 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
533 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800534 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
535 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530536
537 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530538
539 try
540 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800541 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530542 reply.read(name);
543 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500544 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530545 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700546 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700547 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700548 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530549 }
550 auto tupleVector = std::get_if<type>(&name);
551 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
552 {
Alexander Filippov983da552021-02-08 15:26:54 +0300553 int addressFamily = std::get<0>(*i);
554 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700555 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700556 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530557 }
558 return servers;
559}
560
William A. Kennington IIId298f932022-10-17 14:31:38 -0700561ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530562{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700563 auto idStr = stdplus::toStr(id);
564 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800565 if (manager.get().interfaces.find(intfName) !=
566 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800567 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700568 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700569 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
570 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800571 }
572
William A. Kennington IIId298f932022-10-17 14:31:38 -0700573 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700574 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700575 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700576 if (!macStr.empty())
577 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700578 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700579 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800580 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800581 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700582 .idx = 0, // TODO: Query the correct value after creation
583 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700584 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700585 .mac = std::move(mac),
586 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700587 .parent_idx = ifIdx,
588 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800589 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530590
Patrick Williams6aef7692021-05-01 06:39:41 -0500591 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530592 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700593 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800594 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700595 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530596
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800597 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530598
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700599 // write the device file for the vlan interface.
600 config::Parser config;
601 auto& netdev = config.map["NetDev"].emplace_back();
602 netdev["Name"].emplace_back(intfName);
603 netdev["Kind"].emplace_back("vlan");
604 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800605 config.writeFile(
606 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700607
608 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800609 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700610
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800611 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530612}
Ratan Gupta2b106532017-07-25 16:05:02 +0530613
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600614ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530615{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700616 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530617
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700618 writeConfigurationFile();
619 manager.get().reloadConfigs();
620
621 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600622}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700623
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600624ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
625{
626 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530627}
Ratan Gupta2b106532017-07-25 16:05:02 +0530628// Need to merge the below function with the code which writes the
629// config file during factory reset.
630// TODO openbmc/openbmc#1751
631
632void EthernetInterface::writeConfigurationFile()
633{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700634 config::Parser config;
635 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530636 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700637 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800638#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700639 auto mac = MacAddressIntf::macAddress();
640 if (!mac.empty())
641 {
642 link["MACAddress"].emplace_back(mac);
643 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800644#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700645 if (!EthernetInterfaceIntf::nicEnabled())
646 {
647 link["Unmanaged"].emplace_back("yes");
648 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700649 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700650 {
651 auto& network = config.map["Network"].emplace_back();
652 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400653#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700654 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400655#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700656 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400657#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700658 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
659 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
660 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600661 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700662 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800663 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700664 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700665 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
666 {
667 vlans.emplace_back(intf->interfaceName());
668 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700669 }
670 }
671 {
672 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600673 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700674 {
675 ntps.emplace_back(ntp);
676 }
677 }
678 {
679 auto& dnss = network["DNS"];
680 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
681 {
682 dnss.emplace_back(dns);
683 }
684 }
685 {
686 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700687 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700688 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700689 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700690 {
691 address.emplace_back(
692 fmt::format("{}/{}", addr.second->address(),
693 addr.second->prefixLength()));
694 }
695 }
696 }
697 {
698 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700699 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700700 {
701 auto gateway = EthernetInterfaceIntf::defaultGateway();
702 if (!gateway.empty())
703 {
704 gateways.emplace_back(gateway);
705 }
706 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530707
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700708 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700709 {
710 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
711 if (!gateway6.empty())
712 {
713 gateways.emplace_back(gateway6);
714 }
715 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600716 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800717 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700718 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700719 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500720 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700721 auto& neighbors = config.map["Neighbor"];
722 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800723 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700724 auto& neighbor = neighbors.emplace_back();
725 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
726 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800727 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500728 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500729 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700730 auto& dhcp = config.map["DHCP"].emplace_back();
731 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800732 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800733 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
734 dhcp["UseDNS"].emplace_back(dns_enabled);
735 dhcp["UseDomains"].emplace_back(dns_enabled);
736 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
737 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
738 : "false");
739 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
740 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500741 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500742 auto path = config::pathForIntfConf(manager.get().getConfDir(),
743 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700744 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700745 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530746}
747
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800748std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530749{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700750 if (vlan)
751 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700752 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700753 elog<InternalFailure>();
754 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800755#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700756 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600757 try
758 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700759 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600760 }
Patrick Williams5758db32021-10-06 12:29:22 -0500761 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600762 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700763 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600764 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
765 Argument::ARGUMENT_VALUE(value.c_str()));
766 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700767 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530768 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700769 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500770 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
771 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530772 }
773
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300774 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700775 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300776
William A. Kennington III1137a972019-04-20 20:49:58 -0700777 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700778 auto oldMAC =
779 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700780 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530781 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700782 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800783 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530784 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700785 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
786 {
787 intf->MacAddressIntf::macAddress(validMAC);
788 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530789 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500790 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530791
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700792 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800793 manager.get().addReloadPreHook([interface]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800794 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700795 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800796 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800797 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530798 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700799
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300800#ifdef HAVE_UBOOT_ENV
801 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700802 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300803 if (envVar)
804 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500805 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
806 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
807 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
808 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300809 }
810#endif // HAVE_UBOOT_ENV
811
William A. Kennington III1137a972019-04-20 20:49:58 -0700812 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800813#else
814 elog<NotAllowed>(
815 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
816#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530817}
818
Ratan Guptae9c9b812017-09-22 17:15:37 +0530819void EthernetInterface::deleteAll()
820{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530821 // clear all the ip on the interface
822 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700823
824 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800825 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530826}
827
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800828template <typename Addr>
829static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500830{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800831 if (gw.empty())
832 {
833 return;
834 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700835 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500836 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800837 auto ip = stdplus::fromStr<Addr>(gw);
838 if (ip == Addr{})
839 {
840 gw.clear();
841 return;
842 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800843 if (!validIntfIP(ip))
844 {
845 throw std::invalid_argument("Invalid unicast");
846 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800847 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500848 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700849 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500850 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800851 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500852 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800853 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500854 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800855}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700856
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800857std::string EthernetInterface::defaultGateway(std::string gateway)
858{
859 normalizeGateway<stdplus::In4Addr>(gateway);
860 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700861 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800862 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
863 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700864 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700865 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500866}
867
868std::string EthernetInterface::defaultGateway6(std::string gateway)
869{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800870 normalizeGateway<stdplus::In6Addr>(gateway);
871 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500872 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800873 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
874 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500875 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700876 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500877}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700878
879EthernetInterface::VlanProperties::VlanProperties(
880 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800881 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800882 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700883 parentIdx(*info.parent_idx), eth(eth)
884{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800885 VlanIntf::id(*info.vlan_id, true);
886 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700887}
888
889void EthernetInterface::VlanProperties::delete_()
890{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800891 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700892
893 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800894 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700895 std::error_code ec;
896 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
897 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
898
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800899 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800900 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800901 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800902 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800903 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800904 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800905 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800906
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700907 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800908 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700909 {
910 if (intf->ifIdx == parentIdx)
911 {
912 intf->writeConfigurationFile();
913 }
914 }
915
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800916 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700917 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800918 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800919 eth.get().manager.get().addReloadPostHook(
920 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800921
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800922 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800923 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700924 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800925
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800926 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700927}
928
Gunnar Mills57d9c502018-09-14 14:42:34 -0500929} // namespace network
930} // namespace phosphor