Para hacer esto, puede usar tc
solo con u32
filtros o combinarlo con el marcado de iptables (quizás más sencillo si no desea aprender la sintaxis de filtros complejos). En la siguiente publicación detallaré la solución anterior.
Simulando tu configuración
Como ejemplo, consideremos A, B, C y D ejecutando interfaces virtuales de 10 Mbit / s .
Básicamente quieres:
- A <==> B: configuración de 9 Mbit / s para la salida
- A <==> C: configuración de 8 Mbit / s para la salida
Para simular esto, crearé 4 espacios de nombres de red e interfaces virtuales de Ethernet conectadas a un puente.
Por supuesto, en su caso trabajará con NIC reales y el puente será su puerta de enlace o un conmutador dependiendo de su infraestructura.
Entonces, en mi simulación tendremos la siguiente configuración, en una red 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
Primero, la fase de configuración para que pueda comprender de qué está hecha, omítala si no está familiarizado con ella, no es gran cosa. Sin embargo, debe saber que el comando ip netns exec <namespace> <command>
permite ejecutar un comando en un espacio de nombres de red (es decir, en uno de los recuadros del sorteo anterior). Esto también se usará en la siguiente sección.
# 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
Entonces, en este punto, tenemos la configuración descrita anteriormente.
Dando forma al tráfico
Es hora de entrar en el control del tráfico para obtener lo que desea. La tc
herramienta le permite agregar disciplinas de colas:
- Para salir: una vez que el núcleo necesita enviar paquetes y antes de acceder al controlador NIC.
- Para ingresar: después de acceder al controlador NIC y antes de que las rutinas del núcleo se ejecuten sobre los paquetes recibidos.
Viene con 3 nociones: qdisc , clases y filtros . Esas nociones se pueden usar para configurar una gestión compleja del flujo de paquetes y priorizar el tráfico en función de los criterios que desee.
En pocas palabras:
- Los Qdiscs son estructuras donde los paquetes eventualmente se pondrán en cola / en cola.
- Las clases son contenedores para qdiscs que actúan con comportamientos específicos.
- Los filtros son formas de enrutar paquetes entre clases, se pueden definir múltiples de ellos en el mismo punto de entrada con prioridades durante el procesamiento.
Todos estos generalmente funcionan como un árbol donde las hojas son qdiscs y las clases son nodos. La raíz de un árbol o subárbol se declarará como <id>:
y los nodos hijos se declararán como <parent_id>:<children_id>
. Tenga en cuenta esta sintaxis.
Para su caso, tomemos A y rendericemos el árbol con el que desea configurar tc
:
1:
|
|
|
1:1
/ | \
/ | \
/ | \
1:10 1:20 1:30
| | |
| | |
:10 :20 :30
Explicación
1:
es la qdisc raíz adjunta al dispositivo vethA, se tomará explícitamente en cuanto htb
a Hierarchy Token Bucket (la qdisc predeterminada de un dispositivo es pfifo
o pfifo_fast
depende del sistema operativo). Es específicamente apropiado para la gestión de ancho de banda. Los paquetes que no coincidan con los filtros definidos en este nivel irán a 1:30
clase.
1:1
será una htb
clase que limitará todo el tráfico del dispositivo a 10 Mbit / s.
1:10
será una htb
clase que limitará el tráfico de salida a 9 Mbit / s (90% de 10 Mbit / s).
1:20
será una htb
clase que limitará el tráfico de salida a 8 Mbit / s (80% de 10 Mbit / s).
1:30
será una htb
clase que limitará el tráfico a 10 Mbit / s (respaldo).
:10, :20, :30
son sfq
qdisc para la cola de equidad estocástica. En otras palabras, estos qdiscs garantizarán la equidad en la programación de la transmisión en función de los flujos.
Todo esto se configura mediante los siguientes comandos:
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
Lo último que necesitamos es agregar filtros para que los paquetes IP con IP de destino sea igual a B irán a 1:10
clase y los paquetes IP con IP de destino sea igual a C irán a 1:20
clase:
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
Ahora que tiene la idea, deberá agregar tc
reglas similares a B y C para que también se formen las transmisiones hacia A desde estos equipos.
Pruebas
Ahora probémoslo. Para esto estoy acostumbrado a jugar personalmente iperf
, simplemente consiste en un solo binario que puede ejecutarse como cliente o servidor y enviará automáticamente la mayor cantidad de tráfico posible entre ambos hosts.
Entre A y 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
Obtenemos nuestro límite de ancho de banda de 9 Mbit / s .
Entre A y 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
Obtenemos nuestro límite de ancho de banda de 8 Mbit / s .
Entre A y 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
Aquí tenemos la interfaz virtual de velocidad máxima de 10 Mbit / s alcanzada.
Tenga en cuenta que la ráfaga de la primera medida de cada ejecución se puede manejar mejor en htb
clases ajustando el parámetro adecuado.
Limpiar
Para eliminar :
- El filtro de prioridad 1 en
1:
: tc filter del dev vethA parent 1: prio 1 u32
.
- Todos los filtros en
1:
: tc filter del dev vethA parent 1:
.
- Clase
1:20
y sus hijos: tc class del dev vethA parent 1:1 classid
1:20
.
- El árbol entero:
tc qdisc del dev vethA
.
Para limpiar el conjunto de simulación:
# 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