Blame SOURCES/0065-merge-Github-PR-77.patch

a436c4
From 9a7ded387a87accd6437b3e36748d4451e8135f4 Mon Sep 17 00:00:00 2001
a436c4
From: Erik Ekman <erik@kryo.se>
a436c4
Date: Tue, 2 Nov 2021 14:56:25 +0100
a436c4
Subject: [PATCH 65/65] merge Github PR#77
a436c4
a436c4
---
a436c4
 src/core/network.cc | 128 ++++++++++++++++++++++++++++++++++++++++++++
a436c4
 1 file changed, 128 insertions(+)
a436c4
a436c4
diff --git a/src/core/network.cc b/src/core/network.cc
a436c4
index 01a1f51..746ac1b 100644
a436c4
--- a/src/core/network.cc
a436c4
+++ b/src/core/network.cc
a436c4
@@ -93,6 +93,41 @@ struct ethtool_link_settings
a436c4
                                                        supported, advertised, peer advertised. */
a436c4
 };
a436c4
 
a436c4
+/* Recognized module eeprom standards. */
a436c4
+#define ETH_MODULE_SFF_8079     0x1
a436c4
+#define ETH_MODULE_SFF_8472     0x2
a436c4
+#define ETH_MODULE_SFF_8636     0x3
a436c4
+#define ETH_MODULE_SFF_8436     0x4
a436c4
+
a436c4
+struct ethtool_modinfo {
a436c4
+  u32 cmd;
a436c4
+  u32 type;                                       /* SFF standard used in module */
a436c4
+  u32 eeprom_len;                                 /* Length of module eeprom */
a436c4
+  u32 reserved[8];
a436c4
+};
a436c4
+
a436c4
+/* Known id types. */
a436c4
+#define SFF_8024_ID_SOLDERED                    0x2
a436c4
+#define SFF_8024_ID_SFP                         0x3
a436c4
+#define SFF_8024_EXT_ID_DEFINED_BY_2WIRE_ID     0x4
a436c4
+
a436c4
+/* Common connector types. */
a436c4
+#define SFF_8024_CONNECTOR_SC                   0x1
a436c4
+#define SFF_8024_CONNECTOR_LC                   0x7
a436c4
+#define SFF_8024_CONNECTOR_OPTICAL_PIGTAIL      0xb
a436c4
+#define SFF_8024_CONNECTOR_COPPER_PIGTAIL       0x21
a436c4
+#define SFF_8024_CONNECTOR_RJ45                 0x22
a436c4
+#define SFF_8024_CONNECTOR_NON_SEPARABLE        0x23
a436c4
+
a436c4
+#define MAX_EEPROM_SIZE 256
a436c4
+struct ethtool_eeprom {
a436c4
+  u32 cmd;
a436c4
+  u32 magic;                                      /* Only used for eeprom writes */
a436c4
+  u32 offset;                                     /* Read or write offset */
a436c4
+  u32 len;                                        /* Length of read/write */
a436c4
+  u8 data[MAX_EEPROM_SIZE];                       /* Buffer */
a436c4
+};
a436c4
+
a436c4
 #ifndef IFNAMSIZ
a436c4
 #define IFNAMSIZ 32
a436c4
 #endif
a436c4
@@ -131,6 +166,8 @@ struct ethtool_value
a436c4
 #define ETHTOOL_GSET            0x00000001        /* Get settings. */
a436c4
 #define ETHTOOL_GDRVINFO        0x00000003        /* Get driver info. */
a436c4
 #define ETHTOOL_GLINK           0x0000000a        /* Get link status (ethtool_value) */
a436c4
+#define ETHTOOL_GMODULEINFO     0x00000042        /* Get plug-in module information */
a436c4
+#define ETHTOOL_GMODULEEEPROM   0x00000043        /* Get plug-in module eeprom */
a436c4
 #define ETHTOOL_GLINKSETTINGS   0x0000004c        /* Get link mode settings. */
a436c4
 
a436c4
 /* Indicates what features are supported by the interface. */
a436c4
@@ -358,6 +395,96 @@ static bool isVirtual(const string & MAC)
a436c4
 }
a436c4
 
a436c4
 
a436c4
+// Get data for connected transceiver module.
a436c4
+static void scan_module(hwNode & interface, int fd)
a436c4
+{
a436c4
+  struct ifreq ifr;
a436c4
+  struct ethtool_modinfo emodinfo;
a436c4
+  struct ethtool_eeprom eeeprom;
a436c4
+
a436c4
+  emodinfo.cmd = ETHTOOL_GMODULEINFO;
a436c4
+  memset(&ifr, 0, sizeof(ifr));
a436c4
+  strcpy(ifr.ifr_name, interface.getLogicalName().c_str());
a436c4
+  ifr.ifr_data = (caddr_t) &emodinfo;
a436c4
+  // Skip interface if module info not supported.
a436c4
+  if (ioctl(fd, SIOCETHTOOL, &ifr) != 0)
a436c4
+    return;
a436c4
+
a436c4
+  eeeprom.cmd = ETHTOOL_GMODULEEEPROM;
a436c4
+  eeeprom.offset = 0;
a436c4
+  eeeprom.len = emodinfo.eeprom_len;
a436c4
+  if (eeeprom.len > MAX_EEPROM_SIZE)
a436c4
+    eeeprom.len = MAX_EEPROM_SIZE;
a436c4
+  memset(&ifr, 0, sizeof(ifr));
a436c4
+  strcpy(ifr.ifr_name, interface.getLogicalName().c_str());
a436c4
+  ifr.ifr_data = (caddr_t) &eeeprom;
a436c4
+  if (ioctl(fd, SIOCETHTOOL, &ifr) != 0)
a436c4
+    return;
a436c4
+
a436c4
+  switch (emodinfo.type)
a436c4
+  {
a436c4
+    /* SFF 8472 eeprom layout starts with same data as SFF 8079. */
a436c4
+    case ETH_MODULE_SFF_8079:
a436c4
+    case ETH_MODULE_SFF_8472:
a436c4
+      if ((eeeprom.data[0] == SFF_8024_ID_SOLDERED || eeeprom.data[0] == SFF_8024_ID_SFP) &&
a436c4
+          eeeprom.data[1] == SFF_8024_EXT_ID_DEFINED_BY_2WIRE_ID)
a436c4
+      {
a436c4
+        char buffer[32];
a436c4
+        /* Get part number (padded with space). String is stripped inside setConfig. */
a436c4
+        interface.setConfig("module", string((const char*)&eeeprom.data[40], 16));
a436c4
+        int wavelength = eeeprom.data[60] << 8 | eeeprom.data[61];
a436c4
+        /* Skip wavelength for SFP+ cables, they use byte 60 for other data. */
a436c4
+        if ((eeeprom.data[8] & 0x0C) == 0 && wavelength > 0)
a436c4
+        {
a436c4
+          snprintf(buffer, sizeof(buffer), "%dnm", wavelength);
a436c4
+          interface.setConfig("wavelength", buffer);
a436c4
+        }
a436c4
+        int max_length = 0;
a436c4
+        int length;
a436c4
+        length = eeeprom.data[14] * 1000; /* SMF, km */
a436c4
+        if (length > max_length) max_length = length;
a436c4
+        length = eeeprom.data[15] * 100; /* SMF, meter */
a436c4
+        if (length > max_length) max_length = length;
a436c4
+        length = eeeprom.data[16] * 10; /* 50um (OM2), meter */
a436c4
+        if (length > max_length) max_length = length;
a436c4
+        length = eeeprom.data[17] * 10; /* 62.5um (OM1), meter */
a436c4
+        if (length > max_length) max_length = length;
a436c4
+        length = eeeprom.data[18]; /* Copper, meter */
a436c4
+        if (length > max_length) max_length = length;
a436c4
+        length = eeeprom.data[19] * 10; /* OM3, meter */
a436c4
+        if (length > max_length) max_length = length;
a436c4
+        if (max_length > 0)
a436c4
+        {
a436c4
+          snprintf(buffer, sizeof(buffer), "%dm", max_length);
a436c4
+          interface.setConfig("maxlength", buffer);
a436c4
+        }
a436c4
+        switch (eeeprom.data[2])
a436c4
+        {
a436c4
+          case SFF_8024_CONNECTOR_SC:
a436c4
+            interface.setConfig("connector", "SC");
a436c4
+            break;
a436c4
+          case SFF_8024_CONNECTOR_LC:
a436c4
+            interface.setConfig("connector", "LC");
a436c4
+            break;
a436c4
+          case SFF_8024_CONNECTOR_OPTICAL_PIGTAIL:
a436c4
+            interface.setConfig("connector", "optical pigtail");
a436c4
+            break;
a436c4
+          case SFF_8024_CONNECTOR_COPPER_PIGTAIL:
a436c4
+            interface.setConfig("connector", "copper pigtail");
a436c4
+            break;
a436c4
+          case SFF_8024_CONNECTOR_RJ45:
a436c4
+            interface.setConfig("connector", "RJ45");
a436c4
+            break;
a436c4
+          case SFF_8024_CONNECTOR_NON_SEPARABLE:
a436c4
+            interface.setConfig("connector", "non separable");
a436c4
+            break;
a436c4
+        }
a436c4
+      }
a436c4
+      break;
a436c4
+  }
a436c4
+}
a436c4
+
a436c4
+
a436c4
 static void updateCapabilities(hwNode & interface, u32 supported, u32 supported2, u32 speed, u8 duplex, u8 port, u8 autoneg)
a436c4
 {
a436c4
   if(supported & SUPPORTED_TP)
a436c4
@@ -666,6 +793,7 @@ bool scan_network(hwNode & n)
a436c4
       }
a436c4
 
a436c4
       scan_modes(interface, fd);
a436c4
+      scan_module(interface, fd);
a436c4
 
a436c4
       drvinfo.cmd = ETHTOOL_GDRVINFO;
a436c4
       memset(&ifr, 0, sizeof(ifr));
a436c4
-- 
a436c4
2.33.1
a436c4