El retraso de tc qdisc no se ve en la grabación de tcpdump

El retraso de tc qdisc no se ve en la grabación de tcpdump

Tengo dos contenedores de Linux conectados con un par veth. En la interfaz veth de un contenedor, configuro el retraso tc qdisc netem y envío tráfico desde él al otro contenedor. Si observo el tráfico en ambos lados usando tcpdump/wireshark, se puede ver que las marcas de tiempo del mismo paquete en el remitente y el receptor no difieren según el retraso seleccionado.

Quería entender más detalladamente en qué punto libpcap coloca marcas de tiempo para el tráfico de salida correspondiente a tc qdisc. Busqué un esquema/imagen en Internet pero no lo encontré. Encontré este tema (punto de captura de paquetes wirehark) pero aconseja introducir una dirección indirecta al tener un contenedor/interfaz más. Esta no es una solución posible en mi situación. ¿Hay alguna manera de resolver el problema sin introducir interfaces intermedias adicionales (es decir, sin cambiar la topología) y solo grabando en la interfaz veth ya dada pero de tal manera que se pueda ver el retraso?

ACTUALIZAR:

Fui demasiado rápido y me equivoqué. Ni mi solución presente a continuación (igual que la primera variante de solución de la respuesta de @AB), ni la solución con IFB de @AB (ya lo he comprobado) resuelven mi problema. El problema es el desbordamiento de la cola de transmisión de la interfaz a1-eth0del remitente en la topología:

[a1-br0 ---3Gbps---a1-eth0]---100Mbps---r1---100Mbps---r2

Fui demasiado rápido y verifiqué solo el retraso de 10 ms en el enlace entre a1-eth0el enrutador r1. Hoy intenté aumentar el retraso: 100 ms, 200 ms y los resultados (retraso por paquete y gráficos de velocidad que obtengo) comienzan a diferir para la topología anterior y para la topología normal:

[a1-eth0]---100Mbps---r1---100Mbps---r2

Entonces no, ciertamente, para pruebas precisas no puedo tener enlaces adicionales: ni introducidos por el puente Linux, ni por este IFB, ni por ningún otro tercer sistema. Pruebo esquemas de control de congestión. Y quiero hacerlo en una topología específica. Y no puedo cambiar la topología solo por trazar, es decir, si al mismo tiempo se cambian mis resultados/gráficos de velocidad y retraso.

ACTUALIZACIÓN 2:

Entonces parece que se ha encontrado la solución, como se puede ver a continuación (solución NFLOG).

ACTUALIZACIÓN 3:

A continuación se describen algunas desventajas de la solución NFLOG (encabezados de capa de enlace grandes y sumas de verificación TCP incorrectas para paquetes TCP de salida con carga útil cero) y se propone una solución mejor con NFQUEUE que no tiene ninguno de estos problemas:Suma de comprobación de TCP incorrecta para paquetes de salida de longitud cero (capturados con iptables). Sin embargo, para mis tareas (pruebas de esquemas de control de congestión) ni NFLOG ni NFQUEUE son adecuados. Como se explica en el mismo enlace, la velocidad de envío se acelera cuando los paquetes se capturan desde las iptables del kernel (así es como lo entiendo). Entonces, cuando graba en el remitente capturando desde la interfaz (es decir, regularmente) obtiene un volcado de 2 Gigabytes, mientras que si graba en el remitente capturando desde iptables obtiene un volcado de 1 Gigabyte. Mas o menos.

ACTUALIZACIÓN 4:

Finalmente, en mi proyecto utilizo la solución puente de Linux que se describe en mi propia respuesta a continuación.

Respuesta1

De acuerdo con laFlujo de paquetes en Netfilter y General Networkingesquema, capturas tcpdump (PAQUETE_AF) despuéssalida (qdisc). Por lo tanto, es normal que no vea el retraso en tcpdump: el retraso ya estaba presente en la captura inicial.

Tendrías que capturarlo un paso antes, así que involucra un tercer sistema:

S1: sistema1, ejecuta tcpdump en la interfaz saliente
R: enrutador (o puente, según su conveniencia, esto no cambia nada), ejecuta qdisc netem
S2: sistema2, ejecuta tcpdump en la interfaz entrante

 __________________     ________________     __________________
|                  |   |                |   |                  |
| (S1) -- tcpdump -+---+- (R) -- netem -+---+- tcpdump -- (S2) |
|__________________|   |________________|   |__________________|

Eso significa 3 redes.pilasinvolucrados, ya sean reales, vm, espacio de nombres de red (incluidosredes ip, LXC, ...)


Opcionalmente, también es posible hacer trampa y mover todas las configuraciones especiales en el enrutador (o puente) usando unFIBInterfaz conreflejadotráfico: permite mediante un truco (dedicado a este caso) insertar netem más o menos después del ingreso en lugar de en la salida:

 _______     ______________________________________________     _______
|       |   |                                              |   |       |         
| (S1) -+---+- tcpdump -- ifb0 -- netem -- (R) -- tcpdump -+---+- (S2) |
|_______|   |______________________________________________|   |_______|

Hay un ejemplo de uso básico de IFB entc reflejadopágina de manual:

Usando una interfaz ifb, es posible enviar tráfico de entrada a través de una instancia de SFQ:

# modprobe ifb
# ip link set ifb0 up
# tc qdisc add dev ifb0 root sfq
# tc qdisc add dev eth0 handle ffff: ingress
# tc filter add dev eth0 parent ffff: u32 \
  match u32 0 0 \
  action mirred egress redirect dev ifb0

Solo usanetemen ifb0 en lugar de sfq (y en el espacio de nombres de red no inicial, ip link add name ifbX type ifbfunciona bien, sin modprobe).

Esto todavía requiere 3 pilas de red para funcionar correctamente.


usandoNFLLOG

Después de una sugerencia de JenyaKh, resulta que es posible capturar un paquete contcpdump,antessalida (por lo tanto, antes de qdisc) y luego en la salida (después de qdisc): usandoiptables(onftables) para registrar paquetes completos en la infraestructura de registro de netlink y seguir leyéndolos contcpdump, luego nuevamente usandotcpdumpen la interfaz de salida. Esto solo requiere configuraciones en S1 (y ya no necesita un enrutador/puente).

Entonces coniptablesen S1, algo como:

iptables -A OUTPUT -o eth0 -j NFLOG --nflog-group 1

Probablemente deberían agregarse filtros específicos para que coincidan con la prueba realizada, porquetcpdumpEl filtro está limitado en la interfaz nflog (wireshark debería manejarlo mejor).

Si se necesita la captura de respuestas (aquí realizada en un grupo diferente, por lo que requiere una captura adicional)tcpdump):

iptables -A INPUT -i eth0 -j NFLOG --nflog-group 2

Dependiendo de las necesidades también es posible trasladarlos acrudo/SALIDAycrudo/PRERUTAMIENTOen cambio.

Contcpdump:

# tcpdump -i nflog:1 -n -tt ...

Si se utilizó un grupo diferente (= 2) para la entrada:

# tcpdump -i nflog:2 -n -tt ...

Luego, al mismo tiempo, como siempre:

# tcpdump -i eth0 -n -tt ...

Respuesta2

ACTUALIZAR:

Entonces finalmente usé esta solución. Está presente en mi solución. Después de todo, funcionó bien para mí.


Yo (el iniciador del tema) resolví mi problema usando el puente de Linux. Aquí [https://www.linuxquestions.org/questions/linux-networking-3/transferring-all-traffic-through-an-extra-interface-4175656515] Escribí que logré usar el puente de Linux pero descarté la posibilidad:"Pero esta solución no se adapta a mis necesidades, ya que en realidad hay un enlace Ethernet adicional entre las interfaces h1-br0 y h1-eth0. Necesito esto para mediciones de rendimiento, por lo que no puedo tener ningún enlace Ethernet adicional. Me refiero a esta solución con El puente arruina mi topología al introducir enlaces adicionales".

       a1
-----------------
|a1-br0---a1-eth0|---------local network
------------------

¿Por qué descarté la solución primero? Inicialmente, mi topología es:

a1---3Gbps---r1---100Mbps---r2

En el enlace r1---r2tengo la velocidad netem configurada en 100 Mbps, en el enlace a1---r1no hay límites de velocidad. Como la cola de transmisión del enrutador r1que lo conecta al enrutador r2es de 1000 paquetes, tuve el efecto de desbordamiento de la cola (algunos paquetes se descartan) al enviar tráfico desde a1a r2. Y esto estuvo bien. Así es como sucede en el mundo real: las colas de los enrutadores se desbordan en caso de un enlace con cuello de botella.

Ahora hago toda esta investigación para agregar a1---r1también límites de demora y velocidad. Entonces se me ocurrió esta solución usando el puente de Linux. Pero pensé que esta solución no funcionará. A continuación puedes ver la nueva topología con puente Linux:

[a1-br0 ---3Gbps---a1-eth0]---100Mbps---r1---100Mbps---r2

Entonces mi problema con la solución fue que esperaba que el desbordamiento de la cola estuviera presente ahora en la cola de transmisión de la interfaz a1-eth0. Es decir, es igual que en la imagen anterior donde el desbordamiento estaba en la interfaz de r1conexión r2. De manera análoga.

Y este desbordamiento no lo quiero. Porque en la topología normal, sin utilizar el puente de Linux para medir el retraso, no tenemos ningún desbordamiento de la cola de transmisión de a1-eth0:

[a1-eth0]---100Mbps---r1---100Mbps---r2

Pero ayer volví a crear la topología con el puente de Linux (la tercera topología de las dibujadas arriba) y lancé tráfico en la topología que fluye desde a1hacia r2. Verifiqué el trabajo pendiente (número actual de paquetes en cola) de la cola de transmisión de a1-eth0llamar al comando tc -s qdisc show dev a1-eth0en ciclo con un intervalo de 500 ms y el trabajo pendiente de la cola de transmisión a1-br0con el comando análogo.

Esto es lo que vi a1-eth0, recibí los mensajes:

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 9461862 bytes 6393 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 133380b 90p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 15280534 bytes 10323 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 133380b 90p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 21110722 bytes 14257 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 118560b 80p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 26952766 bytes 18199 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 102258b 69p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 32788882 bytes 22137 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 103740b 70p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 38635372 bytes 26082 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 102258b 69p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 44477416 bytes 30024 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 102258b 69p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 50332798 bytes 33975 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 102258b 69p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 56157058 bytes 37905 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 125970b 85p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 61969532 bytes 41828 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 133380b 90p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 67784900 bytes 45752 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 133380b 90p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 73600268 bytes 49676 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 133380b 90p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 79415636 bytes 53600 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 133380b 90p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 85244342 bytes 57533 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 120042b 81p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 91080458 bytes 61471 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 102258b 69p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 96923984 bytes 65414 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 102258b 69p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 102761582 bytes 69353 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 102258b 69p requeues 0 

qdisc netem 8112: root refcnt 2 limit 1000 delay 10.0ms
 Sent 108606590 bytes 73297 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 103740b 70p requeues 0 

Esto es lo que vi a1-br0, recibí los mensajes:

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

qdisc noqueue 0: root refcnt 2 
 Sent 0 bytes 0 pkt (dropped 0, overlimits 0 requeues 0) 
 backlog 0b 0p requeues 0 

Entonces se puede ver que no ocurre ningún desbordamiento a1-eth0y en realidad no "parece" que a1-br0envíe nada, aunque en realidad envía. Entonces, el vínculo entre a1-broy a1-eth0no es como ese (el vínculo del quinto par) entre a1y enrutador r1. No sé por qué es así. Es extraño porque verifiqué que puedo, por ejemplo, establecer la configuración de retardo de netem en a1-br0, por lo que es como una interfaz normal.

De todos modos, comprobé que la solución con el puente satisface todas mis necesidades. Sin embargo, todavía no he explorado por qué funciona (me refiero a lo que expliqué anteriormente: desbordamiento de cola, etc.).


Aquí están los comandos que ejecuté en el host a1como referencia. Sin embargo, entiendo que es difícil entenderlos completamente sin el contexto. Pero, tal vez, ayude a alguien en el futuro:

brctl addbr a1-br0
brctl addif a1-br0 a1-eth0
ip link set dev a1-br0 up
ip addr add dev a1-br0 11.0.0.1/30
ip addr flush dev a1-eth0
route add default gw 11.0.0.2 dev a1-br0
ifconfig a1-eth0 0.0.0.0 up
ethtool -K a1-br0 tx off sg off tso off ufo off

La topología con direcciones IP a las que apliqué los comandos también está presente aquí:Hacer ping a una interfaz del enrutador Linux mediante otra interfaz de este enrutador. Aquí está la topología:

------                           ------                            ------
| a1 |                           | r1 |                            | r2 |
|    | a1-eth0-----------r1-eth0 |    |r1-eth1--------------r2-eth1|    |
-----(11.0.0.1/30)   (11.0.0.2/30)----(11.0.0.9/30)   (11.0.0.10/30)----- 

información relacionada