blob: 20b3e31800c17acafb80e0e2947ded4eee7b8cc0 [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>
18#include <experimental/filesystem>
19
Ratan Gupta91a99cc2017-04-14 16:32:09 +053020namespace phosphor
21{
22namespace network
23{
24
25using namespace phosphor::logging;
26constexpr auto MAC_ADDRESS_FORMAT = "%02X:%02X:%02X:%02X:%02X:%02X";
27constexpr size_t SIZE_MAC = 18;
28constexpr size_t SIZE_BUFF = 512;
29
30EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
31 const std::string& objPath,
Ratan Gupta82549cc2017-04-21 08:45:23 +053032 bool dhcpEnabled,
33 const AddrList& addrs) :
34 Ifaces(bus, objPath.c_str(), true),
35 bus(bus)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053036{
37 auto intfName = objPath.substr(objPath.rfind("/") + 1);
38 interfaceName(intfName);
39 dHCPEnabled(dhcpEnabled);
40 mACAddress(getMACAddress());
Ratan Gupta82549cc2017-04-21 08:45:23 +053041 std::string gateway;
42
43 IP::Protocol addressType = IP::Protocol::IPv4;
44
45 for (auto addr : addrs)
46 {
47 if (addr.addrType == AF_INET6)
48 {
49 addressType = IP::Protocol::IPv6;
50 }
51
52 std::string ipAddressObjectPath = getAddressObjectPath(addressType);
53 this->addrs.emplace(
54 std::make_pair(
55 addr.ipaddress,
56 std::make_unique<phosphor::network::IPAddress>(
57 bus,
58 ipAddressObjectPath.c_str(),
59 *this,
60 addressType,
61 addr.ipaddress,
62 addr.prefix,
63 gateway)));
64 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +053065 // Emit deferred signal.
66 this->emit_object_added();
67}
68
Ratan Gupta82549cc2017-04-21 08:45:23 +053069void EthernetInterface::iP(IP::Protocol protType,
70 std::string ipaddress,
71 uint8_t prefixLength,
72 std::string gateway)
73{
74
75 IP::Protocol protocolType = protType;
76 std::string objectPath = getAddressObjectPath(protocolType);
77
78 this->addrs.emplace(
79 std::make_pair(ipaddress,
80 std::make_unique<phosphor::network::IPAddress>(
81 bus,
82 objectPath.c_str(),
83 *this,
84 protocolType,
85 ipaddress,
86 prefixLength,
87 gateway)));
88}
89
90
Ratan Gupta91a99cc2017-04-14 16:32:09 +053091/*
92Note: We don't have support for ethtool now
93will enable this code once we bring the ethtool
94in the image.
95TODO: https://github.com/openbmc/openbmc/issues/1484
96*/
Ratan Gupta82549cc2017-04-21 08:45:23 +053097
Ratan Gupta91a99cc2017-04-14 16:32:09 +053098InterfaceInfo EthernetInterface::getInterfaceInfo() const
99{
100 int sock{-1};
101 struct ifreq ifr{0};
102 struct ethtool_cmd edata{0};
103 LinkSpeed speed {0};
104 Autoneg autoneg {0};
105 DuplexMode duplex {0};
106 do
107 {
108 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
109 if (sock < 0)
110 {
111 log<level::ERR>("socket creation failed:",
112 entry("ERROR=%s", strerror(errno)));
113 break;
114 }
115
116 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
117 ifr.ifr_data = reinterpret_cast<char*>(&edata);
118
119 edata.cmd = ETHTOOL_GSET;
120
121 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
122 {
123 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
124 entry("ERROR=%s", strerror(errno)));
125 break;
126
127 }
128 speed = edata.speed;
129 duplex = edata.duplex;
130 autoneg = edata.autoneg;
131 }
132 while (0);
133
134 if (sock)
135 {
136 close(sock);
137 }
138 return std::make_tuple(speed, duplex, autoneg);
139}
140
141/** @brief get the mac address of the interface.
142 * @return macaddress on success
143 */
144
145std::string EthernetInterface::getMACAddress() const
146{
147 struct ifreq ifr;
148 struct ifconf ifc;
149 char buf[SIZE_BUFF];
150 char macAddress[SIZE_MAC] = "";
151
152 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
153 if (sock < 0)
154 {
155 log<level::ERR>("socket creation failed:",
156 entry("ERROR=%s", strerror(errno)));
157 return macAddress;
158 }
159
160 ifc.ifc_len = sizeof(buf);
161 ifc.ifc_buf = buf;
162 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
163 {
164 log<level::ERR>("ioctl failed for SIOCGIFCONF:",
165 entry("ERROR=%s", strerror(errno)));
166 return macAddress;
167 }
168
169 struct ifreq* it = ifc.ifc_req;
170 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
171
172 for (; it != end; ++it)
173 {
174 if (interfaceName() == it->ifr_name)
175 {
176 break;
177 }
178 }
179 if (interfaceName() == it->ifr_name)
180 {
181 strcpy(ifr.ifr_name, it->ifr_name);
182 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
183 {
184 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
185 entry("ERROR=%s", strerror(errno)));
186 return macAddress;
187 }
188
189 snprintf(macAddress, SIZE_MAC, MAC_ADDRESS_FORMAT,
190 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
191 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
192 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
193 }
194 return macAddress;
195}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530196
Ratan Gupta82549cc2017-04-21 08:45:23 +0530197size_t EthernetInterface::getAddressCount(IP::Protocol addressType) const
198{
199 size_t count = 0;
200
201 std::for_each(addrs.cbegin(), addrs.cend(),
202 [&count,addressType](const auto & addr)
203 {
204 if (addr.second->type() == addressType)
205 {
206 count += 1;
207 }
208 });
209
210 return count;
211}
212
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530213void EthernetInterface::deleteObject(const std::string& ipaddress)
214{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530215 this->addrs.erase(addrs.find(ipaddress));
216}
217
218std::string EthernetInterface::getAddressObjectPath(IP::Protocol
219 addressType) const
220{
221
222 std::string type = convertForMessage(addressType);
223 type = type.substr(type.rfind('.')+1);
224 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
225
226 std::experimental::filesystem::path objectPath;
227 objectPath /= std::string(OBJ_NETWORK);
228 objectPath /= interfaceName();
229 objectPath /= type;
230 objectPath /= std::to_string(getAddressCount(addressType));
231 return objectPath.string();
232
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530233}
234
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530235}//namespace network
236}//namespace phosphor