Geschwindigkeit/Übertragungsrate eines Netzwerkinterfaces unter Linux reduzieren

Im Rahmen aktueller Arbeiten an Ajax getriebenen Dateiuploads tauchte das Problem auf, mal kurzfristig die Geschwindigkeit einer Netzwerkverbindung drosseln zu müssen, um im lokalen Netz einer länger andauernden Dateitransfer zwischen einem Browser und einem Server zu simulieren.

Aus alten Zeiten hatte ich Werkzeuge wie "wondershaper" oder "trickle" im Kopf. Siehe etwa
http://www.ubuntugeek.com/use-bandwidth-shapers-wondershaper-or-trickle-to-limit-internet-connection-speed.html
http://askubuntu.com/questions/20872/how-do-i-limit-internet-bandwidth
http://unix.stackexchange.com/questions/83888/limit-outgoing-bandwidth-on-an-specific-interface
Diese Tools sind aber sehr alt. Entsprechende Pakete für "trickle" findet man für aktuelle Opensuse Versionen nicht mehr in den Standard-Repositories.

Eine einfach schnelle Lösung für Ethernet-Schnittstellen bietet das CLI Werkzeug "ethtool", das zum Standardumfang der meisten Distributionen gehört. "ethtool" ist ein mächtiges Werkzeug zur Analyse und zur Konfiguration/Manipulation von Schnittstellen. Es lohnt sich, sich damit ein wenig zu beschäftigen. Zu meiner Schande muss ich gestehen, dass ich dies bislang eher versäumt habe.

Für unseren Anwendungszweck ist die Syntax aber sehr einfach. Heißt unser Ethernet Device etwa "enp8s0", so erhalten wir einen Überblick über technische Daten der Schnittstelle mit :

mytux:~ # ethtool enp8s0
Settings for enp8s0:
        Supported ports: [ TP MII ]
        Supported link modes:   10baseT/Half 10baseT/Full 
                                100baseT/Half 100baseT/Full 
                                1000baseT/Half 1000baseT/Full 
        Supported pause frame use: No
        Supports auto-negotiation: Yes
        Advertised link modes:  10baseT/Half 10baseT/Full 
                                100baseT/Half 100baseT/Full 
                                1000baseT/Half 1000baseT/Full 
        Advertised pause frame use: Symmetric Receive-only
        Advertised auto-negotiation: Yes
        Link partner advertised link modes:  10baseT/Half 10baseT/Full 
                                             100baseT/Half 100baseT/Full 
                                             1000baseT/Full 
        Link partner advertised pause frame use: Symmetric Receive-only
        Link partner advertised auto-negotiation: Yes
        Speed: 1000Mb/s
        Duplex: Full
        Port: MII
        PHYAD: 0
        Transceiver: internal
        Auto-negotiation: on
        Supports Wake-on: pumbg
        Wake-on: g
        Current message level: 0x00000033 (51)
                               drv probe ifdown ifup
        Link detected: yes

Welche Netzwerkschnittstellen auf dem eigenen System verfügbar sind, ermittelt man natürlich mit
"ip link show" oder "ifconfig":

mytux:~ # ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: enp8s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
3: enp9s0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether yy:yy:yy:yy:yy:yy brd ff:ff:ff:ff:ff:ff
4: vmnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether nn:nn:nn:nn:nn:nn brd ff:ff:ff:ff:ff:ff
5: vmnet8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether mm:mm:mm:mm:mm:mm brd ff:ff:ff:ff:ff:ff

Die generelle Syntax zur Änderung der Geschwindigkeit mit ethtool ist:

ethtool -s DEVICE speed [SPEED] duplex [DUPLEX]

DEVICE ist durch den Schnittstellennamen, den man über ifconfig ermitteln kann, zu ersetzen. Welche SPEED Werte angegeben werden können, zeigt der Output von "ethtool DEVICE"; s. das Beispiel oben.

Will ich also die Übertragungsrate meiner Netzwerkschnittstelle temporär auf mögliche 10Mb/s reduzieren, so hilft:

mytux:~ # ethtool -s enp8s0 speed 10 duplex full

Und tatsächlich:

mytux:~ # ethtool enp8s0
Settings for enp8s0:
....    
	Link partner advertised auto-negotiation: Yes
        Speed: 10Mb/s
        Duplex: Full
....

Zurücksetzen erfolgt mit

mytux:~ # ethtool -s enp8s0 speed 1000 duplex full

Autonegotiation für weiterreichende Experimente, bei denen man Verbindungskabel abzieht/ansteckt, stoppt man übrigens mit

ethtool -s DEVICE autoneg off

Der Nachteil von "ethtool" gegenüber dem alten "trickle" ist übrigens, dass "trickle" durch Manipulationen im Userspace die Transfergeschwindigkeit für eine bestimmte Anwendung drosseln kann. Das geht mit ethtool nicht.