blob: fc2142499a25eef994e528d99da3ef6a68f65c85 [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 Gupta29b0e432017-05-25 12:51:40 +053033 bool dhcpEnabled) :
Ratan Gupta82549cc2017-04-21 08:45:23 +053034 Ifaces(bus, objPath.c_str(), true),
35 bus(bus)
Ratan Gupta29b0e432017-05-25 12:51:40 +053036
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 Gupta29b0e432017-05-25 12:51:40 +053042 // Emit deferred signal.
43 this->emit_object_added();
44}
45
46void EthernetInterface::setAddressList(const AddrList& addrs)
47{
Ratan Gupta82549cc2017-04-21 08:45:23 +053048 std::string gateway;
49
50 IP::Protocol addressType = IP::Protocol::IPv4;
Ratan Gupta29b0e432017-05-25 12:51:40 +053051 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ratan Gupta82549cc2017-04-21 08:45:23 +053052
53 for (auto addr : addrs)
54 {
55 if (addr.addrType == AF_INET6)
56 {
57 addressType = IP::Protocol::IPv6;
58 }
59
Ratan Gupta65e5abe2017-05-23 13:20:44 +053060 std::string ipAddressObjectPath = generateObjectPath(addressType,
61 addr.ipaddress,
62 addr.prefix,
63 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +053064 this->addrs.emplace(
65 std::make_pair(
Ratan Gupta719f83a2017-06-02 11:54:53 +053066 addr.ipaddress,
67 std::make_unique<phosphor::network::IPAddress>(
68 bus,
69 ipAddressObjectPath.c_str(),
70 *this,
71 addressType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053072 addr.ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +053073 origin,
Ratan Gupta719f83a2017-06-02 11:54:53 +053074 addr.prefix,
75 gateway)));
Ratan Gupta82549cc2017-04-21 08:45:23 +053076 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +053077}
78
Ratan Gupta82549cc2017-04-21 08:45:23 +053079void EthernetInterface::iP(IP::Protocol protType,
80 std::string ipaddress,
81 uint8_t prefixLength,
82 std::string gateway)
83{
Ratan Gupta29b0e432017-05-25 12:51:40 +053084 IP::AddressOrigin origin = IP::AddressOrigin::Static;
85
Ratan Gupta65e5abe2017-05-23 13:20:44 +053086 std::string objectPath = generateObjectPath(protType,
87 ipaddress,
88 prefixLength,
89 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +053090
91 this->addrs.emplace(
92 std::make_pair(ipaddress,
93 std::make_unique<phosphor::network::IPAddress>(
94 bus,
95 objectPath.c_str(),
96 *this,
Ratan Gupta65e5abe2017-05-23 13:20:44 +053097 protType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053098 ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +053099 origin,
Ratan Gupta82549cc2017-04-21 08:45:23 +0530100 prefixLength,
101 gateway)));
102}
103
104
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530105/*
106Note: We don't have support for ethtool now
107will enable this code once we bring the ethtool
108in the image.
109TODO: https://github.com/openbmc/openbmc/issues/1484
110*/
Ratan Gupta82549cc2017-04-21 08:45:23 +0530111
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530112InterfaceInfo EthernetInterface::getInterfaceInfo() const
113{
114 int sock{-1};
115 struct ifreq ifr{0};
116 struct ethtool_cmd edata{0};
117 LinkSpeed speed {0};
118 Autoneg autoneg {0};
119 DuplexMode duplex {0};
120 do
121 {
122 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
123 if (sock < 0)
124 {
125 log<level::ERR>("socket creation failed:",
126 entry("ERROR=%s", strerror(errno)));
127 break;
128 }
129
130 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
131 ifr.ifr_data = reinterpret_cast<char*>(&edata);
132
133 edata.cmd = ETHTOOL_GSET;
134
135 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
136 {
137 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
138 entry("ERROR=%s", strerror(errno)));
139 break;
140
141 }
142 speed = edata.speed;
143 duplex = edata.duplex;
144 autoneg = edata.autoneg;
145 }
146 while (0);
147
148 if (sock)
149 {
150 close(sock);
151 }
152 return std::make_tuple(speed, duplex, autoneg);
153}
154
155/** @brief get the mac address of the interface.
156 * @return macaddress on success
157 */
158
159std::string EthernetInterface::getMACAddress() const
160{
161 struct ifreq ifr;
162 struct ifconf ifc;
163 char buf[SIZE_BUFF];
164 char macAddress[SIZE_MAC] = "";
165
166 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
167 if (sock < 0)
168 {
169 log<level::ERR>("socket creation failed:",
170 entry("ERROR=%s", strerror(errno)));
171 return macAddress;
172 }
173
174 ifc.ifc_len = sizeof(buf);
175 ifc.ifc_buf = buf;
176 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
177 {
178 log<level::ERR>("ioctl failed for SIOCGIFCONF:",
179 entry("ERROR=%s", strerror(errno)));
180 return macAddress;
181 }
182
183 struct ifreq* it = ifc.ifc_req;
184 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
185
186 for (; it != end; ++it)
187 {
188 if (interfaceName() == it->ifr_name)
189 {
190 break;
191 }
192 }
193 if (interfaceName() == it->ifr_name)
194 {
195 strcpy(ifr.ifr_name, it->ifr_name);
196 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
197 {
198 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
199 entry("ERROR=%s", strerror(errno)));
200 return macAddress;
201 }
202
203 snprintf(macAddress, SIZE_MAC, MAC_ADDRESS_FORMAT,
204 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
205 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
206 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
207 }
208 return macAddress;
209}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530210
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530211std::string EthernetInterface::generateId(const std::string& ipaddress,
212 uint8_t prefixLength,
213 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530214{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530215 std::stringstream hexId;
216 std::string hashString = ipaddress;
217 hashString += std::to_string(prefixLength);
218 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530219
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530220 // Only want 8 hex digits.
221 hexId << std::hex << ((std::hash<std::string> {}(
222 hashString)) & 0xFFFFFFFF);
223 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530224}
225
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530226void EthernetInterface::deleteObject(const std::string& ipaddress)
227{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530228 auto it = addrs.find(ipaddress);
229 if( it == addrs.end())
230 {
231 log<level::ERR>("DeleteObject:Unable to find the object.");
232 return;
233 }
234 this->addrs.erase(it);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530235}
236
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530237std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
238 const std::string& ipaddress,
239 uint8_t prefixLength,
240 const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530241{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530242 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530243 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530244 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
245
246 std::experimental::filesystem::path objectPath;
247 objectPath /= std::string(OBJ_NETWORK);
248 objectPath /= interfaceName();
249 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530250 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530251 return objectPath.string();
252
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530253}
254
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530255}//namespace network
256}//namespace phosphor