blob: ed1e1ba919e0b7e59091debe3472a007fb19f0f6 [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 Gupta2b106532017-07-25 16:05:02 +05306#include "ipaddress.hpp"
William A. Kennington III08505792019-01-30 16:00:04 -08007#include "neighbor.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05308#include "network_manager.hpp"
Ratan Gupta2b106532017-07-25 16:05:02 +05309#include "vlan_interface.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +053010
Ratan Gupta82549cc2017-04-21 08:45:23 +053011#include <arpa/inet.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053012#include <linux/ethtool.h>
William A. Kennington IIId7946a72019-04-19 14:24:09 -070013#include <linux/rtnetlink.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053014#include <linux/sockios.h>
Ratan Gupta2b106532017-07-25 16:05:02 +053015#include <net/if.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053016#include <netinet/in.h>
17#include <sys/ioctl.h>
18#include <sys/socket.h>
19#include <unistd.h>
20
Ratan Gupta82549cc2017-04-21 08:45:23 +053021#include <algorithm>
22#include <experimental/filesystem>
Ratan Gupta2b106532017-07-25 16:05:02 +053023#include <fstream>
Patrick Venture189d44e2018-07-09 12:30:59 -070024#include <phosphor-logging/elog-errors.hpp>
25#include <phosphor-logging/log.hpp>
Ratan Gupta2b106532017-07-25 16:05:02 +053026#include <sstream>
27#include <string>
William A. Kennington III1137a972019-04-20 20:49:58 -070028#include <string_view>
Patrick Venture189d44e2018-07-09 12:30:59 -070029#include <xyz/openbmc_project/Common/error.hpp>
Ratan Gupta82549cc2017-04-21 08:45:23 +053030
Ratan Gupta91a99cc2017-04-14 16:32:09 +053031namespace phosphor
32{
33namespace network
34{
35
36using namespace phosphor::logging;
Ratan Gupta2b106532017-07-25 16:05:02 +053037using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -050038using Argument = xyz::openbmc_project::Common::InvalidArgument;
Ratan Gupta2b106532017-07-25 16:05:02 +053039
Johnathan Manteyfaa72e52020-01-08 10:38:58 -080040struct EthernetIntfSocket
41{
42 EthernetIntfSocket(int domain, int type, int protocol)
43 {
44 if ((sock = socket(domain, type, protocol)) < 0)
45 {
46 log<level::ERR>("socket creation failed:",
47 entry("ERROR=%s", strerror(errno)));
48 }
49 }
50
51 ~EthernetIntfSocket()
52 {
53 if (sock >= 0)
54 {
55 close(sock);
56 }
57 }
58
59 int sock{-1};
60};
61
Ratan Gupta91a99cc2017-04-14 16:32:09 +053062EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
63 const std::string& objPath,
Gunnar Mills57d9c502018-09-14 14:42:34 -050064 bool dhcpEnabled, Manager& parent,
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053065 bool emitSignal) :
Gunnar Mills57d9c502018-09-14 14:42:34 -050066 Ifaces(bus, objPath.c_str(), true),
67 bus(bus), manager(parent), objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053068{
69 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053070 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053071 interfaceName(intfName);
Ratan Guptac35481d2017-08-18 06:12:26 +053072 EthernetInterfaceIntf::dHCPEnabled(dhcpEnabled);
Johnathan Mantey5b023f52019-06-24 16:06:37 -070073 EthernetInterfaceIntf::iPv6AcceptRA(getIPv6AcceptRAFromConf());
Ratan Gupta99801ce2020-01-09 18:37:16 +053074 // Don't get the mac address from the system as the mac address
75 // would be same as parent interface.
76 if (intfName.find(".") == std::string::npos)
77 {
78 MacAddressIntf::mACAddress(getMACAddress(intfName));
79 }
Ratan Gupta497c0c92017-08-22 19:15:59 +053080 EthernetInterfaceIntf::nTPServers(getNTPServersFromConf());
Ratan Gupta6dec390f2017-08-20 15:28:12 +053081 EthernetInterfaceIntf::nameservers(getNameServerFromConf());
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -080082#if NIC_SUPPORTS_ETHTOOL
Johnathan Manteycb42fe22019-08-01 13:35:29 -070083 InterfaceInfo ifInfo = EthernetInterface::getInterfaceInfo();
84
85 EthernetInterfaceIntf::autoNeg(std::get<2>(ifInfo));
86 EthernetInterfaceIntf::speed(std::get<0>(ifInfo));
Johnathan Manteyfaa72e52020-01-08 10:38:58 -080087 EthernetInterfaceIntf::linkUp(std::get<3>(ifInfo));
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -080088#endif
Ratan Gupta6dec390f2017-08-20 15:28:12 +053089
Ratan Gupta29b0e432017-05-25 12:51:40 +053090 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053091 if (emitSignal)
92 {
93 this->emit_object_added();
94 }
Ratan Gupta29b0e432017-05-25 12:51:40 +053095}
96
William A. Kennington IIIfbafa252018-11-30 16:53:52 -080097static IP::Protocol convertFamily(int family)
98{
99 switch (family)
100 {
101 case AF_INET:
102 return IP::Protocol::IPv4;
103 case AF_INET6:
104 return IP::Protocol::IPv6;
105 }
106
107 throw std::invalid_argument("Bad address family");
108}
109
Ratan Gupta87c13982017-06-15 09:27:27 +0530110void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +0530111{
Ratan Gupta87c13982017-06-15 09:27:27 +0530112 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530113
Ratan Gupta87c13982017-06-15 09:27:27 +0530114 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +0530115
Ratan Gupta6a387c12017-08-03 13:26:19 +0530116 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530117 {
William A. Kennington IIIfbafa252018-11-30 16:53:52 -0800118 IP::Protocol addressType = convertFamily(addr.addrType);
119 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ratan Guptafc2c7242017-05-29 08:46:06 +0530120 if (dHCPEnabled())
121 {
122 origin = IP::AddressOrigin::DHCP;
123 }
William A. Kennington III16893802019-01-30 16:01:01 -0800124 if (isLinkLocalIP(addr.ipaddress))
Ratan Guptafc2c7242017-05-29 08:46:06 +0530125 {
126 origin = IP::AddressOrigin::LinkLocal;
127 }
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700128 // Obsolete parameter
129 std::string gateway = "";
Ratan Gupta82549cc2017-04-21 08:45:23 +0530130
Gunnar Mills57d9c502018-09-14 14:42:34 -0500131 std::string ipAddressObjectPath = generateObjectPath(
132 addressType, addr.ipaddress, addr.prefix, gateway);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530133
Gunnar Mills57d9c502018-09-14 14:42:34 -0500134 this->addrs.emplace(addr.ipaddress,
135 std::make_shared<phosphor::network::IPAddress>(
136 bus, ipAddressObjectPath.c_str(), *this,
137 addressType, addr.ipaddress, origin,
138 addr.prefix, gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530139 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530140}
141
William A. Kennington III08505792019-01-30 16:00:04 -0800142void EthernetInterface::createStaticNeighborObjects()
143{
144 staticNeighbors.clear();
145
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700146 NeighborFilter filter;
147 filter.interface = ifIndex();
148 filter.state = NUD_PERMANENT;
149 auto neighbors = getCurrentNeighbors(filter);
William A. Kennington III08505792019-01-30 16:00:04 -0800150 for (const auto& neighbor : neighbors)
151 {
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700152 if (!neighbor.mac)
William A. Kennington III08505792019-01-30 16:00:04 -0800153 {
154 continue;
155 }
156 std::string ip = toString(neighbor.address);
157 std::string mac = mac_address::toString(*neighbor.mac);
158 std::string objectPath = generateStaticNeighborObjectPath(ip, mac);
159 staticNeighbors.emplace(ip,
160 std::make_shared<phosphor::network::Neighbor>(
161 bus, objectPath.c_str(), *this, ip, mac,
162 Neighbor::State::Permanent));
163 }
164}
165
William A. Kennington IIId7946a72019-04-19 14:24:09 -0700166unsigned EthernetInterface::ifIndex() const
167{
168 unsigned idx = if_nametoindex(interfaceName().c_str());
169 if (idx == 0)
170 {
171 throw std::system_error(errno, std::generic_category(),
172 "if_nametoindex");
173 }
174 return idx;
175}
176
raviteja-bce379562019-03-28 05:59:36 -0500177ObjectPath EthernetInterface::iP(IP::Protocol protType, std::string ipaddress,
178 uint8_t prefixLength, std::string gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530179{
Ratan Guptafc2c7242017-05-29 08:46:06 +0530180
181 if (dHCPEnabled())
182 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530183 log<level::INFO>("DHCP enabled on the interface"),
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500184 entry("INTERFACE=%s", interfaceName().c_str());
185 dHCPEnabled(false);
186 }
187
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500188 IP::AddressOrigin origin = IP::AddressOrigin::Static;
189
190 int addressFamily = (protType == IP::Protocol::IPv4) ? AF_INET : AF_INET6;
191
192 if (!isValidIP(addressFamily, ipaddress))
193 {
194 log<level::ERR>("Not a valid IP address"),
195 entry("ADDRESS=%s", ipaddress.c_str());
196 elog<InvalidArgument>(Argument::ARGUMENT_NAME("ipaddress"),
197 Argument::ARGUMENT_VALUE(ipaddress.c_str()));
198 }
199
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700200 // Gateway is an obsolete parameter
201 gateway = "";
Nagaraju Goruganti66b974d2017-10-03 08:43:08 -0500202
203 if (!isValidPrefix(addressFamily, prefixLength))
204 {
205 log<level::ERR>("PrefixLength is not correct "),
William A. Kennington IIIf8c78f22019-04-20 20:32:59 -0700206 entry("PREFIXLENGTH=%" PRIu8, prefixLength);
Gunnar Mills57d9c502018-09-14 14:42:34 -0500207 elog<InvalidArgument>(
208 Argument::ARGUMENT_NAME("prefixLength"),
209 Argument::ARGUMENT_VALUE(std::to_string(prefixLength).c_str()));
Ratan Guptafc2c7242017-05-29 08:46:06 +0530210 }
211
Gunnar Mills57d9c502018-09-14 14:42:34 -0500212 std::string objectPath =
213 generateObjectPath(protType, ipaddress, prefixLength, gateway);
214 this->addrs.emplace(ipaddress,
215 std::make_shared<phosphor::network::IPAddress>(
216 bus, objectPath.c_str(), *this, protType, ipaddress,
217 origin, prefixLength, gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530218
Ratan Guptae05083a2017-09-16 07:12:11 +0530219 manager.writeToConfigurationFile();
raviteja-bce379562019-03-28 05:59:36 -0500220 return objectPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530221}
222
William A. Kennington III08505792019-01-30 16:00:04 -0800223ObjectPath EthernetInterface::neighbor(std::string iPAddress,
224 std::string mACAddress)
225{
226 if (!isValidIP(AF_INET, iPAddress) && !isValidIP(AF_INET6, iPAddress))
227 {
228 log<level::ERR>("Not a valid IP address",
229 entry("ADDRESS=%s", iPAddress.c_str()));
230 elog<InvalidArgument>(Argument::ARGUMENT_NAME("iPAddress"),
231 Argument::ARGUMENT_VALUE(iPAddress.c_str()));
232 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700233 if (!mac_address::isUnicast(mac_address::fromString(mACAddress)))
William A. Kennington III08505792019-01-30 16:00:04 -0800234 {
235 log<level::ERR>("Not a valid MAC address",
236 entry("MACADDRESS=%s", iPAddress.c_str()));
237 elog<InvalidArgument>(Argument::ARGUMENT_NAME("mACAddress"),
238 Argument::ARGUMENT_VALUE(mACAddress.c_str()));
239 }
240
241 std::string objectPath =
242 generateStaticNeighborObjectPath(iPAddress, mACAddress);
243 staticNeighbors.emplace(iPAddress,
244 std::make_shared<phosphor::network::Neighbor>(
245 bus, objectPath.c_str(), *this, iPAddress,
246 mACAddress, Neighbor::State::Permanent));
247 manager.writeToConfigurationFile();
248 return objectPath;
249}
250
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800251#if NIC_SUPPORTS_ETHTOOL
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530252/*
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800253 Enable this code if your NIC driver supports the ETHTOOL features.
254 Do this by adding the following to your phosphor-network*.bbappend file.
255 EXTRA_OECONF_append = " --enable-nic-ethtool=yes"
256 The default compile mode is to omit getInterfaceInfo()
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530257*/
258InterfaceInfo EthernetInterface::getInterfaceInfo() const
259{
Ratan K Gupta1a054ae2018-09-15 00:49:51 -0400260 ifreq ifr{0};
261 ethtool_cmd edata{0};
Gunnar Mills57d9c502018-09-14 14:42:34 -0500262 LinkSpeed speed{0};
263 Autoneg autoneg{0};
264 DuplexMode duplex{0};
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800265 LinkUp linkState{false};
266 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
267
268 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530269 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800270 return std::make_tuple(speed, duplex, autoneg, linkState);
271 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530272
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800273 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IFNAMSIZ - 1);
274 ifr.ifr_data = reinterpret_cast<char*>(&edata);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530275
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800276 edata.cmd = ETHTOOL_GSET;
277 if (ioctl(eifSocket.sock, SIOCETHTOOL, &ifr) >= 0)
278 {
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530279 speed = edata.speed;
280 duplex = edata.duplex;
281 autoneg = edata.autoneg;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530282 }
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800283
284 linkState = linkUp();
285
286 return std::make_tuple(speed, duplex, autoneg, linkState);
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530287}
Johnathan Manteyad4bf5c2020-01-24 13:30:39 -0800288#endif
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530289
290/** @brief get the mac address of the interface.
291 * @return macaddress on success
292 */
293
Gunnar Mills57d9c502018-09-14 14:42:34 -0500294std::string
295 EthernetInterface::getMACAddress(const std::string& interfaceName) const
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530296{
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800297 std::string activeMACAddr = MacAddressIntf::mACAddress();
298 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
299
300 if (eifSocket.sock < 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530301 {
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800302 return activeMACAddr;
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530303 }
304
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800305 ifreq ifr{0};
306 std::strncpy(ifr.ifr_name, interfaceName.c_str(), IFNAMSIZ - 1);
307 if (ioctl(eifSocket.sock, SIOCGIFHWADDR, &ifr) != 0)
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530308 {
Ratan Guptada7d3af2017-08-13 17:49:56 +0530309 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500310 entry("ERROR=%s", strerror(errno)));
William A. Kennington III7ed1b282019-04-21 23:38:42 -0700311 elog<InternalFailure>();
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530312 }
313
William A. Kennington III1137a972019-04-20 20:49:58 -0700314 static_assert(sizeof(ifr.ifr_hwaddr.sa_data) >= sizeof(ether_addr));
315 std::string_view hwaddr(reinterpret_cast<char*>(ifr.ifr_hwaddr.sa_data),
316 sizeof(ifr.ifr_hwaddr.sa_data));
317 return mac_address::toString(copyFrom<ether_addr>(hwaddr));
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530318}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530319
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530320std::string EthernetInterface::generateId(const std::string& ipaddress,
321 uint8_t prefixLength,
322 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530323{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530324 std::stringstream hexId;
325 std::string hashString = ipaddress;
326 hashString += std::to_string(prefixLength);
327 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530328
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530329 // Only want 8 hex digits.
Gunnar Mills57d9c502018-09-14 14:42:34 -0500330 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530331 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530332}
333
William A. Kennington III08505792019-01-30 16:00:04 -0800334std::string EthernetInterface::generateNeighborId(const std::string& iPAddress,
335 const std::string& mACAddress)
336{
337 std::stringstream hexId;
338 std::string hashString = iPAddress + mACAddress;
339
340 // Only want 8 hex digits.
341 hexId << std::hex << ((std::hash<std::string>{}(hashString)) & 0xFFFFFFFF);
342 return hexId.str();
343}
344
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530345void EthernetInterface::deleteObject(const std::string& ipaddress)
346{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530347 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530348 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530349 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530350 log<level::ERR>("DeleteObject:Unable to find the object.");
351 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530352 }
353 this->addrs.erase(it);
Ratan Guptae05083a2017-09-16 07:12:11 +0530354 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530355}
356
William A. Kennington III08505792019-01-30 16:00:04 -0800357void EthernetInterface::deleteStaticNeighborObject(const std::string& iPAddress)
358{
359 auto it = staticNeighbors.find(iPAddress);
360 if (it == staticNeighbors.end())
361 {
362 log<level::ERR>(
363 "DeleteStaticNeighborObject:Unable to find the object.");
364 return;
365 }
366 staticNeighbors.erase(it);
367 manager.writeToConfigurationFile();
368}
369
Ratan Guptae9c9b812017-09-22 17:15:37 +0530370void EthernetInterface::deleteVLANFromSystem(const std::string& interface)
Ratan Guptabc886292017-07-25 18:29:57 +0530371{
Ratan Guptabc886292017-07-25 18:29:57 +0530372 auto confDir = manager.getConfDir();
373 fs::path networkFile = confDir;
374 networkFile /= systemd::config::networkFilePrefix + interface +
375 systemd::config::networkFileSuffix;
376
377 fs::path deviceFile = confDir;
378 deviceFile /= interface + systemd::config::deviceFileSuffix;
379
380 // delete the vlan network file
381 if (fs::is_regular_file(networkFile))
382 {
383 fs::remove(networkFile);
384 }
385
386 // delete the vlan device file
387 if (fs::is_regular_file(deviceFile))
388 {
389 fs::remove(deviceFile);
390 }
Ratan Guptabc886292017-07-25 18:29:57 +0530391
392 // TODO systemd doesn't delete the virtual network interface
393 // even after deleting all the related configuartion.
394 // https://github.com/systemd/systemd/issues/6600
395 try
396 {
397 deleteInterface(interface);
398 }
399 catch (InternalFailure& e)
400 {
401 commit<InternalFailure>();
402 }
Ratan Guptae9c9b812017-09-22 17:15:37 +0530403}
404
405void EthernetInterface::deleteVLANObject(const std::string& interface)
406{
407 auto it = vlanInterfaces.find(interface);
408 if (it == vlanInterfaces.end())
409 {
410 log<level::ERR>("DeleteVLANObject:Unable to find the object",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500411 entry("INTERFACE=%s", interface.c_str()));
Ratan Guptae9c9b812017-09-22 17:15:37 +0530412 return;
413 }
414
415 deleteVLANFromSystem(interface);
416 // delete the interface
417 vlanInterfaces.erase(it);
418
Ratan Guptae05083a2017-09-16 07:12:11 +0530419 manager.writeToConfigurationFile();
Ratan Guptabc886292017-07-25 18:29:57 +0530420}
421
Gunnar Mills57d9c502018-09-14 14:42:34 -0500422std::string EthernetInterface::generateObjectPath(
423 IP::Protocol addressType, const std::string& ipaddress,
424 uint8_t prefixLength, const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530425{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530426 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530427 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530428 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
429
430 std::experimental::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530431 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530432 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530433 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530434 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530435}
436
William A. Kennington III08505792019-01-30 16:00:04 -0800437std::string EthernetInterface::generateStaticNeighborObjectPath(
438 const std::string& iPAddress, const std::string& mACAddress) const
439{
440 std::experimental::filesystem::path objectPath;
441 objectPath /= objPath;
442 objectPath /= "static_neighbor";
443 objectPath /= generateNeighborId(iPAddress, mACAddress);
444 return objectPath.string();
445}
446
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700447bool EthernetInterface::iPv6AcceptRA(bool value)
448{
449 if (value == EthernetInterfaceIntf::iPv6AcceptRA())
450 {
451 return value;
452 }
453 EthernetInterfaceIntf::iPv6AcceptRA(value);
454 manager.writeToConfigurationFile();
455 return value;
456}
457
Ratan Gupta87c13982017-06-15 09:27:27 +0530458bool EthernetInterface::dHCPEnabled(bool value)
459{
Ratan Gupta5978dd12017-07-25 13:47:13 +0530460 if (value == EthernetInterfaceIntf::dHCPEnabled())
461 {
462 return value;
463 }
464
Ratan Gupta87c13982017-06-15 09:27:27 +0530465 EthernetInterfaceIntf::dHCPEnabled(value);
Ratan Guptae05083a2017-09-16 07:12:11 +0530466 manager.writeToConfigurationFile();
Ratan Gupta87c13982017-06-15 09:27:27 +0530467 return value;
468}
469
Johnathan Manteyfaa72e52020-01-08 10:38:58 -0800470bool EthernetInterface::linkUp() const
471{
472 EthernetIntfSocket eifSocket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
473 bool value = EthernetInterfaceIntf::linkUp();
474
475 if (eifSocket.sock < 0)
476 {
477 return value;
478 }
479
480 ifreq ifr{0};
481 std::strncpy(ifr.ifr_name, interfaceName().c_str(), IF_NAMESIZE - 1);
482 if (ioctl(eifSocket.sock, SIOCGIFFLAGS, &ifr) == 0)
483 {
484 value = static_cast<bool>(ifr.ifr_flags & IFF_RUNNING);
485 }
486 else
487 {
488 log<level::ERR>("ioctl failed for SIOCGIFFLAGS:",
489 entry("ERROR=%s", strerror(errno)));
490 }
491
492 return value;
493}
494
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530495ServerList EthernetInterface::nameservers(ServerList value)
496{
Manojkiran Eda5fb6c332019-08-21 16:37:29 +0530497 for (const auto& nameserverip : value)
498 {
499 if (!isValidIP(AF_INET, nameserverip) &&
500 !isValidIP(AF_INET6, nameserverip))
501 {
502 log<level::ERR>("Not a valid IP address"),
503 entry("ADDRESS=%s", nameserverip.c_str());
504 elog<InvalidArgument>(
505 Argument::ARGUMENT_NAME("Nameserver"),
506 Argument::ARGUMENT_VALUE(nameserverip.c_str()));
507 }
508 }
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530509 try
510 {
511 EthernetInterfaceIntf::nameservers(value);
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530512 writeConfigurationFile();
Ratan Guptab4005972019-09-19 06:19:16 +0530513 // resolved reads the DNS server configuration from the
514 // network file.
515 manager.restartSystemdUnit(networkdService);
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530516 }
517 catch (InternalFailure& e)
518 {
519 log<level::ERR>("Exception processing DNS entries");
520 }
521 return EthernetInterfaceIntf::nameservers();
522}
523
524ServerList EthernetInterface::getNameServerFromConf()
525{
526 fs::path confPath = manager.getConfDir();
527
528 std::string fileName = systemd::config::networkFilePrefix +
Gunnar Mills57d9c502018-09-14 14:42:34 -0500529 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530530 confPath /= fileName;
531 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530532 config::Parser parser(confPath.string());
533 auto rc = config::ReturnCode::SUCCESS;
534
535 std::tie(rc, servers) = parser.getValues("Network", "DNS");
536 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530537 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530538 log<level::DEBUG>("Unable to get the value for network[DNS]",
539 entry("RC=%d", rc));
Ratan Gupta6dec390f2017-08-20 15:28:12 +0530540 }
541 return servers;
542}
543
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530544void EthernetInterface::loadVLAN(VlanId id)
545{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500546 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530547 std::string path = objPath;
548 path += "_" + std::to_string(id);
549
Gunnar Mills57d9c502018-09-14 14:42:34 -0500550 auto dhcpEnabled =
551 getDHCPValue(manager.getConfDir().string(), vlanInterfaceName);
Ratan Gupta6e8df632017-08-13 09:41:58 +0530552
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530553 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Gunnar Mills57d9c502018-09-14 14:42:34 -0500554 bus, path.c_str(), dhcpEnabled, id, *this, manager);
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530555
Gunnar Mills57d9c502018-09-14 14:42:34 -0500556 // Fetch the ip address from the system
557 // and create the dbus object.
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530558 vlanIntf->createIPAddressObjects();
William A. Kennington III08505792019-01-30 16:00:04 -0800559 vlanIntf->createStaticNeighborObjects();
Ratan Gupta92bc2fe2017-07-26 22:40:21 +0530560
561 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
562 std::move(vlanIntf));
563}
564
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700565ObjectPath EthernetInterface::createVLAN(VlanId id)
Ratan Gupta5978dd12017-07-25 13:47:13 +0530566{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500567 std::string vlanInterfaceName = interfaceName() + "." + std::to_string(id);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530568 std::string path = objPath;
569 path += "_" + std::to_string(id);
570
Ratan Gupta5978dd12017-07-25 13:47:13 +0530571 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
Gunnar Mills57d9c502018-09-14 14:42:34 -0500572 bus, path.c_str(), false, id, *this, manager);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530573
574 // write the device file for the vlan interface.
575 vlanIntf->writeDeviceFile();
576
Gunnar Mills57d9c502018-09-14 14:42:34 -0500577 this->vlanInterfaces.emplace(vlanInterfaceName, std::move(vlanIntf));
Ratan Gupta5978dd12017-07-25 13:47:13 +0530578 // write the new vlan device entry to the configuration(network) file.
Ratan Guptae05083a2017-09-16 07:12:11 +0530579 manager.writeToConfigurationFile();
William A. Kennington IIIf4b4ff82019-04-09 19:06:52 -0700580
581 return path;
Ratan Gupta5978dd12017-07-25 13:47:13 +0530582}
Ratan Gupta2b106532017-07-25 16:05:02 +0530583
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700584bool EthernetInterface::getIPv6AcceptRAFromConf()
585{
586 fs::path confPath = manager.getConfDir();
587
588 std::string fileName = systemd::config::networkFilePrefix +
589 interfaceName() + systemd::config::networkFileSuffix;
590 confPath /= fileName;
591 config::ValueList values;
592 config::Parser parser(confPath.string());
593 auto rc = config::ReturnCode::SUCCESS;
594 std::tie(rc, values) = parser.getValues("Network", "IPv6AcceptRA");
595 if (rc != config::ReturnCode::SUCCESS)
596 {
597 log<level::DEBUG>("Unable to get the value for Network[IPv6AcceptRA]",
598 entry("rc=%d", rc));
599 return false;
600 }
601 return (values[0] == "true");
602}
603
Ratan Gupta497c0c92017-08-22 19:15:59 +0530604ServerList EthernetInterface::getNTPServersFromConf()
605{
606 fs::path confPath = manager.getConfDir();
607
Gunnar Mills57d9c502018-09-14 14:42:34 -0500608 std::string fileName = systemd::config::networkFilePrefix +
609 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta497c0c92017-08-22 19:15:59 +0530610 confPath /= fileName;
Ratan Guptac27170a2017-11-22 15:44:42 +0530611
Ratan Gupta497c0c92017-08-22 19:15:59 +0530612 ServerList servers;
Ratan Guptac27170a2017-11-22 15:44:42 +0530613 config::Parser parser(confPath.string());
614 auto rc = config::ReturnCode::SUCCESS;
615
616 std::tie(rc, servers) = parser.getValues("Network", "NTP");
617 if (rc != config::ReturnCode::SUCCESS)
Ratan Gupta497c0c92017-08-22 19:15:59 +0530618 {
Ratan Guptac27170a2017-11-22 15:44:42 +0530619 log<level::DEBUG>("Unable to get the value for Network[NTP]",
620 entry("rc=%d", rc));
Ratan Gupta497c0c92017-08-22 19:15:59 +0530621 }
Ratan Guptac27170a2017-11-22 15:44:42 +0530622
Ratan Gupta497c0c92017-08-22 19:15:59 +0530623 return servers;
624}
625
626ServerList EthernetInterface::nTPServers(ServerList servers)
627{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500628 auto ntpServers = EthernetInterfaceIntf::nTPServers(servers);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530629
630 writeConfigurationFile();
631 // timesynchd reads the NTP server configuration from the
632 // network file.
Ratan Gupta895f9e52018-11-26 20:57:34 +0530633 manager.restartSystemdUnit(networkdService);
Ratan Gupta497c0c92017-08-22 19:15:59 +0530634 return ntpServers;
635}
Ratan Gupta2b106532017-07-25 16:05:02 +0530636// Need to merge the below function with the code which writes the
637// config file during factory reset.
638// TODO openbmc/openbmc#1751
639
640void EthernetInterface::writeConfigurationFile()
641{
642 // write all the static ip address in the systemd-network conf file
643
644 using namespace std::string_literals;
645 using AddressOrigin =
646 sdbusplus::xyz::openbmc_project::Network::server::IP::AddressOrigin;
647 namespace fs = std::experimental::filesystem;
Ratan Guptae05083a2017-09-16 07:12:11 +0530648
649 // if there is vlan interafce then write the configuration file
650 // for vlan also.
651
Gunnar Mills57d9c502018-09-14 14:42:34 -0500652 for (const auto& intf : vlanInterfaces)
Ratan Guptae05083a2017-09-16 07:12:11 +0530653 {
654 intf.second->writeConfigurationFile();
655 }
656
Ratan Gupta2b106532017-07-25 16:05:02 +0530657 fs::path confPath = manager.getConfDir();
658
Gunnar Mills57d9c502018-09-14 14:42:34 -0500659 std::string fileName = systemd::config::networkFilePrefix +
660 interfaceName() + systemd::config::networkFileSuffix;
Ratan Gupta2b106532017-07-25 16:05:02 +0530661 confPath /= fileName;
662 std::fstream stream;
663
664 stream.open(confPath.c_str(), std::fstream::out);
665 if (!stream.is_open())
666 {
667 log<level::ERR>("Unable to open the file",
668 entry("FILE=%s", confPath.c_str()));
669 elog<InternalFailure>();
670 }
671
672 // Write the device
Ratan K Gupta1a054ae2018-09-15 00:49:51 -0400673 stream << "[Match]\n";
Ratan Gupta2b106532017-07-25 16:05:02 +0530674 stream << "Name=" << interfaceName() << "\n";
675
676 auto addrs = getAddresses();
677
William A. Kennington III15787212019-04-23 19:18:01 -0700678 // Write the link section
679 stream << "[Link]\n";
680 auto mac = MacAddressIntf::mACAddress();
681 if (!mac.empty())
682 {
683 stream << "MACAddress=" << mac << "\n";
684 }
685
Ratan Gupta2b106532017-07-25 16:05:02 +0530686 // write the network section
Ratan K Gupta1a054ae2018-09-15 00:49:51 -0400687 stream << "[Network]\n";
Oskar Senftad21fc22018-07-26 16:32:23 -0400688#ifdef LINK_LOCAL_AUTOCONFIGURATION
Nagaraju Goruganti24afe362017-09-21 07:40:26 -0500689 stream << "LinkLocalAddressing=yes\n";
Oskar Senftad21fc22018-07-26 16:32:23 -0400690#else
691 stream << "LinkLocalAddressing=no\n";
692#endif
Johnathan Mantey5b023f52019-06-24 16:06:37 -0700693 stream << std::boolalpha
694 << "IPv6AcceptRA=" << EthernetInterfaceIntf::iPv6AcceptRA() << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +0530695
696 // Add the VLAN entry
Gunnar Mills57d9c502018-09-14 14:42:34 -0500697 for (const auto& intf : vlanInterfaces)
Ratan Gupta4f67dac2017-08-28 22:18:21 +0530698 {
699 stream << "VLAN=" << intf.second->EthernetInterface::interfaceName()
Gunnar Mills57d9c502018-09-14 14:42:34 -0500700 << "\n";
Ratan Gupta4f67dac2017-08-28 22:18:21 +0530701 }
Ratan Gupta046b2a02019-09-20 15:49:51 +0530702 // Add the NTP server
703 for (const auto& ntp : EthernetInterfaceIntf::nTPServers())
704 {
705 stream << "NTP=" << ntp << "\n";
706 }
707
708 // Add the DNS entry
709 for (const auto& dns : EthernetInterfaceIntf::nameservers())
710 {
711 stream << "DNS=" << dns << "\n";
712 }
713
Nagaraju Gorugantie8b83ec2018-03-26 05:21:45 -0500714 // Add the DHCP entry
715 auto value = dHCPEnabled() ? "true"s : "false"s;
716 stream << "DHCP="s + value + "\n";
717
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600718 // When the interface configured as dhcp, we don't need below given entries
719 // in config file.
720 if (dHCPEnabled() == false)
Ratan Gupta2b106532017-07-25 16:05:02 +0530721 {
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600722 // Static
723 for (const auto& addr : addrs)
724 {
Oskar Senftad21fc22018-07-26 16:32:23 -0400725 if (addr.second->origin() == AddressOrigin::Static
726#ifndef LINK_LOCAL_AUTOCONFIGURATION
727 || addr.second->origin() == AddressOrigin::LinkLocal
728#endif
729 )
Ratan Gupta2b106532017-07-25 16:05:02 +0530730 {
Gunnar Mills57d9c502018-09-14 14:42:34 -0500731 std::string address =
732 addr.second->address() + "/" +
733 std::to_string(addr.second->prefixLength());
Ratan Gupta2b106532017-07-25 16:05:02 +0530734
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600735 stream << "Address=" << address << "\n";
736 }
737 }
738
739 if (manager.getSystemConf())
740 {
William A. Kennington III781f3352019-02-01 21:07:10 -0800741 const auto& gateway = manager.getSystemConf()->defaultGateway();
742 if (!gateway.empty())
743 {
744 stream << "Gateway=" << gateway << "\n";
745 }
William A. Kennington IIId3c249c2019-02-01 21:12:02 -0800746 const auto& gateway6 = manager.getSystemConf()->defaultGateway6();
747 if (!gateway6.empty())
748 {
749 stream << "Gateway=" << gateway6 << "\n";
750 }
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600751 }
Ratan Gupta2b106532017-07-25 16:05:02 +0530752 }
753
William A. Kennington III08505792019-01-30 16:00:04 -0800754 // Write the neighbor sections
755 for (const auto& neighbor : staticNeighbors)
756 {
757 stream << "[Neighbor]"
758 << "\n";
759 stream << "Address=" << neighbor.second->iPAddress() << "\n";
760 stream << "MACAddress=" << neighbor.second->mACAddress() << "\n";
761 }
762
Nagaraju Goruganti210420a2018-03-07 09:22:28 -0600763 // Write the dhcp section irrespective of whether DHCP is enabled or not
764 writeDHCPSection(stream);
765
Ratan Gupta2b106532017-07-25 16:05:02 +0530766 stream.close();
Ratan Gupta2b106532017-07-25 16:05:02 +0530767}
768
769void EthernetInterface::writeDHCPSection(std::fstream& stream)
770{
771 using namespace std::string_literals;
Ratan Gupta2b106532017-07-25 16:05:02 +0530772 // write the dhcp section
773 stream << "[DHCP]\n";
774
775 // Hardcoding the client identifier to mac, to address below issue
776 // https://github.com/openbmc/openbmc/issues/1280
777 stream << "ClientIdentifier=mac\n";
778 if (manager.getDHCPConf())
779 {
780 auto value = manager.getDHCPConf()->dNSEnabled() ? "true"s : "false"s;
781 stream << "UseDNS="s + value + "\n";
782
783 value = manager.getDHCPConf()->nTPEnabled() ? "true"s : "false"s;
784 stream << "UseNTP="s + value + "\n";
785
786 value = manager.getDHCPConf()->hostNameEnabled() ? "true"s : "false"s;
787 stream << "UseHostname="s + value + "\n";
Nagaraju Gorugantie8fca1d2018-02-05 20:32:45 -0600788
789 value =
790 manager.getDHCPConf()->sendHostNameEnabled() ? "true"s : "false"s;
791 stream << "SendHostname="s + value + "\n";
Ratan Gupta2b106532017-07-25 16:05:02 +0530792 }
793}
794
Ratan Guptabd303b12017-08-18 17:10:07 +0530795std::string EthernetInterface::mACAddress(std::string value)
796{
William A. Kennington III1137a972019-04-20 20:49:58 -0700797 ether_addr newMAC = mac_address::fromString(value);
798 if (!mac_address::isUnicast(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530799 {
Gunnar Mills90480c42018-06-19 16:02:17 -0500800 log<level::ERR>("MACAddress is not valid.",
Gunnar Mills57d9c502018-09-14 14:42:34 -0500801 entry("MAC=%s", value.c_str()));
Gunnar Mills90480c42018-06-19 16:02:17 -0500802 elog<InvalidArgument>(Argument::ARGUMENT_NAME("MACAddress"),
803 Argument::ARGUMENT_VALUE(value.c_str()));
Ratan Guptabd303b12017-08-18 17:10:07 +0530804 }
805
William A. Kennington III1137a972019-04-20 20:49:58 -0700806 // We don't need to update the system if the address is unchanged
807 ether_addr oldMAC = mac_address::fromString(MacAddressIntf::mACAddress());
808 if (!equal(newMAC, oldMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530809 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700810 if (!mac_address::isLocalAdmin(newMAC))
Ratan Guptabd303b12017-08-18 17:10:07 +0530811 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700812 try
Ratan Guptabd303b12017-08-18 17:10:07 +0530813 {
Alvin Wang38a63c32019-08-29 22:56:46 +0800814 auto inventoryMAC =
815 mac_address::getfromInventory(bus, interfaceName());
William A. Kennington III1137a972019-04-20 20:49:58 -0700816 if (!equal(newMAC, inventoryMAC))
817 {
818 log<level::ERR>(
819 "Given MAC address is neither a local Admin "
820 "type nor is same as in inventory");
821 elog<InvalidArgument>(
822 Argument::ARGUMENT_NAME("MACAddress"),
823 Argument::ARGUMENT_VALUE(value.c_str()));
824 }
825 }
826 catch (const std::exception& e)
827 {
828 log<level::ERR>("Exception occurred during getting of MAC "
829 "address from Inventory");
830 elog<InternalFailure>();
Ratan Guptabd303b12017-08-18 17:10:07 +0530831 }
832 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700833
834 // Update everything that depends on the MAC value
835 for (const auto& [name, intf] : vlanInterfaces)
Ratan Guptabd303b12017-08-18 17:10:07 +0530836 {
William A. Kennington III1137a972019-04-20 20:49:58 -0700837 intf->MacAddressIntf::mACAddress(value);
Ratan Guptabd303b12017-08-18 17:10:07 +0530838 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700839 MacAddressIntf::mACAddress(value);
Ratan Guptabd303b12017-08-18 17:10:07 +0530840
William A. Kennington III1137a972019-04-20 20:49:58 -0700841 auto interface = interfaceName();
William A. Kennington III7b9e8bd2019-04-23 19:31:31 -0700842 auto envVar = interfaceToUbootEthAddr(interface.c_str());
843 if (envVar)
844 {
845 execute("/sbin/fw_setenv", "fw_setenv", envVar->c_str(),
846 value.c_str());
847 }
William A. Kennington III15787212019-04-23 19:18:01 -0700848 // TODO: would remove the call below and
849 // just restart systemd-netwokd
William A. Kennington III1137a972019-04-20 20:49:58 -0700850 // through https://github.com/systemd/systemd/issues/6696
851 execute("/sbin/ip", "ip", "link", "set", "dev", interface.c_str(),
852 "down");
William A. Kennington III15787212019-04-23 19:18:01 -0700853 manager.writeToConfigurationFile();
Ratan Gupta677ae122017-09-18 16:28:50 +0530854 }
William A. Kennington III1137a972019-04-20 20:49:58 -0700855
856 return value;
Ratan Guptabd303b12017-08-18 17:10:07 +0530857}
858
Ratan Guptae9c9b812017-09-22 17:15:37 +0530859void EthernetInterface::deleteAll()
860{
Gunnar Mills57d9c502018-09-14 14:42:34 -0500861 if (EthernetInterfaceIntf::dHCPEnabled())
Ratan Guptae9c9b812017-09-22 17:15:37 +0530862 {
863 log<level::INFO>("DHCP enabled on the interface"),
Gunnar Mills57d9c502018-09-14 14:42:34 -0500864 entry("INTERFACE=%s", interfaceName().c_str());
Ratan Guptae9c9b812017-09-22 17:15:37 +0530865 }
866
867 // clear all the ip on the interface
868 addrs.clear();
869 manager.writeToConfigurationFile();
870}
871
Gunnar Mills57d9c502018-09-14 14:42:34 -0500872} // namespace network
873} // namespace phosphor