Si un paquete TCP fue parcialmente reconocido, ¿cómo reaccionará el mecanismo de retransmisión?

12

si un cliente tcp envía un paquete, con número de secuencia de 10000 a 20000, a un servidor tcp. El TCP responderá con un ACK con seq_ack 20001.

si intercepto el paquete TCP del cliente y lo divido en 2 segmentos tcp, uno con seq de 10000 a 15000 y el otro con seq de 15001 a 20000. Y luego estos 2 segmentos TCP se envían al servidor TCP. Suponga que el segundo segmento se pierde en el camino. El servidor TCP responderá un ACK con seq_ack 15001.

Ahora, dado que el cliente TCP envía un paquete integral con seq 10000 a 20000, pero obtiene un ACK con 15001, desde el punto de vista del cliente, esto es extraño. ¿Cómo va a reaccionar? En teoría, el cliente debe retransmitir los bytes de la secuencia 15001 a 20000, es decir, el cliente transmitirá nuevos paquetes de la secuencia 15001. Pero, ¿qué tal la práctica, en la implementación de la pila TCP, es la misma que en la teoría?

Creo que en el búfer de envío TCP, cuando se envía un segmento tcp, el segmento aún permanece allí hasta el ACK. Cuando llega el ACK, estos bytes para el segmento se borran del búfer. Hay un puntero en el búfer de envío, cuando llega un ACK, el puntero apunta a la ubicación a la que corresponde el ack_seq. Los bytes que están debajo de ack_seq se borran. De esta manera, ¿no es necesario retransmitir todo el segmento?

misteryes
fuente

Respuestas:

8

Esto se denomina reconocimiento selectivo y ya está incluido en la especificación TCP definida en RFC 2018 . Esto permitiría al cliente reenviar solo los bytes 15001 a 20000 (ya que están en diferentes paquetes / segmentos si los hubiera dividido como usted dice), pero lo más interesante es que incluso permite confirmaciones fuera de orden.

Desde RFC 2018:

Al recibir un ACK que contiene una opción SACK, el emisor de datos DEBE registrar el reconocimiento selectivo para referencia futura. Se supone que el remitente de datos tiene una cola de retransmisión que contiene los segmentos que se han transmitido pero que aún no se han reconocido, en orden de número de secuencia.

Apoyando SACKes no requerido por la especificación TCP. Si el cliente o el servidor no admitieran el reconocimiento selectivo, de hecho, todos los bytes 10000 a 20000 tendrían que ser retransmitidos.

En la implementación de la pila TCP, ¿es lo mismo que en la teoría?

Por SACK lo general, es compatible, ya que el rendimiento, la eficiencia y las ganancias de latencia son importantes, especialmente en una red como Internet.

Sin embargo, estas suposiciones deberían ser ciertas incluso si manipula manualmente los paquetes como lo indicó. De acuerdo con el RFC 793 , como mínimo, toda la ventana de datos tendrá que ser retransmitido, pero el receptor no saber que los datos de recibió es al menos válida . Para detalles de implementación, Sección 3.3 - Números de secuencia de RFC 793.

Para obtener un resumen de todo el proceso con y sin soporte de reconocimiento selectivo, consulte este artículo (que incluye algunos diagramas muy útiles).

Penetración
fuente
es un poco extraño para mí, porque TCP es un protocolo basado en transmisión y orientado a bytes. ¿Por qué debería retransmitir todo el segmento? Me parece que TCP sin SAKC es un protocolo de flujo orientado a segmentos, pero TCP con Sack está orientado a bytes reales. Creo que el RFC no elabora específicamente sobre esto.
misteryes
cómo la pila TCP administra su búfer de envío, es lo mismo que escribí en la pregunta actualizada.
misteryes
@misteryes este artículo describe el proceso (¡con algunos diagramas geniales también!).
Avance
En el enlace que recomendó, parece que el autor aún discute el problema de una manera orientada a segmentos, no de manera orientada a bytes reales. ¿No es así?
misteryes
1
Conocí SACK antes de publicar esta pregunta. Al principio no creo que SACK tenga algo que ver con esta pregunta. En mi opinión, si TCP no está orientado a bytes sino a segmentos, entonces SACK también debería ser el mismo. La diferencia entre SACK-enabled y SACK-disabled es que con SACK, TCP permite un agujero de secuencia en ack_seq. Pero pensé que el agujero de secuencia corresponde a un segmento. mientras que según su dicho, el agujero puede ser la mitad / parte de un segmento.
misteryes
3

Los tamaños de segmento pueden (y lo hacen) cambiar durante la vida útil de una conexión. Afortunadamente, TCP no tiene necesidad de registrar el tamaño del segmento con el que se enviaron previamente los paquetes individuales. Por lo tanto, hará lo siguiente:

  1. Cada vez que llegue un ACK, avance el puntero al primer byte no reconocido en consecuencia y descarte cualquier búfer ahora innecesario.
  2. Cuando surja la necesidad de retransmisión (retransmisión rápida o tiempo de espera; ¡ NO inmediatamente después de la recepción del primer ACK!), Se reenviará en el tamaño de segmento actualmente válido comenzando desde el puntero hasta el primer byte no reconocido.

Ambas operaciones se realizan independientemente del tamaño del segmento en el que se enviaron originalmente estos bytes. Por lo tanto, la teoría debería coincidir con la mayoría de las implementaciones.

Permítanme dar algunos antecedentes para explicar:

¿TCP utiliza bytes o segmentos? Para la aplicación, TCP expone una interfaz de flujo de bytes. Además, todos los campos de encabezado y variables internas están en bytes. Sin embargo, para transmitir información, TCP los divide en segmentos, ya que enviar bytes uno por uno sería un desperdicio :-). El uso de contadores de bytes en todas partes tiene la ventaja de que el tamaño del segmento no necesita permanecer constante durante la vida útil de la conexión:

  • Se están introduciendo opciones, por ejemplo, llevar a cuestas un SACK en una retransmisión (las implementaciones reales encontrarán esto raramente, si es que lo hacen)
  • La ruta MTU cambia, por ejemplo, un enlace a lo largo de la ruta cambia a una MTU más baja o se genera el enlace MTU de cuello de botella. Esto sucede cuando se establecen túneles (VPN, PPPoE) o el protocolo de enrutamiento selecciona un enlace MTU diferente. Esto sucede en IPv4 con el conjunto No fragmentar (verdadero para la mayoría de los TCP modernos); siempre en TCPv6).

Por cierto: SACK no es la respuesta aquí, ya que el receptor (típicamente) solo usará SACK si reconoce un agujero en el flujo de bytes (es decir, si un paquete se perdió pero llegó un paquete siguiente).

Marcel Waldvogel
fuente