TCP MSS mínimo no Linux

9

O TCP MSS no Linux deve ter pelo menos 88 (inclua / net / tcp.h):

/* Minimal accepted MSS. It is (60+60+8) - (20+20). */
#define TCP_MIN_MSS             88U

Minha pergunta é: de onde eles criaram "60 + 60 + 8" e por quê? Eu entendo que 20 + 20 vem do cabeçalho IP + cabeçalho TCP.

EDIT: Depois de olhar mais de perto os cabeçalhos, a fórmula me parece assim:

(MAX_IP_HDR + MAX_TCP_HDR + MIN_IP_FRAG) - (MIN_IP_HDR + MIN_TCP_HDR)

A questão ainda permanece: por quê ? Por que o kernel do Linux usa essa fórmula, proibindo, assim, (um fluxo forçado de) segmentos TCP de, digamos, 20 bytes? Pense no iperf aqui.

EDIT2: Aqui está o meu caso de uso. Ao forçar um MSS baixo no soquete / conexão, todos os pacotes enviados pela pilha terão um tamanho pequeno. Quero definir um MSS baixo ao trabalhar com o iperf para pacotes / segundo teste. Não consigo obter pacotes IP menores que 128 bytes (quadros Ethernet de 142 bytes) no fio por causa desse limite mais baixo para o MSS! Eu gostaria de chegar o mais próximo possível de um tamanho de quadro Ethernet de 64 bytes, conforme RFC 2544. Teoricamente, isso deveria ser possível: 18 + 20 + 20 <64.

Mircea Gherzan
fonte
Como isso proíbe segmentos TCP de 20 bytes?
David Schwartz
MSS significa Tamanho Máximo do Segmento, é o limite superior (não inferior) para o tamanho do segmento em uma conexão específica. TCP_MIN_MSS especifica o limite inferior para esse limite. Portanto, não proíbe de nenhuma maneira segmentos com menos de 88 bytes, apenas afirma que o MSS para qualquer conexão deve ser> = 88 bytes.
21911 Gellaen #
Claro! Desculpe por não ser suficientemente claro. Por favor, veja a edição mais recente.
Mircea Gherzan
Por que você deixou a recompensa expirar? A resposta de David esclarece as coisas para minha satisfação, pelo menos. A diferença entre a resposta dele e a minha é que estamos falando de mínimos diferentes. Quanto vale a pena, há um terceiro mínimo, sendo 41 ou 20 + 20 + 1 byte de dados TCP. Portanto, o tamanho mínimo do pacote depende do motivo que você está perguntando. Espero que 68 seja a resposta certa nos casos em que o kernel usa TCP_MIN_MSS.
Warren Young
Ainda não estou satisfeito com a resposta. Ainda não vejo o motivo pelo qual o kernel não me permite impor um MSS pequeno e arbitrário a um aplicativo. Eu adoraria ter (um fluxo constante de pacotes carregados por TCP) IP de 41 bytes, mas não posso, por causa do TCP_MIN_MSS. Por que não pode ser 1? Que RFC quebraria? Que problema teórico / prático ele causaria? Você tem certeza de que está "fora das especificações"? "Mínimos diferentes"? Há apenas um mínimo de interesse aqui: o menor MSS permitido pelo kernel.
Mircea Gherzan

Respostas:

5

É necessária uma implementação para suportar os cabeçalhos TCP e IP de tamanho máximo, com 60 bytes cada.

Uma implementação deve suportar datagramas de 576 bytes, que mesmo com cabeçalhos máximos significam mais de 8 bytes de dados no datagrama. Para enviar datagramas com mais de 8 bytes de dados, a fragmentação de IP deve colocar pelo menos 8 bytes de dados em pelo menos um dos pacotes que representam os fragmentos do datagrama. Assim, uma implementação deve suportar pelo menos 8 bytes de dados em um pacote.

Juntando isso, uma implementação deve suportar pacotes de 60 + 60 + 8 bytes.

Quando enviamos pacotes que fazem parte de um fluxo TCP, eles têm um cabeçalho IP de 20 bytes (mais opções) e um cabeçalho TCP de 20 bytes (mais opções). Isso deixa um mínimo de (60 + 60 + 8) - (20 + 20) bytes restantes para dados e opções. Portanto, esse é o máximo que podemos assumir com segurança, o TCP MSS de uma implementação.

David Schwartz
fonte
11
Embora o MSS não inclua o cabeçalho (é apenas a carga útil), e o 60programa é
exibido
Uma implementação deve poder suportar um pacote com um cabeçalho de tamanho máximo, mas não estamos enviando um cabeçalho de tamanho máximo. A diferença entre o máximo e o que realmente enviamos está, portanto, disponível para dados e deve ser adicionada ao MSS.
David Schwartz
OK, então você explicou os 8 bytes. Não sei o que você quer dizer com cabeçalho "TCP / IP". Eu sei de um cabeçalho IP e um TCP. E, como Michael apontou, 60 aparece duas vezes. E a RFC discute apenas o "MSS efetivo" e não o mínimo.
Mircea Gherzan 23/10
60 aparece duas vezes, uma para o cabeçalho IP e outra para o cabeçalho TCP.
David Schwartz
68 é apenas sobre fragmentação. "60 + 60 + 8" pode ficar fragmentado. Então, por que se importar com a fragmentação? Até "68 + 20" pode ficar fragmentado. E por que "o outro lado" deve "aceitar" "60 + 60 + 8"? "Aceitar" como em "sem fragmentação"? Conclusão: por que não tenho permissão para enviar "20 + 20" + 10 bytes de dados?
Mircea Gherzan
3

Não sei de onde vem esse número, mas posso dizer que está fora das especificações. O MTU mínimo suportado para redes IP é de 576 bytes, que são 512 bytes de dados e até 64 bytes para cabeçalhos IP + TCP e opções TCP. Esse valor foi escolhido para fornecer despesas gerais decentemente baixas no caso típico.

Minha leitura de bits do código do kernel sugere que o valor que você está mostrando não é arbitrário. Havia uma prática mais antiga de usar apenas a constante bruta 64 no lugar de TCP_MIN_MSS. Portanto, suponho que exista uma rede IP-over-Foo estranha que os desenvolvedores do kernel encontraram que os fez decidir que poderiam aumentar o valor para o que você vê.

O que esse tipo de rede fora do padrão é, no entanto, não posso dizer.

Warren Young
fonte
576 é o MTU para datagramas . Nesse caso, são os limites de pacotes que importam, não os limites de datagrama porque os pacotes TCP definem o bit DF.
David Schwartz
O MTU mínimo definido para datagramas IP e pacotes TCP também são datagramas IP.
31811 Gellaen #
Certo, mas essa limitação de TCP é para pacotes, não para datagramas, porque os datagramas TCP nunca (normalmente) se fragmentam. O único sentido em que a regra do datagrama de 576 bytes importa é que isso significa que a implementação deve ser capaz de suportar pelo menos 8 bytes de dados em um pacote (daí os 8 na fórmula). Caso contrário, seria impossível fragmentar um datagrama de 576 bytes.
David Schwartz