Simule una conexión lenta entre dos máquinas de servidor ubuntu

9

Quiero simular el siguiente escenario: dado que tengo 4 máquinas de servidor ubuntu A, B, C y D. Quiero reducir el ancho de banda de la red en un 20% entre la máquina A y la máquina C y el 10% entre A y B. Cómo Cómo hacer esto usando herramientas de simulación / regulación de red?

Yehia Elshater
fuente
iptables podría tener capacidad de estrangulamiento. Nunca lo usé, pero vale la pena investigarlo.
Michael Martinez
@MichaelMartinez No, no lo hace. tclo hace cuando se usa con marcado iptables.
Xavier Lucas
@XavierLucas es bueno saberlo!
Michael Martinez

Respuestas:

15

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
Xavier Lucas
fuente
1
Muchas gracias por tu asombrosa respuesta. Si es posible, ¿podría agregar los comandos para eliminar los filtros? en caso de que alguien quiera deshacer esta configuración de forma segura después de la simulación.
Yehia Elshater
1
@YahiaZakaria Acabo de agregar esta información en la última parte de mi publicación.
Xavier Lucas
0

Ubuntu tiene IPFW portado desde FreeBSD, e IPFW tiene DUMMYNET que permite administrar varios parámetros de red: ancho de banda, retraso, tasa de pérdida de paquetes, etc.

Kondybas
fuente
0

Lo mejor es usar las herramientas tc con el módulo netem ahora integrado (al menos en el servidor Ubuntu). Puede encontrar más información en este artículo en Stackoverflow .

Luc Stepniewski
fuente
Netem es sobre rtt y emulación de congestión, no sobre ancho de banda.
Xavier Lucas
1
@XavierLucas, tienes razón, para el ancho de banda solo necesitas tc, sin siquiera netem.
Luc Stepniewski
0

El goteo funciona bien.

Esta discusión muestra algunas limitaciones: /unix/109973/how-to-change-speed-limit-of-running-trickle-instance

Mateo
fuente
Trickle se usa para simular el ancho de banda de la red para un programa específico. El OP parece buscar una solución al alcance del host.
Xavier Lucas
Trickled puede usarse para simular un grupo de conexiones (no solo una conexión). De hecho, la pregunta podría interpretarse como "todas las conexiones de host a host".
Mateo