TCP Retransmit und SACK

In einem optimalen Netzwerk gibt es keinen Packet Loss! Diese Aussage kann man vielleicht in einem voll geswitchten LAN vielleicht noch stehen lassen aber sobald ein WAN mitspielt, ist diese Aussage falsch. Denn Paketverluste und variable Latenzzeiten (Roundtriptime) gehören zum Geschäft von TCP und UDP. Auf dieser Seite möchte ich auf diese Details eingehen und mit WireShark auch Beispiele aufzeigen.

Randbedingungen

Für eine Übertragung von Daten in einem Netzwerk haben wir alles das Ziel, dass die Daten schnell und fehlerfrei ankommen. Leider sind Übertragungsnetzwerke alles andere als zuverlässig, denn wie beim Straßenverkehr gibt es manchmal Überlast-Situationen, Blockaden, Umwege etc. und wie ein Logistiker, der seine LKWs auf die Straße schickt, sind die Geschwindigkeit und Entfernung weitere zu berücksichtigende Faktoren. Wenn einige Merksätze machen das Problem deutlich

  • Je länger der Weg (Laufzeit) ist, desto langsamer brauchen auch die Quittungen
    Gerade TCP basiert aber darauf, dass gesendete Pakete auch quittiert werden
  • Verlorene Pakete müssen erneut gesendet werden
    Fehlende Daten sind bei Audio/Video in Grenzen erlaubt aber bei Dokumenten und anderen Dateien ist eine 1:1 Übertragung erforderlich.
  • Wer zu schnell sendet, provoziert Paketverlust
    Denn auch Router haben nur begrenzte Buffer und verwerfen dann überzählige Pakete. Wenn ein Client 1 Megabyte per 1 Gigabit sendet aber der Router auf der anderen Seite gerade 1 MBit "frei" hat, dann müsste er das letzte Paket 10 Sekunden puffern. Der Absender hätte das Paket schon erneut gesendet und kein Router hält so lange ein Pakete in der Queue
  • Paketverlust erhöht die Datenmenge
    Jedes verlorene Paket muss erneut vom Sender übermittelt werden. Das kostet weiter Bandbreite aber auch die Protokolle zum Erkennen und neu Anfordern sind weitere Pakete, die sogar auch wieder verloren gehen können.
  • das "Netzwetter" ist nie statisch
    Es gibt ja auch Nachbarn, die die gleiche Verbindung nutzen und so muss eine Übertragung immer an die aktuellen Gegebenheiten angepasst werden.
  • Sei ein "fairer Teilnehmer"
    Wie im Straßenverkehr sollten sich alle Teilnehmer an Regeln halten. Es hilft nichts, wenn ein Client rücksichtslos Pakete sendet und damit die anderen Übertragungen verdrängt.
  • Sender kann nur indirekt über Latenz messen
    Ein Client hat normalerweise keine Information über die Belastung der einzelnen Teilstecken und selbst wenn er dieses Wissen hätte, kann er nicht vorhersehen, wie andere Teilnehmer darauf reagieren. Ein Client kann also nur anhand der Rückmeldung des Ziels ermitteln, ob der Versand angepasst werden muss.

Das einfache Paket

Ehe wir nun auf große Datenmengen über WAN kommen, schauen wir und einfach mal eine triviale TCP-Verbindung an, indem ich per TELNET eine Verbindung zu einem Webserver (teams.microsoft.com) verbunden habe und das Zeichen "a" sende. Zuerst kommt natürlich der TCP-Handshake mit TCP SYN ACK RES, ehe die Nutzdaten übertragen werden.

Das vierte Paket ist dann die Nutzlast mit dem "a", wie sie unten sehen und der Information, dass die Gegenseite dies bitte mit einem ACK=2 beantwortet. Das Paket 5 wird von meinem Client dann 26ms später auf die Reise gesendet und im Paket 6 kommt von der Gegenseite die Quittung zur Quittung an.

Sie sehen hier aber auch den "t1"-Timer auf meiner Seite. Mein Paket 1 von Client wird vom Server möglichst schnell bearbeitet aber noch kann er keine Antwort liefert. Daher quittiert er sc hon mal die Ankunft mit Q1 und mein Client sendet ein "q1 dazu weil er keine weiteren Daten in seinem Puffer hat. Der TCP-Stack auf meinem Client wartet aber etwas mit "q", denn wenn weitere Daten anliegen, dann kann er sich die Quittung sparen und einfach weiter senden.

Einfache Verluste

Diese Quittungen sind aber erforderlich, um mit Paketverlusten umgehen zu können. Es könnte ja passieren, dass schon mein erstes Nutzdatenpacket auf der Leitung verloren geht. Dann merkt der Empfänger das nicht.

Aber auf meinem Client läuft ein Timer t2, innerhalb dem ich eine Rückantwort des Servers erwarte. Wenn diese ausbleibt, dann ist das Paket ja wohl nicht angekommen und ich muss es noch mal senden. Der Wert für t2 ist aber nicht statisch, sondern TCP passt diesen laufend an die Laufzeit der Pakete an. Der Verlust kann auch auf dem Rückweg passieren. Wenn die Quittung ausbleibt, dann führt auch die zu einem Retransmit:

Damit wird schnell klar, dass Paketverluste in der Regel abgefangen werden, wenn die Rate nicht zu hoch wird. Wenn zu viele Pakete verloren gehen, dann reduziert der Sender immer weiter den Versand und irgendwann bricht die Verbindung auch ab.

Sammeltransport mit Windowsize

Es ist aber eher ungewöhnlich, dass einzelne Zeichen oder Pakete übertragen werden. Ein Ethernet-Packet kann zwar in der Regel 1514 Bytes groß werden aber durch Header aber out PPPoE, DSL, WAN-Beschränkungen auch kleiner sein. Wenn aber nun mehr Bytes anstehen als in ein Paket passen, werden die Daten aufgeteilt und in mehreren Paketen gesendet.

Würde wir nun aber nach jedem Paket auf eine Quittung warten, dann wäre der Durchsatz stark limitiert und die Leitung würde mit einer Verbindung gar nicht ausgelastet. Stellen Sie sich einfach mal vor, dass Sie eine Verbindung mit einer Paketlaufzeit (hin und zurück) von 10ms haben, was im WAN schon gut und im Internet unrealistisch ist. Dann könnten Sie ein Paket mit 1500 Bytes senden und 10ms danach nach Eingang der Quittung das nächste Paket auf die Reise schicken. Sie schaffen so also 100 Pakete pro Sekunde a 1500 Bytes. 150kByte/Sek ist kein akzeptabler Wert. Daher hat TCP schon von Anfang an mit Puffern und einem Übertragungsfenster (TCP Window Scaling, Latenz und Durchsatz) gearbeitet. Die Parameter zur Windowsize verhandeln die Endpunkte schon mit den ersten drei Paketen und können diese auch während der Übertragung immer wieder anpassen. Die Parameter sind je Richtung individuell. Im ersten Paket meldet der Sender an das Ziel was er im für den Rückweg anbietet:

Bei der Verbindung kann der Sender dann gemäß den Vorgaben des Empfängers auch mehrere Pakete in enger Folge senden ohne auf eine Quittung warten zu müssen:

Erst wenn eine gewisse Größe überschritten ist oder keine eingehenden Pakete mehr kommen, sendet der Empfänger dann eine Sammelquittung: Sie sehen das Recht einfach im WireShark, wenn eine Seite mehrere Pakete mit aufsteigender Sequenznummer sendet und die Gegenseite ab und an eine Quittung liefert.

Sie sehen hier aber auch, dass die Quittung nicht die Antwort auf das letzte Pakete ist. Aufgrund der Laufzeit kommt die Quittung auf ein Paket ja einige Millisekunden später an und der Sender möchte ja nicht warten.

SACK - Selective ACK

Nun kann es aber passieren dass ein oder mehrere Pakete verloren gehen. Die Übertragung von TCP ist genau genommen eine serielle Übertragung eines Bitdatenstroms. Der Empfänger sortiert eingehende Pakete in der richtigen Reihenfolge ein und liefert die Nutzdaten als Datenstrom an die Applikation. Der Empfänger quittiert immer die letzte Nummer der komplett empfangenes Byte. Das folgende Bild zeigt dann aber das Dilemma, wenn der Empfänger anhand der nachfolgenden Pakete erkennt, dass eines fehlt. Der Empfänger informiert den Sender aber nicht sofort, sondern wartet in der Regel drei weitere nachfolgende Pakete und eine gewisse Zeit ab, denn das "verlorene" Paket könnte ja einfach nur verspätet sein.

Der Empfänger bekommt ein oder mehrere Quittungen, die aber alle nur Paket 1 quittieren und daher muss der Sender die vergessenen Pakete neu senden. Das ist natürlich höchst ineffizient und daher gibt es die Methode des "Selective Ack", welches die beiden Partner aber bei der Verbindung auch aushandeln müssen:

Sobald dies aber klar, ist, sehen Sie im WireShark bei Paketverlusten dann folgende Pakete. Der Empfänger sendet mit jedem eingegangenen Paket wieder eine Quittung und der ACK-Wert ist weiterhin die Position des letzten Bytes, welches als vollständiger Stream empfangen wurde. Zusätzlich werden aber weitere empfangene "Blöcke" quittiert.

Der ACK bleibt hier bei 529054 stehen aber hinten sehen Sie, dass der "Right Edge" weiter hochzählt. Hier kommen also Quittungen an, die von WireShark als "TCP Dup ACK" gemeldet werden und dem Empfänger sagen, das alle Pakete bis zum Byte "529054" angekommen sind aber dann eine Lücke vorhanden ist. Es geht erst bei 530506 weiter und es kommen weitere nachfolgende Paket an. Hier fehlen also genau 1452 Bytes. Der Sender liefert die später nach. Bis zu vier Segmente sind in einem SACK-Report möglich.

WireShark Analysen

WireShark nimmt ihnen als Administrator viel Arbeit ab und insbesondere die TCP-Analysen zeigen sehr schnell eventuelle Probleme auf. Ich versuche natürlich zuerst einmal die betrachteten Pakete auf die Endpunkte (IP-Adresse und Ports) zu filtern und dann schaue ich weiter. Für Retransmissions und SACK sind. Die hier markierten Probleme sind hilfreich.

Die Zeilen werden aber auch entsprechend in der Übersicht farblich codiert. Sie können also sehr schnell die fraglichen Pakete erkennen. Besonders hilfreich finde ich dazu die Übersichtsleiste am rechten Rand, in der quasi jedes Paket als eine Pixelzeile in der Farbe erscheint. Sie sehen hier schon deutlich viele "schwarze" Bereiche und können so schnell an die relevanten Stellen springen aber auch Muster erkennen:

Hier sehen Sie dann auch, dass die Zeile 3,5,6 wieder melden, dass Pakete fehlen und der Sender diese dann nachliefert. Hier war es ein HTTP-Post an einen Webserver (Upload zu Port 443)

Paketloss überwachen

Nun sind sich nicht immer mit WireShark bewaffnet und der Anwender kann damit schon gar nicht umgehen. Aktive Tests wie End2End File, End2End für Skype for Business Network Assessment. können regelmäßigen Paketverlust teilweise ermitteln aber wenn ein Client 15MBit mit 1500byte Pakete überträgt, dann sind das 10.000 Pakete/Sek also 10 pro Millisekunde. Wenn ihr Netzwerk also nur 5ms "wackelt", dann kostet das 50 Pakete auf einen Schlag und der Client muss erst wieder die Verbindung reparieren und neu anfahren.

Es gehört ja dazu, bei solchen Verlusten erst einmal das Versenden neuer Pakete zu pausieren, bis die verlorenen Pakete nachgesendet werden. Das kann auch mal Sekunden dauern, bis die Verbindung wieder Fahrt aufgenommen hat. Das können Sie partiell bei einem "kopieren" im Explorer Dialog sehen.

Die Einbrüche hier könnten natürlich auch mit Engpässen beim Lesen oder Schreiben auf den Dateisystemen verbunden sein aber bei diesem Durchsatz von 160kbit/s ist das eher unwahrscheinlich. Es gibt nun mehrere Optionen, diese Retransmits zu überwachen anstatt eigene aktive Tests zu starten. Aktive Tests sind natürlich weiterhin wichtig um zumindest auch in den betriebsarmen Zeit ebenfalls Messwerte zu haben.

  • Performance Counter auf dem Client
    Perfmon ist ein sehr taugliches Werkzeug um zumindest einmal global die erneut übertragenen Pakete numerisch zu erfassen

    Diese Werte können natürlich auch per Software ermittelt werden. Leider ist keine getrennte Betrachtung nach Zielen oder Verbindungen möglich.
  • Ressoucemonitor
    Dieses Programm ermittelt deutlich mehr Details. Hier finden Sie jede TCP-Verbindung mit Daten zu Latenzzeit und PaketLoss

    Diese Daten werden aber wohl "generiert" und sind nicht per Perfmon/WMI einfach auszulesen. Details finden Sie dazu auch auf Windows TCP Connection Daten
  • Firwall/Router
    Zumindest Firewalls mit "stateful inspection" müssen die Pakete analysieren und in Reihe bringen. Diese Systeme sollten daher auch in der Lage sein pro Verbindung solche Kennzahlen zu ermitteln und bereit zu stellen. Leider kann ich hier noch nicht mit Beispielen dienen. In der Beschreibung zu NetFlow/SFlow finden sich aber Felder, die genau diese Information enthalten und andere Webseiten haben entsprechende Beispiele

Es gibt also durchaus im Netzwerk Möglichkeiten die "PaketLoss"-Raten von Verbindungen zu erfassen und als Fehlermelder zu nutzen.

Weitere Links