blob: f29c4825d57fc41cd2d609067702bbc860ae96cb [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,
36 Manager& parent) :
Ratan Gupta82549cc2017-04-21 08:45:23 +053037 Ifaces(bus, objPath.c_str(), true),
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053038 bus(bus),
Ratan Gupta47722dc2017-05-26 18:32:23 +053039 manager(parent),
40 objPath(objPath)
Ratan Gupta91a99cc2017-04-14 16:32:09 +053041{
42 auto intfName = objPath.substr(objPath.rfind("/") + 1);
43 interfaceName(intfName);
44 dHCPEnabled(dhcpEnabled);
45 mACAddress(getMACAddress());
Ratan Gupta87c13982017-06-15 09:27:27 +053046 createIPAddressObjects();
Ratan Gupta29b0e432017-05-25 12:51:40 +053047 // Emit deferred signal.
48 this->emit_object_added();
49}
50
Ratan Gupta87c13982017-06-15 09:27:27 +053051void EthernetInterface::createIPAddressObjects()
Ratan Gupta29b0e432017-05-25 12:51:40 +053052{
Ratan Gupta82549cc2017-04-21 08:45:23 +053053 std::string gateway;
Ratan Gupta87c13982017-06-15 09:27:27 +053054 addrs.clear();
Ratan Gupta82549cc2017-04-21 08:45:23 +053055
Ratan Gupta87c13982017-06-15 09:27:27 +053056 auto addrs = getInterfaceAddrs()[interfaceName()];
Ratan Gupta82549cc2017-04-21 08:45:23 +053057 IP::Protocol addressType = IP::Protocol::IPv4;
Ratan Gupta29b0e432017-05-25 12:51:40 +053058 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ratan Guptafc2c7242017-05-29 08:46:06 +053059 route::Table routingTable;
Ratan Gupta82549cc2017-04-21 08:45:23 +053060 for (auto addr : addrs)
61 {
62 if (addr.addrType == AF_INET6)
63 {
64 addressType = IP::Protocol::IPv6;
65 }
Ratan Guptafc2c7242017-05-29 08:46:06 +053066 if (dHCPEnabled())
67 {
68 origin = IP::AddressOrigin::DHCP;
69 }
70 else if (isLinkLocal(addr.ipaddress))
71 {
72 origin = IP::AddressOrigin::LinkLocal;
73 }
74 gateway = routingTable.getGateway(addr.addrType, addr.ipaddress, addr.prefix);
Ratan Gupta82549cc2017-04-21 08:45:23 +053075
Ratan Gupta65e5abe2017-05-23 13:20:44 +053076 std::string ipAddressObjectPath = generateObjectPath(addressType,
77 addr.ipaddress,
78 addr.prefix,
79 gateway);
Ratan Guptafc2c7242017-05-29 08:46:06 +053080
Ratan Gupta82549cc2017-04-21 08:45:23 +053081 this->addrs.emplace(
82 std::make_pair(
Ratan Gupta719f83a2017-06-02 11:54:53 +053083 addr.ipaddress,
84 std::make_unique<phosphor::network::IPAddress>(
85 bus,
86 ipAddressObjectPath.c_str(),
87 *this,
88 addressType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053089 addr.ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +053090 origin,
Ratan Gupta719f83a2017-06-02 11:54:53 +053091 addr.prefix,
92 gateway)));
Ratan Gupta82549cc2017-04-21 08:45:23 +053093 }
Ratan Guptafc2c7242017-05-29 08:46:06 +053094
Ratan Gupta91a99cc2017-04-14 16:32:09 +053095}
96
Ratan Gupta82549cc2017-04-21 08:45:23 +053097void EthernetInterface::iP(IP::Protocol protType,
98 std::string ipaddress,
99 uint8_t prefixLength,
100 std::string gateway)
101{
Ratan Guptafc2c7242017-05-29 08:46:06 +0530102
103 if (dHCPEnabled())
104 {
Ratan Gupta82e1ef92017-06-15 08:39:15 +0530105 log<level::INFO>("DHCP enabled on the interface"),
106 entry("INTERFACE=%s",interfaceName());
Ratan Guptafc2c7242017-05-29 08:46:06 +0530107 return;
108 }
109
Ratan Gupta29b0e432017-05-25 12:51:40 +0530110 IP::AddressOrigin origin = IP::AddressOrigin::Static;
111
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530112 std::string objectPath = generateObjectPath(protType,
113 ipaddress,
114 prefixLength,
115 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530116
117 this->addrs.emplace(
118 std::make_pair(ipaddress,
119 std::make_unique<phosphor::network::IPAddress>(
120 bus,
121 objectPath.c_str(),
122 *this,
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530123 protType,
Ratan Gupta82549cc2017-04-21 08:45:23 +0530124 ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +0530125 origin,
Ratan Gupta82549cc2017-04-21 08:45:23 +0530126 prefixLength,
127 gateway)));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530128
129 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530130}
131
132
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530133/*
134Note: We don't have support for ethtool now
135will enable this code once we bring the ethtool
136in the image.
137TODO: https://github.com/openbmc/openbmc/issues/1484
138*/
Ratan Gupta82549cc2017-04-21 08:45:23 +0530139
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530140InterfaceInfo EthernetInterface::getInterfaceInfo() const
141{
142 int sock{-1};
143 struct ifreq ifr{0};
144 struct ethtool_cmd edata{0};
145 LinkSpeed speed {0};
146 Autoneg autoneg {0};
147 DuplexMode duplex {0};
148 do
149 {
150 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
151 if (sock < 0)
152 {
153 log<level::ERR>("socket creation failed:",
154 entry("ERROR=%s", strerror(errno)));
155 break;
156 }
157
158 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
159 ifr.ifr_data = reinterpret_cast<char*>(&edata);
160
161 edata.cmd = ETHTOOL_GSET;
162
163 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
164 {
165 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
166 entry("ERROR=%s", strerror(errno)));
167 break;
168
169 }
170 speed = edata.speed;
171 duplex = edata.duplex;
172 autoneg = edata.autoneg;
173 }
174 while (0);
175
176 if (sock)
177 {
178 close(sock);
179 }
180 return std::make_tuple(speed, duplex, autoneg);
181}
182
183/** @brief get the mac address of the interface.
184 * @return macaddress on success
185 */
186
187std::string EthernetInterface::getMACAddress() const
188{
189 struct ifreq ifr;
190 struct ifconf ifc;
191 char buf[SIZE_BUFF];
192 char macAddress[SIZE_MAC] = "";
193
194 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
195 if (sock < 0)
196 {
197 log<level::ERR>("socket creation failed:",
198 entry("ERROR=%s", strerror(errno)));
199 return macAddress;
200 }
201
202 ifc.ifc_len = sizeof(buf);
203 ifc.ifc_buf = buf;
204 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
205 {
206 log<level::ERR>("ioctl failed for SIOCGIFCONF:",
207 entry("ERROR=%s", strerror(errno)));
208 return macAddress;
209 }
210
211 struct ifreq* it = ifc.ifc_req;
212 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
213
214 for (; it != end; ++it)
215 {
216 if (interfaceName() == it->ifr_name)
217 {
218 break;
219 }
220 }
221 if (interfaceName() == it->ifr_name)
222 {
223 strcpy(ifr.ifr_name, it->ifr_name);
224 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
225 {
226 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
227 entry("ERROR=%s", strerror(errno)));
228 return macAddress;
229 }
230
231 snprintf(macAddress, SIZE_MAC, MAC_ADDRESS_FORMAT,
232 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
233 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
234 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
235 }
236 return macAddress;
237}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530238
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530239std::string EthernetInterface::generateId(const std::string& ipaddress,
240 uint8_t prefixLength,
241 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530242{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530243 std::stringstream hexId;
244 std::string hashString = ipaddress;
245 hashString += std::to_string(prefixLength);
246 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530247
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530248 // Only want 8 hex digits.
249 hexId << std::hex << ((std::hash<std::string> {}(
Ratan Guptafc2c7242017-05-29 08:46:06 +0530250 hashString)) & 0xFFFFFFFF);
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530251 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530252}
253
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530254void EthernetInterface::deleteObject(const std::string& ipaddress)
255{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530256 auto it = addrs.find(ipaddress);
Ratan Guptafc2c7242017-05-29 08:46:06 +0530257 if (it == addrs.end())
Ratan Gupta29b0e432017-05-25 12:51:40 +0530258 {
Ratan Guptafc2c7242017-05-29 08:46:06 +0530259 log<level::ERR>("DeleteObject:Unable to find the object.");
260 return;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530261 }
262 this->addrs.erase(it);
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530263 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530264}
265
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530266std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
267 const std::string& ipaddress,
268 uint8_t prefixLength,
269 const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530270{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530271 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530272 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530273 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
274
275 std::experimental::filesystem::path objectPath;
Ratan Gupta47722dc2017-05-26 18:32:23 +0530276 objectPath /= objPath;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530277 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530278 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530279 return objectPath.string();
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530280}
281
Ratan Gupta87c13982017-06-15 09:27:27 +0530282bool EthernetInterface::dHCPEnabled(bool value)
283{
284 EthernetInterfaceIntf::dHCPEnabled(value);
285 if (value == true)
286 {
287 manager.writeToConfigurationFile();
288 createIPAddressObjects();
289 }
290 return value;
291}
292
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530293}//namespace network
294}//namespace phosphor