UNIVERSIDADE DO VALE DO RIO DOS SINOS – UNISINOS
CENTRO DE CIÊNCIAS EXATAS E TECNOLÓGICAS
Especialização em Redes de Computadores e Internet
TRANSMISSION CONTROL PROTOCOL
MARINA SIMON BECKER
Orientador: Dr. Marinho Barcellos
São Leopoldo, março de 2001.
Dedico este trabalho ao meu orientador,
pelo incentivo e atenção.
SUMÁRIO
INDICE DE FIGURAS
5
RESUMO
6
ABSTRACT
7
1 INTRODUÇÃO
8
2 TRANSMISSION CONTROL PROTOCOL
9
2.1
2.2
2.3
FUNCIONAMENTO
CONFIABILIDADE
CONTROLES
10
12
13
3 CONTROLE DE SESSÃO
15
3.1
3.2
3.3
3.4
15
17
18
18
ESTABELECENDO UMA CONEXÃO
MANTENDO UMA CONEXÃO
RESETANDO UMA CONEXÃO
ENCERRANDO UMA CONEXÃO
4 CONTROLE DE ERRO
21
4.1
4.2
4.3
21
22
23
TIPOS DE ERRO
DETECÇÃO DE ERRO
RECUPERAÇÃO DE ERRO
5 CONTROLE DE FLUXO
25
5.1
5.2
5.3
5.4
25
26
27
28
JANELA DESLIZANTE
SWS - SILLY WINDOW SYNDROME
PREVENÇÃO DA SWS NO RECEPTOR
PREVENÇÃO DA SWS NO TRANSMISSOR
6 CONTROLE DE CONGESTIONAMENTO
29
6.1
6.2
29
30
SLOW START
CONGESTION AVOIDANCE
7 MECANISMOS AVANÇADOS
32
7.1
7.2
7.3
7.4
32
32
33
33
FAST RETRANSMIT
FAST RECOVERY
SELECTIVE ACKNOWLEDGEMENT
FORWARD ACKNOWLEDGEMENT
8 PROBLEMAS COM IMPLEMENTAÇÕES DO TCP
34
8.1
8.2
8.3
8.4
34
35
36
37
CONTROLE DE CONGESTIONAMENTO
PERFORMANCE
CONFIABILIDADE
GERENCIAMENTO DE RECURSOS
9 CONCLUSÃO
39
REFERÊNCIAS
40
4
INDICE DE FIGURAS
Figura 2.1: Formato do segmento TCP ________________________________________________________ 10
Figura 2.2: Confirmação positiva ____________________________________________________________ 12
Figura 2.3: Confirmações com o uso da janela deslizante _________________________________________ 13
Figura 3.1: Three Way Handshake ___________________________________________________________ 15
Figura 3.2: Segmento solicitando uma conexão _________________________________________________ 16
Figura 3.3: Segmento aceitando uma conexão __________________________________________________ 16
Figura 3.4: Segmento finalizando o estabelecimento de uma conexão ________________________________ 17
Figura 3.5: Encerramento de uma conexão_____________________________________________________ 18
Figura 3.6: Segmento solicitando encerramento da conexão _______________________________________ 19
Figura 3.7: Segmento de confirmação _________________________________________________________ 19
Figura 3.8: Segmento aceitando o encerramento da conexão_______________________________________ 20
Figura 3.9: Segmento confirmando o encerramento da conexão ____________________________________ 20
Figura 4.1: ACKs duplicados _______________________________________________________________ 23
Figura 5.1: Janela deslizante com nenhum segmento confirmado ___________________________________ 26
Figura 5.2: Janela deslizante com um segmento confirmado _______________________________________ 26
RESUMO
Este trabalho tem o objetivo de fazer uma revisão do TCP - Transmission Control
Protocol, que é, hoje, um dos protocolos mais importantes e mais utilizados para a
transmissão de dados em ambientes de rede heterogêneos como a Internet. A proposta é
mostrar o funcionamento do protocolo e os tipos de controle que este possui para garantir a
entrega confiável dos dados ao seu destino, assim como problemas encontrados em algumas
implementações. Embora este trabalho não apresente propostas para melhorias no TCP, ele
resume informações relevantes sobre esse protocolo, fruto de uma revisão bibliográfica
profunda e abrangente. Sua contribuição é dissertar sobre o TCP de forma inédita, adotando
uma estrutura centrada nos mecanismos de controle do protocolo, e após tratando de
problemas verificados em implementações desses mecanismos.
ABSTRACT
This work revisits TCP - Transmission Control Protocol, the most widely used
protocol in the Internet. TCP is used for reliable data transmission, dealing properly with
heterogeneous environments. Although this work does not propose improvements to TCP, it
shows relevant information about the protocol, with a comprehensive bibliographic review. Its
contribution is to discusses TCP in a new way: centering the focus on TCP protocol control
mechanisms, and then addressing the problems found on some TCP implementations.
2
TRANSMISSION CONTROL PROTOCOL
Na pilha de protocolos TCP/IP existem dois protocolos de transporte, o UDP e o TCP.
O TCP é um protocolo de transporte de stream de dados, orientado à conexão, e que fornece a
garantia de um serviço de entrega confiável. Faz parte da pilha TCP/IP e, assim como o UDP,
é encapsulado dentro do pacote IP. O TCP é um protocolo complexo, pois foi desenvolvido
para oferecer confiabilidade trabalhando com diversos ambientes de rede, nas mais diferentes
plataformas e com os mais variados aplicativos.
Para o TCP, um stream de dados é uma seqüência de bits dividida em octetos (oito
bits). A aplicação fornece ao protocolo de transporte os dados em forma de stream, e o
protocolo é livre para segmentar o stream da forma que for melhor para a transmissão. Podese dizer então que o TCP transporta segmentos de stream de dados. Os segmentos que o TCP
transporta possuem o tamanho variável e o tamanho máximo do segmento é definido no
momento em que a conexão é estabelecida.
Por ser um protocolo orientado à conexão, antes de iniciar a transferência de dados, ele
precisa estabelecer uma conexão com o host destino, para que os dois possam fazer uma série
de ajustes, como sincronização, cálculo de tempo, tamanho máximo do segmento, entre
outros.
Assim como o UDP, o TCP suporta o conceito de portas de comunicação. O TCP
identifica cada conexão por end-points. Cada end-point é visto como (host, porta), onde host
é o número IP do host de destino e porta é o número da porta TCP deste host ([12]). Cada
porta de comunicação corresponde a uma fila de mensagens, a um buffer individual. Isto
permite que um host mantenha múltiplas conexões, utilizando uma porta para cada conexão.
Existem algumas RFCs que definem portas específicas para serviços conhecidos, como
TELNET, FTP, HTTP, POP, SMTP, entre outros. O número da porta TCP normalmente é o
mesmo da porta UDP correspondente.
As conexões que o TCP estabelece são full duplex, ou seja, a transferência dos dados
pode ocorrer em ambos os sentidos, possibilitando que os dois hosts conversem durante a
transmissão. Se um dos hosts encerrar a conexão, esta torna-se half duplex, com o fluxo
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
trafegando em apenas um sentido. A vantagem da conexão full duplex em relação a half
duplex, é o piggyback, isto é, o protocolo receptor pode retornar informações de controle para
o transmissor, reduzindo o tráfego na rede.
Para garantir um serviço de entrega confiável, o TCP requer mais CPU e mais largura
de banda que outros protocolos de transporte.
2.1
Funcionamento
Um segmento TCP é formado por duas partes: a primeira parte é o cabeçalho, onde
são enviadas as informações de controle necessárias, e a outra parte é composta dos dados a
serem transportados. O cabeçalho do TCP possui um tamanho fixo de 20 bytes e mais um
campo opcional de tamanho variável. O tamanho do cabeçalho é medido por múltiplos de 32
bits. O formato do segmento do TCP, que será visto a seguir, é definido na RFC 793 ([1]). A
Figura 2.1 mostra o formato do segmento TCP.
32 bits
Source Port
Destination Port
Sequence Number
Acknowledgement Number
Data
Offset
U
R
G
Reserved
A
C
K
P
S
H
R
S
T
S
Y
N
F
I
N
Checksum
Window
Urgent Pointer
Options
Padding
Data
Figura 2.1: Formato do segmento TCP
Source Port (16bits) e Destination Port (16bits): estes campos indicam o
número da porta de origem e o número da porta de destino que serão usadas para
estabelecerem a conexão. O TCP já tem definido portas padrão para diversos tipos de serviço.
Sequence Number (32bits): campo que indica o número de seqüência dos pacotes
que permite a remontagem dos dados no destino. O número de seqüência inicial é definido no
momento em que a conexão estiver sendo estabelecida.
Marina Simon Becker
10
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Acknowledgement Number (32bits): número de reconhecimento, que significa o
próximo byte aguardado pelo destino. Informa que até o byte anterior foi tudo recebido
corretamente.
Data Offset (4bits): chamado também, por alguns autores*, de Header Length
(comprimento do cabeçalho). Indica onde os dados iniciam. Contém um número inteiro
medido em múltiplos de 32 bits. Devem ser incluídos zeros no final do cabeçalho até que ele
se torne um múltiplo de 32 bits.
Reserved (6bits): campo reservado para futura utilização.
Control Bits (6bits): seis bits de controle, que servem para determinar a
finalidade e o conteúdo do segmento. Indicam como interpretar outros campos do cabeçalho.
São eles:
URG = indica que o campo Urgent Pointer é válido.
ACK = indica que o campo Acknowledgement Number é válido.
PSH = indica que o receptor deve entregar os dados para a aplicação
imediatamente, sem esperar encher o buffer.
RST = serve para reiniciar ou rejeitar uma conexão.
SYN = utilizado para solicitar uma conexão.
FIN = utilizado para encerrar uma conexão.
Window (16bits): tamanho da janela oferecido pelo host. Indica quantos bytes podem
ser enviados a partir do byte confirmado (Acknowledgement Number).
Checksum (16bits): campo que faz a checagem da integridade dos dados e do
cabeçalho. A soma de todos os bytes mais o Checksum deve ser igual a zero.
Urgent Pointer (16bits): campo que indica a posição no segmento onde os dados
urgentes terminam.
Options: campo opcional e variável. Uma de suas funções é comunicar o tamanho
máximo dos segmentos (MSS, Maximum Segment Size) que pode ser recebido pelo host. A
opção MSS contém 16bits.
Padding: campo variável, composto de zeros, usado para especificar o final do
cabeçalho e o início dos dados.
Data: esta é a segunda parte do segmento. Logo após o final do cabeçalho, iniciam os
dados que serão transportados.
*
Em [12], apesar de referenciar a RFC 793, refere-se a este campo como HLEN, que é uma abreviatura de
Header Length.
Marina Simon Becker
11
Universidade do Vale do Rio dos Sinos – Unisinos
2.2
Transmission Control Protocol
Confiabilidade
A maioria dos protocolos que oferece serviço confiável de entrega de dados utiliza
uma técnica chamada confirmação positiva (positive acknowledgement), ou seja, para cada
segmento transmitido o receptor envia um segmento com a flag ACK ativa no campo
Control Bits, que significa a confirmação do recebimento do segmento. É através destas
confirmações que o TCP consegue fornecer confiabilidade de entrega, pois só assim ele tem
como saber se o segmento chegou ao seu destino ou não. Um exemplo do funcionamento de
confirmação positiva está ilustrado na Figura 2.2.
Envia segmento 1
Recebe segmento 1
Envia o ACK 2
Recebe o ACK 2
Envia segmento 2
Recebe segmento 2
Envia o ACK 3
Recebe o ACK 3
Envia segmento 3
Recebe segmento 3
Envia o ACK 4
Recebe o ACK 4
Envia segmento 4
Recebe segmento 4
Envia o ACK 5
Recebe o ACK 5
Figura 2.2: Confirmação positiva
Segundo o exemplo da Figura 2.2, somente após a chegada da confirmação do
segmento anterior é que o transmissor pode enviar um novo segmento. Na verdade, este
mecanismo gasta uma considerável largura de banda, pois ele espera a chegada da
confirmação do segmento anterior para poder transmitir um novo segmento. Isto diminui o
throughput na rede, que implica em um mau aproveitamento da banda, pois deixa a rede
ociosa enquanto fica à espera da confirmação.
Existe um mecanismo que faz com que o processo de recebimento de confirmações
seja mais eficaz. Este mecanismo é conhecido como janela deslizante (sliding window), que
será abordado no Capítulo 5. A janela deslizante permite que o transmissor envie múltiplos
segmentos sem necessitar uma confirmação imediata. Por exemplo, se o tamanho da janela *
estiver estipulado para 4 segmentos, o transmissor pode enviar até 4 segmentos e, conforme
chegarem as confirmações, novos segmentos poderão ser enviados. Isto aumenta o throughput
*
O tamanho da janela é estipulado pelo receptor em cada segmento de confirmação.
Marina Simon Becker
12
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
na rede fazendo com que a banda seja melhor aproveitada. A Figura 2.3 ilustra as
confirmações com o uso da janela deslizante.
Envia segmento 1
Envia segmento 2
Envia segmento 3
Envia segmento 4
Recebe o ACK 2
Recebe o ACK 3
Recebe segmento 1
Envia o ACK 2
Recebe segmento 2
Envia o ACK 3
Recebe segmento 3
Envia o ACK 4
Recebe segmento 4
Envia o ACK 5
Recebe o ACK 4
Recebe o ACK 5
Figura 2.3: Confirmações com o uso da janela deslizante
2.3
Controles
Como foi visto anteriormente, o TCP garante um serviço de entrega confiável
utilizando técnicas de confirmação da chegada dos segmentos ao seu destino. Mas somente
isto não é suficiente para que ele possa garantir, além da confiabilidade, um bom
funcionamento, uma boa performance e uma boa utilização da rede. Para isto, ele necessita
fazer uma série de controles, tais como: controle de erro, controle de fluxo, controle de
congestionamento e controle de sessão.
O controle de erro faz com que o TCP certifique-se que os dados estão chegando
corretamente no destino. Existem vários tipos de erro que podem ocorrer com os segmentos
enviados durante uma transmissão, por isto o TCP deve detectar a ocorrência de um erro e
tentar recuperar os segmentos que foram vítimas do erro, garantindo assim, a chegada correta
dos dados no receptor. O controle de erro será tratado no Capítulo 4.
O TCP deve preocupar-se também com o fluxo dos dados durante a transmissão para
garantir melhor performance. O fluxo dos dados diz respeito à velocidade e a quantidade de
dados que estão sendo enviados. Por exemplo, o transmissor deve saber qual é a capacidade
de armazenamento e de processamento do receptor, pois se a capacidade do receptor for muito
pequena, ele não dará conta de tratar muitos dados rapidamente, fazendo que o seu buffer se
esgote e ocasionando o descarte de segmentos. Sendo assim, o transmissor deve diminuir o
Marina Simon Becker
13
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
fluxo de envio para que o receptor possa trata-los de acordo com a sua capacidade. O controle
de fluxo será mostrado no Capítulo 5.
O outro tipo de controle é o controle de congestionamento, que diz respeito à rede,
como o estado dos roteadores que estão ao longo do caminho, entre o transmissor e o
receptor. O TCP deve preocupar-se em evitar o congestionamento da rede, pois uma rede
congestionada ocasiona não só o atraso, como a perda de pacotes, ou em casos mais extremos
é causado o colapso de congestionamento, que pode fazer a rede parar. O controle de
congestionamento será discutido no Capítulo 6.
O controle de sessão cuida do estado das conexões, controlando desde o
estabelecimento até o encerramento de uma conexão. O controle de sessão será abordado no
próximo capítulo.
Marina Simon Becker
14
3
3.1
CONTROLE DE SESSÃO
Estabelecendo uma conexão
Para estabelecer uma conexão o TCP utiliza o Three Way Handshake, que significa,
literalmente, “um aperto de mão em três vias”, onde são necessários apenas 3 segmentos para
que a conexão seja estabelecida. O Three Way Handshake funciona da seguinte maneira: o
host que deseja fazer um pedido de conexão envia um segmento com a flag SYN ativa no
campo Control Bits. Assim que o outro host recebe o pedido de conexão, ele envia um
segmento contendo as flags ACK e SYN ativas, que significa aceitar a conexão. Para finalizar
o estabelecimento da conexão, o primeiro host envia um segmento com a flag ACK, indicando
ter aceitado a conexão com o host. A partir deste momento a conexão é considerada
estabelecida pelo primeiro host. Quando o terceiro segmento é recebido pelo segundo host,
este considera a conexão estabelecida. A partir do momento em que um host considera uma
conexão estabelecida, ele pode iniciar a transferência de dados. A Figura 3.1 mostra o
exemplo de um Three Way Handshake.
Envia SYN
Recebe SYN
Envia ACK, SYN
Recebe ACK, SYN
Envia ACK
Recebe ACK
Figura 3.1: Three Way Handshake
Para ficar mais claro, o exemplo a seguir mostra cada um dos segmentos ilustrados na
Figura 3.1. Estes segmentos foram capturados de uma conexão entre um cliente e um servidor
web. A Figura 3.2 apresenta o conteúdo do primeiro segmento.
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Envia SYN
Source Port
Destination Port
Sequence Number
Acknowledgement Number
Data Offset (MSB 4 bits)
Reserved (LSB 4 bits)
Control Bits
Window
Checksum
Urgent Pointer
Option
1042
80
1084136
0
7 (32-bit word)
0
SYN
8192
0x3047
0x0000
0204021801010402
Figura 3.2: Segmento solicitando uma conexão
No primeiro segmento, o TCP do cliente web envia nos campos Source Port e
Destination Port o número da porta que ele escolheu para estabelecer a conexão e o
número da porta do servidor web que está esperando a conexão. A porta padrão do servidor
web é a porta 80. No campo Sequence Number é enviado o número de seqüência inicial,
que é um número escolhido aleatoriamente pelo TCP. Por ser o primeiro segmento, o campo
Acknowledgement Number é igual a 0, pois ele não sabe ainda o Sequence Number
do servidor web. O campo Data Offset é igual a 7, que indica que o tamanho do
cabeçalho é 7 vezes 32 bits. O campo Reserved é igual a 0, pois não está sendo usado. No
campo Control Bits a flag SYN indica o pedido de conexão. O campo Window indica
que o máximo de segmentos que o TCP do servidor web pode enviar corresponde a 8192
octetos, pois este é o tamanho da janela do cliente web. O Checksum é enviado para o TCP
do servidor web checar a integridade do segmento. O Urgent Pointer é igual a 0, pois
não existem dados urgentes neste segmento. Se existissem dados urgentes neste segmento, a
flag URG no campo Control Bits deveria estar setada. E, por último, o campo
Options é enviado para comunicar o MSS, ou seja, diz qual é o tamanho máximo de
segmento que o TCP do cliente web irá aceitar. Esta opção somente é enviada no segmento de
pedido de conexão e se ela não for enviada, o TCP utiliza o valor padrão para o MSS, que é o
tamanho total do datagrama IP menos os cabeçalhos IP e TCP.
Envia ACK, SYN
Source Port
Destination Port
Sequence Number
Acknowledgement Number
Data Offset (MSB 4 bits)
Reserved (LSB 4 bits)
Control Bits
Window
Checksum
Urgent Pointer
Option
80
1042
174299038
1084137
6 (32-bit word)
0
ACK, SYN
33232
0x3DCF
0x0000
020405B4
Figura 3.3: Segmento aceitando uma conexão
Marina Simon Becker
16
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
A Figura 3.3 apresenta o conteúdo do segundo segmento, que tem no campo
Sequence Number o número de seqüência inicial do servidor web. No campo
Acknowledgement Number tem o Sequence Number do cliente web mais 1,
indicando o próximo segmento que ele espera receber. O campo Control Bits tem as
flags ACK e SYN, indicando aceitar a conexão. O campo Window especifica o tamanho da
janela do servidor web e o campo Option envia o MSS que será aceito pelo TCP do servidor
web.
Envia ACK
Source Port
Destination Port
Sequence Number
Acknowledgement Number
Data Offset (MSB 4 bits)
Reserved (LSB 4 bits)
Control Bits
Window
Checksum
Urgent Pointer
1042
80
1084137
174299039
6 (32-bit word)
0
ACK
8576
0xB5DC
0x0000
Figura 3.4: Segmento finalizando o estabelecimento de uma conexão
A Figura 3.4 ilustra o último segmento do Three Way Handshake. No campo
Sequence Number tem o número pedido no Acknowledgement Number do
segmento anterior, indicando que este é 6.23988
ca
0 Td(m)Tj0.12.88 0 Td(n)1 0 00 Td(r)Tj0.12 Tc1.2 TwT
Marina Simon Becker
17
Universidade do Vale do Rio dos Sinos – Unisinos
3.3
Transmission Control Protocol
Resetando uma conexão
Existem certas ocasiões que a aplicação não consegue encerrar a conexão da maneira
correta. Isto pode acontecer por causa de algum um erro na aplicação, ou simplesmente por
ela ter sido abortada. Nestes casos, o TCP deve utilizar o mecanismo de reset para abortar a
conexão com a outra ponta. O reset é um segmento com o bit RST ligado no campo
Control Bits do cabeçalho TCP. Assim que a outra ponta recebe este segmento, ela deve
saber que a conexão foi abortada por algum motivo, e que não deve mais enviar dados.
3.4
Encerrando uma conexão
O método utilizado para encerrar uma conexão é como o Three Way Handshake. A
diferença é o campo Control Bits. Enquanto que para estabelecer uma conexão utiliza-se
a flag SYN, para finalizar a conexão utiliza-se a flag FIN. Outra diferença é que o segundo
segmento não inclui o FIN junto com o ACK. Primeiro, vai um segmento com a flag FIN,
indicando que um dos hosts não tem mais dados para enviar e quer encerrar a conexão. Em
resposta ao pedido de encerramento de conexão, o outro host envia um segmento com a flag
ACK, avisando que recebeu o pedido. Este, deve então avisar a aplicação que não existem
mais dados para receber e perguntar se pode encerrar a conexão. Caso a aplicação permita o
encerramento da conexão, o TCP envia o segmento com a flag FIN para o outro, que por sua
vez, envia um ACK finalizando a conexão. A Figura 3.5 apresenta o encerramento de uma
conexão.
Envia ACK, FIN
Recebe ACK, FIN
Envia ACK
Recebe ACK
Envia ACK, FIN
Recebe ACK, FIN
Envia ACK
Recebe ACK
Figura 3.5: Encerramento de uma conexão
O exemplo a seguir ilustra o encerramento de uma conexão entre um cliente e um
servidor web, apresentando o conteúdo de cada segmento visto na Figura 3.5. A Figura 3.6
mostra o conteúdo do primeiro segmento.
Marina Simon Becker
18
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Envia ACK, FIN
Source Port
Destination Port
Sequence Number
Acknowledgement Number
Data Offset (MSB 4 bits)
Reserved (LSB 4 bits)
Control Bits
Window
Checksum
Urgent Pointer
1109
80
11127669
5238095
5 (32-bit word)
0
ACK, FIN
8044
0xCC48
0x0000
Figura 3.6: Segmento solicitando encerramento da conexão
Neste caso, o cliente web já recebeu todos os dados que ele queria e decidiu encerrar a
conexão com o servidor web. O TCP envia no campo Control Bits as flags ACK e FIN
ligadas, pois o ACK corresponde à confirmação do último segmento recebido do servidor web
e o FIN diz que ele quer encerrar a conexão.
A Figura 3.7 apresenta o conteúdo do segundo segmento, enviado pelo servidor web.
O segmento contém apenas um ACK no campo Control Bits, somente para confirmar
que recebeu o último segmento.
Envia ACK
Source Port
Destination Port
Sequence Number
Acknowledgement Number
Data Offset (MSB 4 bits)
Reserved (LSB 4 bits)
Control Bits
Window
Checksum
Urgent Pointer
80
1109
5238095
11127670
5 (32-bit word)
0
ACK
8241
0xCB83
0x0000
Figura 3.7: Segmento de confirmação
A Figura 3.8 apresenta o conteúdo do terceiro segmento, que também é enviado pelo
servidor web, pois depois de ter certificado-se com a aplicação que pode encerrar a conexão,
ele envia um segmento com as flags ACK e FIN indicando que a conexão pode ser encerrada.
Note que o Sequence Number e o Acknowledgement Number são os mesmos do
segmento anterior, indicando que este segmento corresponde ao último segmento enviado
pelo cliente web.
Marina Simon Becker
19
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Envia ACK, FIN
Source Port
Destination Port
Sequence Number
Acknowledgement Number
Data Offset (MSB 4 bits)
Reserved (LSB 4 bits)
Control Bits
Window
Checksum
Urgent Pointer
80
1109
5238095
11127670
5 (32-bit word)
0
ACK, FIN
8241
0xCB82
0x0000
Figura 3.8: Segmento aceitando o encerramento da conexão
Para finalizar, a Figura 3.9 apresenta o último segmento do encerramento da conexão,
que contém um ACK, enviado pelo cliente web, indicando que a conexão foi realmente
encerrada.
Envia ACK
Source Port
Destination Port
Sequence Number
Acknowledgement Number
Data Offset (MSB 4 bits)
Reserved (LSB 4 bits)
Control Bits
Window
Checksum
Urgent Pointer
1109
80
11127670
5238096
5 (32-bit word)
0
ACK
8044
0xCC47
0x0000
Figura 3.9: Segmento confirmando o encerramento da conexão
Marina Simon Becker
20
4
4.1
CONTROLE DE ERRO
Tipos de Erro
Os protocolos de transporte da pilha TCP/IP utilizam os serviços da camada inferior,
IP, para a transmissão de datagramas até o host destino. Datagramas IP são encaminhados,
hop a hop, de acordo com tabelas de rotea
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
capacidade de processar os dados entre o transmissor e o receptor for muito diferente. O
segmento realmente chega ao destino, mas o transmissor não sabe se chegou ou não devido a
um atraso no recebimento da confirmação, então ele envia o segmento novamente. Isto faz
com que cópias do mesmo segmento cheguem duas ou mais vezes no receptor. O receptor
deve descartar as cópias destes segmentos. Pacotes replicados consomem,
desnecessariamente, recursos da rede e dos hosts envolvidos.
Pacotes corrompidos são pacotes que não chegam completos no receptor, ou pela
simples troca de um bit no decorrer do caminho, o cálculo da soma de verificação não confere
e o pacote não pode ser reconstruído. Um host ou um roteador descarta o pacote corrompido,
fazendo com que o mesmo tenha que ser retransmitido.
Já a perda de pacotes pode ser ocasionada pela própria rede. Isto é muito comum
quando há um congestionamento e os roteadores necessitem descartar pacotes. Outro motivo
que pode ocasionar perdas é o excesso de fluxo que pode estar fazendo com que o receptor
esteja recebendo mais pacotes do que consegue dar conta, então o seu buffer de entrada esgota
e os pacotes podem ser descartados.
O atraso da chegada de segmentos no receptor pode ser causado pelo mesmo motivo
da perda, só que não chegam a ser descartados. Uma rede congestionada, ou com o fluxo
muito alto, tende a ficar lenta, pois os pacotes ficam no buffer dos roteadores até que eles
consigam encaminhá-los devidamente.
4.2
Detecção de Erro
Uma das formas de detectar segmentos perdidos é através de um timeout, o RTO
(Retransmission Time Out), que é o tempo que o transmissor tem para esperar a chegada de
um ACK. Se o RTO expirar antes da chegada do ACK, então o TCP assume que o segmento
foi perdido. O RTO é definido através do RTT (Round Trip Time), que significa o tempo entre
o envio do segmento e o recebimento do ACK. Estima-se, assim, o tempo entre a ida e a volta
de um segmento. A amostra do RTT é feita iniciando um timer para cada segmento enviado.
Quando chega a confirmação deste segmento, o timer é cancelado. O valor retirado deste
timer é o RTT estimado. O RTO deve ser sempre maior que o RTT, do contrário o timeout
poderá expirar antes da confirmação chegar. O valor do RTO é variável, adaptando-se de
acordo com o desempenho da conexão. O TCP monitora cada conexão e deduz valores
razoáveis para o timeout ([12]). À medida que o desempenho de uma conexão muda, o TCP
revisa o seu valor de timeout adaptando-se a mudança.
A RFC 1122 ([4]) especifica que, no inicio de uma transmissão, quando ainda não
tiver sido calculado o RTT, o RTO deve ser setado para 3 segundos. A RFC 2988 ([21])
sugere que quando o RTO for calculado e o resultado for menor que um segundo, então ele
deve ser arredondado para um segundo. E o valor máximo do RTO não deve passar de 60
segundos.
Marina Simon Becker
22
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Outra maneira de detectar perdas é através de ACKs duplicados (duplicated ACKs).
Suponha que o transmissor envie os segmentos 1, 2, 3 e 4, e o segmento 1 seja perdido. Assim
que o segmento 2 chegar, o receptor enviará um ACK com o número de seqüência do
segmento 1. Quando receber o segmento 3, ele enviará um ACK com o número de seqüência
do segmento 1, e quando o segmento 4 chegar, ele enviará um ACK com o número de
seqüência do segmento 1. Enquanto o segmento 1 não chegar, o receptor enviará ACKs com o
número de seqüência deste segmento. A Figura 4.1 ilustra este exemplo.
Envia segmento 1
Envia segmento 2
Não recebe segmento 1
Envia segmento 3
Recebe segmento 2
Envia o ACK 1
Recebe segmento 3
Envia o ACK 1
Recebe segmento 4
Envia o ACK 1
Envia segmento 4
Recebe o ACK 1
Recebe o ACK 1
Recebe o ACK 1
Figura 4.1: ACKs duplicados
Se vários ACKs possuírem o mesmo número de seqüência, eles serão ACKs
duplicados. Na verdade, o transmissor não consegue distinguir se o segmento foi perdido ou
se simplesmente chegou fora de ordem, então ele assume que mais de 3 ACKs duplicados
significam um segmento perdido.
A detecção de segmentos que chegam fora de ordem é feita e recuperada no próprio
receptor, que os reordena através dos números de seqüência dos segmentos.
4.3
Recuperação de Erro
Para que o TCP possa recuperar um segmento perdido ou corrompido, ele utiliza um
mecanismo de retransmissão. Assim que o erro é detectado, o TCP providencia a
retransmissão do segmento.
Com o algoritmo de Karn o TCP não deve utilizar como amostra o RTT de segmentos
retransmitidos, ou seja, cada vez que um segmento for retransmitido o TCP não deve ligar o
Marina Simon Becker
23
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
timer, ignorando o RTT do segmento retransmitido. Isto pode fazer com que, se o RTT real
aumentar, o TCP não poderá perceber e continuará retransmitindo segmentos, pois o seu
timeout estará desatualizado. Para que isto não aconteça deve ser utilizado o algoritmo de
backoff exponencial descrito a seguir.
O algoritmo de backoff exponencial parte do princípio que, se houve uma
retransmissão, é por que o timeout expirou. Sendo assim, o backoff aumenta o valor do RTO
para que, se houve um aumento do RTT, o timeout não expire novamente para o segmento
retransmitido, que provocaria uma nova retransmissão. O cálculo utilizado para aumentar o
timeout é: novo_timeout = x * timeout, onde x normalmente é igual a 2. Por exemplo, se o
transmissor enviar um segmento e não receber confirmação em 3 segundos, ele faz uma
retransmissão aumentando o timeout para 6 segundos. Se a confirmação não chegar, ele dobra
o timeout para 12 segundos e assim sucessivamente, até ter sucesso ou encerrar a conexão.
Marina Simon Becker
24
5
5.1
CONTROLE DE FLUXO
Janela Deslizante
O TCP permite que o receptor controle a quantidade de dados que serão enviados pelo
transmissor. Isto acontece através do campo Window, que é o tamanho da janela oferecida
pelo receptor a cada ACK de confirmação, indicando o quanto de dados ele pode receber. Isto
eqüivale ao tamanho do buffer que o receptor possui para armazenar os dados. A janela indica
o número máximo de bytes que o transmissor pode enviar.
Esta janela é chamada de janela deslizante, pois a cada confirmação que chega ela
desliza abrindo espaço para novos segmentos serem enviados. O tamanho da janela deslizante
do TCP é variável e o valor dela é medido em quantidade de bytes. O TCP permite que o
tamanho da janela varie com o passar do tempo, pois cada ACK que o receptor envia para
confirmar um segmento é acompanhado pelo tamanho da janela, então a cada ACK o receptor
pode informar um novo tamanho de janela.
A cada ACK o receptor envia o valor da janela para o transmissor. Este valor
corresponde ao tamanho do buffer disponível no receptor no momento em que o ACK foi
enviado. O transmissor utiliza este valor para calcular o tamanho da janela utilizável, que é o
tamanho da janela oferecida pelo receptor menos a janela do transmissor, que guarda os
segmentos que foram enviados e ainda não foram confirmados. Como resultado deste cálculo,
a janela utilizável deve ser sempre igual ou menor que a janela oferecida pelo receptor.
Se, por exemplo, o receptor oferecer uma janela de 2000 bytes, e o tamanho máximo
de cada segmento esteja estipulado em 500 bytes, o transmissor pode utilizar esta janela para
enviar 4 segmentos de 500 bytes cada. Depois que o receptor processar o primeiro segmento,
ele tira de seu buffer os 500 bytes que correspondem a este segmento e envia um ACK para o
transmissor com o valor do campo Window de 2000 bytes. O transmissor, quando recebe o
ACK, faz o cálculo da janela utilizável, que é a janela oferecida de 2000 bytes, menos a
quantidade de bytes que estão em trânsito, que são os 3 segmentos de 500 bytes cada, ou seja,
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
1500 bytes. Isto resulta em uma janela utilizável de 500 bytes, que é o valor máximo que o
transmissor pode enviar.
A Figuras 5.1 ilustra o exemplo apresentando a janela ofertada de 2000 bytes dividida
em 4 segmentos de 500 bytes cada.
1
2
3
4
5
6
7
8
9
10
Figura 5.1: Janela deslizante com nenhum segmento confirmado
Já a Figura 5.2 apresenta como a janela desliza após o recebimento do ACK do
primeiro segmento de 500 bytes, possibilitando a transmissão de mais um segmento de 500
bytes.
1
2
3
4
5
6
7
8
9
10
Figura 5.2: Janela deslizante com um segmento confirmado
Os segmentos que ficam do lado esquerdo da janela são os segmentos que já foram
enviados e confirmados. Os segmentos que estão do lado direito da janela são os segmentos
que ainda não foram enviados. E os segmentos que estão dentro da janela são os que foram
enviados e ainda não foram confirmados ([12]).
5.2
SWS - Silly Window Syndrome
A SWS, ou síndrome da janela desnecessária, pode ocorrer quando o transmissor e o
receptor possuem velocidades diferentes de transmissão e processamento dos dados. Quando
o receptor é muito lento para processar os dados, pode acontecer de ficar sem espaço em
buffer até que consiga retirar os dados ali contidos. Sendo assim, ele envia uma confirmação
para o transmissor com o tamanho da janela igual a zero. O transmissor começa então a enviar
pequenos segmentos para saber se o receptor já pode aceitar mais dados. Se o receptor
permanecer com a janela igual a zero por um período muito longo, o transmissor pode achar
que o receptor falhou e encerrar a conexão ([2]).
Seguindo no exemplo da seção anterior, quando o transmissor recebe a confirmação
do primeiro segmento enviado, são liberados 500 bytes na janela. Se o TCP precisar enviar 50
bytes de dados (com a flag PSH ligada no campo Control Bits), o próximo segmento
será enviado com os 450 bytes restantes. Quando o segmento de 50 bytes chega no receptor,
Marina Simon Becker
26
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
este envia uma confirmação para o transmissor, liberando os 50 bytes na janela para o envio
de dados. Assim, o transmissor envia mais um segmento com 50 bytes de dados, mesmo sem
ter a necessidade de forçar o envio. Isto também provoca a SWS, pois o transmissor começa a
enviar pequenos segmentos, um de cada vez, enquanto que o receptor envia as confirmações
dos pequenos segmentos.
5.3
Prevenção da SWS no receptor
Existem dois algoritmos para prevenir a SWS, que devem ser implementados no
receptor ([2]).
O primeiro tem o objetivo de aperfeiçoar o algoritmo da janela deslizante, fazendo
com que o receptor ofereça uma janela igual a zero ao invés de oferecer uma janela pequena,
até que ele consiga retirar um número suficiente* de bytes de seu buffer. Assim o transmissor
verá que não pode enviar mais dados naquele momento, acumulando os dados em seu próprio
buffer. Quando o receptor perceber que liberou uma quantidade significativa de espaço no seu
buffer, ele volta a oferecer o tamanho da janela anterior. Sendo assim, o transmissor pode
enviar segmentos maiores, pois a janela utilizável terá aumentado significativamente. O
problema é que, se o receptor enviar uma janela igual a zero, o transmissor começará a enviar
pequenos segmentos para saber se o receptor já está aceitando mais dados. O ideal é fazer
com que o receptor diminua o tamanho da janela pela metade do seu valor atual, pois quando
o transmissor fizer o cálculo da janela utilizável, ela ainda será menor que zero, impedindo
que o transmissor envie mais dados.
O outro algoritmo é conhecido como “Every-other ACK”, cujo objetivo é aperfeiçoar o
algoritmo de geração de ACKs, pois normalmente o TCP receptor envia um ACK para cada
segmento recebido, o que é chamado de ACK compulsivo. Existem duas razões para enviar
um ACK imediatamente: uma é para evitar retransmissões, e a outra é para permitir que novos
segmentos possam ser enviados. Mas se poucos dados forem liberados no receptor, um ACK
faria com que o transmissor enviasse um pequeno segmento, e se para cada vez que uma
pequena quantidade de dados for liberada no receptor, ele enviar um ACK, então o transmissor
irá sempre enviar pequenos segmentos a cada ACK que chegar. O algoritmo sugerido é fazer
com que o receptor atrase as confirmações ao transmissor. Desta forma, antes de enviar uma
confirmação, ele espera liberar espaço em seu buffer, podendo até, se já tiver processado
vários segmentos, enviar uma confirmação única para todos eles. Isto é muito bom, pois
economiza banda. O problema desta solução é que o receptor não pode atrasar muito o envio
da confirmação, porque o transmissor pode achar que o segmento foi perdido e isto causaria
uma retransmissão. Outro problema está no cálculo da estimativa do RTT, pois o retardo nas
confirmações pode gerar uma estimativa falsa do RTT, fazendo com que o valor do timeout
do transmissor fique muito grande. Por isto, quando este algoritmo for implementado, devem
ser levados em conta alguns fatores importantes. Um destes fatores é que o receptor deve
saber quanto tempo ele deve esperar acrescentado um timer de espera para enviar a
*
O que o TCP entende por um número suficiente é o que for maior entre 50 por cento de espaço no buffer do
receptor e o valor do tamanho máximo de um segmento.
Marina Simon Becker
27
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
confirmação, que não deve passar dos 500 milissegundos*. Quando um segmento de dados
chegar, ele inicia o timer e, mesmo que nenhum outro segmento chegue quando o timer
expirar, ele deve enviar a confirmação. É sugerido que a espera somente deve acontecer
quando o segmento recebido não contiver o bit PSH setado, e quando não houver nenhuma
atualização da janela para ser enviada. O receptor deve confirmar pelo menos 1 entre 2
segmentos enviados.
5.4
Prevenção da SWS no transmissor
Assim como no receptor, existem 2 algoritmos para a prevenção da SWS no
transmissor.
Um dos algoritmos foi desenvolvido por Michael Greenwald do MIT. O transmissor
utiliza a janela oferecida pelo receptor para calcular a janela utilizável. Então ele compara a
janela oferecida com a janela utilizável e, se a proporção entre uma e outra for menor que um
certo valor, ele pára de enviar segmentos. Se a janela utilizável for muito menor que a janela
oferecida, significa que ainda tem muitos segmentos a serem confirmados, então o TCP
transmissor deve esperar até que a janela utilizável chegue a um certo valor para começar a
enviar novamente. O valor suficiente para evitar a SWS e alcançar um throughput razoável é
de 25% ([2]).
O outro é chamado de Algoritmo de Nagle, cujo objetivo é evitar o envio de
segmentos pequenos. Ao invés do TCP enviar segmentos a medida em que as confirmações
forem chegando, ele deve esperar até que a aplicação forneça dados suficientes para que ele
possa preencher um segmento grande. O que ocorre é que o TCP não sabe o quanto de dados
a aplicação tem para enviar, portanto não pode ser especificado um tempo fixo de espera. O
que o padrão especifica então, é que o TCP utilize um esquema adaptável para retardar a
transmissão, armazenando em seu buffer de saída a quantidade suficiente para preencher um
segmento com o tamanho máximo. Se uma confirmação chegar antes de ter dados suficientes
para preencher um segmento com o tamanho máximo, ele deve enviar todos os dados
acumulados no buffer. Esta regra deve ser aplicada mesmo que a aplicação peça para forçar o
envio (push).
*
Existe um algoritmo adaptativo para medir o intervalo do timer ([2]).
Marina Simon Becker
28
6
CONTROLE DE CONGESTIONAMENTO
Para fazer o controle de congestionamento, o TCP precisa detectar quando há um
congestionamento. Os mecanismos utilizados para a detecção de congestionamento são o
timeout e os ACKs duplicados, abordados no capítulo anterior, pois o TCP originalmente não
conta com notificação explícita de congestionamento (ECN, Explicit Congestion
Notification). Quando um erro é detectado, através do timeout, o TCP assume que existe um
roteador congestionado e que esta foi a causa da perda. Em outras palavras, a maioria das
perdas é causada por congestionamento e não por corrupção. Conforme [3] pacotes
corrompidos são responsáveis por apenas 1% das perdas.
Para diminuir o risco de colapso na rede, cada fluxo TCP é regido por uma política de
controle de congestionamento. Isto assegura que as centenas de fluxos TCP que se cruzam em
um roteador qualquer ocupem uma fatia “justa” da banda disponível (fairness).
6.1
Slow Start
O Slow Start é um mecanismo de controle de congestionamento utilizado para
estabelecer o equilíbrio de uma conexão. O TCP deve iniciar uma transmissão inserindo
segmentos na rede de forma gradual, para que ele possa conhecer a capacidade da rede. O
equilíbrio da conexão é estabelecido cada vez que o TCP começa a inserir dados na rede, ou
seja, a cada início de conexão ou logo após uma perda, fazendo com que a conexão volte ao
normal.
A quantidade de dados que o TCP começa a transmitir é de acordo com o tamanho da
janela do receptor. Quando o receptor oferece uma janela muito grande e a aplicação do
transmissor fornece dados suficientes para preencher aquela janela, o TCP transmissor envia
muitos segmentos ao mesmo tempo. Isto pode gerar perdas caso algum roteador esteja com
muita carga, ocasionando retransmissões. O Slow Start faz com que os segmentos sejam
inseridos na rede de uma forma lenta e gradual, melhorando o aproveitamento da banda e
evitando o risco de um congestionamento na rede.
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
O Slow Start utiliza a janela de congestionamento (cwnd) que é o limite que o
transmissor tem para enviar os dados quando inicia a transmissão ou depois de receber uma
confirmação. A janela oferecida pelo receptor (rwnd) é o limite que o receptor tem para
receber os dados. O limite que deve ser utilizado para a transmissão é o valor mínimo entre
estas duas janelas, ou seja, se a cwnd for menor que a rwnd, então o transmissor deve enviar a
quantidade de dados estipulada na cwnd. Outra variável incluída é a Slow Start Threshold
(ssthresh), que serve para determinar se o algoritmo do Slow Start será utilizado ou não na
transmissão dos dados.
A implementação do Slow Start implica nos seguintes passos: deve ser adicionada a
cwnd, quando uma transmissão iniciar ou reiniciar após a perda de um segmento. Setar o valor
da cwnd para 1 segmento. Para cada ACK que chegar, incrementar a cwnd com 1 segmento e
quando o TCP for transmitir, deve transmitir o mínimo entre a cwnd e a rwnd ([3]).
Quando a janela de congestionamento é iniciada, ela contém o valor de 1 segmento. O
transmissor envia este segmento e espera por sua confirmação. Quando a confirmação chega,
aumenta-se a janela de congestionamento em mais 1 segmento, possibilitando a transmissão
de 2 segmentos. Quando as 2 confirmações chegarem, aumenta-se mais 2 segmentos na
janela, deixando-a com 4 segmentos. Enviando os 4 segmentos, chegarão 4 confirmações,
fazendo com que a janela aumente para 8 segmentos e assim sucessivamente, enquanto a
janela oferecida pelo receptor permitir. A janela de congestionamento cresce de forma
exponencial, o que implica em um crescimento não muito lento.
6.2
Congestion Avoidance
Congestion Avoidance é definida em [3] como uma estratégia dividida em duas partes:
uma consiste em fazer com que a rede avise aos hosts que poderá ocorrer um
congestionamento. Cada roteador que estiver com a sua capacidade em um determinado limite
deverá enviar um sinal para os hosts ativando um certo bit no cabeçalho dos pacotes. A outra
parte da estratégia é implementada nos end-points, que devem decrementar a utilização
quando receberem a notificação e incrementar quando não receberem. O algoritmo definido
em [3] utiliza outros dois algoritmos, o Multiplicative Decrease e o Additive Increase, que
serão descritos a seguir.
Multiplicative Decrease é utilizado após a ocorrência de uma perda. Com a perda de
um segmento (quando expira o timer do transmissor) a janela de congestionamento deve ser
reduzida pela metade até que ela chegue a um tamanho mínimo de 1 segmento. Para os
segmentos que permanecerem na janela permitida, deve ser aplicado o algoritmo de backoff
exponencial, descrito no Capítulo 4.
Additive Increase funciona como o Slow Start, com a diferença que o incremento da
janela de congestionamento é aditivo, em vez de exponencial. Isto faz com que o crescimento
da janela fique mais lento. A janela de congestionamento inicia com 1 segmento e aumenta 1
Marina Simon Becker
30
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
segmento dividido pelo tamanho da janela a cada confirmação que chega, ou seja, cwnd =
cwnd + 1/cwnd. Por ser aditivo, este algoritmo oferece um crescimento mais suave para a
cwnd do que o Slow Start.
Os algoritmos Multiplicative Decrease e Additive Increase devem ser utilizados em
conjunto, da seguinte maneira: em qualquer timeout, deve ser utilizado o algoritmo
Multiplicative Decrease, em qualquer ACK que chegar, deve ser utilizado o algoritmo
Additive Increase e quando o TCP for transmitir, deve transmitir o mínimo entre a cwnd e a
rwnd ([3]).
Marina Simon Becker
31
7
7.1
MECANISMOS AVANÇADOS
Fast Retransmit
De acordo com a RFC 2001 ([10]) o Fast Retransmit surgiu de algumas modificações
no algoritmo Congestion Avoidance de [3]. Inicialmente foi implementado na versão Tahoe
(1988), mas é modificado a cada versão do TCP. Conforme descrito no Capítulo 4, quando
um segmento chega fora de ordem, o TCP receptor gera um ACK duplicado, para avisar ao
transmissor qual o número de seqüência que está sendo esperado. O transmissor, por sua vez,
não sabe se o segmento está realmente fora de ordem ou foi perdido. Normalmente, ele
aguarda a chegada de outros ACKs duplicados para saber o que fazer, pois se forem
segmentos fora de ordem, com 1 ou 2 ACKs duplicados o receptor consegue ordenar, mas se
chegarem 3 ou mais ACKs duplicados, então pode ter sido uma perda. Na chegada de 3 ACKs
duplicados, o transmissor supõe que um segmento foi perdido, retransmitindo o segmento sem
esperar o timer expirar. Após a retransmissão do segmento perdido, o Slow Start é iniciado.
7.2
Fast Recovery
O Fast Recovery é uma modificação acrescentada no método Fast Retransmit,
implementada na versão Reno (1990), e após, modificada na versão New Reno (1999). De
acordo com a RFC 2581 ([15]), o transmissor, depois de receber 3 ACKs duplicados e
retransmitir o segmento, não executa o Slow Start. A razão para não executar o Slow Start é
que talvez o receptor queira dizer que há mais de um segmento perdido. E o receptor somente
pode enviar um ACK duplicado após ter recebido um segmento de dados. Então se, por acaso,
não houver segmentos em transito, o transmissor não deve abruptamente parar de enviar
segmentos, como é feito no Slow Start. O Fast Recovery implementado na versão Reno faz
com que, quando o terceiro ACK duplicado chegue, a janela de congestionamento seja
reduzida pela metade do seu valor atual (Multiplicative Decrease), mas ela não deve ficar
menor que 2 segmentos. Depois de retransmitir o segmento perdido, a janela de
congestionamento deve ser incrementada em 3 vezes o valor de um segmento. Para cada novo
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
ACK duplicado que chegar, incrementa-se a janela de congestionamento com o tamanho do
segmento e transmite um novo segmento, se o valor da janela oferecida pelo receptor permitir.
Quando chegar o ACK do segmento retransmitido, a janela de congestionamento deve ser
incrementada em 3 vezes o valor de um segmento novamente.
7.3
Selective Acknowledgement
Conforme [6] o Selective Acknowledgement (SACK) foi implementado na versão
SACK (variação da versão Reno). Ele preserva as propriedades das versões Tahoe e Reno,
deixando-as mais robustas quanto aos pacotes desordenados e utiliza o RTO como método de
recuperação apenas em último caso. De acordo com a RFC 2018 ([9]), com o SACK o
receptor pode informar ao transmissor quais foram os segmentos que chegaram corretamente,
permitindo então que o transmissor retransmita apenas os segmentos necessários. O SACK
utiliza duas opções no cabeçalho do TCP, uma é “SACK-permitted”, que deve ser enviada
no segmento SYN, assim que a conexão for estabelecida. A outra é a “SACK”, que pode ser
enviada em qualquer conexão que tiver sido iniciada com a opção “SACK-permitted”. A
utilização da opção SACK para ACKs duplicados é definida na RFC 2883 ([19]). Durante o
Fast Recovery, o SACK mantém uma variável chamada “pipe”, que representa o número
estimado de segmentos pendentes ao longo do caminho. Esta variável é incrementada a cada
segmento enviado e decrementada a cada confirmação que chega.
7.4
Forward Acknowledgement
O Forward Acknowledgement (FACK), foi baseado nos princípios do controle de
congestionamento e desenvolvido para ser utilizado em conjunto com a proposta da versão
SACK. O FACK faz um controle mais preciso dos dados que são inseridos na rede durante a
recuperação de uma perda ([7]). O FACK adiciona mais duas variáveis no TCP transmissor,
onde uma é incrementada com a quantidade de dados que foram retransmitidos e
decrementada quando a confirmação destes segmentos chegarem. A outra variável guarda o
valor da opção SACK do cabeçalho do TCP. O cálculo destas variáveis permite ao TCP uma
visão mais precisa do estado da rede durante a conexão.
Marina Simon Becker
33
8
PROBLEMAS COM IMPLEMENTAÇÕES DO TCP
Foram descobertos vários problemas em algumas implementações do TCP. Estes
problemas prejudicam o bom funcionamento do protocolo. Os problemas estão registrados na
RFC 2525 ([14]) e serão descritos neste capítulo. Muitas das especificações citadas aqui estão
padronizadas na RFC 1122 ([4]). Os problemas estão classificados em categorias como:
controle de congestionamento, performance, confiabilidade e gerenciamento de recursos.
8.1
Controle de Congestionamento
Slow start ausente. Conforme visto no Capítulo 6, quando o TCP inicia uma
transmissão ele deve utilizar o Slow Start para iniciar a cwnd com um segmento e incrementala em um segmento a cada confirmação que chegar. Se o Slow Start falhar no início da
conexão, será gerado um fluxo muito intenso, que pode inundar a rede, ocasionando atrasos e
perdas de segmentos. As implementações que apresentam este tipo de problema,
provavelmente, não estão iniciando a cwnd corretamente. Estas implementações irão sofrer
também com o problema de Slow Start ausente após uma retransmissão.
Slow start ausente após uma retransmissão. Assim como no início de uma
transmissão, o Slow Start deve ser iniciado quando ocorre uma retransmissão, para que o TCP
não insira um número muito grande de segmentos, caso haja um congestionamento na rede.
Iniciar o Slow Start quando há um congestionamento é fundamental para manter a
estabilidade da rede. Se a implementação falhar neste ponto, a rede pode ser inundada de
pacotes, gerando um colapso de congestionamento.
Janela de congestionamento não inicializada. Foi visto no Capítulo 3 que quando
uma conexão é estabelecida, os primeiros segmentos vem com a opção MSS. Quando esta
opção não é enviada, é utilizado o valor padrão para o MSS, que é o tamanho de um
datagrama IP, menos os cabeçalhos IP e TCP. A falha na implementação está em usar o valor
da opção MSS para estipular o tamanho do segmento inicial da janela de congestionamento.
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Se a opção não chegar, os segmentos adicionados na janela de congestionamento poderão
conter um tamanho muito grande, inundando a rede e ocasionando a perda de pacotes.
Retransmissão com envio de múltiplos segmentos. Em uma retransmissão, o TCP
deve enviar apenas um único segmento. O envio de múltiplos segmentos pode ocorrer por
causa do campo Options, que aumenta o cabeçalho além dos 20 octetos. Se o TCP não
contabilizar o tamanho do campo Options quando for determinar o quanto de dados ele tem
que retransmitir, ele enviará dados a mais do que o necessário para preencher um único
segmento. Sendo assim, o segmento retransmitido será acompanhado de um pequeno
segmento, que contém dados que não precisam ser retransmitidos. Isto acaba injetando mais
tráfego na rede desnecessariamente, além do que, esta redundância irá gerar um ACK
duplicado do receptor, resultando em mais uma transmissão desnecessária.
Falha no backoff após um RTO. Como está descrito no Capítulo 4, sempre que um
segmento é retransmitido o valor do timeout é dobrado, de acordo com o algoritmo de
backoff. Se isto não ocorrer, o timeout irá expirar antes da chegada do ACK, e se o transmissor
não receber um ACK após numerosas tentativas de retransmissão, a conexão é encerrada. A
RFC 1122 especifica que é obrigatório o backoff exponencial em um RTO e a finalização da
conexão após um período de tempo de, no mínimo, 100 segundos.
8.2
Performance
RTO inicial muito curto. Logo que o TCP inicia a transmissão dos dados, ele não
possui o valor do RTT necessário para calcular o RTO. A RFC 1122 estabelece que a
implementação deve inicializar o RTO com 3 segundos. As conexões que possuem o RTT
muito longo* geram a perda de performance do TCP, resultando em retransmissões
desnecessárias, pois o RTO irá expirar antes da chegada do ACK. Além disto, quando o RTO
for menor que o RTT, o TCP levará um longo tempo para conseguir corrigir o problema,
adaptando a estimativa do RTT com o uso do algoritmo de Karn, como foi visto no Capítulo
4.
Falha ao enviar um FIN. Quando uma aplicação fecha uma conexão, o TCP deve
enviar imediatamente uma notificação FIN. Apesar de não ser estritamente requerido, deve
ser incluído no segmento FIN a flag PSH, para assegurar que o segmento será enviado
imediatamente. Implementações que não fazem isto podem demorar para enviar o FIN,
gerando um grande atraso em conexões com tempo de vida curto. Isto pode diminuir o
throughput, pois demora muito para completar o encerramento da conexão.
*
Deve ser considerado longo qualquer valor de RTT maior que o RTO inicial.
Marina Simon Becker
35
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Falha em guardar segmentos que chegam fora de ordem. Quando o TCP recebe
um segmento fora de ordem (above-sequence*), ele envia o segmento para um buffer. Quando
o sistema necessitar a liberação de memória, é conveniente que o TCP descarte destes
segmentos. Se ele fizer isto raramente não é considerado um problema, mas a preocupação é
com as implementações que sempre descartam os segmentos que chegam fora de ordem.
Adição extra no Congestion Avoidance. A RFC 1122 diz que é obrigatória a
implementação do Congestion Avoidance, que utiliza o incremento aditivo na cwnd (Additive
Increase). Como foi visto no Capítulo 6, isto incrementa a cwnd em um segmento a cada
RTT. Algumas implementações adicionam uma pequena parte de um segmento a este cálculo,
fazendo o crescimento da janela ficar mais agressivo. Em ambientes congestionados isto pode
prejudicar a performance de outras conexões, acrescentando perdas em todas as conexões que
compartilham o mesmo gargalo, prejudicando fairness. Para resolver este problema, é só
retirar o excesso do código da implementação.
Falha em diminuir a janela após a recuperação de uma perda. Como foi abordado
no capítulo anterior, o Fast Recovery permite que o TCP continue enviando novos segmentos
durante a recuperação de uma perda. Algumas implementações fazem isto incrementando
artificialmente a cwnd em três segmentos para os três primeiros ACKs duplicados que
iniciaram o Fast Retransmit, e subseqüentemente um segmento para cada ACK duplicado que
chegar. Quando um ACK chegar liberando novos dados, é reduzido o valor que foi
artificialmente incrementado na cwnd. A implementação que não reduzir este valor irá enviar
muitos segmentos logo após a recuperação da perda, diminuindo a performance e a
estabilidade da rede. Este problema pode ser resolvido fazendo com que o protocolo verifique
se a cwnd foi artificialmente aumentada, para que ele possa então reduzir o aumento.
Intervalo excessivo entre ACKs. Conforme um dos métodos de evitar a SWS descrito
no Capítulo 5, um receptor deve gerar um ACK para, pelo menos, cada dois segmentos de
dados que ele receber. Se receptor esperar muito para enviar o ACK, fará com que o
transmissor gere muito tráfego, diminuindo a performance em ambientes congestionados. A
geração de poucos ACKs aumenta o tempo necessário para que o Slow Start possa abrir a
cwnd, diminuindo a performance e podendo causar a necessidade de retransmissão.
8.3
Confiabilidade
Retransmissão inconsistente. Se, para um determinado número de seqüência, o
transmissor retransmitir dados diferentes daqueles que estão sendo esperados para aquele
número, o receptor irá reconstruir um stream diferente daquele que está sendo enviado pela
aplicação transmissora. Se isto ocorrer, o TCP perde a confiabilidade de entrega.
*
Segmento com um número de sequência acima do número de sequência esperado e abaixo do número de
sequência esperado mais a janela de segmentos recebidos, ou seja: RCV.NXT < SEG.SEQ <
RCV.NXT+RCV.WND.
Marina Simon Becker
36
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Timeout do keep-alive muito curto. Como foi visto no Capítulo 3, o keep-alive é um
mecanismo que serve para checar se uma conexão está ociosa ou se continua ativa. O keepalive possui um timeout de espera para receber a resposta da outra ponta. Se o timeout for
muito curto, o keep-alive poderá encerrar conexões que estão funcionando, mas que
demoraram para responder devido a alguma falha na rede. O problema pode ser resolvido
utilizando um método diferente de timeout para o keep-alive, permitindo um período de
tempo maior antes de desistir da conexão.
Intervalo insuficiente entre keep-alives. Se um keep-alive for incluído em uma
implementação, deve ser configurado o intervalo entre os segmentos do keep-alive, que de
acordo com a RFC 1122, não deve ser menor que 2 horas. Se isto não for considerado, poderá
ocorrer o encerramento de conexões quando houver um congestionamento.
Janela com deadlock. Quando uma aplicação lê somente um byte de uma janela
cheia, a janela não deve ser atualizada para evitar a SWS, como pôde ser visto no Capítulo 5.
Se o host remoto utilizar apenas um byte para verificar se liberou espaço na janela, este byte
pode ser aceito dentro do buffer. Em algumas implementações este é um ponto negativo, pois
dados adicionais podem ficar fora da janela e serem descartados, e estes segmentos
descartados não serão confirmados. Se a aplicação parar de ler os dados, o buffer nunca irá
esvaziar, resultando em um deadlock.
Campo Options excluído do cálculo do MSS. Quando o TCP determina a
quantidade de dados que irá colocar em um segmento, ele calcula o tamanho do segmento
baseado no MTU (Maximum Transfer Unit) da interface de rede, subtraindo o tamanho dos
cabeçalhos IP e TCP. Se os campos Options do IP e do TCP não forem contabilizados junto
com a subtração, o resultado será um segmento muito grande para a interface de saída, que
ainda podem ter o bit DF (don’t fragment) setado no cabeçalho do IP. Com isto a camada do
IP não permite que este pacote seja fragmentado ao ser enviado pela interface. Então, ao invés
de enviar o segmento, o IP informa ao TCP o tamanho correto do MTU da interface. O TCP
calcula novamente o MSS, sem incluir os campos Options dos cabeçalhos IP e TCP, e o
problema se repete. Para resolver este problema, a implementação deverá certificar-se que o
cálculo do MSS inclua os campos Options do IP e TCP, como está especificado na RFC
1122.
8.4
Gerenciamento de Recursos
Falha em enviar um reset após um half duplex close. O TCP deve resetar uma
conexão, enviando um segmento RST, se ele continuar recebendo dados após um “half duplex
close”. Algumas implementações não enviam o RST quando se encontram nesta situação.
Este é um problema sério para TCPs que gerenciam um grande número de conexões, devido a
probabilidade de faltar memória ou processos que monitoram o estado das conexões. A falta
de um RST pode travar uma conexão permanentemente.
Marina Simon Becker
37
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
Falha em enviar um reset com dados pendentes. Quando uma aplicação fechar uma
conexão, ou ficar um longo tempo sem ler nenhum dado recebido, o TCP deve resetar a
conexão enviando um RST. Algumas implementações não conseguem resetar a conexão.
Assim como no problema anterior, os TCPs que gerenciam um grande número de conexões
serão os mais prejudicados.
Marina Simon Becker
38
9
CONCLUSÃO
Desde o seu surgimento, o TCP teve uma evolução surpreendente, indicando que ele
estará sempre sendo desenvolvido, estudado e aprimorado, que o torna um protocolo bastante
complexo.
Este trabalho teve como objetivo descrever o funcionamento do TCP, assim como
mostrar vários mecanismos de controle que foram sendo adicionados ao protocolo com o
passar do tempo, para aprimorar o seu funcionamento e a sua performance. Nenhum dos
mecanismos citados aqui foi aprofundado, eles foram apenas descritos de forma que o leitor
possa ter uma idéia de como o TCP funciona e de onde ele possa buscar a origem destes
mecanismos, caso haja interesse.
RE F E RÊ NCI AS
[1]
J. Postel. Transmission Control Protocol. Request for Comments 793, September 1981.
[2]
D. Clark. Window and Acknowledgement Strategy in TCP. Request for Comments 813,
July 1982.
[3]
V. Jacobson, and M. Karels. Congestion Avoidance and Control. SIGCOMM
Symposium on Communications Architectures and Protocols, pages 314--329, 1988.
ftp://ftp.ee.lbl.gov/papers/congavoid.ps.Z.
[4]
R. Braden. Requirements for Internet Hosts - Communication Layers. Request for
Comments 1122, October 1989.
[5]
T.J. Socolofsky, and C.J. Kale. TCP/IP Tutorial. Request for Comments 1180, January
1991.
[6]
K. Fall, and S. Floyd. Simulation-based Comparisons of Tahoe, Reno, and SACK TCP.
Computer Communication Review, 26(3), July 1996.
[7]
M. Mathis, and J. Mahdavi. Forward Acknowledgement: Refining TCP Congestion
Control. SIGCOMM’96, August 1996.
[8]
A. Kumar. Comparative Performance of Versions of TCP in a Local Network with a
Lossy Link. WINLAB Technical Report-TR129, Rutgers University, October 1996.
[9]
M. Mathis, J. Mahdavi, S. Floyd, and A. Romanow. TCP Selective Acknowledgment
Options. Request for Comments 2018, October 1996.
Universidade do Vale do Rio dos Sinos – Unisinos
Transmission Control Protocol
[10] W. Stevens. TCP Slow Start, Congestion Avoidance, Fast Retransmit, and Fast
Recovery Algorithms. Request for Comments 2001, January 1997.
[11] V. Paxson. End-to-end Internet Packet Dynamics. SIGCOMM’97.
[12] D. Comer, e D. Stevens. Interligação em Rede com TCP/IP – Volume1: Princípios,
Protocolos e Arquitetura. Tradução da terceira edição. Rio de Janeiro: Campus, 1998.
[13] D. Comer, e D. Stevens. Interligação em Rede com TCP/IP – Volume2: Projeto,
Implementação e Detalhes Internos. Tradução da terceira edição. Rio de Janeiro:
Campus, 1999.
[14] V. Paxson. Known TCP Implementation Problems. Request for Comments 2525, March
1999.
[15] M. Allman, V. Paxson, and W. Stevens. TCP Congestion Control. Request for
Comments 2581, April 1999.
[16] S. Floyd, and T. Henderson. The NewReno Modification to TCP's Fast Recovery
Algorithm. Request for Comments 2582, April 1999.
[17] C. Barakat, E. Altman, and W. Dabbous. On TCP Performance in a Heterogeneous
Network: a Survey. IEEE Communications Magazine, January 2000.
[18] M. Handley, J. Padhye, and S. Floyd. TCP Congestion Window Validation. Request for
Comments 2861, June 2000.
[19] S. Floyd, J. Mahdavi, M. Mathis, and M. Podolsky. An Extension to the Selective
Acknowledgement (SACK) Option for TCP. Request for Comments 2883, July 2000.
[20] D. Rubenstein, J. Kurose, and D. Towsley. Detecting Shared Congestion of Flows Via
End-to-end Measurement. ACM SIGMETRICS’00.
[21] V. Paxson, and M. Allman. Computing TCP's Retransmission Timer. Request for
Comments 2988, November 2000.
Marina Simon Becker
41
Download

UNIVERSIDADE DO VALE DO RIO DOS SINOS – UNISINOS