From 1a39de2d0af780c06b55f5a96d5f696da1a6fda3 Mon Sep 17 00:00:00 2001
From: Lyonel Vincent <lyonel@ezix.org>
Date: Tue, 12 Oct 2021 23:33:08 +0200
Subject: [PATCH 57/65] support for new ethtool capabilities
merge Github PR#73
---
src/core/network.cc | 299 +++++++++++++++++++++++++++++---------------
1 file changed, 195 insertions(+), 104 deletions(-)
diff --git a/src/core/network.cc b/src/core/network.cc
index 5aab06d..613c1af 100644
--- a/src/core/network.cc
+++ b/src/core/network.cc
@@ -53,6 +53,7 @@ typedef unsigned long long u64;
typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;
+typedef int8_t s8;
struct ethtool_cmd
{
@@ -70,6 +71,28 @@ struct ethtool_cmd
u32 reserved[4];
};
+#define MAX_LINK_MODE_MASK_SIZE 64
+struct ethtool_link_settings
+{
+ u32 cmd;
+ u32 speed; /* The forced speed, 10Mb, 100Mb, gigabit */
+ u8 duplex; /* Duplex, half or full */
+ u8 port; /* Which connector port */
+ u8 phy_address;
+ u8 autoneg; /* Enable or disable autonegotiation */
+ u8 mdio_support;
+ u8 eth_tp_mdix;
+ u8 eth_tp_mdix_ctrl;
+ s8 link_mode_masks_nwords;
+ u8 transceiver; /* Which tranceiver to use */
+ u8 master_slave_cfg;
+ u8 master_slave_state;
+ u8 reserved1[1];
+ u32 reserved[7];
+ u32 link_mode_masks[3 * MAX_LINK_MODE_MASK_SIZE]; /* Link mode mask fields for modes:
+ supported, advertised, peer advertised. */
+};
+
#ifndef IFNAMSIZ
#define IFNAMSIZ 32
#endif
@@ -108,6 +131,7 @@ 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_GLINKSETTINGS 0x0000004c /* Get link mode settings. */
/* Indicates what features are supported by the interface. */
#define SUPPORTED_10baseT_Half (1 << 0)
@@ -124,10 +148,17 @@ struct ethtool_value
#define SUPPORTED_BNC (1 << 11)
#define SUPPORTED_10000baseT_Full (1 << 12)
-/* The forced speed, 10Mb, 100Mb, gigabit, 10GbE. */
+/* Indicates what features are supported by the interface,
+ * in the second word of the extended bitmap. */
+#define SUPPORTED2_2500baseT_Full (1 << 15)
+#define SUPPORTED2_5000baseT_Full (1 << 16)
+
+/* The forced speed, 10Mb, 100Mb, gigabit, 2.5GbE, 5GbE, 10GbE. */
#define SPEED_10 10
#define SPEED_100 100
#define SPEED_1000 1000
+#define SPEED_2500 2500
+#define SPEED_5000 5000
#define SPEED_10000 10000
/* Duplex, half or full. */
@@ -308,6 +339,168 @@ static bool isVirtual(const string & MAC)
}
+static void updateCapabilities(hwNode & interface, u32 supported, u32 supported2, u32 speed, u8 duplex, u8 port, u8 autoneg)
+{
+ if(supported & SUPPORTED_TP)
+ interface.addCapability("tp", _("twisted pair"));
+ if(supported & SUPPORTED_AUI)
+ interface.addCapability("aui", _("AUI"));
+ if(supported & SUPPORTED_BNC)
+ interface.addCapability("bnc", _("BNC"));
+ if(supported & SUPPORTED_MII)
+ interface.addCapability("mii", _("Media Independant Interface"));
+ if(supported & SUPPORTED_FIBRE)
+ interface.addCapability("fibre",_( "optical fibre"));
+ if(supported & SUPPORTED_10baseT_Half)
+ {
+ interface.addCapability("10bt", _("10Mbit/s"));
+ interface.setCapacity(10000000ULL);
+ }
+ if(supported & SUPPORTED_10baseT_Full)
+ {
+ interface.addCapability("10bt-fd", _("10Mbit/s (full duplex)"));
+ interface.setCapacity(10000000ULL);
+ }
+ if(supported & SUPPORTED_100baseT_Half)
+ {
+ interface.addCapability("100bt", _("100Mbit/s"));
+ interface.setCapacity(100000000ULL);
+ }
+ if(supported & SUPPORTED_100baseT_Full)
+ {
+ interface.addCapability("100bt-fd", _("100Mbit/s (full duplex)"));
+ interface.setCapacity(100000000ULL);
+ }
+ if(supported & SUPPORTED_1000baseT_Half)
+ {
+ interface.addCapability("1000bt", "1Gbit/s");
+ interface.setCapacity(1000000000ULL);
+ }
+ if(supported & SUPPORTED_1000baseT_Full)
+ {
+ interface.addCapability("1000bt-fd", _("1Gbit/s (full duplex)"));
+ interface.setCapacity(1000000000ULL);
+ }
+ if(supported2 & SUPPORTED2_2500baseT_Full)
+ {
+ interface.addCapability("2500bt-fd", _("2.5Gbit/s (full duplex)"));
+ interface.setCapacity(2500000000ULL);
+ }
+ if(supported2 & SUPPORTED2_5000baseT_Full)
+ {
+ interface.addCapability("5000bt-fd", _("5Gbit/s (full duplex)"));
+ interface.setCapacity(5000000000ULL);
+ }
+ if(supported & SUPPORTED_10000baseT_Full)
+ {
+ interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)"));
+ interface.setCapacity(10000000000ULL);
+ }
+ if(supported & SUPPORTED_Autoneg)
+ interface.addCapability("autonegotiation", _("Auto-negotiation"));
+
+ switch(speed)
+ {
+ case SPEED_10:
+ interface.setConfig("speed", "10Mbit/s");
+ interface.setSize(10000000ULL);
+ break;
+ case SPEED_100:
+ interface.setConfig("speed", "100Mbit/s");
+ interface.setSize(100000000ULL);
+ break;
+ case SPEED_1000:
+ interface.setConfig("speed", "1Gbit/s");
+ interface.setSize(1000000000ULL);
+ break;
+ case SPEED_2500:
+ interface.setConfig("speed", "2.5Gbit/s");
+ interface.setSize(2500000000ULL);
+ break;
+ case SPEED_5000:
+ interface.setConfig("speed", "5Gbit/s");
+ interface.setSize(5000000000ULL);
+ break;
+ case SPEED_10000:
+ interface.setConfig("speed", "10Gbit/s");
+ interface.setSize(10000000000ULL);
+ break;
+ }
+ switch(duplex)
+ {
+ case DUPLEX_HALF:
+ interface.setConfig("duplex", "half");
+ break;
+ case DUPLEX_FULL:
+ interface.setConfig("duplex", "full");
+ break;
+ }
+ switch(port)
+ {
+ case PORT_TP:
+ interface.setConfig("port", "twisted pair");
+ break;
+ case PORT_AUI:
+ interface.setConfig("port", "AUI");
+ break;
+ case PORT_BNC:
+ interface.setConfig("port", "BNC");
+ break;
+ case PORT_MII:
+ interface.setConfig("port", "MII");
+ break;
+ case PORT_FIBRE:
+ interface.setConfig("port", "fibre");
+ break;
+ }
+ interface.setConfig("autonegotiation", (autoneg == AUTONEG_DISABLE) ? "off" : "on");
+}
+
+
+static void scan_modes(hwNode & interface, int fd)
+{
+ struct ifreq ifr;
+ struct ethtool_cmd ecmd;
+ struct ethtool_link_settings elink;
+ s8 mask_size;
+
+ elink.cmd = ETHTOOL_GLINKSETTINGS;
+ elink.link_mode_masks_nwords = 0;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, interface.getLogicalName().c_str());
+ ifr.ifr_data = (caddr_t) &elink;
+ // Probe link mode mask count.
+ if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
+ {
+ mask_size = -elink.link_mode_masks_nwords;
+ if (mask_size > 1 && mask_size <= MAX_LINK_MODE_MASK_SIZE)
+ {
+ elink.cmd = ETHTOOL_GLINKSETTINGS;
+ elink.link_mode_masks_nwords = mask_size;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, interface.getLogicalName().c_str());
+ ifr.ifr_data = (caddr_t) &elink;
+ // Read link mode settings.
+ if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
+ {
+ updateCapabilities(interface, elink.link_mode_masks[0], elink.link_mode_masks[1],
+ elink.speed, elink.duplex, elink.port, elink.autoneg);
+ return;
+ }
+ }
+ }
+
+ ecmd.cmd = ETHTOOL_GSET;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, interface.getLogicalName().c_str());
+ ifr.ifr_data = (caddr_t) &ecmd;
+ if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
+ {
+ updateCapabilities(interface, ecmd.supported, 0, ecmd.speed, ecmd.duplex, ecmd.port, ecmd.autoneg);
+ }
+}
+
+
bool scan_network(hwNode & n)
{
vector < string > interfaces;
@@ -322,7 +515,6 @@ bool scan_network(hwNode & n)
{
struct ifreq ifr;
struct ethtool_drvinfo drvinfo;
- struct ethtool_cmd ecmd;
struct ethtool_value edata;
for (unsigned int i = 0; i < interfaces.size(); i++)
@@ -417,108 +609,7 @@ bool scan_network(hwNode & n)
interface.setConfig("link", edata.data ? "yes":"no");
}
- ecmd.cmd = ETHTOOL_GSET;
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, interfaces[i].c_str());
- ifr.ifr_data = (caddr_t) &ecmd;
- if (ioctl(fd, SIOCETHTOOL, &ifr) == 0)
- {
- if(ecmd.supported & SUPPORTED_TP)
- interface.addCapability("tp", _("twisted pair"));
- if(ecmd.supported & SUPPORTED_AUI)
- interface.addCapability("aui", _("AUI"));
- if(ecmd.supported & SUPPORTED_BNC)
- interface.addCapability("bnc", _("BNC"));
- if(ecmd.supported & SUPPORTED_MII)
- interface.addCapability("mii", _("Media Independant Interface"));
- if(ecmd.supported & SUPPORTED_FIBRE)
- interface.addCapability("fibre",_( "optical fibre"));
- if(ecmd.supported & SUPPORTED_10baseT_Half)
- {
- interface.addCapability("10bt", _("10Mbit/s"));
- interface.setCapacity(10000000ULL);
- }
- if(ecmd.supported & SUPPORTED_10baseT_Full)
- {
- interface.addCapability("10bt-fd", _("10Mbit/s (full duplex)"));
- interface.setCapacity(10000000ULL);
- }
- if(ecmd.supported & SUPPORTED_100baseT_Half)
- {
- interface.addCapability("100bt", _("100Mbit/s"));
- interface.setCapacity(100000000ULL);
- }
- if(ecmd.supported & SUPPORTED_100baseT_Full)
- {
- interface.addCapability("100bt-fd", _("100Mbit/s (full duplex)"));
- interface.setCapacity(100000000ULL);
- }
- if(ecmd.supported & SUPPORTED_1000baseT_Half)
- {
- interface.addCapability("1000bt", "1Gbit/s");
- interface.setCapacity(1000000000ULL);
- }
- if(ecmd.supported & SUPPORTED_1000baseT_Full)
- {
- interface.addCapability("1000bt-fd", _("1Gbit/s (full duplex)"));
- interface.setCapacity(1000000000ULL);
- }
- if(ecmd.supported & SUPPORTED_10000baseT_Full)
- {
- interface.addCapability("10000bt-fd", _("10Gbit/s (full duplex)"));
- interface.setCapacity(10000000000ULL);
- }
- if(ecmd.supported & SUPPORTED_Autoneg)
- interface.addCapability("autonegotiation", _("Auto-negotiation"));
-
- switch(ecmd.speed)
- {
- case SPEED_10:
- interface.setConfig("speed", "10Mbit/s");
- interface.setSize(10000000ULL);
- break;
- case SPEED_100:
- interface.setConfig("speed", "100Mbit/s");
- interface.setSize(100000000ULL);
- break;
- case SPEED_1000:
- interface.setConfig("speed", "1Gbit/s");
- interface.setSize(1000000000ULL);
- break;
- case SPEED_10000:
- interface.setConfig("speed", "10Gbit/s");
- interface.setSize(10000000000ULL);
- break;
- }
- switch(ecmd.duplex)
- {
- case DUPLEX_HALF:
- interface.setConfig("duplex", "half");
- break;
- case DUPLEX_FULL:
- interface.setConfig("duplex", "full");
- break;
- }
- switch(ecmd.port)
- {
- case PORT_TP:
- interface.setConfig("port", "twisted pair");
- break;
- case PORT_AUI:
- interface.setConfig("port", "AUI");
- break;
- case PORT_BNC:
- interface.setConfig("port", "BNC");
- break;
- case PORT_MII:
- interface.setConfig("port", "MII");
- break;
- case PORT_FIBRE:
- interface.setConfig("port", "fibre");
- break;
- }
- interface.setConfig("autonegotiation", (ecmd.autoneg == AUTONEG_DISABLE) ? "off" : "on");
- }
+ scan_modes(interface, fd);
drvinfo.cmd = ETHTOOL_GDRVINFO;
memset(&ifr, 0, sizeof(ifr));
--
2.33.1