rfc-1144

Compressing TCP/IP Headers for Low-Speed Serial Links

V. Jacobson
date1990-02 streamLegacy statusPROPOSED STANDARD pages49 canonicalhttps://www.rfc-editor.org/rfc/rfc1144 doi10.17487/RFC1144
This RFC describes a method for compressing the headers of TCP/IP datagrams to improve performance over low speed serial links. The motivation, implementation and performance of the method are described. C code for a sample implementation is given for reference. [STANDARDS-TRACK]

Extracted elements (26)

design-rationale §4.2

Error recovery relies exclusively on TCP's reliable delivery and retransmission mechanism rather than adding a decompressor-to-compressor resync request. Adding such a protocol would require bidirectional compression-layer signaling, constrain network topology, and would not work in practice because a line hit typically obliterates the compressed packet entirely, leaving the decompressor unaware that an error occurred.

tcp, ip

design-rationale §2

Header compression targets a five-byte average compressed header to keep typing traffic under 300 bps (the maximum assumed for full-duplex modem allocation heuristics). A typical typist sends five characters/second; a 300 bps budget leaves 25 bytes/second for headers, or five bytes per keystroke. Five-byte headers also allow small MTUs (100–200 bytes) that prevent bulk-data packets from blocking interactive traffic for more than ~20 ms.

tcp, ip

design-rationale §2

The compression protocol uses a strictly simplex model—no information flows from decompressor back to compressor. This is the minimum topological requirement and supports deployment at intermediate gateways that may see only one direction of a TCP flow due to asymmetric routing. Error recovery is delegated entirely to TCP's retransmission mechanism rather than adding a compression-level recovery dialog.

tcp, ip

design-rationale §3.2.2

The connection ID is limited to one byte (256 maximum simultaneous connections) because in practice no more than sixteen connection states were observed to be needed even on a busy 64-port terminal multiplexer. This simplification allows the IP protocol field in UNCOMPRESSED_TCP packets to double as the connection index without adding a separate field.

tcp, ip

design-rationale §3.2.2

The IP ID field is treated specially in the change mask: when the I bit is clear, the decompressor assumes the IP ID incremented by exactly one (not zero). This is because a delta of one is the common case when only one connection is active, making it worth eliding. A delta of zero is improbable enough that the zero encoding signals a 3-byte extension rather than 'no change'.

tcp, ip

design-rationale §1

The protocol is intentionally TCP-specific rather than general IP compression. UDP datagrams were considered but rejected because they lack datagram-to-datagram coherence (e.g., DNS queries) or the application-layer header dominates (e.g., NFS/RPC). Compressing IP and TCP headers separately was rejected because it increased average compressed header size by 50% and doubled code complexity.

tcp, ip

design-rationale §3.2.2

The PUSH bit is transmitted explicitly in the change mask (P bit) rather than being compressed away, because PUSH can change in any datagram and the compression scheme is information-preserving. The TCP urgent pointer is similarly encoded when URG is set. If the urgent pointer changes with URG clear, an uncompressed packet is sent since this violates RFC 793 but must be handled robustly.

tcp, ip

interoperability-note §B

Appendix B describes two backwards-compatibility scenarios: (1) operating without a framing 'type' byte, where the packet type must be inferred from the first byte of the packet using the TYPE_IP (0x40), TYPE_UNCOMPRESSED_TCP (0x70), and TYPE_COMPRESSED_TCP (0x80) values; and (2) interoperating with SLIP servers that do not support compression, requiring the compressor to be disabled or to detect non-compressing peers.

tcp, ip

interoperability-note §5.3

Data compression (e.g., Lempel-Ziv/modem compression) and header compression are complementary and do not interfere. Applying L-Z compression to data before TCP/IP encapsulation yields slightly better results (~3%) than compressing at the wire/modem level. Applying L-Z after header compression is safe; applying it twice (data and wire) is counterproductive on already-compressed data.

tcp, ip

interoperability-note §5.2

For lines where both interactive and bulk data traffic coexist, the MTU SHOULD be chosen to give a packet transmission time of approximately 200 ms. At 9600 bps this means an MTU of about 192 bytes. With header compression this yields 96% line efficiency; increasing the MTU to 576 bytes improves throughput by only 3% while increasing average interactive delay by 188%.

tcp, ip

normative-requirement §4.1 MUST

After receiving a CRC error indication from the framer, the decompressor MUST set the toss flag and discard all incoming COMPRESSED_TCP packets until it receives either a COMPRESSED_TCP packet with the C bit set (explicit connection number) or an UNCOMPRESSED_TCP packet. This prevents cross-connection state corruption from a missed connection-number packet.

tcp, ip

normative-requirement §5.1 SHOULD

Serial line IP drivers that allow header compression SHOULD include a user-configurable flag to disable compression entirely, for interoperability with existing SLIP links that do not implement this compression. Compression SHOULD default to off until negotiated on.

tcp, ip

normative-requirement §4.2 MUST

The compressor MUST detect TCP retransmissions and send an UNCOMPRESSED_TCP packet to resynchronize the decompressor. Retransmission is inferred when: (a) the sequence number delta is negative, or (b) the sequence number is unchanged and the previous packet contained user data (zero-delta sequence number in a data packet indicates retransmit, not just a pure ack).

tcp, ip

normative-requirement §3.2.3 MUST NOT

The compressor MUST NOT compress IP fragments: if the IP fragment offset field is non-zero or the More Fragments bit is set, the packet MUST be sent as TYPE_IP. Only the first fragment contains the TCP header; compressing it would require expensive completeness checks.

tcp, ip

normative-requirement §3.2.3 MUST

The compressor MUST send an UNCOMPRESSED_TCP packet (rather than COMPRESSED_TCP) whenever the delta in sequence number or acknowledgment number is negative or greater than 2^16−1, as this likely indicates a TCP retransmission which the decompressor needs to resynchronize state.

tcp, ip

normative-requirement §3.1 MUST

The IP header checksum MUST NOT be transmitted in COMPRESSED_TCP packets. Instead, the decompressor regenerates it locally after reconstructing the full IP header. The TCP checksum, being an end-to-end integrity check, MUST be passed through unmodified.

tcp, ip

normative-requirement §5.1 SHOULD

When no negotiation is possible, both compressor and decompressor SHOULD provide exactly sixteen state slots (indexed 0–15). When negotiation is supported, any mutually agreed number from 1 to 256 MAY be used; until negotiated, both sides SHOULD assume sixteen slots.

tcp, ip

protocol-element §3.2.1

Each end of the serial link maintains an array of connection state slots (cstate structures), each holding a 128-byte copy of the last TCP/IP header seen for that connection plus a connection ID. The transmit side uses a circularly-linked LRU list for connection lookup and slot eviction. The receive side indexes slots directly by the connection number extracted from the packet.

tcp, ip

protocol-element §3.2.1

The compressor maintains a circularly-linked LRU list of connection states. On each packet, the most recently used connection is checked first (O(1) common case). On a cache miss, the list is searched linearly; if no state matches, the oldest (tail) state is evicted and reused, and an UNCOMPRESSED_TCP packet seeds the decompressor with the new connection's header.

tcp, ip

protocol-element §3.2.1

Three packet types are defined for compressed TCP/IP: TYPE_IP (0x40) for non-TCP or uncompressible packets, UNCOMPRESSED_TCP (0x70) for the first packet of a connection (carrying the full header with the IP protocol field replaced by a connection index), and COMPRESSED_TCP (0x80) for subsequently compressed packets. TYPE_ERROR (0x00) is a pseudo-type used internally by the receive framer to signal a transmission error to the decompressor.

tcp, ip

protocol-element §3.2.2

Two special-case change mask encodings handle the two most common traffic patterns without encoding individual deltas: SPECIAL_I (S|W|U bits set, A clear) signals echoed interactive traffic where both sequence and ack advance by the last packet's data length; SPECIAL_D (S|A|W|U all set) signals unidirectional data transfer where only the sequence number advances by the last packet's data length. These allow 3-byte compressed headers for these common cases.

tcp, ip

security-consideration §4.1

Header compression removes nearly all redundancy from TCP and IP headers, so the decompressor will silently reconstruct plausible-but-incorrect TCP/IP packets from corrupted compressed input. The TCP checksum (passed through unmodified) detects sequence-number errors with 100% probability for the specific error pattern of a dropped compressed packet. However, cross-connection state contamination after a CRC error has an undetected probability of approximately 2^-16 per packet, mitigated by the toss-until-explicit-connection-number rule.

tcp, ip, security

state-machine §3.2.3

The compressor's decision procedure: (1) non-TCP → TYPE_IP; (2) IP fragment (offset≠0 or MF bit set) → TYPE_IP; (3) SYN, FIN, RST set or ACK clear → TYPE_IP; (4) no matching connection state found → evict LRU slot, send UNCOMPRESSED_TCP; (5) fixed fields changed (TOS, TTL, options, etc.) → UNCOMPRESSED_TCP; (6) delta ack or delta seq out of [0, 2^16-1] → UNCOMPRESSED_TCP; (7) retransmission detected → UNCOMPRESSED_TCP; otherwise → COMPRESSED_TCP.

tcp, ip

state-machine §3.2.4

The decompressor switches on packet type: TYPE_ERROR or unknown type sets a 'toss' flag causing all subsequent COMPRESSED_TCP packets to be discarded until one with the C bit set or an UNCOMPRESSED_TCP arrives. TYPE_IP passes through unchanged. UNCOMPRESSED_TCP restores IPPROTO_TCP, clears the toss flag, and updates the state slot. COMPRESSED_TCP applies deltas to the saved header only if toss is clear; if C bit is set, updates the active connection.

tcp, ip

wire-format §3.2.2

A COMPRESSED_TCP packet consists of: a 1-byte change mask (C, I, P, S, A, W, U bits), an optional 1-byte connection number (when C bit is set), the unmodified 2-byte TCP checksum, and for each bit set in the change mask, a variable-length encoded delta value for that field. The change mask doubles as a header: C signals connection number follows, P copies the TCP PUSH bit, I/S/A/W/U indicate presence of IP ID/sequence/ack/window/urgent deltas respectively.

tcp, ip

wire-format §3.2.2

Delta values in compressed packets use a variable-length encoding: a non-zero byte encodes values 1–255 in a single byte; a zero byte signals a 3-byte extension where the next two bytes are the MSB and LSB of a 16-bit value. Values of zero are encoded as 0x00 0x00 0x00. This scheme handles the common case (small positive deltas) in one byte with a three-instruction encode/decode path.

tcp, ip