Eu escrevi um programa python simples para enviar um datagrama UDP.
import socket
client_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
host_name = socket.gethostname()
host_ip = '1.2.3.4'
print(host_ip)
port = 8080
message = b'0' * 65500
client_socket.sendto(message,(host_ip,port))
Quando executo esse código, ele envia com êxito um pacote UDP. Aqui está o registro do wireshark,
O MTU da minha interface sem fio é 1500, que descobri executando ip link
o comando.
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eno2: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN mode DEFAULT group default qlen 1000
link/ether 58:11:22:82:c2:ec brd ff:ff:ff:ff:ff:ff
altname enp0s31f6
3: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DORMANT group default qlen 1000
link/ether f4:26:79:33:7c:96 brd ff:ff:ff:ff:ff:ff
altname wlp0s20f3
Eu li que não é possível enviar um pacote maior que o MTU de uma interface, então como é que o pacote UDP foi transmitido. Alguém pode me explicar o que está acontecendo aqui?
PS: Tentei enviar para um servidor de minha propriedade e também consegui receber a mensagem.
IPv4 e IPv6 suportam fragmentação abaixo da camada de transporte, embora nem sempre funcione tão bem quanto deveria (algumas redes não retornam a indicação correta do Path MTU, algumas redes descartam fragmentos imediatamente), mas neste caso o sistema operacional conhece seu local MTU e fragmentará o pacote de acordo.
No seu caso, o pacote é fragmentado na camada IP, mas o sistema operacional usa descarregamento de hardware para que a fragmentação seja realmente tratada pela sua NIC e não seja visível para a captura de pacotes. (Isso pode oferecer melhor desempenho, pois o sistema operacional não precisa enfileirar vários pacotes e copiar pedaços de dados de carga útil na memória.)
Use
ethtool -k wlan0 | grep -v '\[fixed\]'
para ver os recursos de descarregamento que você pode ativar/desativar. Provavelmente é 'descarregamento de segmentação genérica' ou 'gso'; você pode desativá-lo temporariamente usandoethtool -K wlan0 gso off
.Além disso, há uma opção de soquete que você pode definir por meio de setsockopt() para cancelar a fragmentação; a chamada send() retornará um código de erro para pacotes muito grandes. Para IPv4 a opção é 'IP_MTU_DISCOVER', para IPv6 é 'IPV6_MTU_DISCOVER'. Ver
man 7 ip
.(Se a sua versão Python não tiver essas constantes, encontre os valores reais em /usr/include – eles devem ser
10
para IP_MTU_DISCOVER e23
para IPV6_MTU_DISCOVER. Por exemplo,setsockopt(SOL_IP, 10, False)
.)(Como observação lateral, as interfaces Wi-Fi têm um MTU máximo potencial de aproximadamente 2.304 – elas simplesmente são padronizadas para 1.500 para permanecerem compatíveis com a configuração Ethernet padrão de 1.500.)