In che modo l'MTU è 65535 in UDP ma Ethernet non consente dimensioni dei frame superiori a 1500 byte


11

Sto usando una Ethernet veloce di 100 Mbps, la cui dimensione del frame è inferiore a 1500 byte (1472 byte per il payload secondo il mio libro di testo). In questo, sono stato in grado di inviare e ricevere un pacchetto UDP di dimensioni del messaggio 65507 byte, il che significa che la dimensione del pacchetto era 65507 + 20 (intestazione IP) + 8 (intestazione UDP) = 65535.

Se la dimensione del payload del frame stesso è massima di 1472 byte (come per il mio libro di testo), come può la dimensione del pacchetto di IP essere maggiore di quella che qui è 65535?

Ho usato il codice mittente come

char buffer[100000];
for (int i = 1; i < 100000; i++)
{
    int len = send (socket_id, buffer, i);
    printf("%d\n", len);
}

Codice ricevitore come

while (len = recv (socket_id, buffer, 100000))
{
     printf("%d\n". len);
}

Ho osservato che send returns -1su i > 65507e recvstampa o riceve un pacchetto di maximum of length 65507.

Risposte:


11

I datagrammi UDP hanno poco a che fare con la dimensione MTU che puoi renderli grandi quanto vuoi fino a 64 KB è il massimo menzionato sopra. Puoi persino inviarne uno in un intero pacchetto purché utilizzi frame jumbo con dimensioni maggiori del datagramma di grandi dimensioni.

Tuttavia, i frame jumbo devono essere supportati da tutte le apparecchiature su cui passerà il frame e questo è un problema. Ai fini pratici, i frame Ethernet sono le dimensioni di trasporto più comuni, l'MTU per questi è di circa 1500 byte, dirò 1500 andando avanti, ma non è sempre. Quando si crea un datagramma UDP più grande dell'MTU sottostante (che come indicato è spesso ethernet), verrà tranquillamente suddiviso in un numero di frame da 1500 byte. Se tcpdump questo traffico vedrai un numero di pacchetti interrotti al confine MTU che avrà il flag più frammenti impostato con un numero di frammento. Il primo pacchetto avrà un numero di frammento pari a 0 e più frammenti impostati e l'ultimo avrà un numero di frammento diverso da zero e più frammenti non impostati.

Quindi perché preoccuparsene? I dettagli di implementazione contano davvero. La frammentazione può danneggiare le prestazioni della rete non più un grosso problema, ma uno di cui essere consapevoli. Se viene utilizzata una dimensione enorme del datagramma, in caso di perdita di frammenti, è necessario inviare nuovamente tutti i datagrammi. Allo stesso modo a volumi elevati e oggi questi sono volumi perfettamente realizzabili, quindi è possibile un'associazione errata dei telai al rimontaggio. Potrebbero inoltre esserci problemi a ottenere pacchetti UDP frammentati per attraversare le configurazioni del firewall aziendale in cui i bilanciatori del carico distribuiscono i pacchetti, se un frammento si trova su un firewall e l'altro su un altro, il traffico verrà eliminato come incompleto.

Quindi non creare datagrammi UDP più grandi della frammentazione della dimensione MTU a meno che non sia necessario e se si debba specificare che l'infrastruttura da comunicare è chiusa (stessa sottorete chiusa) a quel punto i frame jumbo sarebbero probabilmente una buona opzione.


Buone informazioni sulla "bandiera più frammenti". È un flag nell'intestazione UDP o nell'intestazione IP?
Giovanni Gesù,

Nota: alcuni sistemi operativi NON trasmettono UDP se i dati saranno frammentati. 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.
Documento

2

Il livello IP frammenterà il pacchetto sull'estremità di invio, quindi lo riassemblerà sull'estremità ricevente, prima di passarlo a UDP. Dal livello UDP, non si può davvero dire che il pacchetto è stato frammentato. Se usi uno strumento di acquisizione di pacchetti come Wireshark , dovresti essere in grado di vedere che il tuo computer sta ricevendo pacchetti IP limitati all'MTU.


1

Risulta che consentire allo stack TCP / IP di frammentare i pacchetti in base alle esigenze è un sovraccarico molto inferiore rispetto all'invio di singoli pacchetti.


1
Vuoi dire che TCP / IP si sta frammentando e riassemblando se stesso? Se sì, allora perché la gente dice sempre che il tuo codice dovrebbe occuparsi del riassemblaggio alla fine del ricevitore. Finora non ho osservato la frammentazione, ma ho visto molti forum che lo dicono e persino la gente lo accetta.

Per quelli di noi che sono sfidati nel modello OSI, potresti aggiungere qualche dettaglio in più alla tua risposta, per favore?
Robert Harvey,

Ero un po 'cauto perché non so dire se si tratta di compiti o no. È un compromesso: poiché UDP non fornisce garanzie di consegna, se un frammento di pacchetto viene eliminato l'intero pacchetto viene perso. Se si desidera un trasporto affidabile in cima a UDP, è necessario gestire tutto questo da soli; ma se stai facendo (diciamo) protocolli di streaming (o NFS su UDP, che ha preso il percorso simile allo streaming) è più basso sovraccarico semplicemente abbandonare quei pacchetti o ritrasmettere il pacchetto più grande dopo un lungo ritardo, se necessario. Devi bilanciare le tue esigenze con le funzionalità del protocollo e le spese generali del protocollo.
Geekosaur,

1

UDP non sa nulla di MTU. I pacchetti UDP possono avere qualsiasi dimensione compresa tra 8 e 65535 byte. I livelli di protocollo sotto UDP possono inviare un pacchetto di dimensioni specifiche o rifiutano di inviare quel pacchetto con un errore se troppo grande.

Il livello sotto UDP è in genere IP, IPv4 o IPv6. E il pacchetto IP può avere qualsiasi dimensione da 20 (IPv4) / 40 (IPv6) a 65535 byte, che è lo stesso massimo di UDP. Tuttavia, IP supporta un meccanismo chiamato frammentazione . Se un pacchetto IP ha dimensioni maggiori di quelle che il livello sottostante può trasportare, l'IP può dividere un singolo pacchetto in più pacchetti chiamati frammenti. Ogni frammento è in realtà un pacchetto IP a sé stante (ha una propria intestazione IP) e viene anche inviato da solo alla destinazione; è quindi compito della destinazione raccogliere tutti i frammenti e ricostruirne il pacchetto completo prima di passare i dati ricevuti sul livello superiore successivo (ad es. UDP).

Il protocollo Ethernet può trasportare solo frame con un payload tra 46 e 1500 byte (ci sono eccezioni, ma questo va oltre lo scopo di questa risposta). Se i dati del payload sono inferiori a 46 byte, vengono riempiti per essere esattamente 46 byte. Se i dati del payload superano i 1500 byte, l'interfaccia rifiuterà di accettarli. Se ciò accade, spetta ora al livello IP decidere di frammentare il pacchetto, in modo che nessun frammento sia più grande di 1500 byte o segnalare un errore al livello superiore successivo se la frammentazione è stata disabilitata o vietata per questa particolare connessione.

La frammentazione è generalmente da evitare, come

  • spreca risorse dal lato del mittente.
  • spreca risorse sul lato ricevente.
  • aumenta l'overhead del protocollo per la stessa quantità di dati del payload.
  • se si perde un singolo frammento, si perde l'intero pacchetto.
  • se un singolo frammento è danneggiato, l'intero pacchetto è danneggiato.
  • in caso di rinvio, tutti i frammenti devono essere reinviati.

Ecco perché TCP adotta in modo intelligente le dimensioni dei frame in modo che i pacchetti non richiedano mai l'IP per frammentarli. Questo può essere fatto vietando all'IP di frammentare i pacchetti e se l'IP segnala che un pacchetto è troppo grande per essere inviato, TCP riduce la dimensione del frame e riprova, fino a quando non viene più segnalato alcun errore.

Per UDP, tuttavia, questo sarebbe il compito dell'applicazione stessa, poiché UDP è un protocollo "stupido", non ha una logica di gestione propria, il che lo rende molto flessibile, veloce e semplice.

L'unica dimensione UDP su cui puoi contare per essere sempre trasportabile è 576 meno 8 byte di intestazione UDP e meno 20 (v4) / 40 (v6) byte di intestazione IP, poiché lo standard IP richiede che ogni host IP sia in grado di ricevere pacchetti IP con una dimensione totale di 576 byte. L'implementazione del protocollo non sarebbe conforme allo standard se non può accettare pacchetti di almeno quella dimensione. Si noti, tuttavia, che lo standard non dice 576 senza frammentazione, quindi anche un pacchetto IP da 576 byte può essere frammentato tra due host.

L'unica dimensione del pacchetto su cui contare per essere trasportabile senza frammentazione è di 24 byte per IPv4 e 56 byte IPv6, poiché le intestazioni IP più piccole per un frammento sono 20/48 byte (v4 / v6) e un frammento deve avere almeno 4/8 byte (v4 / v6) dati del payload. Pertanto, un sistema di trasporto al di sotto del livello IP che non può trasportare almeno pacchetti di queste dimensioni, non può essere utilizzato per trasportare il traffico IP.

E prima che qualcuno commentasse che un'intestazione IPv6 ha solo 40 byte: questo è corretto ma, a differenza di un'intestazione IPv4, un'intestazione IPv6 standard non ha campi di intestazione per la frammentazione. Se un pacchetto deve essere frammentato, è necessario aggiungere un'intestazione di estensione di frammentazione sotto l'intestazione di base IPv6 e questa estensione di estensione è lunga 8 byte. Inoltre a differenza di IPv4, gli offset di frammentazione in IPv6 sono conteggiati in 8 byte e non in unità di 4 byte, quindi un frammento può trasportare solo un payload che è un multiplo di 8 byte in caso di IPv6.


0

Per rispondere alla tua domanda, "Se la dimensione del payload del frame è al massimo di 1472 byte (come per il mio libro di testo), come può la dimensione del pacchetto di IP essere maggiore di quella che qui è 65535?"

È dovuto a una funzionalità di offload chiamata UFO (UDP Fragmentation Offload). Si prega di fare riferimento a questo link.

È possibile verificare e attivare o disattivare le funzionalità di offloading rispettivamente tramite ethtool -k ethX e ethtool -K ethX.


0

Se stai monitorando i frame in uscita, è possibile che la tua scheda di rete supporti l'offload della segmentazione ed è abilitata. Con l'offload di segmentazione abilitato, la scheda di rete stessa gestisce la segmentazione del pacchetto / frame nella dimensione appropriata, anziché nello stack di rete. Ciò consente alla CPU del computer di eseguire altre attività, migliorando le prestazioni. Su Linux, "ethtool -k [dispositivo]" mostrerà i flag di offload.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.