Connected: An Internet Encyclopedia
RFC 1144 - 3.2.2 Compressed packet format

Top: Connected: An Internet Encyclopedia
Up: Requests For Comments
Up: RFC 1144
Up: 3 The compression algorithm
Up: 3.2 The ugly details
Prev: 3.2.1 Overview
Next: 3.2.3 Compressor processing

### 3.2.2 Compressed packet format

##### Figure 5: The header of a compressed TCP/IP datagram

Figure 5 shows the format of a compressed TCP/IP packet. There is a change mask that identifies which of the fields expected to change per-packet actually changed, a connection number so the receiver can locate the saved copy of the last packet for this TCP connection, the unmodified TCP checksum so the end-to-end data integrity check will still be valid, then for each bit set in the change mask, the amount the associated field changed. (Optional fields, controlled by the mask, are enclosed in dashed lines in the figure.) In all cases, the bit is set if the associated field is present and clear if the field is absent./12/

Since the delta's in the sequence number, etc., are usually small, particularly if the tuning guidelines in section 5 are followed, all the numbers are encoded in a variable length scheme that, in practice, handles most traffic with eight bits: A change of one through 255 is represented in one byte. Zero is improbable (a change of zero is never sent) so a byte of zero signals an extension: The next two bytes are the MSB and LSB, respectively, of a 16 bit value. Numbers larger than 16 bits force an uncompressed packet to be sent. For example, decimal 15 is encoded as hex 0f, 255 as ff, 65534 as 00 ff fe, and zero as 00 00 00. This scheme packs and decodes fairly efficiently: The usual case for both encode and decode executes three instructions on a MC680x0.

The numbers sent for TCP sequence number and ack are the difference/13/ between the current value and the value in the previous packet (an uncompressed packet is sent if the difference is negative or more than 64K). The number sent for the window is also the difference between the current and previous values. However, either positive or negative changes are allowed since the window is a 16 bit field. The packet's urgent pointer is sent if URG is set (an uncompressed packet is sent if the urgent pointer changes but URG is not set). For packet ID, the number sent is the difference between the current and previous values. However, unlike the rest of the compressed fields, the assumed change when I is clear is one, not zero.

There are two important special cases:

1. The sequence number and ack both change by the amount of data in the last packet; no window change or URG.

2. The sequence number changes by the amount of data in the last packet, no ack or window change or URG.

(1) is the case for echoed terminal traffic. (2) is the sender side of non-echoed terminal traffic or a unidirectional data transfer. Certain combinations of the S, A, W and U bits of the change mask are used to signal these special cases. `U' (urgent data) is rare so two unlikely combinations are S W U (used for case 1) and S A W U (used for case 2). To avoid ambiguity, an uncompressed packet is sent if the actual changes in a packet are S * W U.

Since the `active' connection changes rarely (e.g., a user will type for several minutes in a telnet window before changing to a different window), the C bit allows the connection number to be elided. If C is clear, the connection is assumed to be the same as for the last compressed or uncompressed packet. If C is set, the connection number is in the byte immediately following the change mask./14/

From the above, it's probably obvious that compressed terminal traffic usually looks like (in hex): 0B c c d, where the 0B indicates case (1), c c is the two byte TCP checksum and d is the character typed. Commands to vi or emacs, or packets in the data transfer direction of an FTP `put' or `get' look like 0F c c d ... , and acks for that FTP look like 04 c c a where a is the amount of data being acked./15/

12. | The bit `P' in the figure is different from the others: It is a copy of the `PUSH' bit from the TCP header. `PUSH' is a curious anachronism considered indispensable by certain members of the Internet community. Since PUSH can (and does) change in any datagram, an information preserving compression scheme must pass it explicitly.
13. | All differences are computed using two's complement arithmetic.
14. | The connection number is limited to one byte, i.e., 256 simultaneously active TCP connections. In almost two years of operation, the author has never seen a case where more than sixteen connection states would be useful (even in one case where the SLIP link was used as a gateway behind a very busy, 64-port terminal multiplexor). Thus this does not seem to be a significant restriction and allows the protocol field in UNCOMPRESSED_TCP packets to be used for the connection number, simplifying the processing of those packets.
15. | It's also obvious that the change mask changes infrequently and could often be elided. In fact, one can do slightly better by saving the last compressed packet (it can be at most 16 bytes so this isn't much additional state) and checking to see if any of it (except the TCP checksum) has changed. If not, send a packet type that means `compressed TCP, same as last time' and a packet containing only the checksum and data. But, since the improvement is at most 25%, the added complexity and state doesn't seem justified. See appendix C.

Next: 3.2.3 Compressor processing

Connected: An Internet Encyclopedia
RFC 1144 - 3.2.2 Compressed packet format