You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
6.3 KiB
173 lines
6.3 KiB
From 9a7ded387a87accd6437b3e36748d4451e8135f4 Mon Sep 17 00:00:00 2001
|
|
From: Erik Ekman <erik@kryo.se>
|
|
Date: Tue, 2 Nov 2021 14:56:25 +0100
|
|
Subject: [PATCH 65/65] merge Github PR#77
|
|
|
|
---
|
|
src/core/network.cc | 128 ++++++++++++++++++++++++++++++++++++++++++++
|
|
1 file changed, 128 insertions(+)
|
|
|
|
diff --git a/src/core/network.cc b/src/core/network.cc
|
|
index 01a1f51..746ac1b 100644
|
|
--- a/src/core/network.cc
|
|
+++ b/src/core/network.cc
|
|
@@ -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
|
|
@@ -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. */
|
|
@@ -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)
|
|
@@ -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));
|
|
--
|
|
2.33.1
|
|
|