Zum Hauptinhalt springen

6. Paketverlusterkennung (Loss Detection)

Ein QUIC-Sender verwendet Bestätigungen (acknowledgments), um verlorene Pakete zu erkennen, und ein PTO, um sicherzustellen, dass Bestätigungen empfangen werden; siehe Abschnitt 6.2. Dieser Abschnitt bietet eine Beschreibung dieser Algorithmen.

Wenn ein Paket verloren geht, muss der QUIC-Transport von diesem Verlust wiederherstellen, beispielsweise durch erneute Übertragung der Daten, Senden eines aktualisierten Rahmens oder Aufgabe des Rahmens. Weitere Informationen finden Sie in Abschnitt 13.3 von [QUIC-TRANSPORT].

Die Paketverlusterkennung (loss detection) ist pro Paketnummernraum (per packet number space) getrennt, im Gegensatz zur RTT-Messung und Staukontrolle, da RTT und Staukontrolle Eigenschaften des Pfads sind, während die Paketverlusterkennung auch von der Schlüsselverfügbarkeit abhängt.


6.1. Bestätigungsbasierte Erkennung (Acknowledgment-Based Detection)

Die bestätigungsbasierte Paketverlusterkennung implementiert den Geist von TCPs schneller Neuübertragung (Fast Retransmit) [RFC5681], früher Neuübertragung (Early Retransmit) [RFC5827], Vorwärtsbestätigung (Forward Acknowledgment) [FACK], SACK-Verlustwiederherstellung [RFC6675] und RACK-TLP [RFC8985]. Dieser Abschnitt bietet einen Überblick darüber, wie diese Algorithmen in QUIC implementiert sind.

Ein Paket wird als verloren erklärt, wenn es alle folgenden Bedingungen erfüllt:

  • Das Paket ist unbestätigt, in Übertragung (in flight) und wurde vor einem bestätigten Paket gesendet.

  • Das Paket wurde kPacketThreshold Pakete vor einem bestätigten Paket gesendet (Abschnitt 6.1.1), oder es wurde vor ausreichend langer Zeit gesendet (Abschnitt 6.1.2).

Die Bestätigung zeigt an, dass ein später gesendetes Paket zugestellt wurde, und die Paket- und Zeitschwellen bieten eine gewisse Toleranz für die Neuordnung von Paketen.

Das fälschliche Erklären von Paketen als verloren führt zu unnötigen Neuübertragungen und kann aufgrund der Aktionen des Staukontrollers bei der Verlusterkennung zu einer Leistungsverschlechterung führen. Implementierungen können fehlerhafte Neuübertragungen erkennen und die Paket- oder Zeit-Neuordnungsschwelle erhöhen, um zukünftige fehlerhafte Neuübertragungen und Verlustereignisse zu reduzieren. Implementierungen mit adaptiven Zeitschwellen KÖNNEN wählen, mit kleineren anfänglichen Neuordnungsschwellen zu beginnen, um die Wiederherstellungslatenz zu minimieren.

6.1.1. Paketschwelle (Packet Threshold)

Der EMPFOHLENE (RECOMMENDED) Anfangswert für die Paket-Neuordnungsschwelle (kPacketThreshold) ist 3, basierend auf Best Practices für die TCP-Paketverlusterkennung [RFC5681] [RFC6675]. Um TCP ähnlich zu bleiben, SOLLTEN Implementierungen NICHT eine Paketschwelle kleiner als 3 verwenden; siehe [RFC5681].

Einige Netzwerke können höhere Grade an Paket-Neuordnung aufweisen, was dazu führt, dass der Sender fehlerhafte Verluste erkennt. Darüber hinaus könnte die Paket-Neuordnung bei QUIC häufiger auftreten als bei TCP, da Netzwerkelemente, die TCP-Pakete beobachten und neu ordnen könnten, dies bei QUIC nicht tun können und weil QUIC-Paketnummern verschlüsselt sind. Algorithmen, die die Neuordnungsschwelle nach fehlerhafter Verlusterkennung erhöhen, wie RACK [RFC8985], haben sich bei TCP als nützlich erwiesen und werden voraussichtlich bei QUIC mindestens genauso nützlich sein.

6.1.2. Zeitschwelle (Time Threshold)

Sobald ein späteres Paket innerhalb desselben Paketnummernraums bestätigt wurde, SOLLTE ein Endpunkt ein früheres Paket als verloren erklären, wenn es vor einem Schwellenwert-Zeitbetrag gesendet wurde. Um zu vermeiden, dass Pakete zu früh als verloren erklärt werden, MUSS diese Zeitschwelle mindestens auf die lokale Timer-Granularität eingestellt werden, wie durch die Konstante kGranularity angegeben. Die Zeitschwelle ist:

max(kTimeThreshold * max(smoothed_rtt, latest_rtt), kGranularity)

Wenn Pakete, die vor dem größten bestätigten Paket gesendet wurden, noch nicht als verloren erklärt werden können, SOLLTE ein Timer für die verbleibende Zeit eingestellt werden.

Die Verwendung von max(smoothed_rtt, latest_rtt) schützt vor den folgenden beiden Fällen:

  • die neueste RTT-Probe ist niedriger als die geglättete RTT, möglicherweise aufgrund einer Neuordnung, bei der die Bestätigung auf einen kürzeren Pfad gestoßen ist;

  • die neueste RTT-Probe ist höher als die geglättete RTT, möglicherweise aufgrund eines anhaltenden Anstiegs der tatsächlichen RTT, aber die geglättete RTT hat noch nicht aufgeholt.

Die EMPFOHLENE (RECOMMENDED) Zeitschwelle (kTimeThreshold), ausgedrückt als RTT-Multiplikator, ist 9/8. Der EMPFOHLENE (RECOMMENDED) Wert der Timer-Granularität (kGranularity) ist 1 Millisekunde.

Hinweis: TCPs RACK [RFC8985] spezifiziert eine etwas größere Schwelle, äquivalent zu 5/4, für einen ähnlichen Zweck. Die Erfahrung mit QUIC zeigt, dass 9/8 gut funktioniert.

Implementierungen KÖNNEN mit absoluten Schwellen, Schwellen aus früheren Verbindungen, adaptiven Schwellen oder Schwellen experimentieren, die die RTT-Variation einschließen. Kleinere Schwellen reduzieren die Neuordnungsresilienz und erhöhen fehlerhafte Neuübertragungen, und größere Schwellen erhöhen die Verlusterkennungsverzögerung.


6.2. Sonden-Timeout (Probe Timeout)

Ein Sonden-Timeout (PTO) löst das Senden von einem oder zwei Sonden-Datagrammen aus, wenn bestätigungsanfordernde Pakete (ack-eliciting packets) nicht innerhalb der erwarteten Zeitspanne bestätigt werden oder der Server die Adresse des Clients möglicherweise noch nicht validiert hat. Ein PTO ermöglicht es einer Verbindung, sich vom Verlust von End-Paketen oder Bestätigungen zu erholen.

Wie bei der Paketverlusterkennung ist das PTO pro Paketnummernraum (per packet number space). Das heißt, ein PTO-Wert wird für jeden Paketnummernraum berechnet.

Ein PTO-Timer-Ablaufereignis zeigt keinen Paketverlust an und DARF NICHT dazu führen, dass zuvor unbestätigte Pakete als verloren markiert werden. Wenn eine Bestätigung für ein neu bestätigungsanforderndes Paket empfangen wird, erfolgt die Paketverlusterkennung gemäß den Paket- und Zeitschwellenmechanismen; siehe Abschnitt 6.1.

Der in QUIC verwendete PTO-Algorithmus implementiert die Zuverlässigkeitsfunktionen von Tail Loss Probe [RFC8985], RTO [RFC5681] und F-RTO-Algorithmen für TCP [RFC5682]. Die Timeout-Berechnung basiert auf TCPs RTO-Periode [RFC6298].

6.2.1. Berechnung des PTO (Computing PTO)

Wenn ein bestätigungsanforderndes Paket übertragen wird, plant der Sender einen Timer für die PTO-Periode wie folgt:

PTO = smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay

Die PTO-Periode ist die Zeitspanne, die ein Sender auf eine Bestätigung eines gesendeten Pakets warten sollte. Diese Zeitspanne umfasst die geschätzte Netzwerk-RTT (smoothed_rtt), die Variation in der Schätzung (4*rttvar) und max_ack_delay, um die maximale Zeit zu berücksichtigen, um die ein Empfänger das Senden einer Bestätigung verzögern könnte.

Wenn das PTO für Initial- oder Handshake-Paketnummernräume gesetzt wird, wird das max_ack_delay in der PTO-Periodenberechnung auf 0 gesetzt, da erwartet wird, dass der Peer diese Pakete nicht absichtlich verzögert; siehe Abschnitt 13.2.1 von [QUIC-TRANSPORT].

Die PTO-Periode MUSS mindestens kGranularity betragen, um zu vermeiden, dass der Timer sofort abläuft.

Wenn bestätigungsanfordernde Pakete in mehreren Paketnummernräumen in Übertragung sind, MUSS der Timer auf den früheren Wert der Initial- und Handshake-Paketnummernräume eingestellt werden.

Ein Endpunkt DARF NICHT seinen PTO-Timer für den Anwendungsdaten-Paketnummernraum setzen, bis der Handshake bestätigt ist. Dies verhindert, dass der Endpunkt Informationen in Paketen neu überträgt, wenn entweder der Peer noch nicht die Schlüssel hat, um sie zu verarbeiten, oder der Endpunkt noch nicht die Schlüssel hat, um ihre Bestätigungen zu verarbeiten. Zum Beispiel kann dies passieren, wenn ein Client 0-RTT-Pakete an den Server sendet; er tut dies, ohne zu wissen, ob der Server sie entschlüsseln kann. Ähnlich kann dies passieren, wenn ein Server 1-RTT-Pakete sendet, bevor er bestätigt, dass der Client das Zertifikat des Servers verifiziert hat und daher diese 1-RTT-Pakete lesen kann.

Ein Sender SOLLTE seinen PTO-Timer jedes Mal neu starten, wenn ein bestätigungsanforderndes Paket gesendet oder bestätigt wird, oder wenn Initial- oder Handshake-Schlüssel verworfen werden (Abschnitt 4.9 von [QUIC-TLS]). Dies stellt sicher, dass das PTO immer basierend auf der neuesten Schätzung der RTT und für das richtige Paket über Paketnummernräume hinweg gesetzt wird.

Wenn ein PTO-Timer abläuft, MUSS der PTO-Backoff erhöht werden, was dazu führt, dass die PTO-Periode auf das Doppelte ihres aktuellen Werts eingestellt wird. Der PTO-Backoff-Faktor wird zurückgesetzt, wenn eine Bestätigung empfangen wird, außer im folgenden Fall. Ein Server könnte während des Handshakes länger brauchen, um auf Pakete zu antworten als sonst. Um einen solchen Server vor wiederholten Client-Sonden zu schützen, wird der PTO-Backoff bei einem Client nicht zurückgesetzt, der noch nicht sicher ist, dass der Server die Validierung der Adresse des Clients abgeschlossen hat. Das heißt, ein Client setzt den PTO-Backoff-Faktor beim Empfang von Bestätigungen in Initial-Paketen nicht zurück.

Diese exponentielle Reduzierung der Sender-Rate ist wichtig, da aufeinanderfolgende PTOs durch Verlust von Paketen oder Bestätigungen aufgrund schwerer Stauung verursacht werden können. Selbst wenn bestätigungsanfordernde Pakete in mehreren Paketnummernräumen in Übertragung sind, erfolgt die exponentielle Erhöhung des PTO über alle Räume, um übermäßige Belastung des Netzwerks zu verhindern. Zum Beispiel verdoppelt ein Timeout im Initial-Paketnummernraum die Länge des Timeouts im Handshake-Paketnummernraum.

Die Gesamtlänge der Zeit, über die aufeinanderfolgende PTO-Abläufe auftreten, ist durch den Leerlauf-Timeout (idle timeout) begrenzt.

Der PTO-Timer DARF NICHT gesetzt werden, wenn ein Timer für die Zeitschwellen-Paketverlusterkennung gesetzt ist; siehe Abschnitt 6.1.2. Ein Timer, der für die Zeitschwellen-Paketverlusterkennung gesetzt ist, läuft in den meisten Fällen früher ab als der PTO-Timer und ist weniger wahrscheinlich, Daten fehlerhaft neu zu übertragen.

6.2.2. Handshakes und neue Pfade (Handshakes and New Paths)

Wiederaufgenommene Verbindungen über dasselbe Netzwerk KÖNNEN den endgültigen geglätteten RTT-Wert der vorherigen Verbindung als anfängliche RTT der wiederaufgenommenen Verbindung verwenden. Wenn keine vorherige RTT verfügbar ist, SOLLTE die anfängliche RTT auf 333 Millisekunden eingestellt werden. Dies führt dazu, dass Handshakes mit einem PTO von 1 Sekunde beginnen, wie für TCPs anfängliches RTO empfohlen; siehe Abschnitt 2 von [RFC6298].

Eine Verbindung KANN die Verzögerung zwischen dem Senden eines PATH_CHALLENGE und dem Empfang einer PATH_RESPONSE verwenden, um die anfängliche RTT für einen neuen Pfad zu setzen (siehe kInitialRtt in Anhang A.2), aber die Verzögerung SOLLTE NICHT als RTT-Probe betrachtet werden.

Wenn Initial- und Handshake-Schlüssel verworfen werden (siehe Abschnitt 6.4), können alle Initial-Pakete und Handshake-Pakete nicht mehr bestätigt werden, daher werden sie aus den in Übertragung befindlichen Bytes (bytes in flight) entfernt. Die PTO- und Verlusterkennungs-Timer MÜSSEN zurückgesetzt werden, da das Verwerfen von Schlüsseln einen Fortschritt anzeigt und der Verlusterkennungs-Timer möglicherweise für einen jetzt verworfenen Paketnummernraum gesetzt wurde.

6.2.2.1. Vor der Adressvalidierung (Before Address Validation)

Bis der Server die Adresse des Clients auf dem Pfad validiert hat, ist die Menge der Daten, die er senden kann, auf das Dreifache der empfangenen Datenmenge begrenzt, wie in Abschnitt 8.1 von [QUIC-TRANSPORT] angegeben. Wenn keine zusätzlichen Daten gesendet werden können, DARF der PTO-Timer des Servers NICHT gesetzt werden, bis Datagramme vom Client empfangen wurden, da auf PTO gesendete Pakete auf das Anti-Amplifikationslimit angerechnet werden.

Wenn ein Server ein Datagramm vom Client empfängt, wird das Amplifikationslimit erhöht und der Server setzt den PTO-Timer zurück. Wenn der PTO-Timer dann auf eine Zeit in der Vergangenheit eingestellt ist, wird er sofort ausgeführt. Dies vermeidet das Senden neuer 1-RTT-Pakete vor Paketen, die für den Abschluss des Handshakes kritisch sind. Insbesondere kann dies passieren, wenn 0-RTT akzeptiert wird, aber der Server die Adresse des Clients nicht validieren kann.

Da der Server blockiert sein könnte, bis weitere Datagramme vom Client empfangen werden, liegt es in der Verantwortung des Clients, Pakete zu senden, um den Server zu entsperren, bis er sicher ist, dass der Server seine Adressvalidierung abgeschlossen hat (siehe Abschnitt 8 von [QUIC-TRANSPORT]). Das heißt, der Client MUSS den PTO-Timer setzen, wenn der Client keine Bestätigung für eines seiner Handshake-Pakete erhalten hat und der Handshake nicht bestätigt ist (siehe Abschnitt 4.1.2 von [QUIC-TLS]), auch wenn keine Pakete in Übertragung sind. Wenn das PTO ausgelöst wird, MUSS der Client ein Handshake-Paket senden, wenn er Handshake-Schlüssel hat, andernfalls MUSS er ein Initial-Paket in einem UDP-Datagramm mit einer Nutzlast von mindestens 1200 Bytes senden.

6.2.3. Beschleunigung des Handshake-Abschlusses (Speeding up Handshake Completion)

Wenn ein Server ein Initial-Paket mit doppelten CRYPTO-Daten empfängt, kann er annehmen, dass der Client nicht alle CRYPTO-Daten des Servers empfangen hat, die in Initial-Paketen gesendet wurden, oder dass die geschätzte RTT des Clients zu klein ist. Wenn ein Client Handshake- oder 1-RTT-Pakete empfängt, bevor er Handshake-Schlüssel erhält, kann er annehmen, dass einige oder alle Initial-Pakete des Servers verloren gegangen sind.

Um den Handshake-Abschluss unter diesen Bedingungen zu beschleunigen, KANN ein Endpunkt, für eine begrenzte Anzahl von Malen pro Verbindung, ein Paket mit unbestätigten CRYPTO-Daten früher als der PTO-Ablauf senden, vorbehaltlich der Adressvalidierungsgrenzen in Abschnitt 8.1 von [QUIC-TRANSPORT]. Dies höchstens einmal pro Verbindung zu tun, ist ausreichend, um sich schnell von einem einzelnen Paketverlust zu erholen. Ein Endpunkt, der immer Pakete als Reaktion auf den Empfang von Paketen neu überträgt, die er nicht verarbeiten kann, riskiert die Erzeugung eines unendlichen Paketaustauschs.

Ein Endpunkt kann auch zusammengefügte Pakete verwenden (siehe Abschnitt 12.2 von [QUIC-TRANSPORT]), um sicherzustellen, dass jedes Datagramm mindestens eine Bestätigung hervorruft. Zum Beispiel kann ein Client ein Initial-Paket mit PING- und PADDING-Rahmen mit einem 0-RTT-Datenpaket zusammenfügen, und ein Server kann ein Initial-Paket mit einem PING-Rahmen mit einem oder mehreren Paketen in seinem ersten Flug zusammenfügen.

6.2.4. Senden von Sonden-Paketen (Sending Probe Packets)

Wenn ein PTO-Timer abläuft, MUSS ein Sender mindestens ein bestätigungsanforderndes Paket im Paketnummernraum als Sonde senden. Ein Endpunkt KANN bis zu zwei vollständige Datagramme mit bestätigungsanfordernden Paketen senden, um einen teuren aufeinanderfolgenden PTO-Ablauf aufgrund eines einzigen verlorenen Datagramms zu vermeiden oder um Daten aus mehreren Paketnummernräumen zu übertragen. Alle auf einem PTO gesendeten Sonden-Pakete MÜSSEN bestätigungsanfordernd sein.

Zusätzlich zum Senden von Daten im Paketnummernraum, für den der Timer abgelaufen ist, SOLLTE der Sender bestätigungsanfordernde Pakete aus anderen Paketnummernräumen mit in Übertragung befindlichen Daten senden und Pakete wenn möglich zusammenfügen. Dies ist besonders wertvoll, wenn der Server sowohl Initial- als auch Handshake-Daten in Übertragung hat oder wenn der Client sowohl Handshake- als auch Anwendungsdaten in Übertragung hat, da der Peer möglicherweise nur Empfangsschlüssel für einen der beiden Paketnummernräume hat.

Wenn der Sender eine schnellere Bestätigung bei PTO hervorrufen möchte, kann er eine Paketnummer überspringen, um die Bestätigungsverzögerung zu eliminieren.

Ein Endpunkt SOLLTE neue Daten in Pakete einschließen, die bei PTO-Ablauf gesendet werden. Zuvor gesendete Daten KÖNNEN gesendet werden, wenn keine neuen Daten gesendet werden können. Implementierungen KÖNNEN alternative Strategien zur Bestimmung des Inhalts von Sonden-Paketen verwenden, einschließlich des Sendens neuer oder neu übertragener Daten basierend auf den Prioritäten der Anwendung.

Ein Sender hat möglicherweise keine neuen oder zuvor gesendeten Daten zu senden. Betrachten Sie als Beispiel die folgende Ereignisabfolge: neue Anwendungsdaten werden in einem STREAM-Rahmen gesendet, als verloren betrachtet, dann in einem neuen Paket neu übertragen, und dann wird die ursprüngliche Übertragung bestätigt. Wenn keine Daten zu senden sind, SOLLTE der Sender einen PING- oder einen anderen bestätigungsanfordernden Rahmen in einem einzigen Paket senden und den PTO-Timer neu setzen.

Alternativ KANN der Sender, anstatt ein bestätigungsanforderndes Paket zu senden, alle noch in Übertragung befindlichen Pakete als verloren markieren. Dies vermeidet das Senden eines zusätzlichen Pakets, erhöht aber das Risiko, Pakete fehlerhaft als verloren zu erklären, was zu einer unnötigen Ratenreduzierung durch den Staukontroller führt.

Aufeinanderfolgende PTO-Perioden steigen exponentiell an, und infolgedessen steigt die Verbindungswiederherstellungslatenz exponentiell an, während Pakete weiterhin im Netzwerk verworfen werden. Das Senden von zwei Paketen bei PTO-Ablauf erhöht die Resilienz gegenüber Paketverlusten und reduziert somit die Wahrscheinlichkeit aufeinanderfolgender PTO-Ereignisse.

Wenn der PTO-Timer mehrmals abläuft und neue Daten nicht gesendet werden können, müssen Implementierungen zwischen dem Senden derselben Nutzlast jedes Mal oder dem Senden unterschiedlicher Nutzlasten wählen. Das Senden derselben Nutzlast jedes Mal kann einfacher sein und stellt sicher, dass die Rahmen mit der höchsten Priorität zuerst ankommen. Das Senden unterschiedlicher Nutzlasten jedes Mal reduziert die Chancen fehlerhafter Neuübertragungen.


6.3. Behandlung von Retry-Paketen (Handling Retry Packets)

Ein Retry-Paket veranlasst einen Client, ein weiteres Initial-Paket zu senden, wodurch der Verbindungsprozess effektiv neu gestartet wird. Ein Retry-Paket zeigt an, dass das Initial-Paket empfangen, aber nicht verarbeitet wurde. Ein Retry-Paket kann nicht als Bestätigung behandelt werden, da es nicht anzeigt, dass ein Paket verarbeitet wurde, oder die Paketnummer angibt.

Clients, die ein Retry-Paket empfangen, setzen den Staukontroll- und Verlustwiederherstellungsstatus zurück, einschließlich des Zurücksetzens aller ausstehenden Timer. Andere Verbindungsstatus, insbesondere kryptografische Handshake-Nachrichten, werden beibehalten; siehe Abschnitt 17.2.5 von [QUIC-TRANSPORT].

Der Client KANN die Zeitspanne vom Senden des ersten Initial-Pakets bis zum Empfang eines Retry- oder Versionsverhandlungspakets als RTT-Schätzung zum Server berechnen. Der Client KANN diesen Wert anstelle seines Standardwerts für die anfängliche RTT-Schätzung verwenden.


6.4. Verwerfen von Schlüsseln und Paketstatus (Discarding Keys and Packet State)

Wenn Initial- und Handshake-Paketschutzschlüssel verworfen werden (siehe Abschnitt 4.9 von [QUIC-TLS]), können alle mit diesen Schlüsseln gesendeten Pakete nicht mehr bestätigt werden, da ihre Bestätigungen nicht verarbeitet werden können. Der Sender MUSS alle mit diesen Paketen verbundenen Wiederherstellungsstatus verwerfen und MUSS sie aus der Anzahl der in Übertragung befindlichen Bytes (bytes in flight) entfernen.

Endpunkte beenden das Senden und Empfangen von Initial-Paketen, sobald sie mit dem Austausch von Handshake-Paketen beginnen; siehe Abschnitt 17.2.2.1 von [QUIC-TRANSPORT]. Zu diesem Zeitpunkt wird der Wiederherstellungsstatus für alle in Übertragung befindlichen Initial-Pakete verworfen.

Wenn 0-RTT abgelehnt wird, wird der Wiederherstellungsstatus für alle in Übertragung befindlichen 0-RTT-Pakete verworfen.

Wenn ein Server 0-RTT akzeptiert, aber 0-RTT-Pakete, die vor Initial-Paketen ankommen, nicht puffert, werden frühe 0-RTT-Pakete als verloren erklärt, aber dies wird voraussichtlich selten sein.

Es wird erwartet, dass Schlüssel zu einem Zeitpunkt nach der Bestätigung oder Verlustdeklaration der mit ihnen verschlüsselten Pakete verworfen werden. Initial- und Handshake-Geheimnisse werden jedoch verworfen, sobald Handshake- und 1-RTT-Schlüssel sowohl für Client als auch Server als verfügbar nachgewiesen sind; siehe Abschnitt 4.9.1 von [QUIC-TLS].