blob: d7648a247300dc5a2e0d731f2701698cff7fc4bf [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 Gupta4f1c18b2017-05-25 12:59:35 +05304#include "network_manager.hpp"
Ratan Guptafc2c7242017-05-29 08:46:06 +05305#include "routing_table.hpp"
Ratan Gupta91a99cc2017-04-14 16:32:09 +05306
7#include <phosphor-logging/log.hpp>
8
Ratan Gupta82549cc2017-04-21 08:45:23 +05309#include <arpa/inet.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +053010#include <linux/ethtool.h>
11#include <net/if.h>
12#include <linux/sockios.h>
13#include <netinet/in.h>
14#include <sys/ioctl.h>
15#include <sys/socket.h>
16#include <unistd.h>
17
Ratan Gupta82549cc2017-04-21 08:45:23 +053018#include <string>
19#include <algorithm>
Ratan Gupta65e5abe2017-05-23 13:20:44 +053020#include <sstream>
Ratan Gupta82549cc2017-04-21 08:45:23 +053021#include <experimental/filesystem>
22
Ratan Gupta91a99cc2017-04-14 16:32:09 +053023namespace phosphor
24{
25namespace network
26{
27
28using namespace phosphor::logging;
29constexpr auto MAC_ADDRESS_FORMAT = "%02X:%02X:%02X:%02X:%02X:%02X";
30constexpr size_t SIZE_MAC = 18;
31constexpr size_t SIZE_BUFF = 512;
32
33EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
34 const std::string& objPath,
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053035 bool dhcpEnabled,
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053036 Manager& parent,
37 bool emitSignal) :
Ratan Gupta82549cc2017-04-21 08:45:23 +053038 Ifaces(bus, objPath.c_str(), true),
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053039 bus(bus),
Ratan Gupta47722dc2017-05-26 18:32:23 +053040 manager(parent),
41 objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053042{
43 auto intfName = objPath.substr(objPath.rfind("/") + 1);
44 interfaceName(intfName);
45 dHCPEnabled(dhcpEnabled);
46 mACAddress(getMACAddress());
Ratan Gupta87c13982017-06-15 09:27:27 +053047 createIPAddressObjects();
Ratan Gupta29b0e432017-05-25 12:51:40 +053048 // Emit deferred signal.
Ratan Gupta3d3e4fc2017-07-25 13:38:19 +053049 if (emitSignal)
50 {
51 this->emit_object_added();
52 }
Ratan Gupta29b0e432017-05-25 12:51:40 +053053}
54
Ratan Gupta87c13982017-06-15 09:27:27 +053055void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +053056{
Ratan Gupta82549cc2017-04-21 08:45:23 +053057 std::string gateway;
Ratan Gupta87c13982017-06-15 09:27:27 +053058 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +053059
Ratan Gupta87c13982017-06-15 09:27:27 +053060 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta82549cc2017-04-21 08:45:23 +053061 IP::Protocol addressType = IP::Protocol::IPv4;
Ratan Gupta29b0e432017-05-25 12:51:40 +053062 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ratan Guptafc2c7242017-05-29 08:46:06 +053063 route::Table routingTable;
Ratan Gupta6a387c12017-08-03 13:26:19 +053064 for (auto& addr : addrs)
Ratan Gupta82549cc2017-04-21 08:45:23 +053065 {
66 if (addr.addrType == AF_INET6)
67 {
68 addressType = IP::Protocol::IPv6;
69 }
Ratan Guptafc2c7242017-05-29 08:46:06 +053070 if (dHCPEnabled())
71 {
72 origin = IP::AddressOrigin::DHCP;
73 }
74 else if (isLinkLocal(addr.ipaddress))
75 {
76 origin = IP::AddressOrigin::LinkLocal;
77 }
78 gateway = routingTable.getGateway(addr.addrType, addr.ipaddress, addr.prefix);
Ratan Gupta82549cc2017-04-21 08:45:23 +053079
Ratan Gupta65e5abe2017-05-23 13:20:44 +053080 std::string ipAddressObjectPath = generateObjectPath(addressType,
81 addr.ipaddress,
82 addr.prefix,
83 gateway);
Ratan Guptafc2c7242017-05-29 08:46:06 +053084
Ratan Gupta82549cc2017-04-21 08:45:23 +053085 this->addrs.emplace(
Ratan Guptae578d562017-08-02 07:04:16 +053086 std::move(addr.ipaddress),
87 std::make_shared<phosphor::network::IPAddress>(
Ratan Gupta719f83a2017-06-02 11:54:53 +053088 bus,
89 ipAddressObjectPath.c_str(),
90 *this,
91 addressType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053092 addr.ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +053093 origin,
Ratan Gupta719f83a2017-06-02 11:54:53 +053094 addr.prefix,
Ratan Guptae578d562017-08-02 07:04:16 +053095 gateway));
Ratan Gupta82549cc2017-04-21 08:45:23 +053096 }
Ratan Guptafc2c7242017-05-29 08:46:06 +053097
Ratan Gupta91a99cc2017-04-14 16:32:09 +053098}
99
Ratan Gupta82549cc2017-04-21 08:45:23 +0530100void EthernetInterface::iP(IP::Protocol protType,
101 std::string ipaddress,
102 uint8_t prefixLength,
103 std::string gateway)
104{
Ratan Guptafc2c7242017-05-29 08:46:06 +0530105
106 if (dHCPEnabled())
107 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530108 log<level::INFO>("DHCP enabled on the interface"),
109 entry("INTERFACE=%s",interfaceName());
Ratan Guptafc2c7242017-05-29 08:46:06 +0530110 return;
111 }
112
Ratan Gupta29b0e432017-05-25 12:51:40 +0530113 IP::AddressOrigin origin = IP::AddressOrigin::Static;
114
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530115 std::string objectPath = generateObjectPath(protType,
116 ipaddress,
117 prefixLength,
118 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530119
120 this->addrs.emplace(
Ratan Guptae578d562017-08-02 07:04:16 +0530121 std::move(ipaddress),
122 std::make_shared<phosphor::network::IPAddress>(
123 bus,
124 objectPath.c_str(),
125 *this,
126 protType,
127 ipaddress,
128 origin,
129 prefixLength,
130 gateway));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530131
132 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530133}
134
135
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530136/*
137Note: We don't have support for ethtool now
138will enable this code once we bring the ethtool
139in the image.
140TODO: https://github.com/openbmc/openbmc/issues/1484
141*/
Ratan Gupta82549cc2017-04-21 08:45:23 +0530142
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530143InterfaceInfo EthernetInterface::getInterfaceInfo() const
144{
145 int sock{-1};
146 struct ifreq ifr{0};
147 struct ethtool_cmd edata{0};
148 LinkSpeed speed {0};
149 Autoneg autoneg {0};
150 DuplexMode duplex {0};
151 do
152 {
153 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
154 if (sock < 0)
155 {
156 log<level::ERR>("socket creation failed:",
157 entry("ERROR=%s", strerror(errno)));
158 break;
159 }
160
161 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
162 ifr.ifr_data = reinterpret_cast<char*>(&edata);
163
164 edata.cmd = ETHTOOL_GSET;
165
166 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
167 {
168 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
169 entry("ERROR=%s", strerror(errno)));
170 break;
171
172 }
173 speed = edata.speed;
174 duplex = edata.duplex;
175 autoneg = edata.autoneg;
176 }
177 while (0);
178
179 if (sock)
180 {
181 close(sock);
182 }
183 return std::make_tuple(speed, duplex, autoneg);
184}
185
186/** @brief get the mac address of the interface.
187 * @return macaddress on success
188 */
189
190std::string EthernetInterface::getMACAddress() const
191{
192 struct ifreq ifr;
193 struct ifconf ifc;
194 char buf[SIZE_BUFF];
195 char macAddress[SIZE_MAC] = "";
196
197 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
198 if (sock < 0)
199 {
200 log<level::ERR>("socket creation failed:",
201 entry("ERROR=%s", strerror(errno)));
202 return macAddress;
203 }
204
205 ifc.ifc_len = sizeof(buf);
206 ifc.ifc_buf = buf;
207 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
208 {
209 log<level::ERR>("ioctl failed for SIOCGIFCONF:",
210 entry("ERROR=%s", strerror(errno)));
211 return macAddress;
212 }
213
214 struct ifreq* it = ifc.ifc_req;
215 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
216
217 for (; it != end; ++it)
218 {
219 if (interfaceName() == it->ifr_name)
220 {
221 break;
222 }
223 }
224 if (interfaceName() == it->ifr_name)
225 {
226 strcpy(ifr.ifr_name, it->ifr_name);
227 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
228 {
229 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
230 entry("ERROR=%s", strerror(errno)));
231 return macAddress;
232 }
233
234 snprintf(macAddress, SIZE_MAC, MAC_ADDRESS_FORMAT,
235 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
236 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
237 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
238 }
239 return macAddress;
240}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530241
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530242std::string EthernetInterface::generateId(const std::string& ipaddress,
243 uint8_t prefixLength,
244 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530245{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530246 std::stringstream hexId;
247 std::string hashString = ipaddress;
248 hashString += std::to_string(prefixLength);
249 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530250
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530251 // Only want 8 hex digits.
252 hexId << std::hex << ((std::hash<std::string> {}(
Ratan Guptafc2c7242017-05-29 08:46:06 +0530253 hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530254 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530255}
256
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530257void EthernetInterface::deleteObject(const std::string& ipaddress)
258{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530259 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530260 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530261 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530262 log<level::ERR>("DeleteObject:Unable to find the object.");
263 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530264 }
265 this->addrs.erase(it);
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530266 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530267}
268
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530269std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
270 const std::string& ipaddress,
271 uint8_t prefixLength,
272 const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530273{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530274 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530275 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530276 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
277
278 std::experimental::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530279 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530280 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530281 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530282 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530283}
284
Ratan Gupta87c13982017-06-15 09:27:27 +0530285bool EthernetInterface::dHCPEnabled(bool value)
286{
287 EthernetInterfaceIntf::dHCPEnabled(value);
288 if (value == true)
289 {
290 manager.writeToConfigurationFile();
291 createIPAddressObjects();
292 }
293 return value;
294}
295
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530296}//namespace network
297}//namespace phosphor