Simulieren Sie eine langsame Verbindung zwischen zwei Ubuntu-Server-Computern

9

Ich möchte das folgende Szenario simulieren: Vorausgesetzt, ich habe 4 Ubuntu-Server-Computer A, B, C und D. Ich möchte die Netzwerkbandbreite zwischen Computer A und Computer C um 20% und zwischen A und B um 10% reduzieren Tun Sie dies mit Netzwerksimulations- / Drosselungswerkzeugen?

Yehia Elshater
quelle
iptables können drosseln. Ich habe es nie benutzt, aber es lohnt sich, es zu untersuchen.
Michael Martinez
@ MichaelMartinez Nein, tut es nicht. tcfunktioniert bei Verwendung mit iptables-Markierung.
Xavier Lucas
@ XavierLucas gut zu wissen!
Michael Martinez

Antworten:

15

Zu diesem Zweck können Sie die Filterung tcallein mit u32Filtern oder in Kombination mit der Markierung von iptables verwenden (möglicherweise einfacher, wenn Sie die komplexe Filtersyntax nicht lernen möchten). Ich werde im folgenden Beitrag die frühere Lösung detailliert beschreiben.


Simulation Ihres Setups

Betrachten wir als Beispiel A, B, C und D mit virtuellen Schnittstellen mit 10 Mbit / s .

Sie wollen im Grunde:

  • A <==> B: 9 Mbit / s für den Austritt
  • A <==> C: 8 Mbit / s Formgebung für den Austritt

Um dies zu simulieren, erstelle ich 4 Netzwerk-Namespaces und virtuelle Ethernet-Schnittstellen, die an eine Bridge angeschlossen sind.

In Ihrem Fall arbeiten Sie natürlich mit echten Netzwerkkarten, und die Bridge ist je nach Infrastruktur Ihr Gateway oder Switch.

In meiner Simulation haben wir also das folgende Setup in einem 10.0.0.0/24 Netzwerk:

                                  10.0.0.254            

                                  +-------+                     
                                  |       |                     
                                  |  br0  |                     
                                  |       |                   
                                  +---+---+                     
                                      |                         
                                      | veth{A..D}.peer        
                                      |                      
                  +------------+------+-----+------------+     
                  |            |            |            |      
            vethA |      vethB |      vethC |      vethD |      
              +---+---+    +---+---+    +---+---+    +---+---+  
              |       |    |       |    |       |    |       |   
              |   A   |    |   B   |    |   C   |    |   D   |   
              |       |    |       |    |       |    |       |  
              +-------+    +-------+    +-------+    +-------+    

              10.0.0.1      10.0.0.2     10.0.0.3     10.0.0.4           

Erstens, die Setup-Phase, damit Sie verstehen, woraus sie besteht, überspringen Sie sie, wenn Sie mit ihr nicht vertraut sind, keine große Sache. Was Sie jedoch wissen müssen, ist, dass der Befehl ip netns exec <namespace> <command>die Ausführung eines Befehls in einem Netzwerk-Namespace ermöglicht (dh in einem der Felder der vorherigen Zeichnung). Dies wird auch im nächsten Abschnitt verwendet.

# Create the bridge
ip link add br0 type bridge

# Create network namespaces and veth interfaces and plug them into the bridge
for host in {A..D} ; do 
    ip link netns add ${host}
    ip link add veth${host} type veth peer name veth${host}.peer
    ip link set dev veth${host}.peer master br0
    ip link set dev veth${host} netns ${host}
    ip netns exec ${host} ip link set veth${host} up
done

# Assign IPs
ip addr add 10.0.0.254/24 dev br0
ip netns exec A ip addr add 10.0.0.1/24 dev vethA
ip netns exec B ip addr add 10.0.0.2/24 dev vethB
ip netns exec C ip addr add 10.0.0.3/24 dev vethC
ip netns exec D ip addr add 10.0.0.4/24 dev vethD

An diesem Punkt haben wir also das zuvor beschriebene Setup.


Verkehr gestalten

Es ist Zeit, in die Verkehrskontrolle einzusteigen, um das zu bekommen, was Sie wollen. Mit dem tcTool können Sie Warteschlangendisziplinen hinzufügen:

  • Für den Ausgang: Sobald der Kernel Pakete senden muss und bevor er auf den NIC-Treiber zugreift.
  • Für den Eingang: Nach dem Zugriff auf den NIC-Treiber und bevor die Kernel-Routinen über die empfangenen Pakete ausgeführt werden.

Es kommt mit 3 Begriffen: qdisc , Klassen und Filter . Diese Begriffe können verwendet werden, um ein komplexes Paketflussmanagement einzurichten und den Datenverkehr basierend auf den gewünschten Kriterien zu priorisieren.

In einer Nussschale :

  • Qdiscs sind Strukturen, in denen Pakete regelmäßig in die Warteschlange gestellt werden.
  • Klassen sind Container für qdiscs, die mit bestimmten Verhaltensweisen handeln.
  • Filter sind Möglichkeiten zum Weiterleiten von Paketen zwischen Klassen. Mehrere von ihnen können während der Verarbeitung auf demselben Einstiegspunkt mit Prioritäten definiert werden.

All dies funktioniert normalerweise als Baum, in dem Blätter qdiscs und Klassen Knoten sind. Die Wurzel eines Baums oder Teilbaums wird als deklariert <id>:und untergeordnete Knoten werden als deklariert <parent_id>:<children_id>. Beachten Sie diese Syntax.

Nehmen wir für Ihren Fall A und rendern den Baum, mit dem Sie einrichten möchten tc:

                                     1:
                                      |
                                      |
                                      |
                                     1:1
                                   /  |  \
                                  /   |   \
                                 /    |    \
                               1:10  1:20  1:30
                                |     |     |
                                |     |     |
                               :10   :20   :30

Erklärung:

  • 1:Ist die Root-Qdisc an das Gerät vethA angehängt, wird sie explizit wie htbfür Hierarchy Token Bucket verwendet (die Standard-Qdisc eines Geräts ist pfifooder pfifo_fasthängt vom Betriebssystem ab). Es ist speziell für das Bandbreitenmanagement geeignet. Pakete, die nicht mit auf dieser Ebene definierten Filtern übereinstimmen, werden in die 1:30Klasse verschoben.
  • 1:1wird eine htbKlasse sein, die den gesamten Datenverkehr des Geräts auf 10 Mbit / s begrenzt.
  • 1:10wird eine htbKlasse sein, die den Ausgangsverkehr auf 9 Mbit / s (90% von 10 Mbit / s) begrenzt.
  • 1:20wird eine htbKlasse sein, die den Ausgangsverkehr auf 8 Mbit / s (80% von 10 Mbit / s) begrenzt.
  • 1:30wird eine htbKlasse sein, die den Verkehr auf 10 Mbit / s begrenzt (Fallback).
  • :10, :20, :30sind sfqqdisc für Stochastic Fairness Queuing. Mit anderen Worten, diese qdiscs gewährleisten eine faire Übertragungsplanung auf der Grundlage von Datenströmen.

Diese ganze Sache wird durch die folgenden Befehle eingerichtet:

ip netns exec A tc qdisc add dev vethA root handle 1: htb default 30
ip netns exec A tc class add dev vethA parent 1: classid 1:1 htb rate 10mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:10 htb rate 9mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:20 htb rate 8mbit burst 15k
ip netns exec A tc class add dev vethA parent 1:1 classid 1:30 htb rate 10mbit burst 15k
ip netns exec A tc qdsic add dev vethA parent 1:10 handle 10: sfq perturb 10
ip netns exec A tc qdisc add dev vethA parent 1:20 handle 20: sfq perturb 10
ip netns exec A tc qdisc add dev vethA parent 1:30 handle 30: sfq perturb 10

Das Letzte, was wir brauchen, ist das Hinzufügen von Filtern, damit IP-Pakete mit Ziel-IP gleich B in die 1:10Klasse und IP-Pakete mit Ziel-IP gleich C in die 1:20Klasse gehen :

ip netns exec A tc filter add dev vethA parent 1: protocol ip prio 1 u32 match ip dst 10.0.0.2/32 flowid 1:10
ip netns exec A tc filter add dev vethA parent 1: protocol ip prio 2 u32 match ip dst 10.0.0.3/32 flowid 1:20

Nachdem Sie auf die Idee gekommen sind, müssen Sie tcB und C ähnliche Regeln hinzufügen, damit auch die Übertragungen von diesen Rigs in Richtung A geformt werden.


Testen

Jetzt lass es uns testen. Dafür bin ich persönlich gewohnt zu spielen iperf, es besteht einfach aus einer einzelnen Binärdatei, die entweder als Client oder als Server ausgeführt werden kann und automatisch so viel Verkehr wie möglich zwischen beiden Hosts sendet.

Zwischen A und B :

 $ ip netns exec B iperf -s -p 8001
  ...
 $ ip netns exec A iperf -c 10.0.0.2 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.2, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[  5] local 10.0.0.1 port 58191 connected with 10.0.0.2 port 8001
[ ID] Interval       Transfer     Bandwidth
[  5]  0.0- 2.0 sec  2.38 MBytes  9.96 Mbits/sec
[  5]  2.0- 4.0 sec  2.12 MBytes  8.91 Mbits/sec
[  5]  4.0- 6.0 sec  2.00 MBytes  8.39 Mbits/sec
[  5]  6.0- 8.0 sec  2.12 MBytes  8.91 Mbits/sec
[  5]  8.0-10.0 sec  2.00 MBytes  8.39 Mbits/sec
[  5]  0.0-10.1 sec  10.8 MBytes  8.91 Mbits/sec

Wir erreichen unser Bandbreitenlimit von 9 Mbit / s .

Zwischen A und C:

$ ip netns exec C iperf -s -p 8001
...
$ ip netns exec A iperf -c 10.0.0.3 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.3, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[  5] local 10.0.0.1 port 58522 connected with 10.0.0.3 port 8001
[ ID] Interval       Transfer     Bandwidth
[  5]  0.0- 2.0 sec  2.25 MBytes  9.44 Mbits/sec
[  5]  2.0- 4.0 sec  1.75 MBytes  7.34 Mbits/sec
[  5]  4.0- 6.0 sec  1.88 MBytes  7.86 Mbits/sec
[  5]  6.0- 8.0 sec  1.88 MBytes  7.86 Mbits/sec
[  5]  8.0-10.0 sec  1.75 MBytes  7.34 Mbits/sec
[  5]  0.0-10.1 sec  9.62 MBytes  7.98 Mbits/sec

Wir erreichen unser Bandbreitenlimit von 8 Mbit / s .

Zwischen A und D:

$ ip netns exec D iperf -s -p 8001
...
$ ip netns exec A iperf -c 10.0.0.4 -p 8001 -t 10 -i 2
------------------------------------------------------------
Client connecting to 10.0.0.4, TCP port 8001
TCP window size: 21.0 KByte (default)
------------------------------------------------------------
[  5] local 10.0.0.1 port 40614 connected with 10.0.0.4 port 8001
[ ID] Interval       Transfer     Bandwidth
[  5]  0.0- 2.0 sec  2.62 MBytes  11.0 Mbits/sec
[  5]  2.0- 4.0 sec  2.25 MBytes  9.44 Mbits/sec
[  5]  4.0- 6.0 sec  2.38 MBytes  9.96 Mbits/sec
[  5]  6.0- 8.0 sec  2.25 MBytes  9.44 Mbits/sec
[  5]  8.0-10.0 sec  2.38 MBytes  9.96 Mbits/sec
[  5]  0.0-10.2 sec  12.0 MBytes  9.89 Mbits/sec

Hier haben wir die virtuelle Schnittstelle mit voller Geschwindigkeit von 10 Mbit / s erreicht.

Beachten Sie, dass der Burst des ersten Takts jedes Laufs in htbKlassen besser gehandhabt werden kann, indem der entsprechende Parameter angepasst wird.


Aufräumen

Zu entfernen :

  • Der Filter der Priorität 1 auf 1:: tc filter del dev vethA parent 1: prio 1 u32.
  • Alle Filter auf 1:: tc filter del dev vethA parent 1:.
  • Klasse 1:20und ihre Kinder : tc class del dev vethA parent 1:1 classid 1:20.
  • Der ganze Baum : tc qdisc del dev vethA.

So bereinigen Sie das Simulationsset:

# Remove veth pairs and network namespaces
for host in {A..D} ; do
    ip link del dev veth${host}.peer
    ip netns del ${host}
done

# Remove the bridge
ip link del dev br0
Xavier Lucas
quelle
1
Vielen Dank für Ihre tolle Antwort. Könnten Sie nach Möglichkeit die Befehle zum Entfernen der Filter hinzufügen? Nur für den Fall, dass jemand dieses Setup nach der Simulation sicher zurücksetzen möchte.
Yehia Elshater
1
@YahiaZakaria Ich habe diese Informationen gerade im letzten Teil meines Beitrags hinzugefügt.
Xavier Lucas
0

Ubuntu hat IPFW von FreeBSD portiert und IPFW hat DUMMYNET, mit dem verschiedene Netzwerkparameter verwaltet werden können - Bandbreite, Verzögerung, Rate des Paketverlusts usw.

Kondybas
quelle
0

Am besten verwenden Sie die TC-Tools mit dem jetzt integrierten Netem-Modul (zumindest in Ubuntu Server). Weitere Informationen finden Sie in diesem Artikel von Stackoverflow .

Luc Stepniewski
quelle
Bei Netem geht es um RTT- und Überlastungsemulation, nicht um Bandbreite.
Xavier Lucas
1
@XavierLucas, Sie haben Recht, für die Bandbreite brauchen Sie nur tc, ohne auch nur netem.
Luc Stepniewski
0

Trickle funktioniert gut.

Diese Diskussion zeigt einige Einschränkungen: /unix/109973/how-to-change-speed-limit-of-running-trickle-instance

Mathew
quelle
Trickle wird verwendet, um die Netzwerkbandbreite für ein bestimmtes Programm zu simulieren. Das OP scheint nach einer Lösung im Rahmen des Hosts zu suchen.
Xavier Lucas
Trickled kann verwendet werden, um eine Gruppe von Verbindungen zu simulieren (nicht nur eine einzelne Verbindung). In der Tat könnte die Frage als "alle Verbindungen von Host zu Host" interpretiert werden.
Mathew