Para hacer esto, puede usar tcsolo con u32filtros 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 tcherramienta 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 htba Hierarchy Token Bucket (la qdisc predeterminada de un dispositivo es pfifoo pfifo_fastdepende 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:30clase.
1:1será una htbclase que limitará todo el tráfico del dispositivo a 10 Mbit / s.
1:10será una htbclase que limitará el tráfico de salida a 9 Mbit / s (90% de 10 Mbit / s).
1:20será una htbclase que limitará el tráfico de salida a 8 Mbit / s (80% de 10 Mbit / s).
1:30será una htbclase que limitará el tráfico a 10 Mbit / s (respaldo).
:10, :20, :30son sfqqdisc 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:10clase y los paquetes IP con IP de destino sea igual a C irán a 1:20clase:
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 tcreglas 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 htbclases 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:20y 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