7. Staukontrolle (Congestion Control)
Dieses Dokument spezifiziert einen senderseitigen Staukontroller für QUIC, ähnlich TCP NewReno [RFC6582].
Die Signale, die QUIC für die Staukontrolle bereitstellt, sind generisch und darauf ausgelegt, verschiedene senderseitige Algorithmen zu unterstützen. Ein Sender kann einseitig wählen, einen anderen Algorithmus zu verwenden, wie z.B. CUBIC [RFC8312].
Wenn ein Sender einen anderen Controller als den in diesem Dokument spezifizierten verwendet, MUSS der gewählte Controller den Staukontroll-Richtlinien entsprechen, die in Abschnitt 3.1 von [RFC8085] spezifiziert sind.
Ähnlich wie bei TCP zählen Pakete, die nur ACK-Rahmen enthalten, nicht zu den in Übertragung befindlichen Bytes (bytes in flight) und werden nicht durch Staukontrolle gesteuert. Im Gegensatz zu TCP kann QUIC den Verlust dieser Pakete erkennen und KANN diese Information verwenden, um den Staukontroller oder die Rate der reinen ACK-Pakete anzupassen, aber dieses Dokument beschreibt keinen Mechanismus dafür.
Der Staukontroller ist pro Pfad (per path), daher ändern auf anderen Pfaden gesendete Pakete nicht den Staukontroller des aktuellen Pfads, wie in Abschnitt 9.4 von [QUIC-TRANSPORT] beschrieben.
Der Algorithmus in diesem Dokument spezifiziert und verwendet das Staufenster des Controllers in Bytes.
Ein Endpunkt DARF NICHT ein Paket senden, wenn es dazu führen würde, dass bytes_in_flight (siehe Anhang B.2) größer als das Staufenster wäre, es sei denn, das Paket wird bei Ablauf eines PTO-Timers gesendet (siehe Abschnitt 6.2) oder beim Eintreten in die Erholungsphase (siehe Abschnitt 7.3.2).
7.1. Explizite Staubenachrichtigung (Explicit Congestion Notification)
Wenn ein Pfad validiert wurde, um explizite Staubenachrichtigung (ECN) [RFC3168] [RFC8311] zu unterstützen, behandelt QUIC einen Congestion Experienced (CE) Codepoint im IP-Header als Signal für Stau. Dieses Dokument spezifiziert die Reaktion eines Endpunkts, wenn die vom Peer gemeldete ECN-CE-Zählung zunimmt; siehe Abschnitt 13.4.2 von [QUIC-TRANSPORT].
7.2. Anfängliches und minimales Staufenster (Initial and Minimum Congestion Window)
QUIC beginnt jede Verbindung im langsamen Start (slow start) mit dem auf einen Anfangswert gesetzten Staufenster. Endpunkte SOLLTEN ein anfängliches Staufenster vom Zehnfachen der maximalen Datagrammgröße (max_datagram_size) verwenden, während das Fenster auf den größeren Wert von 14.720 Bytes oder das Zweifache der maximalen Datagrammgröße begrenzt wird. Dies folgt der Analyse und den Empfehlungen in [RFC6928] und erhöht das Byte-Limit, um den kleineren 8-Byte-Overhead von UDP im Vergleich zum 20-Byte-Overhead für TCP zu berücksichtigen.
Wenn sich die maximale Datagrammgröße während der Verbindung ändert, SOLLTE das anfängliche Staufenster mit der neuen Größe neu berechnet werden. Wenn die maximale Datagrammgröße verringert wird, um den Handshake abzuschließen, SOLLTE das Staufenster auf das neue anfängliche Staufenster gesetzt werden.
Vor der Validierung der Adresse des Clients kann der Server durch die Anti-Amplifikationsgrenze weiter eingeschränkt werden, wie in Abschnitt 8.1 von [QUIC-TRANSPORT] spezifiziert. Obwohl die Anti-Amplifikationsgrenze verhindern kann, dass das Staufenster vollständig genutzt wird und daher die Erhöhung des Staufensters verlangsamt, beeinflusst sie das Staufenster nicht direkt.
Das minimale Staufenster ist der kleinste Wert, den das Staufenster als Reaktion auf Verlust, eine Erhöhung der vom Peer gemeldeten ECN-CE-Zählung oder anhaltende Überlastung erreichen kann. Der EMPFOHLENE Wert ist 2 * max_datagram_size.
7.3. Staukontrollzustände (Congestion Control States)
Der in diesem Dokument beschriebene NewReno-Staukontroller hat drei verschiedene Zustände, wie in Abbildung 1 dargestellt.
Neuer Pfad oder +------------+
anhaltende Überlastung | Langsamer |
(O)----------------------> | Start |
+------------+
|
Verlust oder
ECN-CE Erhöhung
|
v
+------------+ Verlust oder +------------+
| Stau- | ECN-CE Erhöhung | Erholungs- |
| vermeidung |-------------------->| periode |
+------------+ +------------+
^ |
| |
+--------------------------------+
Bestätigung von Paket, das
während Erholung gesendet wurde
Abbildung 1: Staukontrollzustände und Übergänge
Diese Zustände und die Übergänge zwischen ihnen werden in den nachfolgenden Abschnitten beschrieben.
7.3.1. Langsamer Start (Slow Start)
Ein NewReno-Sender befindet sich im langsamen Start, wenn das Staufenster unterhalb der Schwelle für den langsamen Start liegt. Ein Sender beginnt im langsamen Start, weil die Schwelle für den langsamen Start auf einen unendlichen Wert initialisiert wird.
Während sich ein Sender im langsamen Start befindet, erhöht sich das Staufenster um die Anzahl der bestätigten Bytes, wenn jede Bestätigung verarbeitet wird. Dies führt zu einem exponentiellen Wachstum des Staufensters.
Der Sender MUSS den langsamen Start verlassen und in eine Erholungsperiode eintreten, wenn ein Paket verloren geht oder wenn die von seinem Peer gemeldete ECN-CE-Zählung zunimmt.
Ein Sender tritt erneut in den langsamen Start ein, wenn das Staufenster kleiner als die Schwelle für den langsamen Start ist, was nur nach Erklärung anhaltender Überlastung auftritt.
7.3.2. Erholung (Recovery)
Ein NewReno-Sender tritt in eine Erholungsperiode ein, wenn er den Verlust eines Pakets erkennt oder wenn die von seinem Peer gemeldete ECN-CE-Zählung zunimmt. Ein Sender, der sich bereits in einer Erholungsperiode befindet, bleibt darin und tritt nicht erneut ein.
Beim Eintreten in eine Erholungsperiode MUSS ein Sender die Schwelle für den langsamen Start auf die Hälfte des Werts des Staufensters setzen, wenn Verlust erkannt wird. Das Staufenster MUSS auf den reduzierten Wert der Schwelle für den langsamen Start gesetzt werden, bevor die Erholungsperiode verlassen wird.
Implementierungen KÖNNEN das Staufenster sofort beim Eintreten in eine Erholungsperiode reduzieren oder andere Mechanismen verwenden, wie z.B. Proportional Rate Reduction [PRR], um das Staufenster allmählicher zu reduzieren. Wenn das Staufenster sofort reduziert wird, kann ein einzelnes Paket vor der Reduzierung gesendet werden. Dies beschleunigt die Verlustwiederherstellung, wenn die Daten im verlorenen Paket erneut übertragen werden, und ist ähnlich wie TCP, wie in Abschnitt 5 von [RFC6675] beschrieben.
Die Erholungsperiode zielt darauf ab, die Reduzierung des Staufensters auf einmal pro Rundreise zu begrenzen. Daher ändert sich das Staufenster während einer Erholungsperiode nicht als Reaktion auf neue Verluste oder Erhöhungen der ECN-CE-Zählung.
Eine Erholungsperiode endet und der Sender tritt in die Stauvermeidung ein, wenn ein während der Erholungsperiode gesendetes Paket bestätigt wird. Dies unterscheidet sich geringfügig von TCPs Definition der Erholung, die endet, wenn das verlorene Segment, das die Erholung gestartet hat, bestätigt wird [RFC5681].
7.3.3. Stauvermeidung (Congestion Avoidance)
Ein NewReno-Sender befindet sich in Stauvermeidung, wenn das Staufenster gleich oder größer als die Schwelle für den langsamen Start ist und sich nicht in einer Erholungsperiode befindet.
Ein Sender in Stauvermeidung verwendet einen Additive Increase Multiplicative Decrease (AIMD)-Ansatz, der die Erhöhung des Staufensters auf höchstens eine maximale Datagrammgröße für jedes bestätigte Staufenster begrenzen MUSS.
Der Sender verlässt die Stauvermeidung und tritt in eine Erholungsperiode ein, wenn ein Paket verloren geht oder wenn die von seinem Peer gemeldete ECN-CE-Zählung zunimmt.
7.4. Ignorieren des Verlusts nicht entschlüsselbarer Pakete (Ignoring Loss of Undecryptable Packets)
Während des Handshakes sind möglicherweise einige Paketschutzschlüssel nicht verfügbar, wenn ein Paket ankommt, und der Empfänger kann wählen, das Paket zu verwerfen. Insbesondere können Handshake- und 0-RTT-Pakete nicht verarbeitet werden, bis die Initial-Pakete ankommen, und 1-RTT-Pakete können nicht verarbeitet werden, bis der Handshake abgeschlossen ist. Endpunkte KÖNNEN den Verlust von Handshake-, 0-RTT- und 1-RTT-Paketen ignorieren, die möglicherweise angekommen sind, bevor der Peer Paketschutzschlüssel hatte, um diese Pakete zu verarbeiten. Endpunkte DÜRFEN NICHT den Verlust von Paketen ignorieren, die nach dem frühesten bestätigten Paket in einem gegebenen Paketnummernraum gesendet wurden.
7.5. Sonden-Timeout (Probe Timeout)
Sondenpakete DÜRFEN NICHT durch den Staukontroller blockiert werden. Ein Sender MUSS diese Pakete jedoch als zusätzlich in Übertragung zählen, da diese Pakete Netzwerklast hinzufügen, ohne Paketverlust festzustellen. Beachten Sie, dass das Senden von Sondenpaketen dazu führen kann, dass die in Übertragung befindlichen Bytes des Senders das Staufenster überschreiten, bis eine Bestätigung empfangen wird, die Verlust oder Zustellung von Paketen feststellt.
7.6. Anhaltende Überlastung (Persistent Congestion)
Wenn ein Sender feststellt, dass alle über eine ausreichend lange Dauer gesendeten Pakete verloren gegangen sind, wird angenommen, dass das Netzwerk anhaltende Überlastung erfährt.
7.6.1. Dauer (Duration)
Die Dauer der anhaltenden Überlastung wird wie folgt berechnet:
(smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay) * kPersistentCongestionThreshold
Im Gegensatz zur PTO-Berechnung in Abschnitt 6.2 umfasst diese Dauer max_ack_delay unabhängig von den Paketnummernräumen, in denen Verluste festgestellt werden.
Diese Dauer ermöglicht es einem Sender, so viele Pakete zu senden, bevor anhaltende Überlastung festgestellt wird, einschließlich einiger als Reaktion auf PTO-Ablauf, wie TCP es mit Tail Loss Probes [RFC8985] und einem RTO [RFC5681] tut.
Größere Werte von kPersistentCongestionThreshold führen dazu, dass der Sender weniger reaktiv auf anhaltende Überlastung im Netzwerk wird, was zu aggressivem Senden in ein überlastetes Netzwerk führen kann. Ein zu kleiner Wert kann dazu führen, dass ein Sender unnötigerweise anhaltende Überlastung erklärt, was zu reduziertem Durchsatz für den Sender führt.
Der EMPFOHLENE Wert für kPersistentCongestionThreshold ist 3, was zu einem Verhalten führt, das ungefähr einem TCP-Sender entspricht, der ein RTO nach zwei TLPs erklärt.
Dieses Design verwendet keine aufeinanderfolgenden PTO-Ereignisse, um anhaltende Überlastung festzustellen, da Anwendungsmuster den PTO-Ablauf beeinflussen. Beispielsweise startet ein Sender, der kleine Datenmengen mit Stilleperioden dazwischen sendet, den PTO-Timer jedes Mal neu, wenn er sendet, wodurch möglicherweise verhindert wird, dass der PTO-Timer über einen langen Zeitraum abläuft, selbst wenn keine Bestätigungen empfangen werden. Die Verwendung einer Dauer ermöglicht es einem Sender, anhaltende Überlastung festzustellen, ohne vom PTO-Ablauf abhängig zu sein.
7.6.2. Feststellen anhaltender Überlastung (Establishing Persistent Congestion)
Ein Sender stellt nach Erhalt einer Bestätigung anhaltende Überlastung fest, wenn zwei bestätigungsanfordernde Pakete als verloren erklärt werden und:
-
über alle Paketnummernräume hinweg keines der zwischen den Sendezeiten dieser beiden Pakete gesendeten Pakete bestätigt wird;
-
die Dauer zwischen den Sendezeiten dieser beiden Pakete die Dauer der anhaltenden Überlastung überschreitet (Abschnitt 7.6.1); und
-
eine frühere RTT-Probe existierte, als diese beiden Pakete gesendet wurden.
Diese beiden Pakete MÜSSEN bestätigungsanfordernd sein, da ein Empfänger verpflichtet ist, nur bestätigungsanfordernde Pakete innerhalb seiner maximalen Bestätigungsverzögerung zu bestätigen; siehe Abschnitt 13.2 von [QUIC-TRANSPORT].
Die Periode anhaltender Überlastung SOLLTE NICHT beginnen, bis mindestens eine RTT-Probe vorliegt. Vor der ersten RTT-Probe setzt ein Sender seinen PTO-Timer basierend auf der anfänglichen RTT (Abschnitt 6.2.2), die wesentlich größer als die tatsächliche RTT sein könnte. Das Erfordernis einer früheren RTT-Probe verhindert, dass ein Sender anhaltende Überlastung mit möglicherweise zu wenigen Sonden feststellt.
Da Netzwerküberlastung nicht von Paketnummernräumen beeinflusst wird, SOLLTE anhaltende Überlastung Pakete berücksichtigen, die über Paketnummernräume hinweg gesendet wurden. Ein Sender, der keinen Zustand für alle Paketnummernräume hat, oder eine Implementierung, die Sendezeiten nicht über Paketnummernräume hinweg vergleichen kann, KANN nur den Zustand für den gerade bestätigten Paketnummernraum verwenden. Dies könnte zu einer fehlerhaften Erklärung anhaltender Überlastung führen, führt aber nicht zu einem Versagen bei der Erkennung anhaltender Überlastung.
Wenn anhaltende Überlastung erklärt wird, MUSS das Staufenster des Senders auf das minimale Staufenster (kMinimumWindow) reduziert werden, ähnlich der Reaktion eines TCP-Senders auf ein RTO [RFC5681].
7.6.3. Beispiel (Example)
Das folgende Beispiel veranschaulicht, wie ein Sender anhaltende Überlastung feststellen könnte. Annahme:
smoothed_rtt + max(4*rttvar, kGranularity) + max_ack_delay = 2
kPersistentCongestionThreshold = 3
Betrachten Sie die folgende Ereignissequenz:
| Zeit | Aktion |
|---|---|
| t=0 | Paket #1 senden (Anwendungsdaten) |
| t=1 | Paket #2 senden (Anwendungsdaten) |
| t=1.2 | Bestätigung von #1 empfangen |
| t=2 | Paket #3 senden (Anwendungsdaten) |
| t=3 | Paket #4 senden (Anwendungsdaten) |
| t=4 | Paket #5 senden (Anwendungsdaten) |
| t=5 | Paket #6 senden (Anwendungsdaten) |
| t=6 | Paket #7 senden (Anwendungsdaten) |
| t=8 | Paket #8 senden (PTO 1) |
| t=12 | Paket #9 senden (PTO 2) |
| t=12.2 | Bestätigung von #9 empfangen |
Pakete 2 bis 8 werden als verloren erklärt, wenn die Bestätigung für Paket 9 bei t = 12.2 empfangen wird.
Die Überlastungsperiode wird als die Zeit zwischen den ältesten und neuesten verlorenen Paketen berechnet: 8 - 1 = 7. Die Dauer der anhaltenden Überlastung beträgt 2 * 3 = 6. Da die Schwelle erreicht wurde und keines der Pakete zwischen den ältesten und neuesten verlorenen Paketen bestätigt wurde, wird angenommen, dass das Netzwerk anhaltende Überlastung erfahren hat.
Obwohl dieses Beispiel PTO-Abläufe zeigt, sind sie nicht erforderlich, damit anhaltende Überlastung festgestellt wird.
7.7. Taktung (Pacing)
Ein Sender SOLLTE das Senden aller in Übertragung befindlichen Pakete basierend auf der Eingabe des Staukontrollers takten.
Das Senden mehrerer Pakete ins Netzwerk ohne Verzögerung zwischen ihnen erzeugt einen Paket-Burst, der kurzfristige Überlastung und Verluste verursachen könnte. Sender MÜSSEN entweder Taktung verwenden oder solche Bursts begrenzen. Sender SOLLTEN Bursts auf das anfängliche Staufenster begrenzen; siehe Abschnitt 7.2. Ein Sender mit Kenntnis darüber, dass der Netzwerkpfad zum Empfänger größere Bursts absorbieren kann, KANN eine höhere Grenze verwenden.
Eine Implementierung sollte darauf achten, ihren Staukontroller so zu gestalten, dass er gut mit einem Taktgeber funktioniert. Beispielsweise könnte ein Taktgeber den Staukontroller umhüllen und die Verfügbarkeit des Staufensters steuern, oder ein Taktgeber könnte Pakete takten, die ihm vom Staukontroller übergeben werden.
Die rechtzeitige Zustellung von ACK-Rahmen ist wichtig für eine effiziente Verlustwiederherstellung. Um eine Verzögerung ihrer Zustellung an den Peer zu vermeiden, SOLLTEN Pakete, die nur ACK-Rahmen enthalten, daher nicht getaktet werden.
Endpunkte können Taktung nach Belieben implementieren. Ein perfekt getakteter Sender verteilt Pakete genau gleichmäßig über die Zeit. Für einen fensterbasierten Staukontroller wie den in diesem Dokument kann diese Rate berechnet werden, indem das Staufenster über die RTT gemittelt wird. Ausgedrückt als Rate in Einheiten von Bytes pro Zeit, wobei congestion_window in Bytes ist:
rate = N * congestion_window / smoothed_rtt
Oder ausgedrückt als Inter-Paket-Intervall in Zeiteinheiten:
interval = (smoothed_rtt * packet_size / congestion_window) / N
Die Verwendung eines Werts für N, der klein, aber mindestens 1 ist (z.B. 1,25), stellt sicher, dass Variationen in der RTT nicht zu einer Unternutzung des Staufensters führen.
Praktische Überlegungen wie Paketierung, Planungsverzögerungen und Recheneffizienz können dazu führen, dass ein Sender über Zeiträume, die viel kürzer als eine RTT sind, von dieser Rate abweicht.
Eine mögliche Implementierungsstrategie für Taktung verwendet einen Leaky-Bucket-Algorithmus, bei dem die Kapazität des "Eimers" auf die maximale Burst-Größe begrenzt ist und die Rate, mit der sich der "Eimer" füllt, durch die obige Funktion bestimmt wird.
7.8. Unternutzung des Staufensters (Underutilizing the Congestion Window)
Wenn die in Übertragung befindlichen Bytes kleiner als das Staufenster sind und das Senden nicht durch Taktung begrenzt ist, wird das Staufenster nicht ausreichend genutzt. Dies kann aufgrund unzureichender Anwendungsdaten oder Flusskontrollgrenzen geschehen. Wenn dies auftritt, SOLLTE das Staufenster weder im langsamen Start noch in der Stauvermeidung erhöht werden.
Ein Sender, der Pakete taktet (siehe Abschnitt 7.7), könnte das Senden von Paketen verzögern und das Staufenster aufgrund dieser Verzögerung nicht vollständig nutzen. Ein Sender SOLLTE sich nicht als anwendungsbegrenzt betrachten, wenn er das Staufenster ohne Taktungsverzögerung vollständig genutzt hätte.
Ein Sender KANN alternative Mechanismen implementieren, um sein Staufenster nach Perioden der Unternutzung zu aktualisieren, wie sie für TCP in [RFC7661] vorgeschlagen wurden.