Skip to content

Commit

Permalink
merge Github PR#77
Browse files Browse the repository at this point in the history
  • Loading branch information
yarrick authored and lyonel committed Nov 2, 2021
1 parent 0f26b1b commit 9a7ded3
Showing 1 changed file with 128 additions and 0 deletions.
128 changes: 128 additions & 0 deletions src/core/network.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,41 @@ struct ethtool_link_settings
supported, advertised, peer advertised. */
};

/* Recognized module eeprom standards. */
#define ETH_MODULE_SFF_8079 0x1
#define ETH_MODULE_SFF_8472 0x2
#define ETH_MODULE_SFF_8636 0x3
#define ETH_MODULE_SFF_8436 0x4

struct ethtool_modinfo {
u32 cmd;
u32 type; /* SFF standard used in module */
u32 eeprom_len; /* Length of module eeprom */
u32 reserved[8];
};

/* Known id types. */
#define SFF_8024_ID_SOLDERED 0x2
#define SFF_8024_ID_SFP 0x3
#define SFF_8024_EXT_ID_DEFINED_BY_2WIRE_ID 0x4

/* Common connector types. */
#define SFF_8024_CONNECTOR_SC 0x1
#define SFF_8024_CONNECTOR_LC 0x7
#define SFF_8024_CONNECTOR_OPTICAL_PIGTAIL 0xb
#define SFF_8024_CONNECTOR_COPPER_PIGTAIL 0x21
#define SFF_8024_CONNECTOR_RJ45 0x22
#define SFF_8024_CONNECTOR_NON_SEPARABLE 0x23

#define MAX_EEPROM_SIZE 256
struct ethtool_eeprom {
u32 cmd;
u32 magic; /* Only used for eeprom writes */
u32 offset; /* Read or write offset */
u32 len; /* Length of read/write */
u8 data[MAX_EEPROM_SIZE]; /* Buffer */
};

#ifndef IFNAMSIZ
#define IFNAMSIZ 32
#endif
Expand Down Expand Up @@ -131,6 +166,8 @@ struct ethtool_value
#define ETHTOOL_GSET 0x00000001 /* Get settings. */
#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */
#define ETHTOOL_GLINK 0x0000000a /* Get link status (ethtool_value) */
#define ETHTOOL_GMODULEINFO 0x00000042 /* Get plug-in module information */
#define ETHTOOL_GMODULEEEPROM 0x00000043 /* Get plug-in module eeprom */
#define ETHTOOL_GLINKSETTINGS 0x0000004c /* Get link mode settings. */

/* Indicates what features are supported by the interface. */
Expand Down Expand Up @@ -358,6 +395,96 @@ static bool isVirtual(const string & MAC)
}


// Get data for connected transceiver module.
static void scan_module(hwNode & interface, int fd)
{
struct ifreq ifr;
struct ethtool_modinfo emodinfo;
struct ethtool_eeprom eeeprom;

emodinfo.cmd = ETHTOOL_GMODULEINFO;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, interface.getLogicalName().c_str());
ifr.ifr_data = (caddr_t) &emodinfo;
// Skip interface if module info not supported.
if (ioctl(fd, SIOCETHTOOL, &ifr) != 0)
return;

eeeprom.cmd = ETHTOOL_GMODULEEEPROM;
eeeprom.offset = 0;
eeeprom.len = emodinfo.eeprom_len;
if (eeeprom.len > MAX_EEPROM_SIZE)
eeeprom.len = MAX_EEPROM_SIZE;
memset(&ifr, 0, sizeof(ifr));
strcpy(ifr.ifr_name, interface.getLogicalName().c_str());
ifr.ifr_data = (caddr_t) &eeeprom;
if (ioctl(fd, SIOCETHTOOL, &ifr) != 0)
return;

switch (emodinfo.type)
{
/* SFF 8472 eeprom layout starts with same data as SFF 8079. */
case ETH_MODULE_SFF_8079:
case ETH_MODULE_SFF_8472:
if ((eeeprom.data[0] == SFF_8024_ID_SOLDERED || eeeprom.data[0] == SFF_8024_ID_SFP) &&
eeeprom.data[1] == SFF_8024_EXT_ID_DEFINED_BY_2WIRE_ID)
{
char buffer[32];
/* Get part number (padded with space). String is stripped inside setConfig. */
interface.setConfig("module", string((const char*)&eeeprom.data[40], 16));
int wavelength = eeeprom.data[60] << 8 | eeeprom.data[61];
/* Skip wavelength for SFP+ cables, they use byte 60 for other data. */
if ((eeeprom.data[8] & 0x0C) == 0 && wavelength > 0)
{
snprintf(buffer, sizeof(buffer), "%dnm", wavelength);
interface.setConfig("wavelength", buffer);
}
int max_length = 0;
int length;
length = eeeprom.data[14] * 1000; /* SMF, km */
if (length > max_length) max_length = length;
length = eeeprom.data[15] * 100; /* SMF, meter */
if (length > max_length) max_length = length;
length = eeeprom.data[16] * 10; /* 50um (OM2), meter */
if (length > max_length) max_length = length;
length = eeeprom.data[17] * 10; /* 62.5um (OM1), meter */
if (length > max_length) max_length = length;
length = eeeprom.data[18]; /* Copper, meter */
if (length > max_length) max_length = length;
length = eeeprom.data[19] * 10; /* OM3, meter */
if (length > max_length) max_length = length;
if (max_length > 0)
{
snprintf(buffer, sizeof(buffer), "%dm", max_length);
interface.setConfig("maxlength", buffer);
}
switch (eeeprom.data[2])
{
case SFF_8024_CONNECTOR_SC:
interface.setConfig("connector", "SC");
break;
case SFF_8024_CONNECTOR_LC:
interface.setConfig("connector", "LC");
break;
case SFF_8024_CONNECTOR_OPTICAL_PIGTAIL:
interface.setConfig("connector", "optical pigtail");
break;
case SFF_8024_CONNECTOR_COPPER_PIGTAIL:
interface.setConfig("connector", "copper pigtail");
break;
case SFF_8024_CONNECTOR_RJ45:
interface.setConfig("connector", "RJ45");
break;
case SFF_8024_CONNECTOR_NON_SEPARABLE:
interface.setConfig("connector", "non separable");
break;
}
}
break;
}
}


static void updateCapabilities(hwNode & interface, u32 supported, u32 supported2, u32 speed, u8 duplex, u8 port, u8 autoneg)
{
if(supported & SUPPORTED_TP)
Expand Down Expand Up @@ -666,6 +793,7 @@ bool scan_network(hwNode & n)
}

scan_modes(interface, fd);
scan_module(interface, fd);

drvinfo.cmd = ETHTOOL_GDRVINFO;
memset(&ifr, 0, sizeof(ifr));
Expand Down

0 comments on commit 9a7ded3

Please sign in to comment.