Zusammenfassung

  • Vergrößerte die Kompression ein Datagramm, ließ RFC 1977 es zur Schonung der MTU in nativer PPP-Kapselung senden; die beim Versuch entstandene Wörterbuchänderung blieb dennoch bestehen und wurde am Empfänger nachgebildet.
  • Im nativen Paket fehlte ein LZW-CLEAR. Beide Seiten mussten deshalb aus denselben Eingaben, Codebreiten und Verhältniswerten selbständig denselben adaptiven Löschzeitpunkt ableiten.
  • Die 16-Bit-Sequenz konnte eine Lücke vor dem Decodieren eines späteren komprimierten Pakets anzeigen. Reset-Request/Reset-Ack begann eine neue Geschichte bei null, ohne die alte zu vervollständigen oder zu beglaubigen.

Erst rechnen, dann über die Darstellung entscheiden

Ein Sender wusste nicht im Voraus, dass Daten unkomprimierbar waren. Er führte BSD Compress aus, verglich die Größen und entschied erst danach. Bei deutlicher Expansion musste das ursprüngliche PPP-Paket gesendet werden. Selbst eine Zunahme unter drei Byte sprach normalerweise für die native Form, sofern das komprimierte Ergebnis nicht ausnahmsweise innerhalb der MTU blieb.

Damit vermied das Verfahren eine künstlich kleinere Nutz-MTU. Ein inkompressibles Datagramm sollte nicht allein wegen des Kompressionsrahmens größer werden. Die verworfene Ausgabe bedeutete jedoch nicht, dass nichts geschehen war. LZW hatte Bytes gelesen, Folgen gefunden oder neu angelegt, Codegrenzen verschoben und die Effizienzzähler fortgeschrieben.

Würde der Sender diese Zustandsänderungen zurücknehmen, könnte das nächste tatsächlich komprimierte Paket Einträge verwenden, die der Empfänger nie aufgebaut hat. RFC 1977 verpflichtete den Empfänger daher, ein natives Paket aus dem komprimierbaren Protokollbereich so zu behandeln, als hätte es expandiert. Er komprimierte es lokal, allein um die Historie fortzuführen.

Die Referenzfunktion pf_bsd_incomp beschreibt den Vorgang als vorgetäuschte Kompression. Sie erhöht die Sequenz, zählt Eingabe und hypothetische Ausgabe und legt dieselben Einträge an, ohne einen codierten Strom zu erzeugen. Nativ war die Übertragungsform, nicht der Zustandswechsel.

Das Dateiende fiel weg

Unix compress besaß mit dem Dateiende eine natürliche Grenze. Auf einer PPP-Verbindung wurde das Wörterbuch zu einer fortlaufenden gemeinsamen Erinnerung über Datagrammgrenzen hinweg. Zwei getrennte Implementierungen mussten sie aus derselben Eingabereihenfolge rekonstruieren.

Die CCP-Option bestimmte nur den Ausgangspunkt. Typ 21 bezeichnete BSD Compress, Version musste 001 sein und Dict begrenzte die größte Codebreite auf 9 bis 16 Bit; zwölf galt als übliche Wahl. Der Quelltext im Anhang unterstützte 9 bis 15 Bit. Das war eine Grenze des Beispiels, nicht der ausgehandelten Spezifikation.

Mehr Speicher erlaubte dem Empfänger kein größeres Wörterbuch. Die Obergrenze beeinflusste, wann die Tabelle voll wurde, wann die Codebreite wuchs und wann die adaptive Prüfung löschen durfte. Gerade eine scheinbar großzügige lokale Abweichung hätte die gemeinsame Zeitachse getrennt.

Auch das innere PPP-Protokollfeld folgte einer festen Regel. Werte unter 0x100 mussten vor Sequenzberechnung und Kompression ein Byte lang sein, unabhängig davon, ob Protocol-Field-Compression für die äußere PPP-Verbindung vereinbart war. Beide Seiten brauchten dieselben Eingabebytes.

PPP musste die Network-Layer Protocol Phase und CCP den Zustand Opened erreicht haben. Ein Configure-Ack belegte damit gemeinsame Parameter, aber nicht die spätere Reihenfolge von Kernel, Treiber und Kontrollprozess.

Ein CLEAR, das nicht auf dem Draht stand

Klassisches BSD-LZW reservierte Code 256 für CLEAR. In einem codierten Strom konnte der Sender damit am Paketende das Löschen anzeigen. Ein natives PPP-Paket enthielt keinen LZW-Strom. Verschlechterten inkompressible Daten ein volles Wörterbuch, gab es genau dann keinen zuverlässigen Platz für das ausdrückliche Signal.

RFC 1977 ersetzte die sichtbare Nachricht durch eine reproduzierbare Entscheidung. Der Beispielcode prüfte bei vollem Wörterbuch nach jeweils 10.000 Eingabebytes das Kompressionsverhältnis. Wurde das neue Verhältnis schlechter oder fiel unter eins zu eins, setzte pf_bsd_clear die Breite auf neun Bit, die letzte Belegung sowie Verhältnis und Zähler zurück.

Der Sender erreichte die Entscheidung beim Probeversuch, der Empfänger bei der lokalen Simulation. Sie mussten dieselben Eingabebytes und dieselbe virtuelle Ausgabelänge zählen, Codes gleich vergeben und die Zähler gleich altern lassen. Nur dann lag das unsichtbare Löschen an derselben Paketgrenze.

Der Gewinn war ein schlankes Format ohne MTU-Aufschlag. Der Preis war eine größere Implementierungsoberfläche. Nach dem Löschen bot das leere Wörterbuch zunächst wenig Nutzen; die ersten Pakete erschienen häufig nativ und sahen damit aus wie Verkehr vor der Aktivierung. Die Kapselung verriet nicht, welche Historie gerade entstand.

Die Lücke wird erst später sichtbar

Ein wirklich BSD-komprimiertes Paket trug eine 16-Bit-Sequenz in höchstwertiger Bytefolge. Sie begann nach dem Löschen bei null, stieg für jedes zulässige Paket—auch ein natives—und sprang nach 65535 zurück. Der Empfänger sollte sie vor dem Decodieren prüfen.

Das native Paket selbst hatte diesen Header nicht. Ging es verloren, aktualisierte nur der Sender Wörterbuch und Zähler. Der Empfänger bemerkte die Lücke möglicherweise erst beim nächsten komprimierten Paket, dessen Nummer nicht zu seiner Erwartung passte.

Die Sequenz verhinderte das Weiterdecodieren mit einem erkennbar falschen Wörterbuch. Sie zeigte weder das verlorene Paket noch den Unterschied zwischen Verlust und Umordnung, lieferte keine fehlenden Bytes und authentifizierte keinen Teilnehmer. RFC 1977 verwies bei beschädigten Frames auf den HDLC-FCS und gewöhnliches Verwerfen; seine Security Considerations behandelten Sicherheit nicht. Ein umlaufender Zähler und eine Link-Prüfsumme sind kein kryptografischer Integritätsnachweis.

Reset gibt die Vergangenheit auf

Beim ersten unerwarteten Wert sollte der Empfänger CCP Reset-Request senden und komprimierte Pakete bis Reset-Ack verwerfen. Der Sender musste bei jeder Anfrage löschen und die Sequenz nullen, weil er nicht wusste, ob ein früheres Ack angekommen war. Der Empfänger musste bei jedem passenden Ack ebenfalls löschen.

Das Dokument verglich dies mit dem Abbruch einer „Datei“ und dem Beginn einer neuen. Reset stellte fehlende Einträge nicht wieder her und bescheinigte die alte Historie nicht. Es schuf einen neuen gemeinsamen Anfang. Ein neuer Configure-Request konnte CCP alternativ aus Opened bringen und neu aushandeln, war aber teurer.

Auf einer beschäftigten Verbindung trafen während eines RTT oft mehrere weitere unbrauchbare Pakete ein. Der Empfänger musste ausreichend oft anfragen, aber nicht schneller als die gemessene Rundlaufzeit; jede redundante Anfrage erzeugte ein redundantes Löschen. Eine Sekunde war nur ein Beispiel.

Eine weitere Grenze lag im Rechner. Verarbeitete ein Daemon CCP und der Kernel die Daten, musste das Löschen mit dem Configure-Ack oder Reset-Ack geordnet sein, das die neue Historie eröffnete. Der Empfänger musste vor dem nächsten Paket löschen. Ein korrektes Ack auf dem Draht bewies diese interne Reihenfolge nicht.

Spezifikation ist Bedingung, nicht Ergebnis

RFC 1977 definierte einen kleinen gemeinsamen Kern: zugelassene Eingaben, Version 1, Breitenobergrenze, Verhältnisprüfung, Sequenz und Neustart. IANA führt CCP-Option 21 sowie 0x00FD und 0x00FB für die komprimierten Datagramme weiterhin.

Mit Lu Hengs Vorrang laufender Systeme gelesen, schaffen diese Regeln lokale Prüfbarkeit. Sie ersetzen nicht den Nachweis, dass eine konkrete Verbindung sie gleich ausführte. Dafür braucht es die vollständige Paketfolge einschließlich nativer Eingaben, Breitenwechsel, Zähler und Löschzeitpunkte.

Diese Darstellung erzählt weder die allgemeine CCP-Aushandlung aus RFC 1962 noch das serielle Format aus RFC 1963 oder die Multilink-Umordnung aus RFC 1990. Sie behauptet keine heutige Verbreitung und keine Produktleistung. Ihre historische Grenze ist enger: „unkomprimiert“ bezeichnete bei BSD Compress die Form auf dem Draht, nicht einen stillstehenden Zustand.

Quellen