Zu diesem Zweck können Sie die Filterung tc
allein mit u32
Filtern 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 tc
Tool 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 htb
für Hierarchy Token Bucket verwendet (die Standard-Qdisc eines Geräts ist pfifo
oder pfifo_fast
hä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:30
Klasse verschoben.
1:1
wird eine htb
Klasse sein, die den gesamten Datenverkehr des Geräts auf 10 Mbit / s begrenzt.
1:10
wird eine htb
Klasse sein, die den Ausgangsverkehr auf 9 Mbit / s (90% von 10 Mbit / s) begrenzt.
1:20
wird eine htb
Klasse sein, die den Ausgangsverkehr auf 8 Mbit / s (80% von 10 Mbit / s) begrenzt.
1:30
wird eine htb
Klasse sein, die den Verkehr auf 10 Mbit / s begrenzt (Fallback).
:10, :20, :30
sind sfq
qdisc 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:10
Klasse und IP-Pakete mit Ziel-IP gleich C in die 1:20
Klasse 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 tc
B 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 htb
Klassen 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:20
und 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