3. Compression method (Komprimierungsverfahren)
3. Compression method (Komprimierungsverfahren)
Der Großteil der Header-Informationen bleibt während der Lebensdauer eines Paketstroms unverändert. Bei Nicht-TCP-Paketströmen sind nahezu alle Header-Felder konstant. Bei TCP sind viele Felder konstant, während sich andere mit kleinen und vorhersehbaren Werten ändern.
Um mit der Komprimierung der Header eines Paketstroms zu beginnen, wird ein vollständiger Header mit dem Kontextbezeichner CID über die Verbindung übertragen. Kompressor und Dekompressor speichern den Großteil der Felder dieses vollständigen Headers als Kontext. Der Kontext besteht aus den Feldern des Headers, deren Werte konstant sind und daher überhaupt nicht über die Verbindung gesendet werden müssen, oder die sich zwischen aufeinanderfolgenden Headern so wenig ändern, dass das Senden der Differenz zum vorherigen Wert weniger Bits erfordert als das Senden des absoluten Werts.
Jede Änderung in einem Feld, das im Paketstrom als konstant erwartet wird, veranlasst den Kompressor, erneut einen vollständigen Header zu senden, um den Kontext beim Dekompressor zu aktualisieren. Solange die Kontexte von Kompressor und Dekompressor übereinstimmen, kann ein Header exakt so dekomprimiert werden, wie er vor der Komprimierung war. Wenn jedoch ein vollständiger oder komprimierter Header während der Übertragung verloren geht, kann der Kontext des Dekompressors veraltet sein, da er nicht korrekt aktualisiert wurde. Komprimierte Header werden dann fehlerhaft dekomprimiert.
IPv6 ist nicht für Verbindungen gedacht, bei denen eine große Anzahl beschädigter Pakete an das IPv6-Modul weitergeleitet werden kann. Das bedeutet, dass die Verbindung eine sehr niedrige Bitfehlerrate haben MUSS oder dass Sicherungsschicht-Rahmen durch starke Prüfsummen, Vorwärtsfehlerkorrektur oder ähnliches geschützt sein MÜSSEN. Header-Komprimierung SOLLTE NICHT für IPv4 ohne starke Sicherungsschicht-Prüfsummen verwendet werden. Beschädigte Rahmen werden daher von der Sicherungsschicht verworfen. Die Sicherungsschicht-Implementierung kann dem Header-Komprimierungsmodul anzeigen, dass ein Rahmen beschädigt war, kann aber nicht angeben, zu welchem Paketstrom er gehört, da möglicherweise die CID beschädigt war. Außerdem können Rahmen verschwinden, ohne dass die Sicherungsschicht-Implementierung davon weiß, z. B. wenn die Verbindung eine Mehrfach-Hop-Verbindung ist, bei der Rahmen aufgrund von Überlastung an jedem Hop verworfen werden können. Daher ist der Typ von Verbindungsfehlern, den das Header-Komprimierungsmodul behandeln und verhindern MUSS, Paketverlust.
Das Header-Komprimierungsverfahren benötigt daher Mechanismen zur Aktualisierung des Kontexts beim Dekompressor und zur Erkennung oder Vermeidung fehlerhafter Dekomprimierung. Diese Mechanismen unterscheiden sich erheblich für TCP- und Nicht-TCP-Ströme und werden in den Abschnitten 3.2 und 3.3 beschrieben.
Die Komprimierungsmechanismen in diesem Dokument setzen voraus, dass Pakete zwischen Kompressor und Dekompressor nicht neu angeordnet werden. Wenn die Verbindung Pakete neu anordnet, beschreibt Abschnitt 11 einen Mechanismus zur Sortierung von Paketen vor der Dekomprimierung. Es wird auch angenommen, dass die Sicherungsschicht-Implementierung die Länge eines Pakets angeben kann und dass UDP-Pakete oder getunnelte Pakete keine Auffüllung enthalten.
3.1 Packet types (Pakettypen)
Zusätzlich zu den IPv4- und IPv6-Pakettypen verwendet dieses Komprimierungsverfahren vier Pakettypen. Die Kombination aus dem Sicherungsschicht-Pakettyp und dem Wert der ersten vier Bits des Pakets bestimmt den Pakettyp eindeutig. Details zur Darstellung dieser Pakettypen finden sich in Abschnitt 13.
FULL_HEADER – Bezeichnet ein Paket mit einem unkomprimierten Header, einschließlich CID und, falls kein TCP-Paket, der Generation. Es etabliert oder aktualisiert den Kontext für den durch die CID identifizierten Paketstrom.
COMPRESSED_NON_TCP – Bezeichnet ein Nicht-TCP-Paket mit einem komprimierten Header. Der komprimierte Header besteht aus der CID zur Identifizierung des zur Dekomprimierung verwendeten Kontexts, der Generation zur Erkennung inkonsistenter Kontexte sowie den zufällig geänderten Feldern des Headers.
COMPRESSED_TCP – Bezeichnet ein Paket mit einem komprimierten TCP-Header, das die CID, ein Flag-Oktett zur Identifizierung geänderter Felder sowie die geänderten Felder als Differenz zum vorherigen Wert enthält.
COMPRESSED_TCP_NODELTA – Bezeichnet ein Paket mit einem komprimierten TCP-Header, bei dem alle Felder, die normalerweise als Differenz zum vorherigen Wert gesendet werden, stattdessen unverändert gesendet werden. Dieser Pakettyp wird nur als Antwort auf eine Header-Anforderung vom Dekompressor gesendet. Er DARF NICHT als Ergebnis einer Neuübertragung gesendet werden.
Zusätzlich zu den für die Komprimierung verwendeten Pakettypen werden reguläre IPv4- und IPv6-Pakete verwendet, wenn der Kompressor entscheidet, ein Paket nicht zu komprimieren. Es können zusätzliche Pakettypen verwendet werden, um die Reparatur von TCP-Strömen über eine Verbindung zu beschleunigen, bei der der Dekompressor Pakete an den Kompressor senden kann.
CONTEXT_STATE – Bezeichnet ein spezielles Paket, das vom Dekompressor an den Kompressor gesendet wird, um eine Liste von (TCP-)CIDs zu übermitteln, die die Synchronisation verloren haben. Dieses Paket wird nur über eine einzelne Verbindung gesendet und benötigt daher keinen IP-Header. Das Format ist in Abschnitt 10.2 dargestellt.
3.2 Lost packets in TCP packet streams (Verlorene Pakete in TCP-Paketströmen)
Da TCP-Header unter Verwendung von Differenzen zum vorherigen TCP-Header komprimiert werden, führt der Verlust eines Pakets mit komprimiertem oder vollständigem Header dazu, dass nachfolgende komprimierte Header fehlerhaft dekomprimiert werden, da der zur Dekomprimierung verwendete Kontext nicht korrekt inkrementiert wurde.
Der Verlust eines komprimierten TCP-Headers führt dazu, dass die TCP-Sequenznummer der nachfolgend dekomprimierten TCP-Header um k abweicht, wobei k die Größe des verlorenen Segments ist. Solche fehlerhaft dekomprimierten TCP-Header werden vom TCP-Empfänger verworfen, da die TCP-Prüfsumme den „Abweichung um k"-Fehler in der Sequenznummer für vernünftige k-Werte zuverlässig erkennt.
Der TCP-Reparaturmechanismus überträgt schließlich das verworfene Segment neu, und der Kompressor überwacht TCP-Header, um zu erkennen, wann TCP eine Neuübertragung durchführt. Wenn dies geschieht, sendet der Kompressor einen vollständigen Header, in der Annahme, dass die Neuübertragung auf einen nicht übereinstimmenden Komprimierungszustand beim Dekompressor zurückzuführen ist. [RFC-1144] enthält eine gute Erklärung dieses Mechanismus.
Die Mechanismen aus Abschnitt 10 SOLLTEN verwendet werden, um die Kontextreparatur zu beschleunigen. Dies ist wichtig für mittelschnelle Verbindungen mit hoher Paketverlustrate, z. B. drahtlose Verbindungen. Es ist nicht akzeptabel, nach jedem Paketverlust auf der Verbindung Pakete in Höhe eines Timeout-Werts aufgrund inkonsistenter Kontexte zu verlieren, insbesondere wenn die TCP-Verbindung über ein Weitverkehrsnetz geht.
3.3 Lost packets in UDP and other non-TCP packet streams (Verlorene Pakete in UDP- und anderen Nicht-TCP-Paketströmen)
Fehlerhaft dekomprimierte UDP-Paket-Header und andere Nicht-TCP-Paket-Header sind nicht so gut durch Prüfsummen geschützt wie TCP-Pakete. Es gibt keine Sequenznummer, die um k abweicht und fast sicher einen Prüfsummenfehler verursacht, wie es bei TCP der Fall ist. Die UDP-Prüfsumme deckt nur die Nutzlast, den UDP-Header und den Pseudo-Header ab. Der Pseudo-Header enthält Quell- und Zieladressen, den Transportprotokolltyp und die Länge des Transportpakets. Abgesehen von diesen Feldern wird der Großteil des IPv6-Headers nicht von der UDP-Prüfsumme abgedeckt. Darüber hinaus fehlen anderen Nicht-TCP-Headern vollständig Prüfsummen, z. B. Fragmentierungs-Headern.
Um fehlerhafte Dekomprimierung von Nicht-TCP-Headern sicher zu vermeiden, wird jede Version des Kontexts für einen Nicht-TCP-Paketstrom durch eine Generation identifiziert, eine kleine Zahl, die von den vollständigen Headern getragen wird, die den Kontext etablieren und auffrischen. Komprimierte Header tragen den Generationswert des Kontexts, mit dem sie komprimiert wurden. Wenn der Dekompressor sieht, dass der von einem komprimierten Header getragene Generationswert nicht der Generation seines Kontexts für diesen Paketstrom entspricht, ist der Kontext nicht aktuell, und das Paket MUSS verworfen oder gespeichert werden, bis ein vollständiger Header den richtigen Kontext etabliert.
Differenzkodierung wird nicht für Nicht-TCP-Ströme verwendet, daher ändern komprimierte Nicht-TCP-Header den Kontext nicht. Daher macht der Verlust eines komprimierten Headers nachfolgende Pakete mit komprimierten Headern nicht ungültig. Außerdem ändert sich die Generation nur, wenn sich der Kontext des vollständigen Headers vom Kontext des vorherigen vollständigen Headers unterscheidet. Das bedeutet, dass der Verlust eines vollständigen Headers den Kontext des Dekompressors nur dann veraltet, wenn der vollständige Header den Kontext tatsächlich geändert hätte.
Das Generationsfeld ist 6 Bit lang, sodass sich Generationswerte nach 64 Kontextänderungen wiederholen. Um fehlerhafte Dekomprimierung nach einem Fehlerburst oder einer anderen vorübergehenden Unterbrechung zu vermeiden, DARF der Kompressor denselben Generationswert nicht früher als MIN_WRAP Sekunden wiederverwenden. Ein Dekompressor, der MIN_WRAP Sekunden oder länger getrennt war, MUSS auf den nächsten vollständigen Header warten, bevor er dekomprimiert. Der Kompressor MUSS nach dem Start mindestens MIN_WRAP Sekunden warten, bevor er Nicht-TCP-Header komprimiert. Anstatt Generationswerte vorzeitig wiederzuverwenden, KANN der Kompressor zu einer anderen CID wechseln oder reguläre Header senden, bis MIN_WRAP Sekunden vergangen sind. Der Wert von MIN_WRAP ist in Abschnitt 14 angegeben.
3.3.1 Compression Slow-Start (Komprimierungs-Slow-Start)
Um dem Dekompressor eine schnelle Wiederherstellung nach dem Verlust eines vollständigen Headers, der den Kontext ändert, zu ermöglichen, werden vollständige Header nach einer Kontextänderung in exponentiell wachsenden Abständen periodisch gesendet. Diese Technik vermeidet den Nachrichtenaustausch zwischen Kompressor und Dekompressor, der von anderen Komprimierungsverfahren verwendet wird, z. B. in [RFC-1553]. Dieser Austausch kann für drahtlose mobile Geräte kostspielig sein, da der Sender mehr Energie verbraucht und das Umschalten zwischen Senden und Empfangen Verzögerungen einführen kann. Außerdem können Techniken, die einen Nachrichtenaustausch erfordern, nicht für Simplex-Verbindungen verwendet werden, z. B. direkte Rundfunksatelliten-Kanäle oder Kabelfernsehsysteme, und sind schwer auf Multicast über Mehrfachzugriffs-Verbindungen anzupassen.
|.|..|....|........|................|..............................
^
Änderung Gesendete Pakete: | mit vollständigem Header, . mit komprimiertem Header
Die Abbildung zeigt, wie Pakete nach einer Änderung gesendet werden. Der Kompressor hält für jeden Nicht-TCP-Paketstrom eine Variable F_PERIOD, die verfolgt, wie viele komprimierte Header zwischen vollständigen Headern gesendet werden können. Wenn sich der Header eines Nicht-TCP-Paketstroms so ändert, dass sich sein Kontext ändert, wird ein vollständiger Header gesendet und F_PERIOD auf 1 gesetzt. Nach dem Senden von F_PERIOD komprimierten Headern wird ein vollständiger Header gesendet. Jedes Mal, wenn während des Komprimierungs-Slow-Starts ein vollständiger Header gesendet wird, wird F_PERIOD verdoppelt.
3.3.2 Periodic Header Refreshes (Periodische Header-Aktualisierungen)
Um zu vermeiden, dass zu viele Pakete verloren gehen, wenn der Empfänger seinen Kontext verliert, gibt es eine Obergrenze F_MAX_PERIOD für die Anzahl der Nicht-TCP-Pakete mit komprimierten Headern, die zwischen Header-Aktualisierungen gesendet werden können. Wenn ein Paket gesendet werden soll und seit dem letzten vollständigen Header für diesen Paketstrom F_MAX_PERIOD komprimierte Header gesendet wurden, MUSS ein vollständiger Header gesendet werden.
Um lange Unterbrechungen bei Paketströmen mit niedriger Datenrate zu vermeiden, gibt es auch eine Obergrenze F_MAX_TIME für die Zeit zwischen vollständigen Headern in einem Nicht-TCP-Paketstrom. Wenn ein Paket gesendet werden soll und seit dem letzten vollständigen Header für diesen Paketstrom mehr als F_MAX_TIME Sekunden vergangen sind, MUSS ein vollständiger Header gesendet werden. Die Werte von F_MAX_PERIOD und F_MAX_TIME sind in Abschnitt 14 angegeben.
3.3.3 Rules for sending Full Headers (Regeln für das Senden vollständiger Header)
Der Kompressor KANN den folgenden Pseudocode verwenden, um zu bestimmen, wann für einen Nicht-TCP-Paketstrom ein vollständiger Header gesendet werden soll. Der Code verwaltet zwei Variablen:
C_NUM -- Anzahl der seit dem letzten vollständigen Header gesendeten komprimierten Header.
F_LAST -- Zeitpunkt, zu dem der letzte vollständige Header gesendet wurde.
und verwendet die Funktionen
current_time() gibt die aktuelle Zeit zurück
min(a,b) gibt den kleineren Wert von a und b zurück
Die Prozeduren send_full_header(), increment_generation_value() und send_compressed_header() führen die offensichtlichen Operationen durch.
if ( <dieser Header ändert den Kontext> )
C_NUM := 0;
F_LAST := current_time();
F_PERIOD := 1;
increment_generation_value();
send_full_header();
elseif ( C_NUM >= F_PERIOD )
C_NUM := 0;
F_LAST := current_time();
F_PERIOD := min(2 * F_PERIOD, F_MAX_PERIOD);
send_full_header();
elseif ( current_time() > F_LAST + F_MAX_TIME )
C_NUM := 0;
F_LAST := current_time();
send_full_header();
else
C_NUM := C_NUM + 1
send_compressed_header();
endif
3.3.4 Cost of sending Header Refreshes (Kosten für das Senden von Header-Aktualisierungen)
Wenn jedes f-te Paket einen vollständigen Header trägt, H die Größe des vollständigen Headers und C die Größe des komprimierten Headers ist, beträgt die durchschnittliche Headergröße:
(H-C)/f + C
Für f > 1 ist die durchschnittliche Headergröße um (H-C)/f größer als der komprimierte Header.
In einem Diagramm der durchschnittlichen Headergröße für verschiedene f-Werte gibt es einen deutlichen Knickpunkt in der Kurve, d. h. es gibt eine Grenze, jenseits derer eine weitere Erhöhung von f abnehmende Erträge bringt. F_MAX_PERIOD SOLLTE auf eine Frequenz rechts vom Knickpunkt der Kurve gesetzt werden. Für typische H- und C-Größen, z. B. 48 Oktetten für einen vollständigen Header (IPv6/UDP) und 4 Oktetten für einen komprimierten Header, bedeutet F_MAX_PERIOD > 44, dass vollständige Header weniger als ein Oktett zur durchschnittlichen Headergröße beitragen. Mit einem Vier-Adressen-Routing-Header hätte F_MAX_PERIOD > 115 denselben Effekt.
Der Standardwert F_MAX_PERIOD von 256 (Abschnitt 14) platziert die vollständige Header-Frequenz rechts vom Knickpunkt und bedeutet, dass vollständige Header typischerweise deutlich weniger als ein Oktett zur durchschnittlichen Headergröße beitragen. Für H = 48 und C = 4 trägt der vollständige Header nach Erreichen der durch den Standard-F_MAX_PERIOD bestimmten Steady-State-Header-Aktualisierungsfrequenz etwa 1,4 Bits zur durchschnittlichen Headergröße bei. 1,4 Bits ist ein sehr geringer Overhead.
Nach einer Kontextänderung sendet das exponentielle Backoff-Schema zunächst häufig vollständige Header. Der Standard-F_MAX_PERIOD wird nach dem Senden von 9 vollständigen Headern und 255 komprimierten Headern erreicht. Für einen typischen Sprachstrom mit 20-ms-Sprachproben pro Paket entspricht dies etwas mehr als 5 Sekunden.
Während der gesamten Backoff-Periode tragen vollständige Header bei H = 48 und C = 4 1,5 Oktetten zur durchschnittlichen Headergröße bei. Für 20-ms-Sprachproben dauert es weniger als 1,3 Sekunden, bis vollständige Header weniger als ein Oktett zur durchschnittlichen Headergröße beitragen, und während dieser anfänglichen 1,3 Sekunden fügen vollständige Header weniger als 4 Oktetten zur durchschnittlichen Headergröße hinzu. Die Kosten des exponentiellen Backoffs sind nicht hoch, und da sich die Header von Nicht-TCP-Paketströmen voraussichtlich selten ändern, werden sie über einen langen Zeitraum amortisiert.
Die Kosten für Header-Aktualisierungen in Bezug auf Bandbreite sind höher als bei einem vergleichbaren Hard-State-Verfahren (wie [RFC-1553]), bei dem vollständige Header vom Dekompressor bestätigt werden müssen, bevor komprimierte Header gesendet werden können. Solche Verfahren senden typischerweise einen vollständigen Header plus einige Steuernachrichten, wenn sich der Kontext ändert. Hard-State-Verfahren erfordern mehr Arten von Protokollnachrichten und einen Nachrichtenaustausch. Hard-State-Verfahren erfordern auch eine explizite Behandlung verschiedener Fehlerbedingungen, die Soft-State automatisch behandelt, z. B. den Fall, dass eine Seite unerwartet verschwindet, was bei drahtlosen Verbindungen häufig vorkommt, wenn ein mobiles Gerät außer Reichweite einer Basisstation gerät.
Der Hauptvorteil des Soft-State-Verfahrens besteht darin, dass kein Handshake zwischen Kompressor und Dekompressor erforderlich ist, sodass das Verfahren für Simplex-Verbindungen verwendet werden kann. Die Kosten in Bezug auf Bandbreite sind höher als bei Hard-State-Verfahren, aber die Einfachheit des Dekompressors, die Einfachheit des Protokolls und das Fehlen eines Handshakes zwischen Kompressor und Dekompressor rechtfertigen diese geringen Mehrkosten. Außerdem lässt sich das Soft-State-Verfahren leichter auf Multicast über Mehrfachzugriffs-Verbindungen, z. B. drahtlose Verbindungen, erweitern.