El método utilizado por TCP para
control de la congestión es el basado en la regulación del tráfico inyectado a
la red. Esto supone que implementa funciones que le permiten estudiar cuándo es
posible enviar más tráfico por el enlace, y cuándo se ha superado la capacidad
del mismo y se debe disminuir la carga.
TCP emplea 4 algoritmos
relacionados entre sí a los efectos de efectuar el control de congestión. Ellos
son conocidos con slow start, congestion avoidance, fast retransmit y fast
recovery.
Los algoritmos slow start y
congestion avoidance, deben ser utilizados por la fuente TCP a los efectos de controlar
la cantidad de tráfico inyectado en la red. Para esto se cuenta con tres
variables de estado del protocolo. Estas son cwnd (congestion Windows), que controla
del lado de la fuente la cantidad de datos que se puede enviar sin haber recibido
un ACK, rwnd (receiver’s advertised window) que indica la cantidad de datos que
puede recibir el destino y ssthresh (slow start threshold) que indica en qué
fase de control de congestión se encuentra el transmisor (slow start si es
mayor que cwnd o congestion avoidance si es menor; de ser iguales, se puede
utilizar cualquiera de los dos algoritmos). El mínimo de cwnd y rwnd gobierna
la transmisión. El algoritmo slow start es utilizado al comienzo de una transmisión
a los efectos de que TCP pueda testear la red y conocer su capacidad evitando
congestionarla. También es utilizado en el momento de recuperación ante la pérdida
de algún segmento, indicada por timeout. Luego del three-way handshake, el
tamaño de la ventana inicial de envío (IW: initial Windows) debe ser menor o
igual que 2 x SMSS1 bytes y no mayor a dos segmentos. El valor de ssthresh
debería ser lo más alto posible al comienzo (por ejemplo, igual a rwnd) y deberá
reducirse en caso de congestión. Durante la fase slow start se aumenta cwnd en a
lo sumo SMSS bytes por cada ACK recibido de datos nuevos entregados al receptor.
Esta fase culmina cuando cwnd alcanza a ssthresh o cuando se detecta
congestión.
A partir de allí se inicia la
fase de congestion avoidance donde cwnd se incrementa en un segmento por
round-trip time (tiempo que transcurre entre que sale un segmento y llega el
ACK asociado). Esta fase continúa hasta que se alcanza la congestión
nuevamente.
Durante la fase de congestion
avoindance, la actualización de la variable cwnd, se realiza con la siguiente
fórmula:
cwnd = cwnd + SMSS x SMSS / cwnd
Calculándose cada vez que llega
un ACK no duplicado.
Cuando el transmisor detecta la
pérdida de un segmento, a partir del timer de retransmisión, el valor de ssthresh
debe pasar a ser:
ssthresh = max (FS / 2, 2 x SMSS)
Siendo FS (Flight Size) la
cantidad de datos enviados pero aún no reconocidos o ACKed. Al mismo tiempo, cwnd
no puede ser mayor que LW (Loss Window) que vale 1 segmento y sin importar el
valor de IW. Se identifica con LW al tamaño de cwnd luego de detectar, a través
del timer de retransmisión, una pérdida.
Posteriormente se pasa a la fase
de slow start hasta alcanzar el ssthresh y luego se seguirá con la fase congestion
avoidance.
Cuando se detecta la primera
pérdida en una ventana de datos, mientras no se reparen todos los segmentos de dicha
ventana, la cantidad de segmentos transmitidos e cada RTT no podrán ser mayor a
la mitad de los segmentos salientes cuando la pérdida fue detectada. Luego que todos
los segmentos fueran exitosamente retransmitidos, cwnd no podrá tomar un valor
mayor a ssthresh y la fase siguiente será congestion avoidance. Pérdidas en dos
ventanas de datos sucesivas o en retransmisiones indica congestión e implica
que cwnd y ssthresh deben bajar dos veces.
El receptor TCP debería enviar
inmediatamente un ACK duplicado si recibe un segmento fuera de orden. Con ello
busca informar al transmisor el número de secuencia esperado. Las conclusiones
a las que puede arribar el transmisor ante la llegada de ACK duplicados pueden
ser varias. Primero, puede concluir que está ante la presencia de segmentos
descartados; segundo, que por razones de tránsito en la red, los segmentos
están llegando en desorden al receptor y tercero, que ocurre por duplicación de
los segmentos o de los ACKs en la propia red. El receptor también debería
enviar inmediatamente un ACK para aquel segmento que recibe y que se encuentra
en el hueco del espacio de número de secuencia esperado de forma de colaborar
con el transmisor.
El algoritmo fast retransmit
debería ser utilizado para detectar y reparar pérdidas basado en la recepción
de ACK duplicados. El algoritmo emplea la recepción de 3 ACK duplicados (4 ACKs
idénticos) para concluir que un segmento se ha perdido. El transmisor envía el
segmento que deduce se ha perdido sin esperar que expire el timer de retransmisión, sstresh toma el valor dado
por la ecuación y cwnd toma un valor
dado por la ecuación:
cwnd = ssthresh + 3 x SMSS
(Lo que se conoce como inflado
artificial de cwnd).
Esto hace crecer cwnd en la
cantidad de segmentos (ACK en este caso) que abandonaron la red. Un criterio similar
seguirá por cada ACK duplicado recibido. Luego de ello, el algoritmo fast recovery
gobierna la transmisión mientras no se reciban nuevos ACK duplicados. De ser posible
(según los valores de cwnd y rwnd), se transmite un nuevo segmento y ante la
llegada de un ACK de datos nuevos lleva el valor de cwnd al de ssthresh (lo que
se conoce como desinflado de cwnd). El no pasar a la fase de slow start ante la
pérdida del segmento se justifica en el hecho de que la llegada de ACK
duplicado implica que quien lo envió recibió un segmento, por lo tanto, hay segmentos
que están abandonando la red y por lo tanto dejan de consumir recursos en ella.
Estos algoritmos no se comportan
adecuadamente ante pérdidas múltiples en un “single flight” de segmentos lo que
motivó el desarrollo de un conjunto de implementaciones adicionales.
Para calcular el RTO actual, el
transmisor mantiene 2 variables de estado llamadas SRTT (smothed round-trip time)
y RTTVAR (round-trip time variation). Mientras no se calcule un RTT, el mismo
debe valer como máximo 3 segundos. Cuando se calcula el primer RTT (R), las variables
tomarán los siguientes valores:
SRTT = R
RTTVAR = R/2
RTO = SRTT + max (G, K x RTTVAR)
Donde K = 4 y G es la
granularidad del reloj, medida en segundos.
Para el siguiente cálculo de RTT
(R') los nuevos valores de las variables serán:
RTTVAR = (1 - β) x RTTVAR + β x
|SRTT - R'|
SRTT = (1 - α) x SRTT + α x R'
Donde los valores de α y β
deberían ser 1/8 y ¼ respectivamente.
RTO = SRTT + max (G, K x RTTVAR)
RTO no debería ser menor que 1 ni
mayor que 60 segundos.
La toma de las muestras RTT se
debe realizar utilizando el algoritmo de Karn. Ello implica que no debe hacerse
utilizando segmentos retransmitidos (salvo que se utilice la opción timestamp)
y que en caso de expirar, se debería retransmitir el primer segmento no ACKed y
efectuar un backoff, pasando RTO a valer el doble y lanzarlo nuevamente. Se
debe realizar como mínimo una medida por round-trip time de forma de evitar el
efecto de aliasing en el cálculo de RTO para el caso de ventanas de congestión
grandes.