Compressing IP/UDP/RTP Headers for Low-Speed Serial Links
Extracted elements (31)
Compression and segmentation are intentionally kept as separate layers so that compression can be used independently in situations where segmentation is deemed unnecessary or impractical, and to avoid coupling a reservation protocol into the compression scheme.
Full-duplex operation is preferred over simplex because an explicit CONTEXT_STATE error signal on the reverse path shortens recovery delay substantially and reduces overhead in the no-error case compared to the periodic-refresh approach required for simplex links.
Link-by-link compression of combined IP/UDP/RTP headers (40 bytes) is preferred over end-to-end RTP-only compression (12 bytes) because the resulting compressed size is approximately the same (2–4 bytes) in either case, while the link-by-link approach also benefits from lower delay and loss rate on the local link.
Rather than dedicating a separate bit in the COMPRESSED_RTP mask for CSRC list changes (L bit), the special combination MSTI=1111 (all four of IPv4 ID, RTP marker, RTP sequence, and RTP timestamp bits set simultaneously) signals an extended header form containing the real M/S/T/I values plus CC count and CSRC list, conserving bits in the common case.
RTCP packets are not compressed (beyond IP/UDP headers) because RTCP bandwidth is already limited to 5% of session bandwidth, compressing SDES items would require significantly more shared state per context, and maintaining per-SSRC RTCP contexts in large sessions would thrash the context cache.
The large compression gain for RTP comes from the observation that although several header fields change each packet, the first-order difference is often constant, making the second-order difference zero. By maintaining both the uncompressed header and the first-order differences in shared session state, only an indication that the second-order difference is zero must be communicated, allowing full header reconstruction with no information loss.
For segmentation schemes used alongside header compression, large packets that are segmented should bypass the compressor/decompressor to avoid disrupting the packet sequencing. The context ID byte is placed first in the COMPRESSED_RTP header so it MAY be shared with the segmentation layer if negotiated.
RTCP compression of headers and data is not defined; however, IP and UDP header compression SHOULD still be applied to RTCP packets using the COMPRESSED_UDP packet type. With RTCP occupying at most 5% of session bandwidth, even uncompressed RTCP content remains below 7% of compressed link bandwidth for RTP payloads as small as 37 bytes.
This IP/UDP/RTP compression is designed to fit within the general header compression framework of RFC 2507, which defines TCP and non-TCP as two classes. This specification creates IP/UDP/RTP as a third class extracted from the non-TCP class, and the FULL_HEADER format is intended to be consistent with RFC 2507's definition.
A packet stream with a constantly changing SSRC field SHOULD be entered in the negative cache to avoid consuming all available session contexts. The negative cache is indexed by source/destination IP address and UDP port pairs, not the SSRC field.
Both uncompressed and compressed packets MUST carry the context ID and the 4-bit link sequence number. This sequence number is used to detect packet loss between compressor and decompressor, and each context has its own separate sequence number space.
Fragmented IP packets that are not initial fragments, and packets too short to contain a complete UDP header, MUST NOT be sent as FULL_HEADER packets. Additionally, packets that do not contain at least 12 bytes of UDP data MUST NOT be used to establish RTP context, and if sent as FULL_HEADER, MUST NOT be followed by COMPRESSED_RTP packets.
If any of the normally constant RTP header fields (version, P bit, X bit, payload type, SSRC) change, the uncompressed RTP header MUST be sent via a COMPRESSED_UDP or FULL_HEADER packet rather than a COMPRESSED_RTP packet.
IP/UDP/RTP compression SHOULD maintain state for multiple simultaneous session contexts. It is RECOMMENDED that implementations use a table-driven delta encoder and decoder to allow per-session negotiation of encoding tables, possibly including optimal Huffman encoding.
It is RECOMMENDED that the decompressor periodically verify the UDP checksum (perhaps one out of every 16 packets) to detect errors that go undetected by the 4-bit sequence number (e.g., exactly 16 consecutive losses). On detecting an error, the decompressor should invalidate the context and signal the compressor.
The decompressor SHOULD NOT retransmit the CONTEXT_STATE packet for every compressed packet received for an invalid context; instead it SHOULD limit the retransmission rate to avoid flooding the reverse channel.
The length of the CID MUST either be constant for all contexts, or two additional distinct packet types MUST be provided to separately indicate COMPRESSED_UDP and COMPRESSED_RTP packet formats with 8- and 16-bit CIDs.
When more than one IPv4 header is present in the context, the IP ID fields of encapsulating headers MUST be sent as absolute values (RANDOM fields) in the COMPRESSED_RTP packet. Only the IP ID of the IPv4 header immediately preceding the UDP header may be sent differentially.
Whenever the 4-bit link sequence number for a context increments by other than 1 (except when set by FULL_HEADER or COMPRESSED_NON_TCP), the decompressor MUST invalidate that context and send a CONTEXT_STATE packet. All packets for that context MUST be discarded until a FULL_HEADER or COMPRESSED_NON_TCP packet re-establishes state.
A session context is the shared state maintained between compressor and decompressor for each unique combination of IP source/destination addresses, UDP source/destination ports, and RTP SSRC field. Each context is identified by an 8- or 16-bit Context ID (CID), with a maximum of 65536 contexts. The number of contexts MAY be negotiated.
Each session context stores: the full IP/UDP/RTP headers of the last packet, the first-order difference for the IPv4 ID field (initialized to 1 on FULL_HEADER), the first-order difference for the RTP timestamp (initialized to 0 on FULL_HEADER), the last 4-bit link sequence number, the current generation number, and optionally a context-specific delta encoding table.
Five packet types are defined: FULL_HEADER (uncompressed headers with CID and sequence number), COMPRESSED_RTP (fully compressed IP/UDP/RTP with delta fields), COMPRESSED_UDP (compressed IP/UDP with uncompressed RTP payload), CONTEXT_STATE (decompressor-to-compressor error signal), and optionally COMPRESSED_NON_TCP (non-differential compression from RFC 2507, primarily for IPv6).
A malfunctioning or malicious compressor could cause the decompressor to reconstruct packets with valid IP/UDP/RTP headers and possibly valid UDP checksums that do not match the original packets. End-to-end authentication and integrity mechanisms are unaffected by the compression and can detect such corruption.
Because encryption eliminates the redundancy exploited by this scheme, there is an inducement to forego encryption for low-bandwidth links. RTP specifies an alternative where only the RTP payload is encrypted and headers remain in the clear, allowing compression to still be applied.
No authentication is performed on CONTEXT_STATE packets. An attacker with link access could inject false CONTEXT_STATE packets, causing context invalidations and repeated FULL_HEADER transmissions that reduce compression efficiency and likely cause congestion. However, such an attacker could also disrupt traffic in many other ways.
A session context transitions between VALID and INVALID states. A context becomes INVALID when the decompressor observes the 4-bit link sequence number increment by other than 1. It returns to VALID when a FULL_HEADER or COMPRESSED_NON_TCP packet is received for that context. An advisory (non-invalidating) CONTEXT_STATE may also be sent after a link error indication with the I bit set to 0.
Delta fields use a variable-length encoding: values 0–127 are one byte; values with most-significant two bits 10 are a 14-bit value encoded in two bytes; values with MSBs 11 are a 22-bit value in three bytes. Negative deltas reuse otherwise redundant portions of the positive range. Values outside the range –16384 to 4194303 force an uncompressed header.
The COMPRESSED_RTP header begins with an optional MSB byte for 16-bit CID, then the LSB of CID, then one byte containing M|S|T|I bits and a 4-bit link sequence number. Conditionally following are: 16-bit UDP checksum (if nonzero in context), RANDOM fields (absolute IPv4 IDs for encapsulating headers), optional extended MSTI byte with CC count (if MSTI=1111), delta IPv4 ID, delta RTP sequence, delta RTP timestamp, CSRC list, RTP header extension, RTP data, and padding.
The COMPRESSED_UDP header has the same format as COMPRESSED_RTP except the M, S, and T bits are always 0 and the corresponding delta fields are never included. The UDP data payload (which may contain an uncompressed RTP header) follows directly after the compressed IP/UDP portion.
The CONTEXT_STATE packet begins with a 1-byte type code (1 for 8-bit CID, 2 for 16-bit CID), followed by a 1-byte context count, then a list of blocks each containing: the session context ID (8 or 16 bits), a byte with the I (invalid) flag and 4-bit sequence number, and a byte with a 6-bit generation number.
The FULL_HEADER packet carries the CID and 4-bit sequence number by overwriting the IP and UDP length fields (which are redundant with the link-layer length). For 8-bit CID: first length field holds a 0 bit, a 1 bit, a 4-bit generation, and the 8-bit CID; second length field holds the 4-bit sequence number. For 16-bit CID: first length field holds a 1 bit, a 1 bit, generation, and sequence; second length field holds the full 16-bit CID.