blob: ef7b9df09915442ea8cc01f172bec94e4108f1cc [file] [log] [blame]
Ratan Gupta82549cc2017-04-21 08:45:23 +05301#include "config.h"
2#include "ipaddress.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05303#include "ethernet_interface.hpp"
Ratan Gupta5978dd12017-07-25 13:47:13 +05304#include "vlan_interface.hpp"
Ratan Gupta4f1c18b2017-05-25 12:59:35 +05305#include "network_manager.hpp"
Ratan Guptafc2c7242017-05-29 08:46:06 +05306#include "routing_table.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05307
8#include <phosphor-logging/log.hpp>
9
Ratan Gupta82549cc2017-04-21 08:45:23 +053010#include <arpa/inet.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053011#include <linux/ethtool.h>
12#include <net/if.h>
13#include <linux/sockios.h>
14#include <netinet/in.h>
15#include <sys/ioctl.h>
16#include <sys/socket.h>
17#include <unistd.h>
18
Ratan Gupta82549cc2017-04-21 08:45:23 +053019#include <string>
20#include <algorithm>
Ratan Gupta65e5abe2017-05-23 13:20:44 +053021#include <sstream>
Ratan Gupta82549cc2017-04-21 08:45:23 +053022#include <experimental/filesystem>
23
Ratan Gupta91a99cc2017-04-14 16:32:09 +053024namespace phosphor
25{
26namespace network
27{
28
29using namespace phosphor::logging;
30constexpr auto MAC_ADDRESS_FORMAT = "%02X:%02X:%02X:%02X:%02X:%02X";
31constexpr size_t SIZE_MAC = 18;
32constexpr size_t SIZE_BUFF = 512;
33
34EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
35 const std::string& objPath,
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053036 bool dhcpEnabled,
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053037 Manager& parent,
38 bool emitSignal) :
Ratan Gupta82549cc2017-04-21 08:45:23 +053039 Ifaces(bus, objPath.c_str(), true),
Ratan Gupta5978dd12017-07-25 13:47:13 +053040 confDir(NETWORK_CONF_DIR),
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053041 bus(bus),
Ratan Gupta47722dc2017-05-26 18:32:23 +053042 manager(parent),
43 objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053044{
45 auto intfName = objPath.substr(objPath.rfind("/") + 1);
Ratan Gupta5978dd12017-07-25 13:47:13 +053046 std::replace(intfName.begin(), intfName.end(), '_', '.');
Ratan Gupta91a99cc2017-04-14 16:32:09 +053047 interfaceName(intfName);
48 dHCPEnabled(dhcpEnabled);
49 mACAddress(getMACAddress());
Ratan Gupta5978dd12017-07-25 13:47:13 +053050
Ratan Gupta29b0e432017-05-25 12:51:40 +053051 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053052 if (emitSignal)
53 {
54 this->emit_object_added();
55 }
Ratan Gupta29b0e432017-05-25 12:51:40 +053056}
57
Ratan Gupta87c13982017-06-15 09:27:27 +053058void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +053059{
Ratan Gupta82549cc2017-04-21 08:45:23 +053060 std::string gateway;
Ratan Gupta87c13982017-06-15 09:27:27 +053061 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +053062
Ratan Gupta87c13982017-06-15 09:27:27 +053063 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta5978dd12017-07-25 13:47:13 +053064
Ratan Gupta82549cc2017-04-21 08:45:23 +053065 IP::Protocol addressType = IP::Protocol::IPv4;
Ratan Gupta29b0e432017-05-25 12:51:40 +053066 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ratan Guptafc2c7242017-05-29 08:46:06 +053067 route::Table routingTable;
Ratan Gupta5978dd12017-07-25 13:47:13 +053068
Ratan Gupta6a387c12017-08-03 13:26:19 +053069 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +053070 {
71 if (addr.addrType == AF_INET6)
72 {
73 addressType = IP::Protocol::IPv6;
74 }
Ratan Guptafc2c7242017-05-29 08:46:06 +053075 if (dHCPEnabled())
76 {
77 origin = IP::AddressOrigin::DHCP;
78 }
79 else if (isLinkLocal(addr.ipaddress))
80 {
81 origin = IP::AddressOrigin::LinkLocal;
82 }
83 gateway = routingTable.getGateway(addr.addrType, addr.ipaddress, addr.prefix);
Ratan Gupta82549cc2017-04-21 08:45:23 +053084
Ratan Gupta65e5abe2017-05-23 13:20:44 +053085 std::string ipAddressObjectPath = generateObjectPath(addressType,
86 addr.ipaddress,
87 addr.prefix,
88 gateway);
Ratan Guptafc2c7242017-05-29 08:46:06 +053089
Ratan Gupta82549cc2017-04-21 08:45:23 +053090 this->addrs.emplace(
Ratan Guptae578d562017-08-02 07:04:16 +053091 std::move(addr.ipaddress),
92 std::make_shared<phosphor::network::IPAddress>(
Ratan Gupta719f83a2017-06-02 11:54:53 +053093 bus,
94 ipAddressObjectPath.c_str(),
95 *this,
96 addressType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053097 addr.ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +053098 origin,
Ratan Gupta719f83a2017-06-02 11:54:53 +053099 addr.prefix,
Ratan Guptae578d562017-08-02 07:04:16 +0530100 gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +0530101 }
Ratan Guptafc2c7242017-05-29 08:46:06 +0530102
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530103}
104
Ratan Gupta82549cc2017-04-21 08:45:23 +0530105void EthernetInterface::iP(IP::Protocol protType,
106 std::string ipaddress,
107 uint8_t prefixLength,
108 std::string gateway)
109{
Ratan Guptafc2c7242017-05-29 08:46:06 +0530110
111 if (dHCPEnabled())
112 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530113 log<level::INFO>("DHCP enabled on the interface"),
114 entry("INTERFACE=%s",interfaceName());
Ratan Guptafc2c7242017-05-29 08:46:06 +0530115 return;
116 }
117
Ratan Gupta29b0e432017-05-25 12:51:40 +0530118 IP::AddressOrigin origin = IP::AddressOrigin::Static;
119
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530120 std::string objectPath = generateObjectPath(protType,
121 ipaddress,
122 prefixLength,
123 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530124
125 this->addrs.emplace(
Ratan Guptae578d562017-08-02 07:04:16 +0530126 std::move(ipaddress),
127 std::make_shared<phosphor::network::IPAddress>(
128 bus,
129 objectPath.c_str(),
130 *this,
131 protType,
132 ipaddress,
133 origin,
134 prefixLength,
135 gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530136
137 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530138}
139
140
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530141/*
142Note: We don't have support for ethtool now
143will enable this code once we bring the ethtool
144in the image.
145TODO: https://github.com/openbmc/openbmc/issues/1484
146*/
Ratan Gupta82549cc2017-04-21 08:45:23 +0530147
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530148InterfaceInfo EthernetInterface::getInterfaceInfo() const
149{
150 int sock{-1};
151 struct ifreq ifr{0};
152 struct ethtool_cmd edata{0};
153 LinkSpeed speed {0};
154 Autoneg autoneg {0};
155 DuplexMode duplex {0};
156 do
157 {
158 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
159 if (sock < 0)
160 {
161 log<level::ERR>("socket creation failed:",
162 entry("ERROR=%s", strerror(errno)));
163 break;
164 }
165
166 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
167 ifr.ifr_data = reinterpret_cast<char*>(&edata);
168
169 edata.cmd = ETHTOOL_GSET;
170
171 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
172 {
173 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
174 entry("ERROR=%s", strerror(errno)));
175 break;
176
177 }
178 speed = edata.speed;
179 duplex = edata.duplex;
180 autoneg = edata.autoneg;
181 }
182 while (0);
183
184 if (sock)
185 {
186 close(sock);
187 }
188 return std::make_tuple(speed, duplex, autoneg);
189}
190
191/** @brief get the mac address of the interface.
192 * @return macaddress on success
193 */
194
195std::string EthernetInterface::getMACAddress() const
196{
197 struct ifreq ifr;
198 struct ifconf ifc;
199 char buf[SIZE_BUFF];
200 char macAddress[SIZE_MAC] = "";
201
202 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
203 if (sock < 0)
204 {
205 log<level::ERR>("socket creation failed:",
206 entry("ERROR=%s", strerror(errno)));
207 return macAddress;
208 }
209
210 ifc.ifc_len = sizeof(buf);
211 ifc.ifc_buf = buf;
212 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
213 {
214 log<level::ERR>("ioctl failed for SIOCGIFCONF:",
215 entry("ERROR=%s", strerror(errno)));
216 return macAddress;
217 }
218
219 struct ifreq* it = ifc.ifc_req;
220 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
221
222 for (; it != end; ++it)
223 {
224 if (interfaceName() == it->ifr_name)
225 {
226 break;
227 }
228 }
229 if (interfaceName() == it->ifr_name)
230 {
231 strcpy(ifr.ifr_name, it->ifr_name);
232 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
233 {
234 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
235 entry("ERROR=%s", strerror(errno)));
236 return macAddress;
237 }
238
239 snprintf(macAddress, SIZE_MAC, MAC_ADDRESS_FORMAT,
240 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
241 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
242 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
243 }
244 return macAddress;
245}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530246
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530247std::string EthernetInterface::generateId(const std::string& ipaddress,
248 uint8_t prefixLength,
249 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530250{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530251 std::stringstream hexId;
252 std::string hashString = ipaddress;
253 hashString += std::to_string(prefixLength);
254 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530255
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530256 // Only want 8 hex digits.
257 hexId << std::hex << ((std::hash<std::string> {}(
Ratan Guptafc2c7242017-05-29 08:46:06 +0530258 hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530259 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530260}
261
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530262void EthernetInterface::deleteObject(const std::string& ipaddress)
263{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530264 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530265 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530266 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530267 log<level::ERR>("DeleteObject:Unable to find the object.");
268 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530269 }
270 this->addrs.erase(it);
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530271 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530272}
273
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530274std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
275 const std::string& ipaddress,
276 uint8_t prefixLength,
277 const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530278{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530279 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530280 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530281 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
282
283 std::experimental::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530284 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530285 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530286 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530287 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530288}
289
Ratan Gupta87c13982017-06-15 09:27:27 +0530290bool EthernetInterface::dHCPEnabled(bool value)
291{
Ratan Gupta5978dd12017-07-25 13:47:13 +0530292 if (value == EthernetInterfaceIntf::dHCPEnabled())
293 {
294 return value;
295 }
296
Ratan Gupta87c13982017-06-15 09:27:27 +0530297 EthernetInterfaceIntf::dHCPEnabled(value);
Ratan Gupta5978dd12017-07-25 13:47:13 +0530298 if (value)
Ratan Gupta87c13982017-06-15 09:27:27 +0530299 {
300 manager.writeToConfigurationFile();
301 createIPAddressObjects();
302 }
303 return value;
304}
305
Ratan Gupta5978dd12017-07-25 13:47:13 +0530306void EthernetInterface::createVLAN(VlanId id)
307{
308 std::string vlanInterfaceName = interfaceName() + "." +
309 std::to_string(id);
310 std::string path = objPath;
311 path += "_" + std::to_string(id);
312
313
314 auto vlanIntf = std::make_unique<phosphor::network::VlanInterface>(
315 bus,
316 path.c_str(),
317 EthernetInterfaceIntf::dHCPEnabled(),
318 id,
319 *this,
320 manager);
321
322 // write the device file for the vlan interface.
323 vlanIntf->writeDeviceFile();
324
325 this->vlanInterfaces.emplace(std::move(vlanInterfaceName),
326 std::move(vlanIntf));
327 // write the new vlan device entry to the configuration(network) file.
328 manager.writeToConfigurationFile();
329
330}
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530331}//namespace network
332}//namespace phosphor