blob: 3fcb489e62068289d01ff78ed055b88873452fc9 [file] [log] [blame]
Ratan Gupta91a99cc2017-04-14 16:32:09 +05301#include "ethernet_interface.hpp"
2
3#include <phosphor-logging/log.hpp>
4
5#include <linux/ethtool.h>
6#include <net/if.h>
7#include <linux/sockios.h>
8#include <netinet/in.h>
9#include <sys/ioctl.h>
10#include <sys/socket.h>
11#include <unistd.h>
12
13namespace phosphor
14{
15namespace network
16{
17
18using namespace phosphor::logging;
19constexpr auto MAC_ADDRESS_FORMAT = "%02X:%02X:%02X:%02X:%02X:%02X";
20constexpr size_t SIZE_MAC = 18;
21constexpr size_t SIZE_BUFF = 512;
22
23EthernetInterface::EthernetInterface(sdbusplus::bus::bus& bus,
24 const std::string& objPath,
25 bool dhcpEnabled) :
26 details::EthernetIface(bus, objPath.c_str(), true)
27{
28 auto intfName = objPath.substr(objPath.rfind("/") + 1);
29 interfaceName(intfName);
30 dHCPEnabled(dhcpEnabled);
31 mACAddress(getMACAddress());
32 // Emit deferred signal.
33 this->emit_object_added();
34}
35
36/*
37Note: We don't have support for ethtool now
38will enable this code once we bring the ethtool
39in the image.
40TODO: https://github.com/openbmc/openbmc/issues/1484
41*/
42InterfaceInfo EthernetInterface::getInterfaceInfo() const
43{
44 int sock{-1};
45 struct ifreq ifr{0};
46 struct ethtool_cmd edata{0};
47 LinkSpeed speed {0};
48 Autoneg autoneg {0};
49 DuplexMode duplex {0};
50 do
51 {
52 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
53 if (sock < 0)
54 {
55 log<level::ERR>("socket creation failed:",
56 entry("ERROR=%s", strerror(errno)));
57 break;
58 }
59
60 strncpy(ifr.ifr_name, interfaceName().c_str(), sizeof(ifr.ifr_name));
61 ifr.ifr_data = reinterpret_cast<char*>(&edata);
62
63 edata.cmd = ETHTOOL_GSET;
64
65 if (ioctl(sock, SIOCETHTOOL, &ifr) < 0)
66 {
67 log<level::ERR>("ioctl failed for SIOCETHTOOL:",
68 entry("ERROR=%s", strerror(errno)));
69 break;
70
71 }
72 speed = edata.speed;
73 duplex = edata.duplex;
74 autoneg = edata.autoneg;
75 }
76 while (0);
77
78 if (sock)
79 {
80 close(sock);
81 }
82 return std::make_tuple(speed, duplex, autoneg);
83}
84
85/** @brief get the mac address of the interface.
86 * @return macaddress on success
87 */
88
89std::string EthernetInterface::getMACAddress() const
90{
91 struct ifreq ifr;
92 struct ifconf ifc;
93 char buf[SIZE_BUFF];
94 char macAddress[SIZE_MAC] = "";
95
96 int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
97 if (sock < 0)
98 {
99 log<level::ERR>("socket creation failed:",
100 entry("ERROR=%s", strerror(errno)));
101 return macAddress;
102 }
103
104 ifc.ifc_len = sizeof(buf);
105 ifc.ifc_buf = buf;
106 if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
107 {
108 log<level::ERR>("ioctl failed for SIOCGIFCONF:",
109 entry("ERROR=%s", strerror(errno)));
110 return macAddress;
111 }
112
113 struct ifreq* it = ifc.ifc_req;
114 const struct ifreq* const end = it + (ifc.ifc_len / sizeof(struct ifreq));
115
116 for (; it != end; ++it)
117 {
118 if (interfaceName() == it->ifr_name)
119 {
120 break;
121 }
122 }
123 if (interfaceName() == it->ifr_name)
124 {
125 strcpy(ifr.ifr_name, it->ifr_name);
126 if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0)
127 {
128 log<level::ERR>("ioctl failed for SIOCGIFHWADDR:",
129 entry("ERROR=%s", strerror(errno)));
130 return macAddress;
131 }
132
133 snprintf(macAddress, SIZE_MAC, MAC_ADDRESS_FORMAT,
134 ifr.ifr_hwaddr.sa_data[0], ifr.ifr_hwaddr.sa_data[1],
135 ifr.ifr_hwaddr.sa_data[2], ifr.ifr_hwaddr.sa_data[3],
136 ifr.ifr_hwaddr.sa_data[4], ifr.ifr_hwaddr.sa_data[5]);
137 }
138 return macAddress;
139}
140}//namespace network
141}//namespace phosphor