Como é o MTU é 65535 em UDP, mas a Ethernet não permite o tamanho do quadro acima de 1500 bytes
11
Estou usando uma ethernet rápida de 100 Mbps, cujo tamanho de quadro é menor que 1500 bytes (1472 bytes para carga útil, de acordo com o meu livro). Nisso, consegui enviar e receber um pacote UDP com tamanho de mensagem 65507 bytes, o que significa que o tamanho do pacote era 65507 + 20 (cabeçalho IP) + 8 (cabeçalho UDP) = 65535.
Se o tamanho da carga útil do quadro em si é máximo de 1472 bytes (conforme meu livro didático), como o tamanho do pacote IP pode ser maior do que o que aqui é 65535?
Eu usei o código do remetente como
char buffer[100000];
for (int i = 1; i < 100000; i++)
{
int len = send (socket_id, buffer, i);
printf("%d\n", len);
}
Os datagramas UDP têm pouco a ver com o tamanho da MTU; você pode torná-los do tamanho que quiser até os 64K, no máximo mencionado acima. Você pode até enviar um deles em um pacote inteiro, desde que esteja usando jumbo-frames com um tamanho maior que o datagrama grande.
No entanto, os jumbo-frames devem ser suportados por todo o equipamento que o frame passará, e isso é um problema. Para propósitos práticos, os quadros Ethernet são o tamanho de transporte mais comum; a MTU é de cerca de 1500 bytes, diremos 1500 daqui para frente, mas nem sempre. Quando você cria um datagrama UDP maior que o MTU subjacente (que, como indicado na maioria das vezes é ethernet), ele será dividido em vários quadros de 1500 bytes. Se você despejar esse tráfego, verá vários pacotes quebrados no limite da MTU, que terão o sinalizador de mais fragmentos definido junto com um número de fragmento. O primeiro pacote terá um número de fragmento 0 e mais fragmentos serão definidos e o último terá um número de fragmento diferente de zero e mais fragmentos não serão configurados.
Então, por que se importar? Os detalhes da implementação são realmente importantes. A fragmentação pode prejudicar o desempenho da rede, não é mais um grande problema, mas um fato a ser observado. Se um tamanho enorme de datagrama for usado, se algum fragmento for perdido, todos os datagramas precisarão ser reenviados. Igualmente em volumes altos e hoje esses volumes são perfeitamente alcançáveis, é possível a associação incorreta de quadros na remontagem. Também pode haver problemas ao obter pacotes UDP fragmentados para atravessar configurações de firewall corporativo, onde os balanceadores de carga distribuem os pacotes, se um fragmento estiver em um firewall e outro em outro, o tráfego será descartado como incompleto.
Portanto, não crie datagramas UDP maiores que a fragmentação do tamanho da MTU, a menos que você precise e se precisar especificar que a infraestrutura que está sendo comunicada está próxima (o mesmo fechamento da sub-rede); nesse ponto, os jumbo-frames provavelmente seriam uma boa opção.
Boas informações sobre a 'flag mais fragmentos'. Isso é um sinalizador no cabeçalho UDP ou no cabeçalho IP?
John Jesus
Nota: Alguns sistemas operacionais NÃO transmitirão UDP se os dados forem fragmentados. IE Linux doc,By default, Linux UDP does path MTU (Maximum Transmission Unit) discovery. This means the kernel will keep track of the MTU to a specific target IP address and return EMSGSIZE when a UDP packet write exceeds it.
Rahly 26/09/16
2
A camada IP fragmentará seu pacote na extremidade de envio e a remontará novamente na extremidade de recebimento, antes de passá-lo para o UDP. Na camada UDP, você não pode realmente dizer que o pacote foi fragmentado. Se você usar uma ferramenta de captura de pacotes como o Wireshark , poderá ver que seu computador está recebendo pacotes IP limitados à MTU.
Você quer dizer que o TCP / IP está se fragmentando e se remontando? Se sim, então por que as pessoas dizem o tempo todo que seu código deve cuidar da remontagem no final do receptor. Não observei fragmentação a partir de agora, mas já vi muitos fóruns dizendo isso e até pessoas aceitando.
Para aqueles de nós que são desafiados pelo modelo OSI, você poderia adicionar um pouco mais de detalhes à sua resposta, por favor?
Robert Harvey
Eu estava sendo um pouco cauteloso porque não sei dizer se isso é lição de casa ou não. É uma desvantagem: como o UDP não oferece garantias de entrega, se algum fragmento de pacote for descartado, o pacote inteiro será perdido. Se você deseja um transporte confiável no topo do UDP, precisará lidar com tudo isso sozinho; mas se você estiver usando (digamos) protocolos de streaming (ou NFS sobre UDP, que seguiu o caminho do streaming), será uma sobrecarga mais baixa simplesmente eliminar esses pacotes ou retransmitir o pacote maior após um longo atraso, se necessário. Você precisa equilibrar suas necessidades com os recursos e as despesas gerais do protocolo.
Geekosaur #
1
O UDP não sabe nada sobre o MTU. Pacotes UDP podem ter qualquer tamanho de 8 a 65535 bytes. As camadas de protocolo abaixo do UDP podem enviar um pacote de um tamanho específico ou serão rejeitadas para enviar esse pacote com um erro se for muito grande.
A camada abaixo do UDP é geralmente IP, IPv4 ou IPv6. E pacotes IP podem ter qualquer tamanho de 20 (IPv4) / 40 (IPv6) a 65535 bytes, que é o mesmo máximo que o UDP. No entanto, o IP suporta um mecanismo chamado fragmentação . Se um pacote IP tiver um tamanho maior do que o que a camada abaixo pode transportar, o IP poderá dividir um único pacote em vários pacotes chamados fragmentos. Cada fragmento é, de fato, um pacote IP próprio (possui um cabeçalho IP próprio) e também é enviado sozinho para o destino; é tarefa do destino coletar todos os fragmentos e reconstruir o pacote completo deles antes de passar os dados recebidos na próxima camada superior (por exemplo, UDP).
O protocolo Ethernet pode transportar apenas quadros com uma carga útil entre 46 e 1500 bytes (há exceções, mas isso está além do escopo desta resposta). Se os dados da carga útil forem inferiores a 46 bytes, eles serão preenchidos com precisão de 46 bytes. Se os dados da carga útil ultrapassarem 1500 bytes, a interface se recusará a aceitá-los. Se isso acontecer, cabe à camada IP decidir agora fragmentar o pacote, para que nenhum fragmento seja maior que 1500 bytes ou relate um erro para a próxima camada superior se a fragmentação tiver sido desabilitada ou proibida para essa conexão específica.
Geralmente, a fragmentação deve ser evitada, como
desperdiça recursos no lado do remetente.
desperdiça recursos no lado do receptor.
aumenta a sobrecarga do protocolo para a mesma quantidade de dados de carga útil.
se um único fragmento for perdido, o pacote inteiro será perdido.
se um único fragmento estiver corrompido, o pacote inteiro estará corrompido.
em caso de reenvio, todos os fragmentos devem ser reenviados.
É por isso que o TCP adota inteligentemente seu tamanho de quadro para que os pacotes nunca exijam o IP para fragmentá-los. Isso pode ser feito proibindo o IP de fragmentar pacotes e, se o IP relatar que um pacote é muito grande para ser enviado, o TCP reduz o tamanho do quadro e tenta novamente, até que nenhum erro seja mais relatado.
Para o UDP, porém, essa seria a tarefa do próprio aplicativo, pois o UDP é um protocolo "burro", não possui lógica de gerenciamento própria, o que o torna muito flexível, rápido e simples.
O único tamanho UDP em que você pode confiar para ser sempre transportável é o cabeçalho UDP de 576 menos 8 bytes e o cabeçalho IP de 20 (v4) / 40 (v6) bytes, pois o padrão IP exige que todo host IP possa receber pacotes IP com um tamanho total de 576 bytes. Sua implementação de protocolo não estaria em conformidade com o padrão se não puder aceitar pacotes com pelo menos esse tamanho. Observe, no entanto, que o padrão não diz 576 sem fragmentação; portanto, mesmo um pacote IP de 576 bytes pode ser fragmentado entre dois hosts.
O único tamanho de pacote no qual você pode confiar para ser transportável sem fragmentação é de 24 bytes para IPv4 e 56 bytes para IPv6, pois os menores cabeçalhos IP de um fragmento são 20/48 bytes (v4 / v6) e um fragmento deve ter pelo menos 4/8 dados de carga útil de bytes (v4 / v6). Portanto, um sistema de transporte abaixo da camada IP que não pode transportar pelo menos pacotes de tamanhos de teses, não pode ser usado para transportar tráfego IP.
E antes que alguém comente que um cabeçalho IPv6 possui apenas 40 bytes: Isso está correto, mas, diferentemente de um cabeçalho IPv4, um cabeçalho IPv6 padrão não possui campos de cabeçalho para fragmentação. Se um pacote precisar ser fragmentado, um cabeçalho de extensão de fragmentação deverá ser adicionado abaixo do cabeçalho base IPv6 e esse cabeçalho de extensão terá 8 bytes. Além disso, diferentemente do IPv4, as compensações de fragmentação no IPv6 são contadas em unidades de 8 bytes e não de 4 bytes, portanto, um fragmento pode transportar apenas uma carga útil com múltiplos de 8 bytes no caso do IPv6.
Para responder à sua pergunta: "Se o tamanho da carga útil do quadro em si é máximo de 1472 bytes (conforme meu livro didático), como o tamanho do pacote IP pode ser maior que o tamanho 65535?"
É devido a um recurso de descarregamento chamado UFO (UDP Fragmentation Offload). Por favor, consulte este link.
Você pode verificar e alternar os recursos de descarregamento via ethtool -k ethX e ethtool -K ethX, respectivamente.
Se você estiver monitorando quadros de saída, é possível que seu adaptador de rede suporte o descarregamento de segmentação e ele esteja ativado. Com o descarregamento de segmentação ativado, a própria placa de rede lida com a segmentação do pacote / quadro no tamanho apropriado, em vez da pilha de rede. Isso libera a CPU no computador para executar outras tarefas, melhorando o desempenho. No Linux, "ethtool -k [device]" mostrará os sinalizadores de descarregamento.
By default, Linux UDP does path MTU (Maximum Transmission Unit) discovery. This means the kernel will keep track of the MTU to a specific target IP address and return EMSGSIZE when a UDP packet write exceeds it.
A camada IP fragmentará seu pacote na extremidade de envio e a remontará novamente na extremidade de recebimento, antes de passá-lo para o UDP. Na camada UDP, você não pode realmente dizer que o pacote foi fragmentado. Se você usar uma ferramenta de captura de pacotes como o Wireshark , poderá ver que seu computador está recebendo pacotes IP limitados à MTU.
fonte
Acontece que permitir que a pilha TCP / IP fragmente pacotes conforme necessário é uma sobrecarga muito menor do que o envio de pacotes individuais.
fonte
O UDP não sabe nada sobre o MTU. Pacotes UDP podem ter qualquer tamanho de 8 a 65535 bytes. As camadas de protocolo abaixo do UDP podem enviar um pacote de um tamanho específico ou serão rejeitadas para enviar esse pacote com um erro se for muito grande.
A camada abaixo do UDP é geralmente IP, IPv4 ou IPv6. E pacotes IP podem ter qualquer tamanho de 20 (IPv4) / 40 (IPv6) a 65535 bytes, que é o mesmo máximo que o UDP. No entanto, o IP suporta um mecanismo chamado fragmentação . Se um pacote IP tiver um tamanho maior do que o que a camada abaixo pode transportar, o IP poderá dividir um único pacote em vários pacotes chamados fragmentos. Cada fragmento é, de fato, um pacote IP próprio (possui um cabeçalho IP próprio) e também é enviado sozinho para o destino; é tarefa do destino coletar todos os fragmentos e reconstruir o pacote completo deles antes de passar os dados recebidos na próxima camada superior (por exemplo, UDP).
O protocolo Ethernet pode transportar apenas quadros com uma carga útil entre 46 e 1500 bytes (há exceções, mas isso está além do escopo desta resposta). Se os dados da carga útil forem inferiores a 46 bytes, eles serão preenchidos com precisão de 46 bytes. Se os dados da carga útil ultrapassarem 1500 bytes, a interface se recusará a aceitá-los. Se isso acontecer, cabe à camada IP decidir agora fragmentar o pacote, para que nenhum fragmento seja maior que 1500 bytes ou relate um erro para a próxima camada superior se a fragmentação tiver sido desabilitada ou proibida para essa conexão específica.
Geralmente, a fragmentação deve ser evitada, como
É por isso que o TCP adota inteligentemente seu tamanho de quadro para que os pacotes nunca exijam o IP para fragmentá-los. Isso pode ser feito proibindo o IP de fragmentar pacotes e, se o IP relatar que um pacote é muito grande para ser enviado, o TCP reduz o tamanho do quadro e tenta novamente, até que nenhum erro seja mais relatado.
Para o UDP, porém, essa seria a tarefa do próprio aplicativo, pois o UDP é um protocolo "burro", não possui lógica de gerenciamento própria, o que o torna muito flexível, rápido e simples.
O único tamanho UDP em que você pode confiar para ser sempre transportável é o cabeçalho UDP de 576 menos 8 bytes e o cabeçalho IP de 20 (v4) / 40 (v6) bytes, pois o padrão IP exige que todo host IP possa receber pacotes IP com um tamanho total de 576 bytes. Sua implementação de protocolo não estaria em conformidade com o padrão se não puder aceitar pacotes com pelo menos esse tamanho. Observe, no entanto, que o padrão não diz 576 sem fragmentação; portanto, mesmo um pacote IP de 576 bytes pode ser fragmentado entre dois hosts.
O único tamanho de pacote no qual você pode confiar para ser transportável sem fragmentação é de 24 bytes para IPv4 e 56 bytes para IPv6, pois os menores cabeçalhos IP de um fragmento são 20/48 bytes (v4 / v6) e um fragmento deve ter pelo menos 4/8 dados de carga útil de bytes (v4 / v6). Portanto, um sistema de transporte abaixo da camada IP que não pode transportar pelo menos pacotes de tamanhos de teses, não pode ser usado para transportar tráfego IP.
E antes que alguém comente que um cabeçalho IPv6 possui apenas 40 bytes: Isso está correto, mas, diferentemente de um cabeçalho IPv4, um cabeçalho IPv6 padrão não possui campos de cabeçalho para fragmentação. Se um pacote precisar ser fragmentado, um cabeçalho de extensão de fragmentação deverá ser adicionado abaixo do cabeçalho base IPv6 e esse cabeçalho de extensão terá 8 bytes. Além disso, diferentemente do IPv4, as compensações de fragmentação no IPv6 são contadas em unidades de 8 bytes e não de 4 bytes, portanto, um fragmento pode transportar apenas uma carga útil com múltiplos de 8 bytes no caso do IPv6.
fonte
Para responder à sua pergunta: "Se o tamanho da carga útil do quadro em si é máximo de 1472 bytes (conforme meu livro didático), como o tamanho do pacote IP pode ser maior que o tamanho 65535?"
É devido a um recurso de descarregamento chamado UFO (UDP Fragmentation Offload). Por favor, consulte este link.
Você pode verificar e alternar os recursos de descarregamento via ethtool -k ethX e ethtool -K ethX, respectivamente.
fonte
Se você estiver monitorando quadros de saída, é possível que seu adaptador de rede suporte o descarregamento de segmentação e ele esteja ativado. Com o descarregamento de segmentação ativado, a própria placa de rede lida com a segmentação do pacote / quadro no tamanho apropriado, em vez da pilha de rede. Isso libera a CPU no computador para executar outras tarefas, melhorando o desempenho. No Linux, "ethtool -k [device]" mostrará os sinalizadores de descarregamento.
fonte