RFC 3545

Enhanced Compressed RTP (CRTP) for Links with High Delay, Packet Loss and Reordering

πŸ“… published July 2003, from ietf

(part 1 of 5, more coming bestie πŸ’–)

okay so this one is a Standards Track doc from July 2003 πŸ¦‹ It's by T. Koren (Cisco Systems), S. Casner (Packet Design), J. Geevarghese (Motorola India Electronics Ltd.), B. Thompson (Cisco Systems) and P. Ruddy (Cisco Systems). The title block doesn't list anything it obsoletes or updates, so it's a fresh standard πŸ’…


Status of this Memo

ok so this part is the legal-ish bit, but it's giving "this is an actual internet standard" ✨ It's an Internet standards track protocol for the Internet community, and it asks people to discuss it and suggest improvements 🫢 For the current standardization state and status, check the "Internet Official Protocol Standards" (STD 1) doc. And distribution of this memo is unlimited 🌈

Copyright (C) The Internet Society (2003). All Rights Reserved. πŸ’œ

Abstract

okay the big picture 🧚 This doc describes a header compression scheme for point to point links that have packet loss and long delays. It's built on Compressed Real-time Transport Protocol (CRTP), which is the IP/UDP/RTP header compression from RFC 2508 πŸ’–

CRTP doesn't do great on links like that. Packet loss corrupts the context, and because of the long delay, way more packets get thrown away before the context is fixed 😭 So this doc adds a few extensions to CRTP to fix that. The main trick is changing how the compressor updates the context at the decompressor: updates get repeated, and they include updates to both full and differential context parameters ✨ With all that, CRTP performs well over links with packet loss, packet reordering and long delays. iconic πŸ‘‘

Table of Contents

   1.  Introduction .................................................  2
       1.1.  CRTP Operation .........................................  4
       1.2.  How do contexts get corrupted? .........................  4
       1.3.  Preventing context corruption ..........................  5
       1.4.  Specification of Requirements ..........................  5
   2.  Enhanced CRTP ................................................  5
       2.1.  Extended COMPRESSED_UDP packet .........................  6
       2.2.  CRTP Headers Checksum .................................. 11
       2.3.  Achieving robust operation ............................. 13
             2.3.1.  Examples ....................................... 15
   3.  Negotiating usage of enhanced-CRTP ........................... 18
   4.  Security Considerations ...................................... 18
   5.  Acknowledgements ............................................. 19
   6.  References ................................................... 19
       6.1.  Normative References ................................... 19
       6.2.  Informative References ................................. 20
   7.  Intellectual Property Rights Notice .......................... 20
   8.  Authors' Addresses ........................................... 21
   9.  Full Copyright Statement ..................................... 22

1. Introduction 🌸

okay so RTP header compression (CRTP) from RFC 2508 was made to shrink the header overhead of IP/UDP/RTP datagrams by compressing all three headers πŸ“ Most of the time the IP/UDP/RTP headers get squished down to 2-4 bytes. literally tiny πŸ™ˆ

CRTP was designed for reliable point to point links with short delays. It does not perform well over links with a high rate of packet loss, packet reordering and long delays πŸ’€

Here's an example: a PPP session tunneled over an IP level tunneling protocol like L2TP. The packets inside the tunnel travel over an IP network, so they can get lost and reordered 😬 The longer the tunnel, the longer the round trip time.

Another example is an IP network that uses layer 2 technologies like ATM and Frame Relay for its access portion. Layer 2 transport networks such as ATM and Frame Relay act like point to point serial links, in that they don't reorder packets 🫧 But Frame Relay and ATM virtual circuits used as IP access technologies often have a low bit rate. These circuits are different from low speed serial links because they can span a bigger physical distance than a point to point serial link does. The speed of light delays inside the layer 2 transport network lead to higher round trip delays between the endpoints of the circuit 🌍 And congestion inside that layer 2 network can cause an effective drop rate for the virtual circuit that's way higher than the error rates usually seen on point to point serial links. yikes 😭

It might be desirable to extend existing CRTP implementations so they also work over IP tunnels and other virtual circuits, where packet losses, reordering and long delays are common ✨ So this doc defines modifications and extensions to CRTP that make it more robust to both packet loss and misordering between the compressor and the decompressor. It does this by repeating updates and by letting the sender include absolute (uncompressed) values, not just delta values, for selected context parameters πŸ’… Yes, these new mechanisms add some extra overhead, but the overall compression is still substantial. So the enhanced CRTP is suitable for lots of the scenarios above, like tunneling and other virtual circuits πŸ¦‹

RFC 3095 defines another RTP header compression scheme, called Robust Header Compression [ROHC]. ROHC was developed with wireless links as the main target. It brought in new compression mechanisms whose main goal was to get the combination of robustness against packet loss and maximal compression efficiency πŸ”₯ ROHC is expected to be the preferred compression mechanism over links where compression efficiency matters. BUT ROHC was designed with the same link assumptions as CRTP, which means the compression scheme doesn't have to handle misordering of compressed packets between the compressor and decompressor. That misordering can happen when packets ride in an IP tunnel across multiple hops 🫠

At some point in the future, ROHC enhancements might be defined so it can work well even when compressed packets get misordered. The result might be more efficient than the compression protocol in this document. However, there are lots of environments where the enhanced CRTP defined here may be the preferred choice πŸ’– Especially where CRTP is already implemented, because the extra work to implement these extensions is expected to be small ✨ There are also cases where how simple the enhanced CRTP is to implement, compared to ROHC, matters more than ROHC's performance advantages 🧚

1.1. CRTP Operation πŸŽ€

so when an RTP stream is being compressed, a session context gets defined ✨ For each context, the session state is established and shared between the compressor and the decompressor. Once the context state is established, compressed packets can be sent πŸ’œ

The context state is made up of the full IP/UDP/RTP headers, a few first order differential values, a link sequence number, a generation number and a delta encoding table 🌸

The headers part of the context is set by the FULL_HEADER packet, which always starts a compression session. The first order differential values (delta values) are set by sending COMPRESSED_RTP packets that include updates to the delta values πŸ“

The context state must be synchronized between the compressor and decompressor for successful decompression to take place. If the context gets out of sync, the decompressor can't restore the compressed headers accurately. So the decompressor invalidates the context and sends a CONTEXT_STATE packet to the compressor, saying the context has been corrupted. To resume compression, the compressor must re-establish the context. 🚨

While the context is corrupted, the decompressor throws away all the packets it gets for that context 😭 Since the CRTP context repair mechanism involves feedback from the decompressor, context repair takes at least as long as the round trip time of the link. If the round trip time is long, and especially if the link bandwidth is high, many packets get discarded before the context is repaired. On links like that, it's desirable to minimize context invalidation πŸ™

1.2. How do contexts get corrupted? πŸ’€

As long as the fields in the combined IP/UDP/RTP headers change the way they're expected to for the sequence of packets in a session, those headers can be compressed, and the decompressor can fully restore them using the context state ✨ When the headers don't change as expected, some of the full or delta values of the context have to be updated 🫢 For example, the RTP timestamp is expected to increment by delta RTP timestamp (dT). But if silence suppression is used, packets aren't sent during silent periods. So when voice activity resumes, packets are sent again, but the RTP timestamp goes up by a big value instead of by dT. In this case an update must be sent. (okay it's lowercase in the original, but it's giving "must be sent" energy πŸ’…)

If a packet carrying an update to some context state values is lost, the state at the decompressor doesn't get updated 😩 The shared state is now different at the compressor and the decompressor. When the next packet arrives at the decompressor, it fails to restore the compressed headers accurately, because the context state at the decompressor is different from the state at the compressor.

1.3. Preventing context corruption 🧚

Here's the tea: the decompressor doesn't fail when a packet is lost. It fails when the next compressed packet arrives 🫠 If the next packet happens to include the same context update as the lost packet, the context at the decompressor can be updated successfully and decompression can carry on uninterrupted ✨

If the lost packet included an update to a delta field, like the delta RTP timestamp (dT), the next packet can't make up for the loss. The update to a delta value is relative to the previous packet, which was the one that got lost 😭 But if the update is for an absolute value, like the full RTP timestamp or the RTP payload type, that update can be repeated in the next packet, independent of the lost packet πŸ’– So it's really useful to be able to update the absolute values of the context.

The next chapter describes several extensions to CRTP that add the ability to selectively update absolute values of the context, instead of sending a FULL_HEADER packet. These sit alongside the existing updates of the delta values πŸ¦‹ This enhanced CRTP is meant to minimize context invalidation, and so improve performance over lossy links with a long round trip time πŸ‘‘

1.4. Specification of Requirements πŸ“œ

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119]. 🫢

2. Enhanced CRTP ✨

okay bestie, this is where the glow-up happens πŸ¦‹ This chapter spells out every change in this enhanced version of CRTP. There are two big ones:

  • Extensions to the COMPRESSED_UDP packet that let you update the differential RTP values in the decompressor context, and selectively update the absolute IPv4 ID and these RTP values: sequence number, timestamp, payload type, CSRC count and CSRC list. This keeps context sync intact even when some packets get lost πŸ’…
  • A "headers checksum" that the compressor inserts and the decompressor strips out when the UDP checksum isn't present. Validation of the decompressed headers is still possible this way, so the decompressor can check whether context sync was lost after a packet loss πŸ”

Then there's an algorithm that uses these changes together with repeated updates, so the whole thing runs robustly over links with packet loss and long delay. literally iconic πŸ‘‘

2.1. Extended COMPRESSED_UDP packet

okay so, you can handle some packet loss between the compressor and decompressor using the "twice" algorithm from RFC 2508 🌸 as long as the context stays in sync. In that algorithm, the delta values get added to the previous context twice (or more), which makes the same change that would have happened if the missing packets had arrived. The result gets checked with the UDP checksum βœ… To keep the context in sync, you have to reliably communicate both the absolute value and the delta value whenever the delta value changes. In a lot of environments, you can get enough reliability just by repeating the update in each of several successive packets. it's giving redundancy, no cap 🫢

The COMPRESSED_UDP packet already covers sending the absolute values of the differential RTP fields. But RFC 2508 says it resets the delta RTP timestamp, and that's the limitation this enhanced version gets rid of πŸŽ€ Here's the simple fix. RFC 2508 describes COMPRESSED_UDP as the same format as COMPRESSED_RTP, except the M, S and T bits are always 0 and the matching delta fields are never included. This enhanced version changes that rule: the T bit MAY be nonzero to show that the delta RTP timestamp is included explicitly, instead of being reset to zero. no more forced reset, bestie πŸ’–

A second change adds another byte of flag bits to COMPRESSED_UDP so you can include only selected uncompressed fields of the RTP header, instead of carrying the full RTP header inside the UDP data 🧚 The extra flags do make the computation a bit more complicated, but the bit savings are worth it when the differential field updates get sent over and over in successive COMPRESSED_UDP packets. Now there are flag bits for both delta values and absolute values, so the names changed too. The original S, T and I bits, which signal delta inclusion, get renamed dS, dT and dI. Inclusion of absolute values is now signalled by S, T and I. The M bit stays absolute, same as before. There's a brand-new P flag for the absolute RTP payload type value, and a new C flag for the CSRC count. When C=1, one more byte follows the two flag bytes to carry the absolute value of the four-bit CC field in the RTP header πŸ’…

The last of the three COMPRESSED_UDP changes is about the IPv4 ID field πŸ“ RFC 2508's COMPRESSED_UDP can already send a new value for the delta IPv4 ID, but not the absolute value, which only the FULL_HEADER packet carries. So a new I flag gets added to COMPRESSED_UDP to show the absolute IPv4 ID value is included. The I flag takes the place of the dS flag. dS isn't needed in COMPRESSED_UDP, because the delta RTP sequence number always stays 1 in the decompressor context, so it never has to be updated. Heads up: IPv6 has no IP ID field, so when you compress IPv6 packets, both the I and the dI flags are always set to 0 ⚠️

Here's the flags/sequence byte for the original COMPRESSED_UDP packet, just for reference:

   +---+---+---+---+---+---+---+---+
   | 0 | 0 | 0 |dI | link sequence |
   +---+---+---+---+---+---+---+---+

And here's the new flags/sequence byte, plus the extension flags byte for COMPRESSED_UDP. The new F flag says whether the extension flags byte is included πŸ¦‹

   +---+---+---+---+---+---+---+---+
   | F | I |dT |dI | link sequence |
   +---+---+---+---+---+---+---+---+
   : M : S : T : P : C : 0 : 0 : 0 :  (if F = 1)
   +...+...+...+...+...+...+...+...+
   dI  = delta IPv4 ID
   dT  = delta RTP timestamp
   I   = absolute IPv4 ID
   F   = additional flags byte
   M   = marker bit
   S   = absolute RTP sequence number
   T   = absolute RTP timestamp
   P   = RTP payload type
   C   = CSRC count
   CID = Context ID

When F=0, there's only one flags byte, and the only flags you get are dI, dT and I. In that case the packet carries the full RTP header. Same as RFC 2508, if dI=0, the decompressor doesn't change deltaI. If dT=0, the decompressor sets deltaT to 0 🌈

When C=1, one more byte follows the two flag bytes. This byte holds the CC, which is the count of CSRC identifiers, in its lower 4 bits:

   +---+---+---+---+---+---+---+---+
   | F | I |dT |dI | link sequence |
   +---+---+---+---+---+---+---+---+
   : M : S : T : P : C : 0 : 0 : 0 :  (if F = 1)
   +...+...+...+...+...+...+...+...+
   : 0 : 0 : 0 : 0 :      CC       :  (if C = 1)
   +...+...+...+...+...............+

The bits marked "0" in the second flag byte and the CC byte SHOULD be set to zero by the sender and SHOULD be ignored by the receiver πŸ™ˆ that's the rule, bestie.

Now for some example packet formats, so you can see the new flags in action ✨ First up, when F=0, the "traditional" COMPRESSED_UDP packet, which carries the full RTP header as part of the UDP data:

     0   1   2   3   4   5   6   7
   +...............................+
   :   msb of session context ID   :  (if 16-bit CID)
   +-------------------------------+
   |   lsb of session context ID   |
   +---+---+---+---+---+---+---+---+
   |F=0| I |dT |dI | link sequence |
   +---+---+---+---+---+---+---+---+
   :                               :
   +         UDP checksum          +  (if nonzero in context)
   :                               :
   +...............................+
   :                               :
   +        "RANDOM" fields        +  (if encapsulated)
   :                               :
   +...............................+
   :         delta IPv4 ID         :  (if dI = 1)
   +...............................+
   :      delta RTP timestamp      :  (if dT = 1)
   +...............................+
   :                               :
   +           IPv4 ID             +  (if I = 1)
   :                               :
   +...............................+
   |           UDP data            |
   :   (uncompressed RTP header)   :

When F=1, there's an extra flags byte, and the flags you get are dI, dT, I, M, S, T, P and C. If C=1, one more byte shows up that includes the number of CSRC identifiers. When F=1, the packet doesn't carry the full RTP header. It only includes the fields from the RTP header that the flags select. Same as RFC 2508, if dI=0, the decompressor doesn't change deltaI. But unlike RFC 2508, if dT=0, the decompressor KEEPS THE CURRENT deltaT in the context (it DOES NOT set deltaT to 0) 🚨 pay attention to that one, it's a plot twist.

An enhanced COMPRESSED_UDP packet is pretty similar in contents and behaviour to a COMPRESSED_RTP packet, but it has more flag bits, and some of them stand for absolute values of RTP header fields πŸ’œ

COMPRESSED_UDP with individual RTP fields, when F=1:

     0   1   2   3   4   5   6   7
   +...............................+
   :   msb of session context ID   :  (if 16-bit CID)
   +-------------------------------+
   |   lsb of session context ID   |
   +---+---+---+---+---+---+---+---+
   |F=1| I |dT |dI | link sequence |
   +---+---+---+---+---+---+---+---+
   | M | S | T | P | C | 0 | 0 | 0 |
   +---+---+---+---+---+---+---+---+
   : 0 : 0 : 0 : 0 :      CC       :  (if C = 1)
   +...+...+...+...+...............+
   :                               :
   +         UDP checksum          +  (if nonzero in context)
   :                               :
   +...............................+
   :                               :
   :        "RANDOM" fields        :  (if encapsulated)
   :                               :
   +...............................+
   :         delta IPv4 ID         :  (if dI = 1)
   +...............................+
   :      delta RTP timestamp      :  (if dT = 1)
   +...............................+
   :                               :
   +           IPv4 ID             +  (if I = 1)
   :                               :
   +...............................+
   :                               :
   +     RTP sequence number       +  (if S = 1)
   :                               :
   +...............................+
   :                               :
   +                               +
   :                               :
   +         RTP timestamp         +  (if T = 1)
   :                               :
   +                               +
   :                               :
   +...............................+
   :       RTP payload type        :  (if P = 1)
   +...............................+
   :                               :
   :           CSRC list           :  (if CC > 0)
   :                               :
   +...............................+
   :                               :
   :      RTP header extension     :  (if X set in context)
   :                               :
   +-------------------------------+
   |                               |
   /           RTP data            /
   /                               /
   |                               |
   +-------------------------------+
   :            padding            :  (if P set in context)
   +...............................+

Usage for the enhanced COMPRESSED_UDP packet πŸŽ€

It's smart for the compressor to refresh the decompressor's state every so often πŸ’… That way the decompressor doesn't have to send CONTEXT_STATE messages after unrecoverable packet loss. Using the flags F=0 and I=1, dI=1, dT=1, the COMPRESSED_UDP packet refreshes all the context parameters ✨

When you compress over a lossy link with a long round trip delay, you want to keep context invalidation to a minimum 😭 If the delta values keep changing, the context could get invalidated a lot. In those cases, the compressor MAY choose to always send absolute values and never delta values, using COMPRESSED_UDP packets with the flags F=1, and any of S, T, I as necessary 🌸

2.2. CRTP Headers Checksum πŸŽ€

okay so [RFC 2508](#) in Section 3.3.5 talks about using the UDP checksum to double-check header reconstruction now and then, or when the "twice" algorithm is in use. but if a stream has no UDP checksum (the value is zero), that check just can't happen πŸ’€. so this enhanced CRTP gives the compressor a fix: it MAY swap that null UDP checksum for a 16-bit headers checksum (HDRCKSUM), and the decompressor takes it back out after validating. ngl this option is never used with IPv6, because a null UDP checksum isn't allowed there πŸ™…β€β™€οΈ

a new flag C in the FULL_HEADER packet (more on that below) says, when set, that every COMPRESSED_UDP and COMPRESSED_RTP packet sent in that context will have HDRCKSUM inserted. the compressor MAY set C when the UDP packet carried in the FULL_HEADER originally had a checksum of zero. if C is set, the FULL_HEADER packet itself MUST also have HDRCKSUM inserted. and if a packet in the same stream later shows up at the compressor with a UDP checksum present, then a new FULL_HEADER MUST be sent with the flag cleared to re-establish the context πŸ”„

the HDRCKSUM is calculated like a UDP checksum, except it doesn't cover all of the UDP data. it's the 16-bit one's complement of the one's complement sum of the pseudo-IP header (as defined for UDP), the UDP header, the first 12 bytes of the UDP data (which are assumed to hold the fixed part of an RTP header), and the CSRC list. the extended part of the RTP header beyond the CSRC list and the RTP data will not be included in the HDRCKSUM. the HDRCKSUM goes in the COMPRESSED_UDP or COMPRESSED_RTP packet wherever a UDP checksum would have been. and the decompressor MUST zero out the UDP checksum field in the reconstructed packets 🧚

for a non-RTP context, there might be fewer than 12 UDP data bytes. the IP and UDP headers can still get compressed into a COMPRESSED_UDP packet anyway. in this case, the HDRCKSUM is calculated over the pseudo-IP header, the UDP header, and whatever UDP data bytes are present. if the number of data bytes is odd, a zero padding byte gets appended just for the checksum math, but it's not transmitted 🫢

the HDRCKSUM does not validate the RTP data. so if the link layer delivers packets without checking for errors, errors in the RTP data won't be detected. over links like that, the compressor SHOULD add the HDRCKSUM if a UDP checksum is not present, and the decompressor SHOULD validate each reconstructed packet to make sure at least the headers are correct. this ensures the packet gets delivered to the right destination. if only the HDRCKSUM is available, the RTP data will be delivered even if it includes errors, which might be a desirable feature for applications that can tolerate errors in the RTP data. the same holds for the extended part of the RTP header beyond the CSRC list πŸ’œ

here's the format of the FULL_HEADER length fields with the new flag C, which tells you a header checksum will be added in COMPRESSED_UDP and COMPRESSED_RTP packets:

For 8-bit context ID:

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|0|1| Generation|      CID      |  First length field
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|            0        |C|  seq  |  Second length field
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  C=1: HDRCKSUM will be added

For 16-bit context ID:

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|1|1| Generation| 0   |C|  seq  |  First length field
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+  C=1: HDRCKSUM will be added

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|              CID              |  Second length field
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

2.3. Achieving robust operation πŸ¦‹

enhanced CRTP stays robust by sending changes multiple times, so the compressor and decompressor stay in sync. this method is described by a number "N" that represents the quality of the link between the hosts. what it means is that the probability of more than N adjacent packets getting lost on this link is small. for every change in a full value or a delta value, if the compressor includes the change in N+1 consecutive packets, then the decompressor can keep its context state in sync with the compressor using the "twice" algorithm, as long as no more than N adjacent packets are lost ✨

since updates are repeated in N+1 packets, if at least one of those N+1 update packets is received by the decompressor, both the full and delta values in its context get updated, and the context stays synchronized with the context at the compressor. so as long as fewer than N+1 adjacent packets are lost, the context at the decompressor is guaranteed to be synchronized with the context at the compressor, and using the "twice" algorithm to recover from packet loss will successfully update the context and restore the compressed packets πŸ‘‘

the link sequence number cycles in 16 packets, so it's not always clear how many packets were lost. for example, if the previous link sequence number was 5 and the current number is 4, one possibility is that 15 packets were lost. but another possibility is that, due to misordering, packet 5 arrived before packet 4, and they're really adjacent. if there's an interpretation of the link sequence numbers that could be a gap of less than N+1, the "twice" algorithm may be applied that many times and verified with the UDP checksum (or the HDRCKSUM) πŸ”

when more than N packets are lost, all of the repetitions of an update might have been lost, so the context state may be different at the compressor and decompressor. the decompressor can still try to recover by making one or more guesses for how many packets were lost, and then applying the "twice" algorithm that many times 🎲

however, since the IPv4 ID field is not included in the checksum, this does not validate the IPv4 ID. πŸ’€

the conclusion is that for IPv4, if more than N packets were lost, the decompressor SHOULD NOT try to recover using the "twice" algorithm, and instead SHOULD invalidate the context and send a CONTEXT_STATE packet. in IPv6, the decompressor MAY always try to recover from packet loss by using the "twice" algorithm and verifying the result with the UDP checksum 🌈

it's up to the implementation to derive an appropriate N for a link. the value is maintained independently for each context and is not required to be the same for all contexts. when compressing a new stream, the compressor sets a value of N for that context and sends N+1 FULL_HEADER packets. the compressor MUST also repeat each subsequent COMPRESSED_UDP update N+1 times. the value of N may be changed for an existing context by sending a new sequence of FULL_HEADER packets πŸ“

the decompressor learns the value of N by counting the number of times the FULL_HEADER packet is repeated, and storing the resulting value in the corresponding context. if some of the FULL_HEADER packets are lost, the decompressor may still be able to determine the correct value of N by observing the change in the 4-bit sequence number carried in the FULL_HEADER packets. any inaccuracy in the counting will lead the decompressor to assume a smaller value of N than the compressor is sending. this is safe, because the only negative consequence is that the decompressor might send a CONTEXT_STATE packet when it wasn't really necessary. in response, the compressor will send FULL_HEADER packets again, giving the decompressor another opportunity to count the correct N πŸ™ˆ

the sending of FULL_HEADER packets is also triggered by a change in one of the fields held constant in the context, such as the IP TOS. if such a change happens while the compressor is in the middle of sending the N+1 FULL_HEADER packets, then the compressor MUST send N+1 FULL_HEADER packets after making the change. this could cause the decompressor to receive more than N+1 FULL_HEADER packets in a row, with the result that it assumes a larger value for N than is correct. that could lead to an undetected loss of context synchronization. so the compressor MUST change the "generation" number in the context and in the FULL_HEADER packet when it begins sending the sequence of N+1 FULL_HEADER packets, so the decompressor can detect the new sequence. for IPv4, this is a change in behavior relative to RFC 2508 πŸ’…

CONTEXT_STATE packets SHOULD also be repeated N+1 times (using the same sequence number for each context) to provide a similar measure of robustness against packet loss. here N can be the largest N of all contexts included in the CONTEXT_STATE packet, or any number the decompressor finds necessary in order to ensure robustness πŸŽ€

2.3.1. Examples ✨

Okay bestie, let's look at some examples of enhanced CRTP's robust operation using N+1 repetitions of updates πŸ¦‹ Picture an audio codec sending a sample every 10 milliseconds. The first talkspurt is 1 second long, then there are 2 seconds of silence, then another talkspurt πŸ’– In this first example, the IPv4 ID field doesn't go up at a constant rate, because the host is busy generating other uncorrelated traffic streams at the same time. So the delta IPv4 ID changes for every packet πŸ™ˆ

We'll use some short notations πŸ’…

    FH    FULL_HEADER
    CR    COMPRESSED_RTP
    CU    COMPRESSED_UDP

On a link with low loss, we can just use COMPRESSED_RTP packets with the basic CRTP method from RFC 2508. Here's the packet sequence:

    seq Time pkt    updates and comments
     #       type
    1   10   FH
    2   20   CR     dI dT=10
    3   30   CR     dI
    4   40   CR     dI
    ...
    100 1000 CR     dI

    101 3010 CR     dI dT=2010
    102 3020 CR     dI dT=10
    103 3030 CR     dI
    104 3040 CR     dI
    ...

Look at that πŸ‘€ If a packet gets lost in this sequence, we can't recover, because "twice" won't work with the unpredictable IPv4 ID. The context has to be invalidated πŸ’€

Here's the same example using the enhanced CRTP method from this document, when N=2. Notice that the compressor only sends the absolute IPv4 ID (I) and not the delta IPv4 ID (dI) 🧚

    seq Time pkt  CU flags            updates and comments
     #       type F I dT dI M S T P
    1   10   FH
    2   20   FH                             repeat constant fields
    3   30   FH                             repeat constant fields
    4   40   CU   1 1  1  0 M 0 1 0   I T=40 dT=10
    5   50   CU   1 1  1  0 M 0 1 0   I T=50 dT=10 repeat update T & dT
    6   60   CU   1 1  1  0 M 0 1 0   I T=60 dT=10 repeat update T & dT
    7   70   CU   1 1  0  0 M 0 0 0   I
    8   80   CU   1 1  0  0 M 0 0 0   I
    ...
    100 1000 CU   1 1  0  0 M 0 0 0   I

    101 3010 CU   1 1  0  0 M 0 1 0   I T=3010  T changed, keep deltas
    102 3020 CU   1 1  0  0 M 0 1 0   I T=3020  repeat updated T
    103 3030 CU   1 1  0  0 M 0 1 0   I T=3030  repeat updated T
    104 3040 CU   1 1  0  0 M 0 0 0   I
    105 3050 CU   1 1  0  0 M 0 0 0   I
    ...

Now for the second example, same sequence but this time the delta IP ID is constant 🌸 First, basic CRTP on a lossless link:

    seq Time pkt    updates and comments
     #       type
    1   10   FH
    2   20   CR     dI dT=10
    3   30   CR
    4   40   CR
    ...
    100 1000 CR

    101 3010 CR     dT=2010
    102 3020 CR     dT=10
    103 3030 CR
    104 3040 CR
    ...

For the equivalent in enhanced CRTP, the more efficient COMPRESSED_RTP packet can still be used once the deltas are all established 🌈

    seq Time pkt  CU flags            updates and comments
     #       type F I dT dI M S T P
    1   10   FH
    2   20   FH                             repeat constant fields
    3   30   FH                             repeat constant fields
    4   40   CU   1 1  1  1 M 0 1 0   I dI T=40 dT=10
    5   50   CU   1 1  1  1 M 0 1 0   I dI T=50 dT=10  repeat updates
    6   60   CU   1 1  1  1 M 0 1 0   I dI T=60 dT=10  repeat updates
    7   70   CR
    8   80   CR
    ...
    100 1000 CR

    101 3010 CU   1 0  0  0 M 0 1 0   T=3010  T changed, keep deltas
    102 3020 CU   1 0  0  0 M 0 1 0   T=3020  repeat updated T
    103 3030 CU   1 0  0  0 M 0 1 0   T=3030  repeat updated T
    104 3040 CR
    105 3050 CR
    ...

And here's the second example with IPv6 πŸ¦‹ Basic CRTP on a lossless link first:

    seq Time pkt    updates and comments
     #       type
    1   10   FH
    2   20   CR     dT=10
    3   30   CR
    4   40   CR
    ...
    100 1000 CR

    101 3010 CR     dT=2010
    102 3020 CR     dT=10
    103 3030 CR
    104 3040 CR
    ...

Enhanced CRTP equivalent, once the deltas are established:

    seq Time pkt  CU flags            updates and comments
     #       type F I dT dI M S T P
    1   10   FH
    2   20   FH                             repeat constant fields
    3   30   FH                             repeat constant fields
    4   40   CU   1 0  1  0 M 0 1 0   T=40 dT=10
    5   50   CU   1 0  1  0 M 0 1 0   T=50 dT=10  repeat updates
    6   60   CU   1 0  1  0 M 0 1 0   T=60 dT=10  repeat updates
    7   70   CR
    8   80   CR
    ...
    100 1000 CR

    101 3010 CU   1 0  0  0 M 0 1 0   T=3010  T changed, keep deltas
    102 3020 CU   1 0  0  0 M 0 1 0   T=3020  repeat updated T
    103 3030 CU   1 0  0  0 M 0 1 0   T=3030  repeat updated T
    104 3040 CR
    105 3050 CR
    ...

3. Negotiating usage of enhanced-CRTP πŸŽ€

Whether CRTP gets used over a particular link depends on the link-layer protocol, so the negotiation is expected to be defined separately for each link layer πŸ’œ

Link layers that already have a negotiation for CRTP as specified in RFC 2508 will need an extension to that negotiation to indicate enhanced CRTP, as defined in this document. The reason is that the syntax of the existing packet formats has been extended πŸ”₯


4. Security Considerations πŸ”

Okay, security time, and this one's serious bestie 😭 Encryption wipes out the redundancy this compression scheme depends on, so there's some pull toward skipping encryption just to get decent performance on a low-bandwidth link. But when encrypting the data and not the headers is good enough, RTP does define an alternative: only the RTP payload gets encrypted and the headers stay in the clear [SRTP]. That lets compression still be applied 🌈

A malfunctioning or malicious compressor could make the decompressor rebuild packets that don't match the originals, yet still have valid IP, UDP and RTP headers, and possibly even valid UDP check-sums πŸ’€ That kind of corruption can be caught with end-to-end authentication and integrity mechanisms, which compression doesn't affect. The constant parts of authentication headers get compressed as described in [IPHCOMP] ✨

Nothing authenticates the CONTEXT_STATE control packet this protocol sends 😬 An attacker on the link between decompressor and compressor could inject fake CONTEXT_STATE packets and make compression less efficient, which would probably lead to congestion on the link. But honestly, an attacker with access to the link could mess with the traffic in lots of other ways anyway πŸ™„

There's also a potential denial-of-service threat with compression techniques that put non-uniform computational load on the receiver. An attacker could inject pathological datagrams into the stream that are expensive to decompress, overloading the receiver and slowing down processing of other streams. This compression, though, doesn't show any significant non-uniformity, so that threat doesn't really apply here πŸ›‘οΈ


5. Acknowledgements 🫢

The authors want to thank Van Jacobson, co-author of RFC 2508, plus the authors of RFC 2507: Mikael Degermark, Bjorn Nordgren, and Stephen Pink πŸ’• They also want to thank Dana Blair, Francois Le Faucheur, Tim Gleeson, Matt Madison, Hussein Salama, Mallik Tatipamula, Mike Thomas, Alex Tweedly, Herb Wildfeuer, Andrew Johnson, and Dan Wing 🌷


6. References πŸ“š

6.1. Normative References

[CRTP]    Casner, S. and V. Jacobson, "Compressing IP/UDP/RTP Headers
          for Low-Speed Serial Links", RFC 2508, February 1999.

[IPHCOMP] Degermark, M., Nordgren, B. and S. Pink, "IP Header
          Compression", RFC 2507, February 1999.

[IPCPHC]  Koren, T., Casner, S. and C. Bormann, "IP Header
          Compression over PPP", RFC 3544, July 2003.

[KEYW]    Bradner, S. "Key words for use in RFCs to Indicate
          Requirement Levels", BCP 14, RFC 2119, March 1997.

[RTP]     Schulzrinne, H., Casner, S., Frederick, R. and V. Jacobson,
          "RTP: A Transport Protocol for Real-Time Applications", RFC
          3550, July 2003.

6.2. Informative References

[ROHC]    Bormann, C., Burmeister, C., Degermark, M., Fukushima, H.,
          Hannu, H., Jonsson, L., Hakenberg, R., Koren, T., Le, K.,
          Liu, Z., Martensson, A., Miyazaki, A., Svanbro, K., Wiebke,
          T., Yoshimura, T. and H. Zheng, "RObust Header Compression
          (ROHC): Framework and four profiles: RTP, UDP, ESP, and
          uncompressed", RFC 3095, July 2001.

[SRTP]    Baugher, M., McGrew, D., Carrara, E., Naslund, M. and K.
          Norrman, "The Secure Real-time Transport Protocol", Work in
          Progress.

7. Intellectual Property Rights Notice βš–οΈ

The IETF doesn't take a position on whether any intellectual property or other rights claimed to relate to the technology in this document are valid or in scope, or on whether licenses for them are available. It also doesn't say it has searched for such rights πŸ€·β€β™€οΈ For how the IETF handles rights in standards-track and standards-related documents, check BCP-11. Copies of claimed rights submitted for publication, any assurances of licences to be made available, and the results of attempts to get a general licence or permission for implementers or users of this specification can all be obtained from the IETF Secretariat πŸ“¬

The IETF invites anyone interested to tell it about any copyrights, patents, patent applications, or other proprietary rights that might cover technology needed to practise this standard. Send that information to the IETF Executive Director πŸ’Œ


8. Authors' Addresses πŸ’Œ

Tmima Koren
Cisco Systems, Inc.
170 West Tasman Drive
San Jose, CA  95134-1706
USA

EMail: tmima@cisco.com


Stephen L. Casner
Packet Design
3400 Hillview Avenue, Building 3
Palo Alto, CA  94304
USA

EMail: casner@acm.org


John Geevarghese
Motorola India Electronics Ltd.
No. 33 A Ulsoor Road
Bangalore, India

EMail: geevjohn@hotmail.com


Bruce Thompson
Cisco Systems, Inc.
170 West Tasman Drive
San Jose, CA  95134-1706
USA

EMail: brucet@cisco.com


Patrick Ruddy
Cisco Systems, Inc.
3rd Floor
96 Commercial Street
Leith, Edinburgh  EH6 6LX
Scotland

EMail: pruddy@cisco.com

Copyright (C) The Internet Society (2003). All Rights Reserved. πŸŽ€

okay bestie, this part is the legal stuff, but it's still important. πŸ’… The document and its translations can be copied and handed to others, and derivative works that comment on or explain it, or help with implementing it, can be made, copied, published and distributed, in whole or in part, without restriction of any kind. The one catch is that the above copyright notice and this paragraph have to be included on all those copies and derivative works. πŸ“œ

The document itself may not be modified in any way, such as by removing the copyright notice or the references to the Internet Society or other Internet organizations. The exceptions are when it's needed for developing Internet standards, in which case the procedures for copyrights defined in the Internet Standards process must be followed, or when it's needed to translate it into languages other than English. 🌍

The limited permissions above are perpetual and will not be revoked by the Internet Society or its successors or assigns. Forever and ever, no cap. ✨

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. πŸ™ˆ

Acknowledgement 🫢

Funding for the RFC Editor function is currently provided by the Internet Society. 🌸

πŸ“¦ where this page comes from