How to Determine Network Interface Capacity via sysfs on Linux Systems


2 views

When working with network interfaces on Linux systems, determining the maximum supported speed (capacity) is crucial for network configuration and troubleshooting. While tools like lshw provide this information conveniently, accessing the raw data through sysfs offers more programmatic control.

The capacity information isn't directly exposed as a single file in /sys/class/net/eth0/device/. Instead, we need to look at multiple attributes:

# Check supported speeds (capabilities)
cat /sys/class/net/eth0/speed

# Alternative way through PCI device info
cat /sys/class/net/eth0/device/subsystem_device

Here's a Python script that combines multiple sysfs sources to determine interface capacity:

import os

def get_interface_capacity(interface):
    speed_path = f"/sys/class/net/{interface}/speed"
    try:
        with open(speed_path) as f:
            speed = int(f.read().strip())
            return f"{speed}Mbit/s"
    except (FileNotFoundError, ValueError):
        pass
    
    # Fallback to ethtool if available
    try:
        import subprocess
        result = subprocess.run(['ethtool', interface], 
                              capture_output=True, text=True)
        for line in result.stdout.splitlines():
            if 'Supported link modes' in line:
                return line.split(':')[1].strip()
    except FileNotFoundError:
        pass
    
    return "Unknown"

print(get_interface_capacity('eth0'))

For comprehensive interface information, consider these approaches:

# Using ethtool (requires package installation)
sudo ethtool eth0

# Using ip command
ip -s link show eth0

# Parsing lspci output
lspci -vv -s $(basename $(readlink /sys/class/net/eth0/device)) | grep -i speed

Remember that the speed file in sysfs shows the current negotiated speed, not necessarily the maximum capability. For maximum supported speeds, you'll need to examine:

  • The interface's driver capabilities
  • PCI subsystem information
  • Physical connection limitations

When working with network interfaces in Linux, understanding the maximum supported speed (capacity) is crucial for network configuration, monitoring, and troubleshooting. While tools like lshw provide this information, developers often need programmatic access through sysfs.

Looking at the sysfs directory structure (/sys/class/net/eth0/device/), the capacity information isn't directly exposed as a readable file. This differs from other hardware attributes that are directly accessible in sysfs.

Here are several methods to programmatically obtain the interface capacity:

Method 1: Using ethtool

The most reliable way is through the ethtool command:

#include <stdio.h>
#include <stdlib.h>

int main() {
    FILE *fp;
    char path[1035];
    
    fp = popen("ethtool eth0 | grep 'Speed' | awk '{print $2}'", "r");
    if (fp == NULL) {
        printf("Failed to run command\n");
        return 1;
    }
    
    while (fgets(path, sizeof(path), fp) != NULL) {
        printf("Interface speed: %s", path);
    }
    
    pclose(fp);
    return 0;
}

Method 2: PCI Device Direct Query

For PCI-based network cards, you can query the PCI configuration:

# Read the PCI device capabilities
cat /sys/class/net/eth0/device/config | xxd -l 64 -g 1

# Or use setpci (requires root)
sudo setpci -s 00:19.0 CAP_EXP+0x12.l

Method 3: Kernel Module Parameters

Some drivers expose this information in their module parameters:

# For Intel e1000e driver
grep -r "max_speed" /sys/module/e1000e/parameters/

The network interface capacity isn't stored as a simple value in sysfs because:

  • Capability negotiation is dynamic and depends on link state
  • Different interfaces may report capabilities differently
  • The actual supported speeds are determined by multiple hardware factors

For production code, consider using the Linux kernel's netlink interface or the ethtool IOCTL interface:

#include <linux/ethtool.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>

int get_eth_speed(int sock, const char *ifname) {
    struct ifreq ifr;
    struct ethtool_cmd edata;
    
    strncpy(ifr.ifr_name, ifname, IFNAMSIZ-1);
    ifr.ifr_data = (void *)&edata;
    
    edata.cmd = ETHTOOL_GSET;
    if (ioctl(sock, SIOCETHTOOL, &ifr) == -1) {
        perror("ioctl");
        return -1;
    }
    
    return ethtool_cmd_speed(&edata);
}

While sysfs doesn't provide a direct file for network interface capacity, multiple reliable methods exist to programmatically obtain this information. The choice depends on your specific requirements and environment constraints.