Pour ce faire, vous pouvez utiliser tc
seul avec des u32
filtres ou combiné avec le marquage iptables (peut-être plus simple si vous ne voulez pas apprendre la syntaxe des filtres complexes). Je vais dans le post suivant détailler l'ancienne solution.
Simuler votre configuration
À titre d'exemple, considérons A, B, C et D exécutant des interfaces virtuelles à 10 Mbit / s .
Vous voulez essentiellement:
- A <==> B: mise en forme à 9 Mbit / s pour la sortie
- A <==> C: mise en forme de 8 Mbit / s pour la sortie
Afin de simuler cela, je vais créer 4 espaces de noms réseau et interfaces Ethernet virtuelles connectés à un pont.
Bien sûr, dans votre cas, vous travaillerez avec de vraies cartes réseau et le pont sera votre passerelle ou un commutateur en fonction de votre infrastructure.
Donc, dans ma simulation, nous aurons la configuration suivante, dans un réseau 10.0.0.0/24:
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
Tout d'abord, la phase de configuration afin que vous puissiez comprendre de quoi elle est faite, ignorez-la si vous ne la connaissez pas, ce n'est pas grave. Ce que vous devez cependant savoir, c'est que la commande ip netns exec <namespace> <command>
permet d'exécuter une commande dans un espace de noms réseau (c'est-à-dire dans l'une des cases du dessin précédent). Cela sera également utilisé dans la section suivante.
# 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
Donc, à ce stade, nous avons la configuration décrite précédemment.
Façonner le trafic
Il est temps d'entrer dans le contrôle du trafic afin d'obtenir ce que vous voulez. L' tc
outil vous permet d'ajouter des disciplines de mise en file d'attente:
- Pour la sortie: une fois que le noyau doit envoyer des paquets et avant d'accéder au pilote NIC.
- Pour l'entrée: après avoir accédé au pilote NIC et avant que les routines du noyau ne soient exécutées sur les paquets reçus.
Il est livré avec 3 notions: qdisc , classes et filtres . Ces notions peuvent être utilisées pour configurer une gestion complexe du flux de paquets et hiérarchiser le trafic en fonction du ou des critères que vous souhaitez.
En un mot :
- Les Qdisc sont des structures où les paquets seront finalement mis en file d'attente / retirés de la file d'attente.
- Les classes sont des conteneurs pour les qdisc agissant avec des comportements spécifiques.
- Les filtres sont des moyens d'acheminer les paquets entre les classes, plusieurs d'entre eux peuvent être définis sur le même point d'entrée avec des priorités pendant le traitement.
Tout cela fonctionne généralement comme un arbre où les feuilles sont des disques qd et les classes sont des nœuds. La racine d'un arbre ou d'un sous-arbre sera déclarée comme <id>:
et les nœuds enfants seront déclarés comme <parent_id>:<children_id>
. Gardez cette syntaxe à l'esprit.
Pour votre cas, prenons A et rendons l'arbre avec lequel vous souhaitez configurer tc
:
1:
|
|
|
1:1
/ | \
/ | \
/ | \
1:10 1:20 1:30
| | |
| | |
:10 :20 :30
Explication:
1:
est le qdisc racine attaché au périphérique vethA, il sera pris explicitement comme htb
pour le compartiment de jetons de hiérarchie (le qdisc par défaut d'un périphérique est pfifo
ou pfifo_fast
dépend du système d'exploitation). Il est particulièrement approprié pour la gestion de la bande passante. Les paquets qui ne correspondent pas aux filtres définis à ce niveau iront en 1:30
classe.
1:1
sera une htb
classe limitant l'ensemble du trafic de l'appareil à 10 Mbit / s.
1:10
sera une htb
classe limitant le trafic de sortie à 9 Mbit / s (90% de 10 Mbit / s).
1:20
sera une htb
classe limitant le trafic de sortie à 8 Mbit / s (80% de 10 Mbit / s).
1:30
sera une htb
classe limitant le trafic à 10 Mbit / s (repli).
:10, :20, :30
sont sfq
qdisc pour la mise en file d'attente d'équité stochastique. En d'autres termes, ces qdiscs garantiront l'équité de la planification de la transmission en fonction des flux.
Tout cela est configuré par les commandes suivantes:
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
La dernière chose dont nous avons besoin est d'ajouter des filtres pour que les paquets IP avec IP de destination égal à B iront en 1:10
classe et les paquets IP avec IP de destination égal à C iront en 1:20
classe:
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
Maintenant que vous avez l'idée, vous devrez ajouter des tc
règles similaires à B et C afin que les transmissions vers A de ces plates-formes soient également façonnées.
Essai
Maintenant, testons-le. Pour cela, je suis personnellement habitué à jouer avec iperf
, il se compose simplement d'un seul binaire qui peut être exécuté en tant que client ou serveur et enverra automatiquement autant de trafic que possible entre les deux hôtes.
Entre A et 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
Nous obtenons notre limite de bande passante de 9 Mbit / s .
Entre A et 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
Nous obtenons notre limite de bande passante de 8 Mbit / s .
Entre A et 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
Nous avons ici l'interface virtuelle pleine vitesse de 10 Mbit / s atteinte.
Notez que la rafale de la première mesure de chaque exécution peut être mieux gérée dans les htb
classes en ajustant le paramètre adéquat.
Nettoyer
Ôter :
- Le filtre de priorité 1 sur
1:
: tc filter del dev vethA parent 1: prio 1 u32
.
- Tous les filtres
1:
: tc filter del dev vethA parent 1:
.
- Classe
1:20
et ses enfants: tc class del dev vethA parent 1:1 classid
1:20
.
- L'arbre entier:
tc qdisc del dev vethA
.
Pour nettoyer l'ensemble de simulation:
# 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