2.2.5 Wechselwirkungen mit IP- und Subnetz-Schicht

Ein Ziel der Schichten-Einteilung bei Netzarchitekturen besteht darin, daß eine Schicht jeweils eine möglichst abgeschlossene Aufgabe erfüllt; die Wechselwirkungen mit anderen Schichten sollen minimal sein. Prakisch gibt es bei UDP aber doch eine Reihe solcher Wechselwirkungen mit darunterliegenden Schichten, die in diesem Abschnitt behandelt werden sollen.

Fragmentierung auf IP-Ebene

Wenn ein UDP-Datagramm eine bestimmte Größe überschreitet, kann es passieren, daß das zu seinem Transport benötigte IP-Paket die MTU zumindest eines der auf dem Weg zum Ziel durchquerten Subnetze übersteigt. Darauf reagiert IP mit der Ihnen schon bekannten Technik der Fragmentierung. Außer einem Performance-Verlust bemerkt die Transportschicht davon nichts. Die Fragmentierung der IP-Datagramme sowie deren nachfolgende Reassemblierung auf dem Ziel-Rechner ist also für die Transportprotokolle transparent.

Trotz dieser Transparenz empfiehlt es sich, Fragmentierungen nach Möglichkeit zu vermeiden. Jedes einzelne Fragment ist ein komplettes IP-Paket, das unabhängig von anderen durch das Netz geroutet wird. Sofern auch nur eines dieser Fragmente verlorengeht, so ist bei Bedarf das gesamte IP-Datagramm noch einmal zu senden. Dafür ist allerdings eine höhere Schicht verantwortlich, da IP über keinerlei Mechanismen verfügt, um Datagramme bzw. Fragmente selbständig wiederholen zu können.

TCP versucht von sich aus, Fragmentierungen generell zu vermeiden. Anwendungen haben in der Regel auch keine Möglichkeit, TCP zum Senden derart großer Pakete zu zwingen, daß eine Fragmentierung erfolgen muß. Dagegen ist es bei UDP sehr einfach, die IP-Fragmentierung hervorzurufen. Das wollen wir uns an einem kleinen Beispiel ansehen.

Der Klient aus unserer Beispiel-Kommunikation soll jetzt eine lange Nachricht an den Server schicken. Konkret im Ethernet-LAN erfolgt eine Fragmentierung, sobald die Daten des UDP-Pakets eine Länge von 1472 überschreiten.


Frage 2.2.5.1:

Wie ergibt sich die Zahl 1472?


Senden wir also eine Folge von 1473 Bytes. Dann muß IP zwei Fragmente bilden, wobei das erste wahrscheinlich 1472 Bytes und das zweite genau 1 Byte enthält. Mit Hilfe von snoop läßt sich der Ablauf wieder sehr schön verfolgen:

________________________________
  1   0.00000 yang.informatik.tu-chemnitz.de -> ultra.informatik.tu-chemnitz.de
      ETHER Type=0800 (IP), size = 1514 bytes
  1   0.00000 yang.informatik.tu-chemnitz.de -> ultra.informatik.tu-chemnitz.de
      IP  D=134.109.192.89 S=134.109.192.215 LEN=1500, ID=52441
  1   0.00000 yang.informatik.tu-chemnitz.de -> ultra.informatik.tu-chemnitz.de
      UDP D=9 S=33884 LEN=1481
  1   0.00000 yang.informatik.tu-chemnitz.de -> ultra.informatik.tu-chemnitz.de
      DISCARD C port=33884  !"#$%&'()*+,-./0123
________________________________
  2   0.00013 yang.informatik.tu-chemnitz.de -> ultra.informatik.tu-chemnitz.de
      ETHER Type=0800 (IP), size = 60 bytes
  2   0.00013 yang.informatik.tu-chemnitz.de -> ultra.informatik.tu-chemnitz.de
      UDP continuation ID=52441

Die detaillierte Ausgabe finden Sie hier [udpfrag.txt].


Frage 2.2.5.2:

Wo und wie oft wird der UDP-Kopf gesendet, wenn eine IP-Fragmentierung eintritt?


Ermittlung der MTU

Neuere TCP/IP-Implementierungen, z.B. in Linux 2.x und Solaris 2.x, nutzen den im RFC 1191 (Path MTU Discovery) beschriebenen Algorithmus zur Ermittlung der MTU und passen so die Größe der von ihnen ausgesendeten IP-Datagramme automatisch den konkreten Gegenheiten im Netz an.

Diesen Algorithmus hatten Sie im wesentlichen bereits in Kapitel 1A kennengelernt. Er beruht auf der Verwendung des Don't-Fragment-Flags. Empfängt ein Router ein Datagramm mit gesetztem DF-Bit, das aber für die Weiterleitung zum Ziel fragmentiert werden müßte, so generiert er eine ICMP-Meldung Destination Unreachable: fragmentation needed and DF set. Diese hat bei vielen Routern die im RFC 1191 beschriebene erweiterte Form, d.h., sie beinhaltet gleich die zum Erreichen des nächsten Routers bzw. auch des Endsystems zulässige MTU.

UDP und ARP

Ist ein UDP-Datagramm an eine Ethernet-Adresse zu senden, die noch nicht oder nach einem Timeout nicht mehr im ARP-Cache des Systems steht, so muß die TCP/IP-Implementierung zunächst eine ARP-Anfrage absetzen. Erst nachdem die zugehörige ARP-Antwort eingetroffen ist, kann das zum Transport der UDP-Nachricht generierte IP-Datagramm gesendet werden.

Nun stellt sich die Frage, wie sich die Implementierung verhält, wenn während des Wartens auf die ARP-Antwort weitere IP-Pakete an dieselbe Zieladresse abgesendet werden sollen. Das passiert z.B. dann, wenn das UDP-Paket die MTU übersteigt, so daß zu seiner Übertragung mehrere IP-Fragmente nötig sind. Diese Fragmente werden innerhalb sehr kurzer Zeit erzeugt.

Die konkrete Antwort hängt vom verwendeten System ab. Generell ist aber immer mit einem Verlust des Datagramms zu rechnen. Vielfach kann die Software intern nur ein einziges Datagramm zwischengespeichern, so daß z.B. beim Eintreffen der ARP-Antwort nur noch das letzte Fragment vorliegt und deshalb auch nur dieses ausgesendet wird.

Der Empfänger muß bei dessen Empfang nicht einmal eine ICMP-Meldung Time Exceeded: fragment reassembly time exceeded generieren, da diese nur für den hier nicht vorliegenden Fall gefordert ist, daß das erste Fragment (dasjenige mit Fragment-Offset 0) empfangen wurde. Stevens begründet dies damit, daß der Empfänger einer solchen ICMP-Fehlernachricht den Nutzerprozeß, der das fragmentierte UDP-Datagramm gesendet hat, nicht ermitteln kann, da durch den Verlust des ersten Fragments der Header der Transportschicht und somit die Portnummer des Senders nicht zur Verfügung steht.

Auf diesen durch ARP bedingten Verlust von IP-Datagrammen muß eine höhere Schicht (z.B. TCP oder bei UDP die Anwendungsschicht) geeignet reagieren, in der Regel durch das über Timeouts gesteuerte Wiederholen von Paketen, wie es z.B. bei NFS geschieht.

Es sei noch angemerkt, daß im Extremfall für jedes Fragment unseres IP-Datagramms, also mit sehr hoher Frequenz eine ARP-Anfrage nach dem gleichen Ziel abgesetzt wird, so daß wir ein sog. ARP flooding auf dem Netz sehen. RFC 1122 fordert allerdings einen Mechanismus, um diese Erscheinung zu vermeiden. Pro Ziel wird eine Maximalrate von einer Anfrage in der Sekunde empfohlen.

Maximale Größe von UDP-Datagrammen

Oft stellt sich die Frage nach der Maximallänge der Nutzdaten eines UDP-Datagramms. Nach der Theorie ergibt sich folgende Überlegung: IP-Datagramme kodieren ihre Länge mit 16 Bit, so daß sie nicht länger als 65535 Byte sein können. Davon gehen der IP-Kopf mit 20 Byte sowie der UDP-Kopf mit 8 Byte ab. Somit verbleiben 65507 Byte für die UDP-Daten.

Ob diese Anzahl auch wirklich genutzt werden kann, hängt von der konkret verwendeten TCP/IP-Implementierung sowie der API ab. So sind z.B. nicht alle Systeme in der Lage, 65535 Byte lange IP-Pakete zu verarbeiten.

Bei der Socket-API kann eine Anwendung sowohl die Größe des Empfangs- als auch des Sendepuffers in bestimmten Grenzen festlegen. Die Standard-Puffergröße beträgt in der Mehrzahl der Fälle mindestens 8192 Byte, da NFS vorzugsweise seine Daten in Blöcken dieser Länge liest und schreibt.

Mehrere UDP-basierte Dienste (z.B. RIP, DNS, TFTP, BOOTP und SNMP) begrenzen vielfach ihre Datenlänge bewußt auf sehr geringe Werte um die 512 Byte, um unter dem Limit von 576 Byte zu bleiben. Von allen Implementierungen wird gefordert, wenigstens 576 Byte lange Datagramme empfangen zu können.


© Holger Trapp, 22.5.1998