369 lines
12 KiB
Diff
369 lines
12 KiB
Diff
|
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
|
||
|
|