26

I'm in the process of upgrading my Ethernet to 10 Gbps to speed up the connectivity of my local network. Regretfully, a machine on my network has ran out of PCIe slots, so a native 10 GbE PCIe adapter is not an option. A USB adapter is the only feasible alternative - as 5 Gbps Ethernet switches and USB adapters are hard to find and expensive, the decision was made to run the server with two 2.5 Gbps Ethernet to USB 3 adapters based on the Realtek RTL8156 chipset, which is readily-available. Then, they're together at the Ethernet level using link aggregation in a LAG/LACP, and connected to a 2.5/10 Gbps switch.

These USB adapters can be recognized by Linux as the following. I've also determined beforehand that both adapters can operate independently at 2.5 Gbps by assigning an IP address to each NIC and running a iperf3 test.

$ dmesg
[    5.118103] usb 4-4: new SuperSpeed USB device number 2 using xhci_hcd
[    5.138434] usb 4-4: New USB device found, idVendor=0bda, idProduct=8156, bcdDevice=31.04
[    5.138436] usb 4-4: New USB device strings: Mfr=1, Product=2, SerialNumber=6
[    5.138438] usb 4-4: Product: USB 10/100/1G/2.5G LAN
[    5.138439] usb 4-4: Manufacturer: Realtek
[    5.138440] usb 4-4: SerialNumber: 401300ÿÿÿÿ
[    6.970319] cdc_ncm 4-4:2.0: MAC-Address: 00:e0:4c:68:10:e6
[    6.970325] cdc_ncm 4-4:2.0: setting rx_max = 16384
[    6.970356] cdc_ncm 4-4:2.0: setting tx_max = 16384
[    6.984099] cdc_ncm 4-4:2.0 eth0: register 'cdc_ncm' at usb-0000:0a:00.3-4, CDC NCM (NO ZLP), 00:e0:4c:68:10:e6

lsusb

Bus 004 Device 002: ID 0bda:8156 Realtek Semiconductor Corp. USB 10/100/1G/2.5G LAN Bus 002 Device 002: ID 0bda:8156 Realtek Semiconductor Corp. USB 10/100/1G/2.5G LAN

The machine in question is running a Linux hypervisor (Proxmox), and two network interfaces are recognized as enx00e04c680152 and enx00e04c6810e6 (I believe udev/systemd generated the names based on their MAC addresses). To bond two interfaces together, on Proxmox I used the following settings:

Linux Bond
* Name: bond0
* Autostart: Yes
* Slaves: enx00e04c680152 enx00e04c6810e6
* Mode: LACP (802.3ad)
* Hash policy: layer3+4

On the switch, I created a Port Channel Group with LACP enabled in Active mode, and selected two 2.5 Gbps ports that were connected to the server. Linux also reports that both card are detected and bonded from its own perspective:

# ip link | grep enx
3: enx00e04c6810e6: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000
4: enx00e04c680152: <BROADCAST,MULTICAST,SLAVE,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master bond0 state UP mode DEFAULT group default qlen 1000

Unfortunately, for some reason, Linux cannot establish an LACP link with the switch no matter what, Linux kernel keeps telling me that "No 802.3ad response from the link partner for any adapters in the bond".

# dmesg
[ 1004.491253] bond0: Warning: No 802.3ad response from the link partner for any adapters in the bond
[ 1034.527234] bond0: Warning: No 802.3ad response from the link partner for any adapters in the bond
[ 1064.547217] bond0: Warning: No 802.3ad response from the link partner for any adapters in the bond

The status file /proc/net/bonding/bond0 shows that IEEE 802.3ad is active, but a link is not successfully established. This can be seen from the fact that the "Aggregator ID" for both NICs are different, and that both of them entered "churned" state, which essentially means the link failed,

# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v6.1.15-1-pve

Bonding Mode: IEEE 802.3ad Dynamic link aggregation Transmit Hash Policy: layer3+4 (1) MII Status: up MII Polling Interval (ms): 100 Up Delay (ms): 0 Down Delay (ms): 0 Peer Notification Delay (ms): 0

802.3ad info LACP active: on LACP rate: slow Min links: 0 Aggregator selection policy (ad_select): stable System priority: 65535 System MAC address: 8a:f5:1c:f4:8b:70 Active Aggregator Info: Aggregator ID: 1 Number of ports: 1 Actor Key: 10 Partner Key: 1 Partner Mac Address: 00:00:00:00:00:00

Slave Interface: enx00e04c680152 MII Status: up Speed: 2500 Mbps Duplex: half Link Failure Count: 0 Permanent HW addr: 00:e0:4c:68:01:52 Slave queue ID: 0 Aggregator ID: 1 Actor Churn State: none Partner Churn State: churned Actor Churned Count: 0 Partner Churned Count: 1 details actor lacp pdu: system priority: 65535 system mac address: 8a:f5:1c:f4:8b:70 port key: 10 port priority: 255 port number: 1 port state: 77 details partner lacp pdu: system priority: 65535 system mac address: 00:00:00:00:00:00 oper key: 1 port priority: 255 port number: 1 port state: 1

Slave Interface: enx00e04c6810e6 MII Status: up Speed: 2500 Mbps Duplex: half Link Failure Count: 0 Permanent HW addr: 00:e0:4c:68:10:e6 Slave queue ID: 0 Aggregator ID: 2 Actor Churn State: churned Partner Churn State: churned Actor Churned Count: 1 Partner Churned Count: 1 details actor lacp pdu: system priority: 65535 system mac address: 8a:f5:1c:f4:8b:70 port key: 10 port priority: 255 port number: 2 port state: 69 details partner lacp pdu: system priority: 65535 system mac address: 00:00:00:00:00:00 oper key: 1 port priority: 255 port number: 1 port state: 1

比尔盖子
  • 1,403

1 Answers1

35

TL;DR

These network adapters should be switched to the vendor-specific mode (bConfigurationValue: 1) and be controlled by Linux driver r8152. The default mode (bConfigurationValue: 2) with the generic cdc_ncm driver has limited functionality, so not all features will work correctly.

Analysis

After multiple days of troubleshooting, I've eventually determined the root cause. The clue is hardware information reported by ethtool:

# ethtool enx00e04c6810e6
Settings for enx00e04c6810e6:
    Supported ports: [  ]
    Supported link modes:   Not reported
    Supported pause frame use: No
    Supports auto-negotiation: No
    Supported FEC modes: Not reported
    Advertised link modes:  Not reported
    Advertised pause frame use: No
    Advertised auto-negotiation: No
    Advertised FEC modes: Not reported
    Speed: 2500Mb/s
    Duplex: Half
    Auto-negotiation: off
    Port: Twisted Pair
    PHYAD: 0
    Transceiver: internal
    MDI-X: Unknown
        Current message level: 0x00000007 (7)
                               drv probe link
    Link detected: yes

Note how important hardware information, like auto-negotiation or supported link modes are unavailable from the device driver. Also note how the driver claims the adapter is running in 2.5 Gbps half-duplex, which is unusual. I suspect Linux's bonding module doesn't work due to incomplete hardware information or feature support.

Upon further investigation, I found that by default, these Realtek 2.5 Gbps USB adapters were running in generic USB CDC-NCM mode. This is a standard mode defined by USB, but only limited functionality is available. To enable the full hardware features of these adapters, one must switch them from the standard mode (bConfigurationValue: 2) to the vendor-specific mode (bConfigurationValue: 1). The current mode can be checked by examining the file bConfigurationValue in /sys/bus/usb/devices/.

First, examine the USB hardware via lsusb and lsusb -t:

# lsusb
Bus 004 Device 002: ID 0bda:8156 Realtek Semiconductor Corp. USB 10/100/1G/2.5G LAN
Bus 002 Device 002: ID 0bda:8156 Realtek Semiconductor Corp. USB 10/100/1G/2.5G LAN

lsusb -t

/: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 10000M |__ Port 4: Dev 2, If 0, Class=Communications, Driver=cdc_ncm, 5000M |__ Port 4: Dev 2, If 1, Class=CDC Data, Driver=cdc_ncm, 5000M /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/3p, 10000M |__ Port 2: Dev 2, If 0, Class=Communications, Driver=cdc_ncm, 5000M |__ Port 2: Dev 2, If 1, Class=CDC Data, Driver=cdc_ncm, 5000M

One can see that the driver cdc_ncm is used.

Next, make sure you're looking at the correct device in /sys/bus/usb/devices (you need to adjust /2-2/ and 4-4 according to the output of lsusb -t) by checking the content of manufacturer first, it should be Realtek. Then, examine the bConfigurationValue under the same directory.

# cat /sys/bus/usb/devices/2-2/manufacturer 
Realtek
# cat /sys/bus/usb/devices/2-2/bConfigurationValue 
2

cat /sys/bus/usb/devices/4-4/manufacturer

Realtek

cat /sys/bus/usb/devices/4-4/bConfigurationValue

2

The bConfigurationValue is 2, which means it's in CDC_NCM mode. To manually switch the mode for debugging, run:

# echo 1 > /sys/bus/usb/devices/2-2/bConfigurationValue 
# echo 1 > /sys/bus/usb/devices/4-4/bConfigurationValue 

After the switch, Linux will start controlling them using the r8152 driver, rather than the generic cdc_ncm driver. In dmesg, one can see:

[ 8439.270745] r8152 2-2:1.0: load rtl8156b-2 v1 04/15/21 successfully
[ 8439.397031] r8152 2-2:1.0 (unnamed net_device) (uninitialized): netif_napi_add_weight() called with weight 256
[ 8439.397202] r8152 2-2:1.0 eth0: v1.12.13
[ 8439.397220] usbcore: registered new interface driver r8152
[ 8439.399436] r8152 2-2:1.0 enx00e04c680152: renamed from eth0
[ 8505.003557] r8152 4-4:1.0: load rtl8156b-2 v1 04/15/21 successfully
[ 8505.044832] r8152 4-4:1.0 eth0: v1.12.13
[ 8505.047901] r8152 4-4:1.0 enx00e04c6810e6: renamed from eth0

lsusb -t will also report that r8152 is now in charge of the network adapters.

# lsusb -t
/:  Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/4p, 10000M
    |__ Port 4: Dev 2, If 0, Class=Vendor Specific Class, Driver=r8152, 5000M
/:  Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/3p, 10000M
    |__ Port 2: Dev 2, If 0, Class=Vendor Specific Class, Driver=r8152, 5000M

If the adapters can be recognized by r8152, create a udev rule to apply it automatically (note that at this point, all adapters have been detached from bonding mode, so bonding will not work unless you manually recreate it, so it's easier to just add a udev rule and reboot).

Solution

First, find the VID and PID of the network adapter, which can vary depending on its brand.

# lsusb
Bus 004 Device 002: ID 0bda:8156 Realtek Semiconductor Corp. USB 10/100/1G/2.5G LAN
Bus 002 Device 002: ID 0bda:8156 Realtek Semiconductor Corp. USB 10/100/1G/2.5G LAN

Then create the following udev rule:

ACTION=="add", SUBSYSTEMS=="usb", ATTR{idVendor}=="0bda", ATTR{idProduct}=="8156", ATTR{bConfigurationValue}="1"

Save the rule as a file such as /etc/udev/rules.d/90-usb-r8152-ethernet.rules, and reboots the system. Note that one should adjust the idVendor and idProduct here to match the VID and PID listed by lsusb.

After the switch, ethtool is able to obtain hardware information about the adapter:

# ethtool enx00e04c680152 
Settings for enx00e04c680152:
    Supported ports: [ TP    MII ]
    Supported link modes:   10baseT/Half 10baseT/Full
                            100baseT/Half 100baseT/Full
                            1000baseT/Half 1000baseT/Full
                            2500baseT/Full
    Supported pause frame use: No
    Supports auto-negotiation: Yes
    Supported FEC modes: Not reported
    Advertised link modes:  10baseT/Half 10baseT/Full
                            100baseT/Half 100baseT/Full
                            1000baseT/Full
                            2500baseT/Full
    Advertised pause frame use: No
    Advertised auto-negotiation: Yes
    Advertised FEC modes: Not reported
    Link partner advertised link modes:  10baseT/Half 10baseT/Full
                                         100baseT/Half 100baseT/Full
                                         1000baseT/Full
                                         2500baseT/Full
    Link partner advertised pause frame use: No
    Link partner advertised auto-negotiation: Yes
    Link partner advertised FEC modes: Not reported
    Speed: 2500Mb/s
    Duplex: Full
    Auto-negotiation: on
    Port: MII
    PHYAD: 32
    Transceiver: internal
    Supports Wake-on: pumbg
    Wake-on: g
        Current message level: 0x00007fff (32767)
                               drv probe link timer ifdown ifup rx_err tx_err tx_queued intr tx_done rx_status pktdata hw wol
    Link detected: yes

LACP can also be established:

# cat /proc/net/bonding/bond0
Ethernet Channel Bonding Driver: v6.1.15-1-pve

Bonding Mode: IEEE 802.3ad Dynamic link aggregation Transmit Hash Policy: layer3+4 (1) MII Status: up MII Polling Interval (ms): 100 Up Delay (ms): 0 Down Delay (ms): 0 Peer Notification Delay (ms): 0

802.3ad info LACP active: on LACP rate: slow Min links: 0 Aggregator selection policy (ad_select): stable System priority: 65535 System MAC address: 8a:f5:1c:f4:8b:70 Active Aggregator Info: Aggregator ID: 1 Number of ports: 2 Actor Key: 11 Partner Key: 1 Partner Mac Address: 8c:1f:64:9a:c2:5f

Slave Interface: enx00e04c680152 MII Status: up Speed: 2500 Mbps Duplex: full Link Failure Count: 0 Permanent HW addr: 00:e0:4c:68:01:52 Slave queue ID: 0 Aggregator ID: 1 Actor Churn State: monitoring Partner Churn State: monitoring Actor Churned Count: 0 Partner Churned Count: 1 details actor lacp pdu: system priority: 65535 system mac address: 8a:f5:1c:f4:8b:70 port key: 11 port priority: 255 port number: 1 port state: 61 details partner lacp pdu: system priority: 65535 system mac address: 8c:1f:64:9a:c2:5f oper key: 1 port priority: 32768 port number: 2 port state: 61

Slave Interface: enx00e04c6810e6 MII Status: up Speed: 2500 Mbps Duplex: full Link Failure Count: 0 Permanent HW addr: 00:e0:4c:68:10:e6 Slave queue ID: 0 Aggregator ID: 1 Actor Churn State: monitoring Partner Churn State: monitoring Actor Churned Count: 1 Partner Churned Count: 1 details actor lacp pdu: system priority: 65535 system mac address: 8a:f5:1c:f4:8b:70 port key: 11 port priority: 255 port number: 2 port state: 61 details partner lacp pdu: system priority: 65535 system mac address: 8c:1f:64:9a:c2:5f oper key: 1 port priority: 32768 port number: 3 port state: 61

比尔盖子
  • 1,403