blob: 3374c6f7f6c5ac6d68e5f094342a74821b92b5a7 [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 }
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500240 }
William A. Kennington III59e5b912022-11-02 02:49:46 -0700241 catch (const std::exception& e)
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500242 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700243 lg2::error("Invalid IP {NET_IP}: {ERROR}", "NET_IP", ipaddress, "ERROR",
244 e);
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500245 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
246 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
247 }
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700248 std::optional<stdplus::SubnetAny> ifaddr;
William A. Kennington III59e5b912022-11-02 02:49:46 -0700249 try
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500250 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700251 ifaddr.emplace(*addr, prefixLength);
William A. Kennington III59e5b912022-11-02 02:49:46 -0700252 }
253 catch (const std::exception& e)
254 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700255 lg2::error("Invalid prefix length {NET_PFX}: {ERROR}", "NET_PFX",
256 prefixLength, "ERROR", e);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500257 elog<InvalidArgument>(
258 Argument::ARGUMENT_NAME("prefixLength"),
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700259 Argument::ARGUMENT_VALUE(stdplus::toStr(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530260 }
261
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700262 auto it = addrs.find(*ifaddr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800263 if (it == addrs.end())
264 {
265 it = std::get<0>(addrs.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700266 *ifaddr,
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800267 std::make_unique<IPAddress>(bus, std::string_view(objPath), *this,
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700268 *ifaddr, IP::AddressOrigin::Static)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800269 }
270 else
271 {
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800272 if (it->second->origin() == IP::AddressOrigin::Static)
273 {
274 return it->second->getObjPath();
275 }
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800276 it->second->IPIfaces::origin(IP::AddressOrigin::Static);
277 }
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530278
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700279 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800280 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700281
William A. Kennington III434a9432022-11-04 18:38:46 -0700282 return it->second->getObjPath();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530283}
284
Patrick Williams6aef7692021-05-01 06:39:41 -0500285ObjectPath EthernetInterface::neighbor(std::string ipAddress,
286 std::string macAddress)
William A. Kennington III08505792019-01-30 16:00:04 -0800287{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700288 std::optional<stdplus::InAnyAddr> addr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700289 try
William A. Kennington III08505792019-01-30 16:00:04 -0800290 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700291 addr.emplace(stdplus::fromStr<stdplus::InAnyAddr>(ipAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700292 }
293 catch (const std::exception& e)
294 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700295 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700296 ipAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500297 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipAddress"),
298 Argument::ARGUMENT_VALUE(ipAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800299 }
William A. Kennington III434a9432022-11-04 18:38:46 -0700300
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700301 std::optional<stdplus::EtherAddr> lladdr;
William A. Kennington III434a9432022-11-04 18:38:46 -0700302 try
William A. Kennington III08505792019-01-30 16:00:04 -0800303 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700304 lladdr.emplace(stdplus::fromStr<stdplus::EtherAddr>(macAddress));
William A. Kennington III434a9432022-11-04 18:38:46 -0700305 }
306 catch (const std::exception& e)
307 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700308 lg2::error("Not a valid MAC address {NET_MAC}: {ERROR}", "NET_MAC",
309 macAddress, "ERROR", e);
Patrick Williams6aef7692021-05-01 06:39:41 -0500310 elog<InvalidArgument>(Argument::ARGUMENT_NAME("macAddress"),
311 Argument::ARGUMENT_VALUE(macAddress.c_str()));
William A. Kennington III08505792019-01-30 16:00:04 -0800312 }
313
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700314 auto it = staticNeighbors.find(*addr);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800315 if (it == staticNeighbors.end())
316 {
317 it = std::get<0>(staticNeighbors.emplace(
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700318 *addr, std::make_unique<Neighbor>(bus, std::string_view(objPath),
319 *this, *addr, *lladdr,
320 Neighbor::State::Permanent)));
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800321 }
322 else
323 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700324 auto str = stdplus::toStr(*lladdr);
William A. Kennington IIIadd08712022-11-17 16:31:19 -0800325 if (it->second->macAddress() == str)
326 {
327 return it->second->getObjPath();
328 }
329 it->second->NeighborObj::macAddress(str);
William A. Kennington IIIa429c9d2022-11-15 18:00:45 -0800330 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700331
332 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800333 manager.get().reloadConfigs();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700334
William A. Kennington III434a9432022-11-04 18:38:46 -0700335 return it->second->getObjPath();
William A. Kennington III08505792019-01-30 16:00:04 -0800336}
337
Patrick Williams6aef7692021-05-01 06:39:41 -0500338bool EthernetInterface::ipv6AcceptRA(bool value)
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700339{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700340 if (ipv6AcceptRA() != EthernetInterfaceIntf::ipv6AcceptRA(value))
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700341 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700342 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800343 manager.get().reloadConfigs();
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700344 }
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700345 return value;
346}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700347
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700348bool EthernetInterface::dhcp4(bool value)
349{
350 if (dhcp4() != EthernetInterfaceIntf::dhcp4(value))
351 {
352 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800353 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700354 }
355 return value;
356}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700357
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700358bool EthernetInterface::dhcp6(bool value)
359{
360 if (dhcp6() != EthernetInterfaceIntf::dhcp6(value))
361 {
362 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800363 manager.get().reloadConfigs();
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700364 }
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700365 return value;
366}
367
Patrick Williams6aef7692021-05-01 06:39:41 -0500368EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled(DHCPConf value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530369{
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700370 auto old4 = EthernetInterfaceIntf::dhcp4();
371 auto new4 = EthernetInterfaceIntf::dhcp4(value == DHCPConf::v4 ||
372 value == DHCPConf::v4v6stateless ||
373 value == DHCPConf::both);
374 auto old6 = EthernetInterfaceIntf::dhcp6();
375 auto new6 = EthernetInterfaceIntf::dhcp6(value == DHCPConf::v6 ||
376 value == DHCPConf::both);
377 auto oldra = EthernetInterfaceIntf::ipv6AcceptRA();
378 auto newra = EthernetInterfaceIntf::ipv6AcceptRA(
379 value == DHCPConf::v6stateless || value == DHCPConf::v4v6stateless ||
380 value == DHCPConf::v6 || value == DHCPConf::both);
381
382 if (old4 != new4 || old6 != new6 || oldra != newra)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530383 {
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700384 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800385 manager.get().reloadConfigs();
Ratan Gupta5978dd12017-07-25 13:47:13 +0530386 }
Ratan Gupta87c13982017-06-15 09:27:27 +0530387 return value;
388}
389
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700390EthernetInterface::DHCPConf EthernetInterface::dhcpEnabled() const
391{
392 if (dhcp6())
393 {
394 return dhcp4() ? DHCPConf::both : DHCPConf::v6;
395 }
396 else if (dhcp4())
397 {
398 return ipv6AcceptRA() ? DHCPConf::v4v6stateless : DHCPConf::v4;
399 }
400 return ipv6AcceptRA() ? DHCPConf::v6stateless : DHCPConf::none;
401}
402
Tejas Patil2c0fc562021-08-03 19:13:46 +0530403size_t EthernetInterface::mtu(size_t value)
404{
William A. Kennington III2e09d272022-10-14 17:15:00 -0700405 const size_t old = EthernetInterfaceIntf::mtu();
406 if (value == old)
Tejas Patil2c0fc562021-08-03 19:13:46 +0530407 {
408 return value;
409 }
William A. Kennington III2e09d272022-10-14 17:15:00 -0700410 const auto ifname = interfaceName();
William A. Kennington III3e471c52022-10-27 19:46:07 -0700411 return EthernetInterfaceIntf::mtu(ignoreError("SetMTU", ifname, old, [&] {
William A. Kennington III2e09d272022-10-14 17:15:00 -0700412 system::setMTU(ifname, value);
413 return value;
414 }));
Tejas Patil2c0fc562021-08-03 19:13:46 +0530415}
416
Patrick Williams6aef7692021-05-01 06:39:41 -0500417bool EthernetInterface::nicEnabled(bool value)
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700418{
Patrick Williams6aef7692021-05-01 06:39:41 -0500419 if (value == EthernetInterfaceIntf::nicEnabled())
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700420 {
421 return value;
422 }
423
William A. Kennington IIIc922d5e2022-01-21 01:08:31 -0800424 EthernetInterfaceIntf::nicEnabled(value);
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700425 writeConfigurationFile();
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800426 if (!value)
427 {
428 // We only need to bring down the interface, networkd will always bring
429 // up managed interfaces
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800430 manager.get().addReloadPreHook(
William A. Kennington III2e09d272022-10-14 17:15:00 -0700431 [ifname = interfaceName()]() { system::setNICUp(ifname, false); });
William A. Kennington III329b5fb2021-11-09 17:19:30 -0800432 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800433 manager.get().reloadConfigs();
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800434
435 return value;
436}
437
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530438ServerList EthernetInterface::staticNameServers(ServerList value)
439{
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700440 for (auto& ip : value)
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530441 {
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700442 try
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530443 {
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700444 ip = stdplus::toStr(stdplus::fromStr<stdplus::InAnyAddr>(ip));
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700445 }
446 catch (const std::exception& e)
447 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700448 lg2::error("Not a valid IP address {NET_IP}: {ERROR}", "NET_IP", ip,
449 "ERROR", e);
William A. Kennington IIIc9f672e2022-11-04 14:35:53 -0700450 elog<InvalidArgument>(Argument::ARGUMENT_NAME("StaticNameserver"),
451 Argument::ARGUMENT_VALUE(ip.c_str()));
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530452 }
453 }
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700454
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700455 value = EthernetInterfaceIntf::staticNameServers(std::move(value));
456
457 writeConfigurationFile();
458 manager.get().reloadConfigs();
459
460 return value;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530461}
462
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600463void EthernetInterface::loadNTPServers(const config::Parser& config)
464{
465 EthernetInterfaceIntf::ntpServers(getNTPServerFromTimeSyncd());
466 EthernetInterfaceIntf::staticNTPServers(
467 config.map.getValueStrings("Network", "NTP"));
468}
469
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700470void EthernetInterface::loadNameServers(const config::Parser& config)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530471{
472 EthernetInterfaceIntf::nameservers(getNameServerFromResolvd());
William A. Kennington IIIa520a392022-08-08 12:17:34 -0700473 EthernetInterfaceIntf::staticNameServers(
William A. Kennington III34bb3e22022-08-18 15:17:22 -0700474 config.map.getValueStrings("Network", "DNS"));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530475}
476
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600477ServerList EthernetInterface::getNTPServerFromTimeSyncd()
478{
479 ServerList servers; // Variable to capture the NTP Server IPs
Patrick Williams89d734b2023-05-10 07:50:25 -0500480 auto method = bus.get().new_method_call(TIMESYNCD_SERVICE,
481 TIMESYNCD_SERVICE_PATH,
482 PROPERTY_INTERFACE, METHOD_GET);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600483
484 method.append(TIMESYNCD_INTERFACE, "LinkNTPServers");
485
486 try
487 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800488 auto reply = bus.get().call(method);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600489 std::variant<ServerList> response;
490 reply.read(response);
491 servers = std::get<ServerList>(response);
492 }
493 catch (const sdbusplus::exception::SdBusError& e)
494 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700495 lg2::error("Failed to get NTP server information from "
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700496 "systemd-timesyncd: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700497 "ERROR", e);
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600498 }
499
500 return servers;
501}
502
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530503ServerList EthernetInterface::getNameServerFromResolvd()
504{
505 ServerList servers;
William A. Kennington III2e09d272022-10-14 17:15:00 -0700506 auto OBJ_PATH = fmt::format("{}{}", RESOLVED_SERVICE_PATH, ifIdx);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530507
508 /*
509 The DNS property under org.freedesktop.resolve1.Link interface contains
510 an array containing all DNS servers currently used by resolved. It
511 contains similar information as the DNS server data written to
512 /run/systemd/resolve/resolv.conf.
513
514 Each structure in the array consists of a numeric network interface index,
515 an address family, and a byte array containing the DNS server address
516 (either 4 bytes in length for IPv4 or 16 bytes in lengths for IPv6).
517 The array contains DNS servers configured system-wide, including those
518 possibly read from a foreign /etc/resolv.conf or the DNS= setting in
519 /etc/systemd/resolved.conf, as well as per-interface DNS server
520 information either retrieved from systemd-networkd or configured by
521 external software via SetLinkDNS().
522 */
523
524 using type = std::vector<std::tuple<int32_t, std::vector<uint8_t>>>;
525 std::variant<type> name; // Variable to capture the DNS property
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800526 auto method = bus.get().new_method_call(RESOLVED_SERVICE, OBJ_PATH.c_str(),
527 PROPERTY_INTERFACE, METHOD_GET);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530528
529 method.append(RESOLVED_INTERFACE, "DNS");
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530530
531 try
532 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800533 auto reply = bus.get().call(method);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530534 reply.read(name);
535 }
Patrick Williamsc38b0712022-07-22 19:26:54 -0500536 catch (const sdbusplus::exception_t& e)
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530537 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700538 lg2::error(
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700539 "Failed to get DNS information from systemd-resolved: {ERROR}",
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700540 "ERROR", e);
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530541 }
542 auto tupleVector = std::get_if<type>(&name);
543 for (auto i = tupleVector->begin(); i != tupleVector->end(); ++i)
544 {
Alexander Filippov983da552021-02-08 15:26:54 +0300545 int addressFamily = std::get<0>(*i);
546 std::vector<uint8_t>& ipaddress = std::get<1>(*i);
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700547 servers.push_back(stdplus::toStr(
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700548 addrFromBuf(addressFamily, stdplus::raw::asView<char>(ipaddress))));
Manojkiran Edaacd6dd52019-10-15 15:00:51 +0530549 }
550 return servers;
551}
552
William A. Kennington IIId298f932022-10-17 14:31:38 -0700553ObjectPath EthernetInterface::createVLAN(uint16_t id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530554{
William A. Kennington III9b2a20d2023-06-17 14:05:48 -0700555 auto idStr = stdplus::toStr(id);
556 auto intfName = fmt::format(FMT_COMPILE("{}.{}"), interfaceName(), idStr);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800557 if (manager.get().interfaces.find(intfName) !=
558 manager.get().interfaces.end())
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800559 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700560 lg2::error("VLAN {NET_VLAN} already exists", "NET_VLAN", id);
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700561 elog<InvalidArgument>(Argument::ARGUMENT_NAME("VLANId"),
562 Argument::ARGUMENT_VALUE(idStr.c_str()));
Jiaqing Zhao33b4eaa2022-04-12 23:11:40 +0800563 }
564
William A. Kennington IIId298f932022-10-17 14:31:38 -0700565 auto objRoot = std::string_view(objPath).substr(0, objPath.rfind('/'));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700566 auto macStr = MacAddressIntf::macAddress();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700567 std::optional<stdplus::EtherAddr> mac;
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700568 if (!macStr.empty())
569 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700570 mac.emplace(stdplus::fromStr<stdplus::EtherAddr>(macStr));
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700571 }
William A. Kennington III13d665c2022-11-15 20:34:40 -0800572 auto info = AllIntfInfo{InterfaceInfo{
William A. Kennington III9c441fd2023-02-24 13:40:01 -0800573 .type = ARPHRD_ETHER,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700574 .idx = 0, // TODO: Query the correct value after creation
575 .flags = 0,
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700576 .name = intfName,
William A. Kennington IIIfd862be2022-10-09 18:40:55 -0700577 .mac = std::move(mac),
578 .mtu = mtu(),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700579 .parent_idx = ifIdx,
580 .vlan_id = id,
William A. Kennington III13d665c2022-11-15 20:34:40 -0800581 }};
Ratan Gupta5978dd12017-07-25 13:47:13 +0530582
Patrick Williams6aef7692021-05-01 06:39:41 -0500583 // Pass the parents nicEnabled property, so that the child
Manojkiran Edaca8b91b2020-05-28 09:28:42 +0530584 // VLAN interface can inherit.
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700585 auto vlanIntf = std::make_unique<EthernetInterface>(
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800586 bus, manager, info, objRoot, config::Parser(), nicEnabled());
William A. Kennington IIId298f932022-10-17 14:31:38 -0700587 ObjectPath ret = vlanIntf->objPath;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530588
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800589 manager.get().interfaces.emplace(intfName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530590
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700591 // write the device file for the vlan interface.
592 config::Parser config;
593 auto& netdev = config.map["NetDev"].emplace_back();
594 netdev["Name"].emplace_back(intfName);
595 netdev["Kind"].emplace_back("vlan");
596 config.map["VLAN"].emplace_back()["Id"].emplace_back(std::move(idStr));
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800597 config.writeFile(
598 config::pathForIntfDev(manager.get().getConfDir(), intfName));
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700599
600 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800601 manager.get().reloadConfigs();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700602
William A. Kennington III7b90bc82022-11-17 14:55:12 -0800603 return ret;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530604}
Ratan Gupta2b106532017-07-25 16:05:02 +0530605
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600606ServerList EthernetInterface::staticNTPServers(ServerList value)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530607{
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700608 value = EthernetInterfaceIntf::staticNTPServers(std::move(value));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530609
William A. Kennington IIIa7485302023-05-30 16:57:57 -0700610 writeConfigurationFile();
611 manager.get().reloadConfigs();
612
613 return value;
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600614}
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700615
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600616ServerList EthernetInterface::ntpServers(ServerList /*servers*/)
617{
618 elog<NotAllowed>(NotAllowedArgument::REASON("ReadOnly Property"));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530619}
Ratan Gupta2b106532017-07-25 16:05:02 +0530620// Need to merge the below function with the code which writes the
621// config file during factory reset.
622// TODO openbmc/openbmc#1751
623
624void EthernetInterface::writeConfigurationFile()
625{
William A. Kennington III95a49a22022-08-18 17:50:05 -0700626 config::Parser config;
627 config.map["Match"].emplace_back()["Name"].emplace_back(interfaceName());
Ratan Gupta2b106532017-07-25 16:05:02 +0530628 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700629 auto& link = config.map["Link"].emplace_back();
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800630#ifdef PERSIST_MAC
William A. Kennington III95a49a22022-08-18 17:50:05 -0700631 auto mac = MacAddressIntf::macAddress();
632 if (!mac.empty())
633 {
634 link["MACAddress"].emplace_back(mac);
635 }
Johnathan Mantey609c12d2022-02-03 09:23:09 -0800636#endif
William A. Kennington III95a49a22022-08-18 17:50:05 -0700637 if (!EthernetInterfaceIntf::nicEnabled())
638 {
639 link["Unmanaged"].emplace_back("yes");
640 }
Johnathan Manteyd0679f92019-10-29 16:20:28 -0700641 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700642 {
643 auto& network = config.map["Network"].emplace_back();
644 auto& lla = network["LinkLocalAddressing"];
Oskar Senftad21fc22018-07-26 16:32:23 -0400645#ifdef LINK_LOCAL_AUTOCONFIGURATION
William A. Kennington III95a49a22022-08-18 17:50:05 -0700646 lla.emplace_back("yes");
Oskar Senftad21fc22018-07-26 16:32:23 -0400647#else
William A. Kennington III95a49a22022-08-18 17:50:05 -0700648 lla.emplace_back("no");
Oskar Senftad21fc22018-07-26 16:32:23 -0400649#endif
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700650 network["IPv6AcceptRA"].emplace_back(ipv6AcceptRA() ? "true" : "false");
651 network["DHCP"].emplace_back(dhcp4() ? (dhcp6() ? "true" : "ipv4")
652 : (dhcp6() ? "ipv6" : "false"));
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600653 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700654 auto& vlans = network["VLAN"];
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800655 for (const auto& [_, intf] : manager.get().interfaces)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700656 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700657 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
658 {
659 vlans.emplace_back(intf->interfaceName());
660 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700661 }
662 }
663 {
664 auto& ntps = network["NTP"];
Asmitha Karunanithi003b8b72022-01-06 04:17:59 -0600665 for (const auto& ntp : EthernetInterfaceIntf::staticNTPServers())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700666 {
667 ntps.emplace_back(ntp);
668 }
669 }
670 {
671 auto& dnss = network["DNS"];
672 for (const auto& dns : EthernetInterfaceIntf::staticNameServers())
673 {
674 dnss.emplace_back(dns);
675 }
676 }
677 {
678 auto& address = network["Address"];
William A. Kennington III59e5b912022-11-02 02:49:46 -0700679 for (const auto& addr : addrs)
William A. Kennington III95a49a22022-08-18 17:50:05 -0700680 {
William A. Kennington III59e5b912022-11-02 02:49:46 -0700681 if (originIsManuallyAssigned(addr.second->origin()))
William A. Kennington III95a49a22022-08-18 17:50:05 -0700682 {
683 address.emplace_back(
684 fmt::format("{}/{}", addr.second->address(),
685 addr.second->prefixLength()));
686 }
687 }
688 }
689 {
690 auto& gateways = network["Gateway"];
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700691 if (!dhcp4())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700692 {
693 auto gateway = EthernetInterfaceIntf::defaultGateway();
694 if (!gateway.empty())
695 {
696 gateways.emplace_back(gateway);
697 }
698 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530699
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700700 if (!dhcp6())
William A. Kennington III95a49a22022-08-18 17:50:05 -0700701 {
702 auto gateway6 = EthernetInterfaceIntf::defaultGateway6();
703 if (!gateway6.empty())
704 {
705 gateways.emplace_back(gateway6);
706 }
707 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600708 }
Johnathan Mantey817012a2020-01-30 15:07:39 -0800709 }
William A. Kennington III95a49a22022-08-18 17:50:05 -0700710 config.map["IPv6AcceptRA"].emplace_back()["DHCPv6Client"].emplace_back(
William A. Kennington III8060c0d2022-08-18 19:19:34 -0700711 dhcp6() ? "true" : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500712 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700713 auto& neighbors = config.map["Neighbor"];
714 for (const auto& sneighbor : staticNeighbors)
Lei YUcb2d4082021-08-12 15:26:49 +0800715 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700716 auto& neighbor = neighbors.emplace_back();
717 neighbor["Address"].emplace_back(sneighbor.second->ipAddress());
718 neighbor["MACAddress"].emplace_back(sneighbor.second->macAddress());
Lei YUcb2d4082021-08-12 15:26:49 +0800719 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500720 }
Ravi Tejaa5a09442020-07-17 00:57:33 -0500721 {
William A. Kennington III95a49a22022-08-18 17:50:05 -0700722 auto& dhcp = config.map["DHCP"].emplace_back();
723 dhcp["ClientIdentifier"].emplace_back("mac");
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800724 const auto& conf = manager.get().getDHCPConf();
William A. Kennington III5b179382022-11-15 15:23:26 -0800725 auto dns_enabled = conf.dnsEnabled() ? "true" : "false";
726 dhcp["UseDNS"].emplace_back(dns_enabled);
727 dhcp["UseDomains"].emplace_back(dns_enabled);
728 dhcp["UseNTP"].emplace_back(conf.ntpEnabled() ? "true" : "false");
729 dhcp["UseHostname"].emplace_back(conf.hostNameEnabled() ? "true"
730 : "false");
731 dhcp["SendHostname"].emplace_back(conf.sendHostNameEnabled() ? "true"
732 : "false");
Ravi Tejaa5a09442020-07-17 00:57:33 -0500733 }
Patrick Williams89d734b2023-05-10 07:50:25 -0500734 auto path = config::pathForIntfConf(manager.get().getConfDir(),
735 interfaceName());
William A. Kennington III95a49a22022-08-18 17:50:05 -0700736 config.writeFile(path);
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700737 lg2::info("Wrote networkd file: {CFG_FILE}", "CFG_FILE", path);
Ratan Gupta2b106532017-07-25 16:05:02 +0530738}
739
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800740std::string EthernetInterface::macAddress([[maybe_unused]] std::string value)
Ratan Guptabd303b12017-08-18 17:10:07 +0530741{
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700742 if (vlan)
743 {
Jagpal Singh Gillf78a4152023-04-17 21:17:56 -0700744 lg2::error("Tried to set MAC address on VLAN");
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700745 elog<InternalFailure>();
746 }
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800747#ifdef PERSIST_MAC
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700748 stdplus::EtherAddr newMAC;
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600749 try
750 {
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700751 newMAC = stdplus::fromStr<stdplus::EtherAddr>(value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600752 }
Patrick Williams5758db32021-10-06 12:29:22 -0500753 catch (const std::invalid_argument&)
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600754 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700755 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Asmitha Karunanithi86f659e2021-01-05 00:16:03 -0600756 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
757 Argument::ARGUMENT_VALUE(value.c_str()));
758 }
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700759 if (!newMAC.isUnicast())
Ratan Guptabd303b12017-08-18 17:10:07 +0530760 {
William A. Kennington III1d25ca42023-05-30 16:55:28 -0700761 lg2::error("MAC Address {NET_MAC} is not valid", "NET_MAC", value);
Gunnar Mills90480c42018-06-19 16:02:17 -0500762 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
763 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530764 }
765
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300766 auto interface = interfaceName();
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700767 auto validMAC = stdplus::toStr(newMAC);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300768
William A. Kennington III1137a972019-04-20 20:49:58 -0700769 // We don't need to update the system if the address is unchanged
William A. Kennington IIIb7d6a1a2023-06-17 02:00:53 -0700770 auto oldMAC =
771 stdplus::fromStr<stdplus::EtherAddr>(MacAddressIntf::macAddress());
William A. Kennington IIIbb0eacc2022-10-21 15:22:06 -0700772 if (newMAC != oldMAC)
Ratan Guptabd303b12017-08-18 17:10:07 +0530773 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700774 // Update everything that depends on the MAC value
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800775 for (const auto& [_, intf] : manager.get().interfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530776 {
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700777 if (intf->vlan && intf->vlan->parentIdx == ifIdx)
778 {
779 intf->MacAddressIntf::macAddress(validMAC);
780 }
Ratan Guptabd303b12017-08-18 17:10:07 +0530781 }
Patrick Williams6aef7692021-05-01 06:39:41 -0500782 MacAddressIntf::macAddress(validMAC);
Ratan Guptabd303b12017-08-18 17:10:07 +0530783
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700784 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800785 manager.get().addReloadPreHook([interface]() {
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800786 // The MAC and LLADDRs will only update if the NIC is already down
William A. Kennington III2e09d272022-10-14 17:15:00 -0700787 system::setNICUp(interface, false);
William A. Kennington III6bfdf3e2021-11-09 17:15:12 -0800788 });
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800789 manager.get().reloadConfigs();
Ratan Gupta677ae122017-09-18 16:28:50 +0530790 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700791
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300792#ifdef HAVE_UBOOT_ENV
793 // Ensure that the valid address is stored in the u-boot-env
William A. Kennington III69f45542022-09-24 23:28:14 -0700794 auto envVar = interfaceToUbootEthAddr(interface);
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300795 if (envVar)
796 {
Asmitha Karunanithi33bc9a92020-08-13 08:48:33 -0500797 // Trimming MAC addresses that are out of range. eg: AA:FF:FF:FF:FF:100;
798 // and those having more than 6 bytes. eg: AA:AA:AA:AA:AA:AA:BB
799 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
800 validMAC.c_str());
Alexander Filippov76b2aa32020-07-10 13:28:55 +0300801 }
802#endif // HAVE_UBOOT_ENV
803
William A. Kennington III1137a972019-04-20 20:49:58 -0700804 return value;
Jiaqing Zhao69cfa312022-02-18 16:52:55 +0800805#else
806 elog<NotAllowed>(
807 NotAllowedArgument::REASON("Writing MAC address is not allowed"));
808#endif // PERSIST_MAC
Ratan Guptabd303b12017-08-18 17:10:07 +0530809}
810
Ratan Guptae9c9b812017-09-22 17:15:37 +0530811void EthernetInterface::deleteAll()
812{
Ratan Guptae9c9b812017-09-22 17:15:37 +0530813 // clear all the ip on the interface
814 addrs.clear();
William A. Kennington IIIbd649af2021-10-08 17:55:13 -0700815
816 writeConfigurationFile();
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800817 manager.get().reloadConfigs();
Ratan Guptae9c9b812017-09-22 17:15:37 +0530818}
819
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800820template <typename Addr>
821static void normalizeGateway(std::string& gw)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500822{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800823 if (gw.empty())
824 {
825 return;
826 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700827 try
Ravi Tejaa5a09442020-07-17 00:57:33 -0500828 {
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800829 auto ip = stdplus::fromStr<Addr>(gw);
830 if (ip == Addr{})
831 {
832 gw.clear();
833 return;
834 }
William A. Kennington IIIbbf5e9e2023-02-01 14:58:38 -0800835 if (!validIntfIP(ip))
836 {
837 throw std::invalid_argument("Invalid unicast");
838 }
William A. Kennington III9ca5c8e2022-12-14 14:40:52 -0800839 gw = stdplus::toStr(ip);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500840 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700841 catch (const std::exception& e)
Ravi Tejaa5a09442020-07-17 00:57:33 -0500842 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800843 lg2::error("Invalid GW `{NET_GW}`: {ERROR}", "NET_GW", gw, "ERROR", e);
Ravi Tejaa5a09442020-07-17 00:57:33 -0500844 elog<InvalidArgument>(Argument::ARGUMENT_NAME("GATEWAY"),
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800845 Argument::ARGUMENT_VALUE(gw.c_str()));
Ravi Tejaa5a09442020-07-17 00:57:33 -0500846 }
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800847}
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700848
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800849std::string EthernetInterface::defaultGateway(std::string gateway)
850{
851 normalizeGateway<stdplus::In4Addr>(gateway);
852 if (gateway != defaultGateway())
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700853 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800854 gateway = EthernetInterfaceIntf::defaultGateway(std::move(gateway));
855 manager.get().reloadConfigs();
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700856 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700857 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500858}
859
860std::string EthernetInterface::defaultGateway6(std::string gateway)
861{
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800862 normalizeGateway<stdplus::In6Addr>(gateway);
863 if (gateway != defaultGateway6())
Ravi Tejaa5a09442020-07-17 00:57:33 -0500864 {
William A. Kennington IIId4ff7312023-02-03 14:19:17 -0800865 gateway = EthernetInterfaceIntf::defaultGateway6(std::move(gateway));
866 manager.get().reloadConfigs();
Ravi Tejaa5a09442020-07-17 00:57:33 -0500867 }
William A. Kennington IIIf6f0cf32022-11-04 14:28:42 -0700868 return gateway;
Ravi Tejaa5a09442020-07-17 00:57:33 -0500869}
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700870
871EthernetInterface::VlanProperties::VlanProperties(
872 sdbusplus::bus_t& bus, stdplus::const_zstring objPath,
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800873 const InterfaceInfo& info, stdplus::PinnedRef<EthernetInterface> eth) :
William A. Kennington IIIb6452542022-11-15 18:09:12 -0800874 VlanIfaces(bus, objPath.c_str(), VlanIfaces::action::defer_emit),
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700875 parentIdx(*info.parent_idx), eth(eth)
876{
William A. Kennington IIId99e6db2022-11-15 20:39:45 -0800877 VlanIntf::id(*info.vlan_id, true);
878 emit_object_added();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700879}
880
881void EthernetInterface::VlanProperties::delete_()
882{
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800883 auto intf = eth.get().interfaceName();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700884
885 // Remove all configs for the current interface
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800886 const auto& confDir = eth.get().manager.get().getConfDir();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700887 std::error_code ec;
888 std::filesystem::remove(config::pathForIntfConf(confDir, intf), ec);
889 std::filesystem::remove(config::pathForIntfDev(confDir, intf), ec);
890
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800891 if (eth.get().ifIdx > 0)
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800892 {
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800893 eth.get().manager.get().interfacesByIdx.erase(eth.get().ifIdx);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800894 }
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800895 auto it = eth.get().manager.get().interfaces.find(intf);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800896 auto obj = std::move(it->second);
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800897 eth.get().manager.get().interfaces.erase(it);
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800898
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700899 // Write an updated parent interface since it has a VLAN entry
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800900 for (const auto& [_, intf] : eth.get().manager.get().interfaces)
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700901 {
902 if (intf->ifIdx == parentIdx)
903 {
904 intf->writeConfigurationFile();
905 }
906 }
907
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800908 if (eth.get().ifIdx > 0)
William A. Kennington III67b09da2022-10-31 14:09:53 -0700909 {
William A. Kennington III6d217512022-11-17 16:18:01 -0800910 // We need to forcibly delete the interface as systemd does not
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800911 eth.get().manager.get().addReloadPostHook(
912 [idx = eth.get().ifIdx]() { system::deleteIntf(idx); });
William A. Kennington III6d217512022-11-17 16:18:01 -0800913
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800914 // Ignore the interface so the reload doesn't re-query it
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800915 eth.get().manager.get().ignoredIntf.emplace(eth.get().ifIdx);
William A. Kennington III67b09da2022-10-31 14:09:53 -0700916 }
William A. Kennington III93f5c6d2022-11-17 16:23:44 -0800917
William A. Kennington III9ede1b72022-11-21 01:59:28 -0800918 eth.get().manager.get().reloadConfigs();
William A. Kennington III09f3a4a2022-10-25 02:59:16 -0700919}
920
Gunnar Mills57d9c502018-09-14 14:42:34 -0500921} // namespace network
922} // namespace phosphor