Per fare ciò puoi utilizzare da tc
solo con i u32
filtri o in combinazione con il segno iptables (forse più semplice se non vuoi imparare la sintassi dei filtri complessi). Nel prossimo post descriverò in dettaglio la soluzione precedente.
Simulazione della configurazione
Ad esempio, consideriamo A, B, C e D con interfacce virtuali a 10 Mbit / s .
In pratica vuoi:
- A <==> B: modellazione 9 Mbit / s per uscita
- A <==> C: 8 Mbit / s per modellare l'uscita
Per simularlo creerò 4 spazi dei nomi di rete e interfacce Ethernet virtuali collegate a un bridge.
Ovviamente, nel tuo caso lavorerai con NIC reali e il bridge sarà il tuo gateway o uno switch a seconda della tua infrastruttura.
Quindi nella mia simulazione avremo la seguente configurazione, in una rete 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
Innanzitutto, la fase di installazione è in modo da poter capire di cosa è fatta, saltarla se non si ha familiarità con essa, non è un grosso problema. Quello che devi sapere, tuttavia, è che il comando ip netns exec <namespace> <command>
consente di eseguire un comando in uno spazio dei nomi di rete (ovvero in una delle caselle del disegno precedente). Questo sarà usato anche nella prossima sezione.
# 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
Quindi a questo punto abbiamo la configurazione descritta in precedenza.
Dare forma al traffico
È tempo di prendere il controllo del traffico per ottenere quello che vuoi. Lo tc
strumento consente di aggiungere discipline di accodamento:
- Per uscita: una volta che il kernel ha bisogno di inviare pacchetti e prima di accedere al driver NIC.
- Per l'ingresso: dopo aver effettuato l'accesso al driver della scheda di rete e prima che le routine del kernel vengano eseguite sui pacchetti ricevuti.
Viene fornito con 3 nozioni: qdisc , classi e filtri . Queste nozioni possono essere utilizzate per impostare una complessa gestione del flusso di pacchetti e dare priorità al traffico in base a qualsiasi criterio / criterio desideri.
In breve:
- I Qdisc sono strutture in cui i pacchetti verranno accodati / accodati per via endovenosa.
- Le classi sono contenitori per qdisc che agiscono con comportamenti specifici.
- I filtri sono modi per instradare i pacchetti tra le classi, molti di essi possono essere definiti sullo stesso punto di ingresso con priorità durante l'elaborazione.
Tutti questi di solito funzionano come un albero in cui le foglie sono qdisc e le classi sono nodi. La radice di un albero o sottostruttura sarà dichiarata come <id>:
e i nodi figli saranno dichiarati come <parent_id>:<children_id>
. Tieni presente questa sintassi.
Per il tuo caso, prendiamo A e rendiamo l'albero con il quale desideri impostare tc
:
1:
|
|
|
1:1
/ | \
/ | \
/ | \
1:10 1:20 1:30
| | |
| | |
:10 :20 :30
Spiegazione :
1:
è il qdisc radice collegato al dispositivo vethA, verrà preso esplicitamente come htb
per la gerarchia token bucket (il qdisc predefinito di un dispositivo è pfifo
o pfifo_fast
dipende dal sistema operativo). È specificamente appropriato per la gestione della bandwith. I pacchetti non corrispondenti ai filtri definiti a questo livello andranno in 1:30
classe.
1:1
sarà una htb
classe che limita l'intero traffico del dispositivo a 10 Mbit / s.
1:10
sarà una htb
classe che limita il traffico in uscita a 9 Mbit / s (90% di 10 Mbit / s).
1:20
sarà una htb
classe che limita il traffico in uscita a 8 Mbit / s (80% di 10 Mbit / s).
1:30
sarà una htb
classe che limita il traffico a 10 Mbit / s (fallback).
:10, :20, :30
siamo sfq
qdisc per Accodamento equità stocastica. In altre parole, questi qdisc assicureranno l'equità nella programmazione della trasmissione basata sui flussi.
L'intera cosa è impostata dai seguenti comandi:
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
L'ultima cosa di cui abbiamo bisogno è aggiungere filtri in modo che i pacchetti IP con IP di destinazione uguale a B passino alla 1:10
classe e i pacchetti IP con IP di destinazione uguale a C andranno alla 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
Ora che hai avuto l'idea, dovrai aggiungere tc
regole simili a B e C in modo che anche le trasmissioni verso A da questi rig siano modellate.
analisi
Ora proviamo. Per questo sono personalmente abituato a giocareiperf
, consiste semplicemente in un singolo binario che può essere eseguito come client o come server e invierà automaticamente il maggior traffico possibile tra entrambi gli host.
Tra A e 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
Otteniamo i nostri 9 Mbit / s limite di banda .
Tra A e 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
Otteniamo il nostro limite di banda 8 Mbit / s .
Tra A e 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
Qui abbiamo raggiunto la velocità massima dell'interfaccia virtuale di 10 Mbit / s .
Si noti che il burst della prima misura di ogni corsa può essere gestito meglio in htb
classi regolando il parametro adeguato.
Pulire
Rimuovere :
- Il filtro di priorità 1
1:
: tc filter del dev vethA parent 1: prio 1 u32
.
- Tutti i filtri su
1:
: tc filter del dev vethA parent 1:
.
- Classe
1:20
ed i suoi figli: tc class del dev vethA parent 1:1 classid
1:20
.
- L'intero albero:
tc qdisc del dev vethA
.
Per ripulire il set di simulazione:
# 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