Wie ist die MTU ist 65535 in UDP, aber Ethernet erlaubt keine Frame-Größe mehr als 1500 Bytes
10
Ich verwende ein schnelles Ethernet mit 100 Mbit / s, dessen Frame-Größe weniger als 1500 Byte beträgt (1472 Byte für die Nutzlast gemäß meinem Lehrbuch). Dadurch konnte ich ein UDP-Paket mit einer Nachrichtengröße von 65507 Byte senden und empfangen, was bedeutet, dass die Paketgröße 65507 + 20 (IP-Header) + 8 (UDP-Header) = 65535 war.
Wenn die Nutzlastgröße des Frames selbst maximal 1472 Byte beträgt (gemäß meinem Lehrbuch), wie kann die Paketgröße von IP größer sein als die hier 65535?
Ich habe den Absendercode als verwendet
char buffer[100000];
for (int i = 1; i < 100000; i++)
{
int len = send (socket_id, buffer, i);
printf("%d\n", len);
}
UDP-Datagramme haben wenig mit der MTU-Größe zu tun. Sie können sie so groß machen, wie Sie möchten, bis zu den oben genannten maximal 64 KB. Sie können sogar einen von ihnen in einem ganzen Paket senden, solange Sie Jumbo-Frames verwenden, deren Größe größer ist als das große Datagramm.
Jumbo-Frames müssen jedoch von allen Geräten unterstützt werden, über die der Frame fährt, und dies ist ein Problem. Aus praktischen Gründen sind Ethernet-Frames die am häufigsten verwendete Transportgröße. Die MTU für diese Frames beträgt ca. 1500 Byte. Ich werde sagen, dass 1500 in Zukunft verwendet werden, aber dies ist nicht immer der Fall. Wenn Sie ein UDP-Datagramm erstellen, das größer als die zugrunde liegende MTU ist (bei der es sich, wie angegeben, meistens um Ethernet handelt), wird es stillschweigend in eine Anzahl von 1500-Byte-Frames aufgeteilt. Wenn Sie diesen Datenverkehr tcpdumpen, wird an der MTU-Grenze eine Reihe von Paketen unterbrochen, bei denen das Flag für mehr Fragmente zusammen mit einer Fragmentnummer gesetzt ist. Das erste Paket hat eine Fragmentnummer von 0 und je mehr Fragmente gesetzt sind, und das letzte hat eine Fragmentnummer ungleich Null und mehr Fragmente sind nicht gesetzt.
Warum also kümmern? Das Implementierungsdetail ist tatsächlich wichtig. Fragmentierung kann die Leistung im Netzwerk beeinträchtigen. Dies ist kein großes Problem mehr, sondern ein Problem, dessen Sie sich bewusst sein müssen. Wenn eine große Datagrammgröße verwendet wird, müssen die gesamten Datagramme erneut gesendet werden, falls ein Fragment verloren geht. Gleichermaßen bei hohen Volumina und heute sind dies perfekt erreichbare Volumina, dann ist eine falsche Zuordnung von Rahmen beim Zusammenbau möglich. Es kann auch Probleme geben, fragmentierte UDP-Pakete zum Durchlaufen von Unternehmensfirewall-Konfigurationen zu erhalten, bei denen Load Balancer die Pakete verteilen. Wenn sich ein Fragment auf einer Firewall und das andere auf einer anderen befindet, wird der Datenverkehr als unvollständig gelöscht.
Erstellen Sie also keine UDP-Datagramme, die größer als die Fragmentierung der MTU-Größe sind, es sei denn, Sie müssen angeben, dass die Infrastruktur, zwischen der kommuniziert wird, geschlossen ist (dasselbe Subnetz geschlossen). Zu diesem Zeitpunkt sind Jumbo-Frames wahrscheinlich eine gute Option.
Gute Informationen über die Flagge "Mehr Fragmente". Ist das ein Flag im UDP-Header oder im IP-Header?
Johannes Jesus
Hinweis: Einige Betriebssysteme übertragen KEIN UDP, wenn Daten fragmentiert werden. 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
2
Die IP-Schicht fragmentiert Ihr Paket auf der sendenden Seite und setzt es dann auf der empfangenden Seite wieder zusammen, bevor es an UDP weitergeleitet wird. Auf der UDP-Ebene können Sie nicht wirklich erkennen, dass das Paket fragmentiert wurde. Wenn Sie ein Paketerfassungstool wie Wireshark verwenden , sollten Sie feststellen können, dass Ihr Computer IP-Pakete empfängt, die auf die MTU beschränkt sind.
Es stellt sich heraus, dass das Zulassen, dass der TCP / IP-Stapel Pakete nach Bedarf fragmentiert, viel weniger Aufwand bedeutet als das Senden einzelner Pakete.
Meinen Sie damit, dass TCP / IP sich selbst fragmentiert und wieder zusammensetzt? Wenn ja, warum sagen die Leute dann die ganze Zeit, dass Ihr Code für den Zusammenbau auf der Empfängerseite sorgen soll? Ich habe bis jetzt keine Fragmentierung beobachtet, aber viele Foren gesehen, die dies sagen, und sogar Leute, die es akzeptieren.
Könnten Sie für diejenigen von uns, die mit dem OSI-Modell konfrontiert sind, Ihrer Antwort bitte etwas mehr Details hinzufügen?
Robert Harvey
Ich war ein bisschen käfig, weil ich nicht sagen kann, ob dies Hausaufgaben sind oder nicht. Es ist ein Kompromiss: Da UDP keine Zustellgarantien übernimmt, geht das gesamte Paket verloren, wenn ein Paketfragment verworfen wird. Wenn Sie einen zuverlässigen Transport auf UDP wünschen, müssen Sie dies alles selbst erledigen. Wenn Sie jedoch (sagen wir) Streaming-Protokolle (oder NFS über UDP, das den Streaming-ähnlichen Pfad verwendet hat) ausführen, ist der Aufwand geringer, wenn Sie diese Pakete entweder einfach verwerfen oder das größere Paket bei Bedarf nach einer längeren Verzögerung erneut übertragen. Sie müssen Ihre Anforderungen gegen Protokollfunktionen und Protokollaufwand abwägen.
Geekosaurier
0
Um Ihre Frage zu beantworten: "Wenn die Nutzlastgröße des Frames selbst maximal 1472 Byte beträgt (gemäß meinem Lehrbuch), wie kann die Paketgröße von IP größer sein als die hier angegebene 65535?"
Dies liegt an einer Offloading-Funktion namens UFO (UDP Fragmentation Offload). Bitte beziehen Sie sich auf diesen Link.
Sie können Offloading-Funktionen über ethtool -k ethX bzw. ethtool -K ethX überprüfen und umschalten.
Wenn Sie ausgehende Frames überwachen, unterstützt Ihr Netzwerkadapter möglicherweise das Segmentierungs-Offloading und ist aktiviert. Wenn das Segmentierungs-Offloading aktiviert ist, übernimmt die Netzwerkkarte selbst die Segmentierung des Pakets / Frames in die entsprechende Größe und nicht in den Netzwerkstapel. Dadurch kann die CPU im Computer andere Aufgaben ausführen und die Leistung verbessern. Unter Linux zeigt "ethtool -k [Gerät]" die Offload-Flags an.
UDP weiß nichts über MTU. UDP-Pakete können eine beliebige Größe von 0 bis 65535 Byte haben. Die Protokollschichten unter UDP können entweder ein Paket einer bestimmten Größe senden oder lehnen es ab, dieses Paket mit einem Fehler zu senden, wenn es zu groß ist.
Die Schicht unter UDP ist normalerweise IP, entweder IPv4 oder IPv6. Und IP-Pakete können genau wie UDP eine beliebige Größe von 0 bis 65535 Byte haben. IP unterstützt jedoch einen Mechanismus namens Fragmentierung . Wenn ein IP-Paket größer ist als das, was die darunter liegende Schicht transportieren kann, kann IP ein einzelnes Paket in mehrere Pakete aufteilen, die als Fragmente bezeichnet werden. Jedes Fragment ist in der Tat ein eigenes IP-Paket (hat einen eigenen IP-Header) und wird auch einzeln an das Ziel gesendet. Es ist dann die Aufgabe des Ziels, alle Fragmente zu sammeln und das vollständige Paket daraus neu zu erstellen, bevor die empfangenen Daten an die nächsthöhere Schicht (z. B. UDP) übergeben werden.
Das Ethernet-Protokoll kann nur Frames mit einer Nutzlast zwischen 46 und 1500 Byte transportieren (es gibt Ausnahmen, die jedoch den Rahmen dieser Antwort sprengen). Wenn die Nutzdaten weniger als 46 Byte betragen, werden sie mit genau 46 Byte aufgefüllt. Wenn die Nutzdaten über 1500 Byte liegen, lehnt die Schnittstelle die Annahme ab. In diesem Fall hat sich die Schnittstelle geweigert, dies zu akzeptieren, da die Daten zu groß waren. Es liegt nun an der IP-Schicht, entweder das Paket zu fragmentieren, sodass kein Fragment größer als 1500 Byte ist, oder einen Fehler an den nächsten zu melden höhere Ebene, wenn die Fragmentierung für diese bestimmte Verbindung deaktiviert oder verboten wurde.
Fragmentierung ist generell zu vermeiden, da
verschwendet Ressourcen auf der Absenderseite.
Es verschwendet Ressourcen auf der Empfängerseite.
Es erhöht den Protokoll-Overhead für die gleiche Menge an Nutzdaten.
Wenn ein einzelnes Fragment verloren geht, geht das gesamte Paket verloren.
Wenn ein einzelnes Fragment beschädigt ist, ist das gesamte Paket beschädigt.
Im Falle eines erneuten Sendens müssen alle Fragmente erneut gesendet werden.
Aus diesem Grund nimmt TCP seine Frame-Größe intelligent an, sodass die Pakete niemals IP benötigen, um sie zu fragmentieren. Dies kann erreicht werden, indem IP verboten wird, Pakete zu fragmentieren. Wenn IP meldet, dass ein Paket zu groß zum Senden ist, reduziert TCP die Frame-Größe und versucht es erneut, bis kein Fehler mehr gemeldet wird.
Für UDP wäre dies jedoch die Aufgabe der Anwendung selbst, da UDP ein "dummes" Protokoll ist und keine eigene Verwaltungslogik hat, was es sehr flexibel, schnell und einfach macht.
Die einzige UDP-Größe, auf die Sie sich verlassen können, um immer transportierbar zu sein, ist 576 minus 8 Byte UDP-Header und minus 20 (v4) oder 48 (v6) Byte IP-Header, da der IP-Standard erfordert, dass jeder IP-Host IP-Pakete mit empfangen kann eine Gesamtgröße von 576 Bytes. Ihre Protokollimplementierung wäre nicht standardkonform, wenn sie keine Pakete mit mindestens dieser Größe akzeptieren könnte. Beachten Sie jedoch, dass der Standard nicht 576 ohne Fragmentierung sagt, sodass sogar ein 576-Byte-IP-Paket zwischen zwei Hosts fragmentiert werden kann.
Die einzige Paketgröße, auf die Sie sich verlassen können, um ohne Fragmentierung transportiert zu werden, beträgt 24 Byte für IPv4 und 56 Byte für IPv6, da die kleinsten IP-Header für ein Fragment 20/48 Byte (v4 / v6) sind und ein Fragment mindestens 4/8 haben muss Nutzdaten für Bytes (v4 / v6). Daher kann ein Transportsystem unterhalb der IP-Schicht, das nicht mindestens Pakete dieser Größe transportieren kann, nicht zum Transport von IP-Verkehr verwendet werden.
Und bevor jemand kommentiert, dass ein IPv6-Header nur 40 Bytes hat: Das ist richtig, aber im Gegensatz zu einem IPv4-Header hat ein Standard-IPv6-Header keine Headerfelder für die Fragmentierung. Wenn ein Paket fragmentiert werden muss, muss unterhalb des IPv6-Basisheaders ein Fragmentierungserweiterungsheader hinzugefügt werden, und dieser Erweiterungsheader ist 8 Byte lang. Im Gegensatz zu IPv4 werden Fragmentierungs-Offsets in IPv6 in 8 Byte und nicht in 4-Byte-Einheiten gezählt, sodass ein Fragment nur eine Nutzlast tragen kann, die im Fall von IPv6 ein Vielfaches von 8 Byte ist.
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.
Die IP-Schicht fragmentiert Ihr Paket auf der sendenden Seite und setzt es dann auf der empfangenden Seite wieder zusammen, bevor es an UDP weitergeleitet wird. Auf der UDP-Ebene können Sie nicht wirklich erkennen, dass das Paket fragmentiert wurde. Wenn Sie ein Paketerfassungstool wie Wireshark verwenden , sollten Sie feststellen können, dass Ihr Computer IP-Pakete empfängt, die auf die MTU beschränkt sind.
quelle
Es stellt sich heraus, dass das Zulassen, dass der TCP / IP-Stapel Pakete nach Bedarf fragmentiert, viel weniger Aufwand bedeutet als das Senden einzelner Pakete.
quelle
Um Ihre Frage zu beantworten: "Wenn die Nutzlastgröße des Frames selbst maximal 1472 Byte beträgt (gemäß meinem Lehrbuch), wie kann die Paketgröße von IP größer sein als die hier angegebene 65535?"
Dies liegt an einer Offloading-Funktion namens UFO (UDP Fragmentation Offload). Bitte beziehen Sie sich auf diesen Link.
Sie können Offloading-Funktionen über ethtool -k ethX bzw. ethtool -K ethX überprüfen und umschalten.
quelle
Wenn Sie ausgehende Frames überwachen, unterstützt Ihr Netzwerkadapter möglicherweise das Segmentierungs-Offloading und ist aktiviert. Wenn das Segmentierungs-Offloading aktiviert ist, übernimmt die Netzwerkkarte selbst die Segmentierung des Pakets / Frames in die entsprechende Größe und nicht in den Netzwerkstapel. Dadurch kann die CPU im Computer andere Aufgaben ausführen und die Leistung verbessern. Unter Linux zeigt "ethtool -k [Gerät]" die Offload-Flags an.
quelle
UDP weiß nichts über MTU. UDP-Pakete können eine beliebige Größe von 0 bis 65535 Byte haben. Die Protokollschichten unter UDP können entweder ein Paket einer bestimmten Größe senden oder lehnen es ab, dieses Paket mit einem Fehler zu senden, wenn es zu groß ist.
Die Schicht unter UDP ist normalerweise IP, entweder IPv4 oder IPv6. Und IP-Pakete können genau wie UDP eine beliebige Größe von 0 bis 65535 Byte haben. IP unterstützt jedoch einen Mechanismus namens Fragmentierung . Wenn ein IP-Paket größer ist als das, was die darunter liegende Schicht transportieren kann, kann IP ein einzelnes Paket in mehrere Pakete aufteilen, die als Fragmente bezeichnet werden. Jedes Fragment ist in der Tat ein eigenes IP-Paket (hat einen eigenen IP-Header) und wird auch einzeln an das Ziel gesendet. Es ist dann die Aufgabe des Ziels, alle Fragmente zu sammeln und das vollständige Paket daraus neu zu erstellen, bevor die empfangenen Daten an die nächsthöhere Schicht (z. B. UDP) übergeben werden.
Das Ethernet-Protokoll kann nur Frames mit einer Nutzlast zwischen 46 und 1500 Byte transportieren (es gibt Ausnahmen, die jedoch den Rahmen dieser Antwort sprengen). Wenn die Nutzdaten weniger als 46 Byte betragen, werden sie mit genau 46 Byte aufgefüllt. Wenn die Nutzdaten über 1500 Byte liegen, lehnt die Schnittstelle die Annahme ab. In diesem Fall hat sich die Schnittstelle geweigert, dies zu akzeptieren, da die Daten zu groß waren. Es liegt nun an der IP-Schicht, entweder das Paket zu fragmentieren, sodass kein Fragment größer als 1500 Byte ist, oder einen Fehler an den nächsten zu melden höhere Ebene, wenn die Fragmentierung für diese bestimmte Verbindung deaktiviert oder verboten wurde.
Fragmentierung ist generell zu vermeiden, da
Aus diesem Grund nimmt TCP seine Frame-Größe intelligent an, sodass die Pakete niemals IP benötigen, um sie zu fragmentieren. Dies kann erreicht werden, indem IP verboten wird, Pakete zu fragmentieren. Wenn IP meldet, dass ein Paket zu groß zum Senden ist, reduziert TCP die Frame-Größe und versucht es erneut, bis kein Fehler mehr gemeldet wird.
Für UDP wäre dies jedoch die Aufgabe der Anwendung selbst, da UDP ein "dummes" Protokoll ist und keine eigene Verwaltungslogik hat, was es sehr flexibel, schnell und einfach macht.
Die einzige UDP-Größe, auf die Sie sich verlassen können, um immer transportierbar zu sein, ist 576 minus 8 Byte UDP-Header und minus 20 (v4) oder 48 (v6) Byte IP-Header, da der IP-Standard erfordert, dass jeder IP-Host IP-Pakete mit empfangen kann eine Gesamtgröße von 576 Bytes. Ihre Protokollimplementierung wäre nicht standardkonform, wenn sie keine Pakete mit mindestens dieser Größe akzeptieren könnte. Beachten Sie jedoch, dass der Standard nicht 576 ohne Fragmentierung sagt, sodass sogar ein 576-Byte-IP-Paket zwischen zwei Hosts fragmentiert werden kann.
Die einzige Paketgröße, auf die Sie sich verlassen können, um ohne Fragmentierung transportiert zu werden, beträgt 24 Byte für IPv4 und 56 Byte für IPv6, da die kleinsten IP-Header für ein Fragment 20/48 Byte (v4 / v6) sind und ein Fragment mindestens 4/8 haben muss Nutzdaten für Bytes (v4 / v6). Daher kann ein Transportsystem unterhalb der IP-Schicht, das nicht mindestens Pakete dieser Größe transportieren kann, nicht zum Transport von IP-Verkehr verwendet werden.
Und bevor jemand kommentiert, dass ein IPv6-Header nur 40 Bytes hat: Das ist richtig, aber im Gegensatz zu einem IPv4-Header hat ein Standard-IPv6-Header keine Headerfelder für die Fragmentierung. Wenn ein Paket fragmentiert werden muss, muss unterhalb des IPv6-Basisheaders ein Fragmentierungserweiterungsheader hinzugefügt werden, und dieser Erweiterungsheader ist 8 Byte lang. Im Gegensatz zu IPv4 werden Fragmentierungs-Offsets in IPv6 in 8 Byte und nicht in 4-Byte-Einheiten gezählt, sodass ein Fragment nur eine Nutzlast tragen kann, die im Fall von IPv6 ein Vielfaches von 8 Byte ist.
quelle