blob: 06dd4167548cc6b940aa64b991e064a1d42d1bf5 [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"
4
5#include <phosphor-logging/log.hpp>
6
Ratan Gupta82549cc2017-04-21 08:45:23 +05307#include <arpa/inet.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +05308#include <linux/ethtool.h>
9#include <net/if.h>
10#include <linux/sockios.h>
11#include <netinet/in.h>
12#include <sys/ioctl.h>
13#include <sys/socket.h>
14#include <unistd.h>
15
Ratan Gupta82549cc2017-04-21 08:45:23 +053016#include <string>
17#include <algorithm>
Ratan Gupta65e5abe2017-05-23 13:20:44 +053018#include <sstream>
Ratan Gupta82549cc2017-04-21 08:45:23 +053019#include <experimental/filesystem>
20
Ratan Gupta91a99cc2017-04-14 16:32:09 +053021namespace phosphor
22{
23namespace network
24{
25
26using namespace phosphor::logging;
27constexpr auto MAC_ADDRESS_FORMAT = "%02X:%02X:%02X:%02X:%02X:%02X";
28constexpr size_t SIZE_MAC = 18;
29constexpr size_t SIZE_BUFF = 512;
30
31EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
32 const std::string& objPath,
Ratan Gupta82549cc2017-04-21 08:45:23 +053033 bool dhcpEnabled,
34 const AddrList& addrs) :
35 Ifaces(bus, objPath.c_str(), true),
36 bus(bus)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053037{
38 auto intfName = objPath.substr(objPath.rfind("/") + 1);
39 interfaceName(intfName);
40 dHCPEnabled(dhcpEnabled);
41 mACAddress(getMACAddress());
Ratan Gupta82549cc2017-04-21 08:45:23 +053042 std::string gateway;
43
44 IP::Protocol addressType = IP::Protocol::IPv4;
45
46 for (auto addr : addrs)
47 {
48 if (addr.addrType == AF_INET6)
49 {
50 addressType = IP::Protocol::IPv6;
51 }
52
Ratan Gupta65e5abe2017-05-23 13:20:44 +053053 std::string ipAddressObjectPath = generateObjectPath(addressType,
54 addr.ipaddress,
55 addr.prefix,
56 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +053057 this->addrs.emplace(
58 std::make_pair(
Ratan Gupta719f83a2017-06-02 11:54:53 +053059 addr.ipaddress,
60 std::make_unique<phosphor::network::IPAddress>(
61 bus,
62 ipAddressObjectPath.c_str(),
63 *this,
64 addressType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053065 addr.ipaddress,
Ratan Gupta719f83a2017-06-02 11:54:53 +053066 addr.prefix,
67 gateway)));
Ratan Gupta82549cc2017-04-21 08:45:23 +053068 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +053069 // Emit deferred signal.
70 this->emit_object_added();
71}
72
Ratan Gupta82549cc2017-04-21 08:45:23 +053073void EthernetInterface::iP(IP::Protocol protType,
74 std::string ipaddress,
75 uint8_t prefixLength,
76 std::string gateway)
77{
Ratan Gupta65e5abe2017-05-23 13:20:44 +053078 std::string objectPath = generateObjectPath(protType,
79 ipaddress,
80 prefixLength,
81 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +053082
83 this->addrs.emplace(
84 std::make_pair(ipaddress,
85 std::make_unique<phosphor::network::IPAddress>(
86 bus,
87 objectPath.c_str(),
88 *this,
Ratan Gupta65e5abe2017-05-23 13:20:44 +053089 protType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053090 ipaddress,
91 prefixLength,
92 gateway)));
93}
94
95
Ratan Gupta91a99cc2017-04-14 16:32:09 +053096/*
97Note: We don't have support for ethtool now
98will enable this code once we bring the ethtool
99in the image.
100TODO: https://github.com/openbmc/openbmc/issues/1484
101*/
Ratan Gupta82549cc2017-04-21 08:45:23 +0530102
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530103InterfaceInfo EthernetInterface::getInterfaceInfo() const
104{
105 int sock{-1};
106 struct ifreq ifr{0};
107 struct ethtool_cmd edata{0};
108 LinkSpeed speed {0};
109 Autoneg autoneg {0};
110 DuplexMode duplex {0};
111 do
112 {
113 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
114 if (sock < 0)
115 {
116 log<level::ERR>("socket creation failed:",
117 entry("ERROR=%s", strerror(errno)));
118 break;
119 }
120
121 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
122 ifr.ifr_data = reinterpret_cast<char*>(&edata);
123
124 edata.cmd = ETHTOOL_GSET;
125
126 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
127 {
128 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
129 entry("ERROR=%s", strerror(errno)));
130 break;
131
132 }
133 speed = edata.speed;
134 duplex = edata.duplex;
135 autoneg = edata.autoneg;
136 }
137 while (0);
138
139 if (sock)
140 {
141 close(sock);
142 }
143 return std::make_tuple(speed, duplex, autoneg);
144}
145
146/** @brief get the mac address of the interface.
147 * @return macaddress on success
148 */
149
150std::string EthernetInterface::getMACAddress() const
151{
152 struct ifreq ifr;
153 struct ifconf ifc;
154 char buf[SIZE_BUFF];
155 char macAddress[SIZE_MAC] = "";
156
157 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
158 if (sock < 0)
159 {
160 log<level::ERR>("socket creation failed:",
161 entry("ERROR=%s", strerror(errno)));
162 return macAddress;
163 }
164
165 ifc.ifc_len = sizeof(buf);
166 ifc.ifc_buf = buf;
167 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
168 {
169 log<level::ERR>("ioctl failed for SIOCGIFCONF:",
170 entry("ERROR=%s", strerror(errno)));
171 return macAddress;
172 }
173
174 struct ifreq* it = ifc.ifc_req;
175 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
176
177 for (; it != end; ++it)
178 {
179 if (interfaceName() == it->ifr_name)
180 {
181 break;
182 }
183 }
184 if (interfaceName() == it->ifr_name)
185 {
186 strcpy(ifr.ifr_name, it->ifr_name);
187 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
188 {
189 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
190 entry("ERROR=%s", strerror(errno)));
191 return macAddress;
192 }
193
194 snprintf(macAddress, SIZE_MAC, MAC_ADDRESS_FORMAT,
195 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
196 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
197 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
198 }
199 return macAddress;
200}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530201
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530202std::string EthernetInterface::generateId(const std::string& ipaddress,
203 uint8_t prefixLength,
204 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530205{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530206 std::stringstream hexId;
207 std::string hashString = ipaddress;
208 hashString += std::to_string(prefixLength);
209 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530210
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530211 // Only want 8 hex digits.
212 hexId << std::hex << ((std::hash<std::string> {}(
213 hashString)) & 0xFFFFFFFF);
214 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530215}
216
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530217void EthernetInterface::deleteObject(const std::string& ipaddress)
218{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530219 this->addrs.erase(addrs.find(ipaddress));
220}
221
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530222std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
223 const std::string& ipaddress,
224 uint8_t prefixLength,
225 const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530226{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530227 std::string type = convertForMessage(addressType);
228 type = type.substr(type.rfind('.')+1);
229 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
230
231 std::experimental::filesystem::path objectPath;
232 objectPath /= std::string(OBJ_NETWORK);
233 objectPath /= interfaceName();
234 objectPath /= type;
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530235 objectPath /= generateId(ipaddress,prefixLength,gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530236 return objectPath.string();
237
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530238}
239
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530240}//namespace network
241}//namespace phosphor