blob: 5429bbc268bb7eeeabefac9ba0fe7af75359cd0c [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 Gupta91a99cc2017-04-14 16:32:09 +05305
6#include <phosphor-logging/log.hpp>
7
Ratan Gupta82549cc2017-04-21 08:45:23 +05308#include <arpa/inet.h>
Ratan Gupta91a99cc2017-04-14 16:32:09 +05309#include <linux/ethtool.h>
10#include <net/if.h>
11#include <linux/sockios.h>
12#include <netinet/in.h>
13#include <sys/ioctl.h>
14#include <sys/socket.h>
15#include <unistd.h>
16
Ratan Gupta82549cc2017-04-21 08:45:23 +053017#include <string>
18#include <algorithm>
Ratan Gupta65e5abe2017-05-23 13:20:44 +053019#include <sstream>
Ratan Gupta82549cc2017-04-21 08:45:23 +053020#include <experimental/filesystem>
21
Ratan Gupta91a99cc2017-04-14 16:32:09 +053022namespace phosphor
23{
24namespace network
25{
26
27using namespace phosphor::logging;
28constexpr auto MAC_ADDRESS_FORMAT = "%02X:%02X:%02X:%02X:%02X:%02X";
29constexpr size_t SIZE_MAC = 18;
30constexpr size_t SIZE_BUFF = 512;
31
32EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
33 const std::string& objPath,
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053034 bool dhcpEnabled,
35 Manager& parent) :
Ratan Gupta82549cc2017-04-21 08:45:23 +053036 Ifaces(bus, objPath.c_str(), true),
Ratan Gupta4f1c18b2017-05-25 12:59:35 +053037 bus(bus),
38 manager(parent)
Ratan Gupta29b0e432017-05-25 12:51:40 +053039
Ratan Gupta91a99cc2017-04-14 16:32:09 +053040{
41 auto intfName = objPath.substr(objPath.rfind("/") + 1);
42 interfaceName(intfName);
43 dHCPEnabled(dhcpEnabled);
44 mACAddress(getMACAddress());
Ratan Gupta29b0e432017-05-25 12:51:40 +053045 // Emit deferred signal.
46 this->emit_object_added();
47}
48
49void EthernetInterface::setAddressList(const AddrList& addrs)
50{
Ratan Gupta82549cc2017-04-21 08:45:23 +053051 std::string gateway;
52
53 IP::Protocol addressType = IP::Protocol::IPv4;
Ratan Gupta29b0e432017-05-25 12:51:40 +053054 IP::AddressOrigin origin = IP::AddressOrigin::Static;
Ratan Gupta82549cc2017-04-21 08:45:23 +053055
56 for (auto addr : addrs)
57 {
58 if (addr.addrType == AF_INET6)
59 {
60 addressType = IP::Protocol::IPv6;
61 }
62
Ratan Gupta65e5abe2017-05-23 13:20:44 +053063 std::string ipAddressObjectPath = generateObjectPath(addressType,
64 addr.ipaddress,
65 addr.prefix,
66 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +053067 this->addrs.emplace(
68 std::make_pair(
Ratan Gupta719f83a2017-06-02 11:54:53 +053069 addr.ipaddress,
70 std::make_unique<phosphor::network::IPAddress>(
71 bus,
72 ipAddressObjectPath.c_str(),
73 *this,
74 addressType,
Ratan Gupta82549cc2017-04-21 08:45:23 +053075 addr.ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +053076 origin,
Ratan Gupta719f83a2017-06-02 11:54:53 +053077 addr.prefix,
78 gateway)));
Ratan Gupta82549cc2017-04-21 08:45:23 +053079 }
Ratan Gupta91a99cc2017-04-14 16:32:09 +053080}
81
Ratan Gupta82549cc2017-04-21 08:45:23 +053082void EthernetInterface::iP(IP::Protocol protType,
83 std::string ipaddress,
84 uint8_t prefixLength,
85 std::string gateway)
86{
Ratan Gupta29b0e432017-05-25 12:51:40 +053087 IP::AddressOrigin origin = IP::AddressOrigin::Static;
88
Ratan Gupta65e5abe2017-05-23 13:20:44 +053089 std::string objectPath = generateObjectPath(protType,
90 ipaddress,
91 prefixLength,
92 gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +053093
94 this->addrs.emplace(
95 std::make_pair(ipaddress,
96 std::make_unique<phosphor::network::IPAddress>(
97 bus,
98 objectPath.c_str(),
99 *this,
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530100 protType,
Ratan Gupta82549cc2017-04-21 08:45:23 +0530101 ipaddress,
Ratan Gupta29b0e432017-05-25 12:51:40 +0530102 origin,
Ratan Gupta82549cc2017-04-21 08:45:23 +0530103 prefixLength,
104 gateway)));
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530105
106 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530107}
108
109
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530110/*
111Note: We don't have support for ethtool now
112will enable this code once we bring the ethtool
113in the image.
114TODO: https://github.com/openbmc/openbmc/issues/1484
115*/
Ratan Gupta82549cc2017-04-21 08:45:23 +0530116
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530117InterfaceInfo EthernetInterface::getInterfaceInfo() const
118{
119 int sock{-1};
120 struct ifreq ifr{0};
121 struct ethtool_cmd edata{0};
122 LinkSpeed speed {0};
123 Autoneg autoneg {0};
124 DuplexMode duplex {0};
125 do
126 {
127 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
128 if (sock < 0)
129 {
130 log<level::ERR>("socket creation failed:",
131 entry("ERROR=%s", strerror(errno)));
132 break;
133 }
134
135 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
136 ifr.ifr_data = reinterpret_cast<char*>(&edata);
137
138 edata.cmd = ETHTOOL_GSET;
139
140 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
141 {
142 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
143 entry("ERROR=%s", strerror(errno)));
144 break;
145
146 }
147 speed = edata.speed;
148 duplex = edata.duplex;
149 autoneg = edata.autoneg;
150 }
151 while (0);
152
153 if (sock)
154 {
155 close(sock);
156 }
157 return std::make_tuple(speed, duplex, autoneg);
158}
159
160/** @brief get the mac address of the interface.
161 * @return macaddress on success
162 */
163
164std::string EthernetInterface::getMACAddress() const
165{
166 struct ifreq ifr;
167 struct ifconf ifc;
168 char buf[SIZE_BUFF];
169 char macAddress[SIZE_MAC] = "";
170
171 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
172 if (sock < 0)
173 {
174 log<level::ERR>("socket creation failed:",
175 entry("ERROR=%s", strerror(errno)));
176 return macAddress;
177 }
178
179 ifc.ifc_len = sizeof(buf);
180 ifc.ifc_buf = buf;
181 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
182 {
183 log<level::ERR>("ioctl failed for SIOCGIFCONF:",
184 entry("ERROR=%s", strerror(errno)));
185 return macAddress;
186 }
187
188 struct ifreq* it = ifc.ifc_req;
189 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
190
191 for (; it != end; ++it)
192 {
193 if (interfaceName() == it->ifr_name)
194 {
195 break;
196 }
197 }
198 if (interfaceName() == it->ifr_name)
199 {
200 strcpy(ifr.ifr_name, it->ifr_name);
201 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
202 {
203 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
204 entry("ERROR=%s", strerror(errno)));
205 return macAddress;
206 }
207
208 snprintf(macAddress, SIZE_MAC, MAC_ADDRESS_FORMAT,
209 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
210 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
211 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
212 }
213 return macAddress;
214}
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530215
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530216std::string EthernetInterface::generateId(const std::string& ipaddress,
217 uint8_t prefixLength,
218 const std::string& gateway)
Ratan Gupta82549cc2017-04-21 08:45:23 +0530219{
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530220 std::stringstream hexId;
221 std::string hashString = ipaddress;
222 hashString += std::to_string(prefixLength);
223 hashString += gateway;
Ratan Gupta82549cc2017-04-21 08:45:23 +0530224
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530225 // Only want 8 hex digits.
226 hexId << std::hex << ((std::hash<std::string> {}(
227 hashString)) & 0xFFFFFFFF);
228 return hexId.str();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530229}
230
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530231void EthernetInterface::deleteObject(const std::string& ipaddress)
232{
Ratan Gupta29b0e432017-05-25 12:51:40 +0530233 auto it = addrs.find(ipaddress);
234 if( it == addrs.end())
235 {
236 log<level::ERR>("DeleteObject:Unable to find the object.");
237 return;
238 }
239 this->addrs.erase(it);
Ratan Gupta4f1c18b2017-05-25 12:59:35 +0530240 manager.writeToConfigurationFile();
Ratan Gupta82549cc2017-04-21 08:45:23 +0530241}
242
Ratan Gupta65e5abe2017-05-23 13:20:44 +0530243std::string EthernetInterface::generateObjectPath(IP::Protocol addressType,
244 const std::string& ipaddress,
245 uint8_t prefixLength,
246 const std::string& gateway) const
Ratan Gupta82549cc2017-04-21 08:45:23 +0530247{
Ratan Gupta82549cc2017-04-21 08:45:23 +0530248 std::string type = convertForMessage(addressType);
Ratan Gupta29b0e432017-05-25 12:51:40 +0530249 type = type.substr(type.rfind('.') + 1);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530250 std::transform(type.begin(), type.end(), type.begin(), ::tolower);
251
252 std::experimental::filesystem::path objectPath;
253 objectPath /= std::string(OBJ_NETWORK);
254 objectPath /= interfaceName();
255 objectPath /= type;
Ratan Gupta29b0e432017-05-25 12:51:40 +0530256 objectPath /= generateId(ipaddress, prefixLength, gateway);
Ratan Gupta82549cc2017-04-21 08:45:23 +0530257 return objectPath.string();
258
Ratan Gupta2eff84f2017-04-20 19:19:15 +0530259}
260
Ratan Gupta91a99cc2017-04-14 16:32:09 +0530261}//namespace network
262}//namespace phosphor