组织:中国互动出版网(http://www.china-pub.com/) RFC文档中文翻译计划(http://www.china-pub.com/compters/emook/aboutemook.htm) E-mail:ouyang@china-pub.com 译者: 李超(licc_li licc_li@sina.com) 译文发布时间:2001-5-23 版权:本中文翻译文档版权归中国互动出版网所有。可以用于非商业用途自由转载,但必须 保留本文档的翻译及版权信息。 Network Working Group S. Casner Request for Comments: 2508 Cisco Systems Category: Standards Track V. Jacobson Cisco Systems February 1999 低速串行链路下IP/UDP/RTP数据包头的压缩 (RFC 2508 Compressing IP/UDP/RTP Headers for Low-Speed Serial Links) 本备忘录的状态 本文档讲述了一种Internet社区的Internet标准跟踪协议,它需要进一步进行讨论和建议以 得到改进。请参考最新版的“Internet正式协议标准” (STD1)来获得本协议的标准化程度 和状态。本备忘录的发布不受任何限制。 版权声明 Copyright (C) The Internet Society (1999). All Rights Reserved. 摘要 本文描述了一种对IP/UDP/RTP数据报头进行压缩的方法,它可以降低在低速串行链路上 的网络开销。多数情况下,三个头可压缩到2-4字节。 请赐教并将您的建议发送到工作组邮件列表rem-conf@es.net或直接给作者。 本文中的关键字“必须”,“必须不”,“要求的”,“应该”,“不应该”,“会”,“不会”, “建议”,“或许”,“可选的”在 RFC 2119 中解释。 目录 本备忘录的状态 1 版权声明 1 摘要 1 1. 介绍 2 2. 设想和折中 2 2.1. 单工与全双工 3 2.2. 分片与分层 3 3.压缩算法 3 3.1.基本概念 3 3.2 RTP数据包头压缩 4 3.3协议 5 3.4. RTCP控制包压缩 12 3.5.非RTP UDP包压缩 13 4.与分片的交互 13 5.压缩协商 13 6.致谢 14 7.参考文献 14 8. 安全性考虑 14 9.作者地址 15 10.版权声明 15 1. 介绍 随着实时传输协议(RTP)成为正式的RFC[1]发行,人们对于利用RTP实现不同的网络音视 频应用程序间互操作的兴趣也日益增长。然而,我们也注意到,当使用低速链路如14.4Kb/s 或28.8Kb/s拨号时,12字节的RTP头对于仅有20字节的负载而言开销实在太大。(为了减少 头占用的字节,一些已经在类似环境下存在的应用通常使用自定义的协议,而这样做的代价 就是削减了RTP相关的功能。) 事实上,正如在TCP中已经取得巨大成功,也可通过压缩技术来令IP/UDP/RTP包头变小。 这时,压缩可以针对于RTP头(在端到端应用中),或者IP,UDP,RTP的组合头(在Link-by-Link 应用中)。将40字节的组合头一起进行压缩比仅压缩12字节的RTP头更具实际效果,因为两 种情况下的结果大小均为约2-4字节。同时,由于延迟和丢失率都很低,对Link-by-Link应 用进行压缩性能上也更好。因此我们在这里定义的方法就是针对Link-by-link应用下 IP/UDP/RTP头进行组合压缩。 本文定义的压缩方案可应用于IPv4包、IPv6包或封装了多个IP头的包。为了能同时在IPv6 和IPv4下使用,这里定义的IP/UDP/RTP压缩符合[3]中规定的通用压缩框架。该框架把TCP 和非TCP定义为IP之上的两个传输类。本规范将IP/UDP/TCP从非TCP类中抽取出来创建为第三 类。 2. 设想和折中 本压缩方案的目标是,在不发送UDP校验和的情况下,将大多数包的IP/UDP/RTP头压缩到 2个字节,在带校验和时则压缩到4个字节。这一方案的提出主要是受使用14.4kb/s和 28.8kb/s拨号调制解调器发送音视频时遇到的相关问题所引起。这些链路提供全双工通信, 所以协议利用了这点,尽管协议在用于单工链路时可能性能会有所下降。该方案在本地链路 上往返时间(RTT)很低,从而实现性能最高。 为了降低低速链路下的延迟,除了在第四节中确定了分片和压缩中可能使用的一些交互 外,本规范并未提出大型数据包的分片和占先策略。分片方案可能会单独定义并与本压缩方 案配合使用。 应该注意到,实现的简单性是评价压缩方案的一个重要因素。通信服务器可能要用一个 处理器支持多达100个拨号调制解调器的数据压缩。因此,如下的考虑都是比较恰当的,即 在设计阶段为了实现简单而牺牲一些通用性,或者在设计上灵活通用但为了简单性可对设计 进行子集化。通过在压缩和解压器之间用更复杂的模型通信改变头字段还可以达成更好的压 缩效果,但其复杂性却是没必要的。下一节将讨论这里列出的一些折中方案。 2.1. 单工与全双工 在没有其它限制的情况下,单工链路上的压缩方案应成为首选。但为防止错误发生,单 工链路上的操作需要用一个含有压缩状态信息的未压缩包头进行周期性的刷新。如果明显的 错误信号可以返回,则恢复延迟也可以实质性地缩短,无错误情况的开销也会降低。为了实 现这些性能的优化,本规范包括了一个可逆向发送的明显错误指示。 在单工链路中,可以使用周期性刷新来取代。解压器一旦侦测到错误存在于某个特定的 流中,它可以简单地放弃该流中所有的包直到接收到一个未压缩的头为止,然后继续解压。 其致命弱点在于可能要在恢复解压前要放弃大量的包。周期性刷新的方法在[3]的3.3节中进 行描述,它应用于单工链路的IP/UDP/RTP压缩,或者应用于其它非TCP包流的高延迟链路。 2.2. 分片与分层 在低速链路上发送大型数据包所需时间而导致的延迟对于单向音频应用不算什么大问 题,因为接收方可以适应延迟变动。但对于交互式的交谈,最小端到端延迟是非常关键的。 对大的,非实时数据包进行分片以允许小的实时包在分片间隙进行传送可以降低这种延迟。 本规范只处理压缩,并且假定,如果包括分片,也将被处理为一个单独层。将分片和压 缩按这种方式进行集成并不可取,因为一旦如此,在没有必要或不可能进行分片的情况下, 连压缩都不能使用。类似地,应该避免预留协议的任何需求。除了要求链路层提供一些包类 型码,一个包长度指示和良好的错误检测外,该压缩方案可独立于任何其它机制而应用在本 地链路的两端。 相反,单独对IP/UDP和RTP层进行压缩丢失了太多的压缩效率,这些效率可以通过将它们 一起对待而得到。由于相同的函数可以应用于所有层,实现跨越这些协议层边界的方案是恰 当的。 3.压缩算法 本文定义的压缩算法主要利用了RFC 1144[2]描述的TCP/IP头压缩的设计。读者可以参考 该RFC获取更多的关于对包头进行压缩的基本动机和通用原理。 3.1.基本概念 对TCP头压缩的研究发现,IP和TCP头有一半的字节在整个连接期间保持不变,这正是降 低数据率的两个要素中的首要因素。因此,在发送一次未压缩头之后,可以将这些字段从其 后的压缩头中除去。其余的压缩来自对变化字段进行区分编码以减少长度,以及在通常情况 下根据包长度计算变化而完全删除掉变化字段。这一长度由链路层协议指示。 对于RTP头的压缩也可以采用一些相同的技术。不过最大的收获在于人们发现,尽管每个 包中总有几个字节要发生变化,但包与包之间的区别却是恒定的,因此二次差分为0。在会 话期间,通过维护压缩与解压器共享的未压缩头与一次差分序列,所需通信的便只有二次差 分为0的指示了。在这种情况下,如果不考虑任何信息丢失,则解压器在收到一个压缩包后 可以通过将一次差分结果加到保存的未压缩头来重建原始包头。象TCP/IP头压缩为多个同时 的TCP连接维护一个共享状态一样,IP/UDP/RTP压缩也应该为多个会话环境维护状态。一个 会话环境是由IP源地址和目的地址,UDP源端口和目的端口,以及RTP的SSRC字段定义。解压 器在实现时可以对这些字段使用哈希函数来检索存储的会话环境列表。压缩包携带一个称为 会话环境标识符或者CID的小整数来指示该包应该解释到哪个环境中。解压方可以使用CID 直接在存储的环境列表中来进行检索。 由于RTP压缩是无损压缩,它可应用于任何可从中受益的UDP通信。当然最可能的例子就 是RTP包,不过也可以使用试探法来判断一个包是否为RTP包,因为即便试探法给出的答案是 错的也不会造成什么损害。这样做需要对所有的UDP包或者至少对偶数端口号的包(见3.4节) 执行压缩算法。 为了避免将来无谓地重试,大多数压缩器在实现时都要维护包流的一个“拒绝缓存”来 记录那些多次作为RTP包尝试而压缩失败的包。压缩失败往往意味着潜在的RTP包头中一些在 多数时间应保持恒定字段却发生了变化,如负载类型字段。即便其它类似的字段都保持不变, 为了避免耗尽所有的可用会话环境,一个SSRC字段不断改变的包流也应放入拒绝缓存。拒绝 缓存可通过源IP地址和目的IP地址以及UDP端口对进行索引,而SSRC字段因为可能发生变化 不能用来作为索引。当RTP压缩失败,IP和UDP头仍然可以被压缩。分片后不是初始片的IP 包和长度不够容纳一个完整UDP头的包都不能作为FULL_HEADER发送。另外,没有容纳至少12 字节UDP数据的包也不能用于创建RTP环境。如果这样的包作为FULL_HEADER包发送,它后面 可以跟随COMPRESSED_UDP包但不能跟随COMPRESSED_RTP包。 3.2 RTP数据包头压缩 在IPv4包头中只有总长度,包ID和校验和字段会发生改变。因为在链路层已经提供了长 度,这里总长度是冗余的,同时由于本压缩方案必须依靠链路层实现良好的错误检测(如PPP 的CRC[4]),头校验和也可以省略掉。于是只剩下了包ID,而在假定没有IP分片的情况下它 也无参加通信。不过为了保持无损压缩,包ID的变化也将被传输。对每个包而言,包ID通常 每次加1或者一个很小的整数值。(有些系统中包ID的增量为交换的字节数,这对压缩效率 有一些轻微的影响。)而IPv6包头既没有包ID字段,也没有头校验和字段,只有负载长度字 段会发生变化。 由于在IP层和链路层均有相应字段,UDP头中的长度字段也是冗余的。如果选择不产生UDP 校验和则UDP的校验和字段为常数0。否则必须对校验和进行交互通信以保证无损压缩。一个 重要原则就是为需要的应用程序维护端到端的错误检测。 在RTP头中,作为特定环境标识的一部分,给定的环境的SSRC标识符是恒定不变的。对大 多数包而言,只有顺序号和时间戳是因包而异的。如果没有包丢失或者乱序,顺序号应按步 进值1逐包改变。对音频包,时间戳应按采样周期增加。对于视频,时间戳在每帧的第一个 包是发生改变,而在后面该帧的其它包中保持不变。如果每个视频帧只占据一个包,且视频 帧按照恒定的速率产生,则帧与帧之间时间戳的变化也是恒定的。 注意到每当这种情况出现,顺序号和时间戳字段的二次差分均为0,所以下一个包头的相应 字段值可通过前一个未压缩包头的该字段加上存在会话环境一次差分值得到。当二次差分不 为0时,变化量通常也要远小于字段中所有位的数目,所以可通过对新的一次差分进行编码 并传输该编码来达到压缩的目的,不用传输绝对值。 一个音频会话峰(talkspurt)中M位将在第一个包中设置,而一个视频帧中M位在最后一个 包中设置。如果它作为一个常量字段则每次变化都要发送整个RTP头,如此会造成压缩效率 明显下降。因此,压缩头中的一位将明确地携带M位。如果包通过RTP混合器流动,特别是音 频数据,则CSRC列表和CC记数将发生改变。但CSRC列表将在会话峰期间保持不变,所以它只 需在发生变化时才发送。 3.3协议 压缩协议必须维护一个状态牢靠的压缩器和解压器的共享信息集合。对每个IP/UDP/RTP 包流都有一个单独的通过源地址IP,目的地址IP,UDP端口对和RTP SSRC字段组合定义的会 话环境。要维护的会话环境数目可通过双方协商而定。每个环境通过一个8位或者16位的标 识符来标识,具体范围要根据协商的环境数量决定,所以最大值为65536。未压缩和压缩的 包都必须携带环境ID和一个4位的用来检测包通信中丢失的顺序号。每个环境都有自己的顺 序号空间,所以单个包的丢失只会影响到一个环境。 每个环境共享的信息包括如下项目 ? 完整的IP, UDP和RTP头,对最后一个由压缩器发送或者解压器重建的包,可能还 包括CSRC表。 ? IPv4 ID字段的一次差分结果,当收到环境中的一个未压缩IP头时初始化为1,每 次收到一个压缩包中的delta IPv4 ID字段时更新。 ? RTP时间戳字段的一次差分结果,当收到环境中的一个未压缩IP头时初始化为0, 每次收到一个压缩包中的delta RTP时间戳字段时更新。 ? 最后一个4位顺序号,用来检测双方通信时的包丢失情况。 ? IPv6(见[3])UDP包的非差分编码当前产生号。对于IPv4,如果没有使用下面定 义的COMPRESSED_NON_TCP包类型,则产生号可设置为0。 ? 一个经过双方协商,可选的环境相关的delta编码表(见3.3.4节)。 为了在不同的压缩和解压器形式下进行通信,本协议依靠链路层为除IPv4和IPv6外的四 种新的包格式提供指示: FULL_HEADER – 传送未压缩IP头和任何用来在解压方为特定环境建立未压缩头状态 的后续头和数据。FULL_HEADER包也携带了8或16位的会话环境标识符和4位的顺序号用来建 立双方的同步。格式见3.3.1节。 COMPRESSED_UDP – 传送压缩到6字节或更少字节(如禁用UDP校验和则通常为2字节) 的IP和UDP头,后面是任何未压缩形式的后续头(可能为RTP)和数据。当RTP头的常量字段有 所不同时才使用包类型。RTP包头包括一个会变化的SSRC字段值,所以可能重定义会话环境。 其格式在3.3.3节定义。 COMPRESSED_RTP – 表示RTP头和IP及UDP头一起压缩。该头的大小可以是2个字节,或 者当需要传送变化时更多一些。当二次差分值(至少在通常的常量字段)为0时使用包类型。 它包括delta编码,它是为了能在未压缩RTP头发送后并当改变发生时对于那些变化字段建立 一次差分队列。其格式在3.3.2中定义。 CONTEXT_STATE – 一种由解压器发送给压缩器的特殊包,用来传输已经或者可能已经 失去同步的环境ID。该包仅通过点到点链路发送,所以它不需要IP头。其格式在3.3.5中定 义。 当本压缩方案作为通用头压缩框架[3]的一部分用于IPv6时,还可使用另一种包类型: COMPRESSED_NON_TCP –无须进行差分编码传输[3]定义的压缩IP/UDP包。如果用于 IPv4,为了能携带IPv4 ID字段,它比前面所讲的COMPRESSED_UDP要多用1到2个字节。而IPv6 没有ID字段,这种非差分压缩在包丢失时更有弹性。 在PPP协议[4]中为这些包格式分配代码应由IANA决定。 3.3.1. FULL_HEADER (未压缩) 包格式 此处定义的FULL_HEADER和[3]中所给出的定义是一致的。在那里有关于各种方案的 完整设计细节。它在IPv4中通常就是一个IP头,后面接着是一个UDP头和UDP负载(可能为一 个RTP头及其负载)。不过,FULL_HEADER也可以携带IP封装的包,其中可能有两个IP头 及其相应的UDP和RTP。对于IPv6,该包还可能是IPv6和IPv4头的组合。通常每个后续头都 由前一个头的类型字段来指示。 FULL_HEADER包与IPv4或IPv6包的区别在于它必须携带压缩环境ID和4位的顺序号。为了 避免头变大,这些值被插入到IP和UDP头的长度字段中,因为实际的长度可以根据链路层提 供的长度推算出来。这里需要2个16位长的字段:它们来自包中的头两个可用头。对于 IPv4/UDP包,第一个长度字段是IP头总长度字段,第二个字段是UDP头长度字段。对于IPv4 封装包,第一个长度字段为第一个IP头的总长度字段,第二个字段是第二个IP头的总长度字 段。 如5.3.2节所规定,环境ID(CID)和4位顺序号的位置取决于是采用8位还是16位环境ID, 如下图所示(16位宽,左边为最高位): 对于8位环境ID: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0|1| Generation| CID | 第一长度字段 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 0 | seq | 第二长度字段 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 对于16位环境ID: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1|1| Generation| 0 | seq | 第一长度字段 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | CID | 第二长度字段 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 第一长度字段的起始位表示CID的长度。CID的长度要么对于所有环境均相同,要么必须 提供两个额外包类型来分别指示COMPRESSED_UDP和COMPRESSED_RTP包格式采用8位还是16位 CID。 对于IP/UDP/RTP压缩方案,第一长度字段的第二位为1表示当前为4位顺序号。 在IPv6的COMPRESSED_NON_TCP包中使用Generation字段方法如[3]所述。IPv4实现不使用 COMPRESSED_NON_TCP包,压缩器应该将generation字段设置为0。为了使IPv4和IPv6操作一 致,当解压器接收到Generation值后就将它存在环境中,并在CONTEXT_STATE包中返回最近 的值。 当接收到一个FULL_HEADER时,接收方将整个头存在由环境ID选择的环境中。4位顺序号 也存在环境中,从而可实现解压器和压缩器的同步。在使用COMPRESSED_NON_TCP包时,顺序 号插入到该包的“Data字段”中,并且D位设置参照[3]的第6节所述。在接收到 COMPRESSED_NON_TCP包后,接收方将Generation号和存在环境中的值进行比较。如果不同, 则环境已经过期,需要用该FULL_HEADER包来进行刷新。如果一致,则压缩的IP和UDP头信息, 顺序号,以及RTP头都存入已保存的环境中。 保存环境所需要的内存数量取决于FULL_HEADER中到底封装了多少个头。最大头的大小可 通过压缩/解压缩双方协商得到。 3.3.2. COMPRESSED_RTP包格式 如果包中RTP头的二次差分值为0,则解压器只需在前一个包的未压缩头上加上存储的一 次差分值就可以重建该包。双方之间只需传输会话环境标识符和顺序号就可以维持同步和检 测出丢失包。 如果包中RTP头某些字段的二次差分值不为0,则要在双方要传输这些字段的新的一次差 分结果的压缩编码。除了要把新的一次差分值加到解压器会话环境的未压缩头上,也要加到 那些二次差分为0的后续包的相应字段上并显式地存储到环境里。每当一次差分改变时,都 要对其进行传输和存储。在实际应用中,唯一需要用到一次差分的字段就是IPv4 ID字段和 RTP时间戳字段。 RTP顺序号字段的增量为1。如果顺序号变化不是1,则必须进行通信以报告该区别,但并 不因此为下一个包重新设置期望的变化值。期望的一次差分值仍然为1,这样如果下一个包 按顺序来到就不用再为变化进行通信。 对于RTP时间戳,当发送FULL_HEADER, COMPRESSED_NON_TCP和COMPRESSED_UDP包刷新RTP 状态时,存储的一次差分初始化为0。如果下一个包的时间戳一样(如相同的视频帧),则二 次差分值为0。否则必须将两个包时间戳的差别作为新的一次差分传输并存入环境中,该值 将被加到解压器环境存储的未压缩头时间戳上。每当后续包的一次差分改变时,都要用该变 化来更新环境。 类似地,由于IPv4 ID字段每次递增1,当用FULL_HEADER刷新状态或以非压缩形式发送携 带ID字段的COMPRESSED_NON_TCP包时,该字段的一次差分初始化为1。然后,每当一次差分 改变其变化都会重传并存到环境中。 这里还用了一个掩蔽码来表示哪个字段发生了非预期变化。除了小链路顺序号外,要在 压缩的IP/UDP/RTP头中进行传输的项列表如下: I = IPv4包ID (非IPv4头为常数0) U = UDP校验和 M = RTP标志位 S = RTP顺序号 T = RTP时间戳 L = RTP CSRC记数和列表 如果用4位作为链路顺序号来进行丢失检测,包头中就没有足够的位逐一分配给上面的几 项并填充到一个单字节中随环境ID发送。 因为发送源要么在会话中所有的包里包括UDP校验和,要么就根本不用校验和,所以没必 要显式地携带U位表示UDP校验和的存在。如果以未压缩包头初始化会话状态时其校验和非0, 就说明在所有的后续压缩包中都将插入16位的未编码校验和,直到发送了另一个未压缩包改 变该设置。对于剩余的几项,用于CSRC记数和列表的L位可能是使用频率最低的。与其专门 在掩蔽码中用一位来表示CSRC改变,还不如采用另外一种不常用的位组合。该位组合称为 MSTI。如果IP包ID,RTP标志位,RTP顺序号和RTP时间戳的位都已经被使用,这种特殊情况 表示其后可能有一种扩展形式的压缩RTP包头。该包头将包括一个额外字节,其中含有4位加 上CC记数的实际值。当CSRC列表(长度由CC记数表示)出现在未压缩RTP头中时也将被包含 其中。 假设RTP头中的其余字段(版本, P位, X位, 负载类型和SSRC标识符)都保持相对恒定。 特别地,对于给定的环境SSRC标识符定义为常量,因为SSRC标识符是选择环境的一个因素。 如果任何其它字段发生变化,都必须按照3.3.3节要求发送未压缩RTP包。 下图中,带点划线的压缩IP/UDP/RTP头表示可选字段。最高位为0。多字节字段按照网络 字节顺序发送(最高字节在先)。Delta字段通常如图所示为单字节,但根据具体delta值也可 能为2或3字节,如3.3.4节所解释。 0 1 2 3 4 5 6 7 +...............................+ : 会话环境 ID 的msb : (如果使用16位CID) +-------------------------------+ | 会话环境 ID 的lsb | +---+---+---+---+---+---+---+---+ | M | S | T | I | 链路顺序号 | +---+---+---+---+---+---+---+---+ : : + UDP 校验和 + (如果环境中校验和为非0) : : +...............................+ : : + "RANDOM" fields + (如果被封装) : : +...............................+ : M'| S'| T'| I'| CC : (如果MSTI = 1111) +...............................+ : delta IPv4 ID : (如果I或I' = 1) +...............................+ : delta RTP 顺序号 : (如果S或S' = 1) +...............................+ : delta RTP 时间戳 : (如果T或T' = 1) +...............................+ : : : CSRC list : (如果MSTI = 1111 : : 并且CC非0) : : +...............................+ : : : RTP 头扩展 : (如果环境中设置了X位) : : : : +-------------------------------+ | | | RTP 数据 | / / / / | | +-------------------------------+ : 填充 : (如果环境中设置了P位) +...............................+ 如果FULL_HEADER初始化的环境中IPv4头数目多余1,则封装头的IP ID字段必须如[3]所 述按照绝对值形式发送。这些字段标识为"RANDOM"字段。它们按照与原始包中相同的顺序被 插入COMPRESSED_RTP包,如图所示,其后紧接着是UDP校验和或MSTI字节。除非IPv4包正好 在UDP头之前,该头的IP ID才会被区别发送,例如,如果二次差分为0,或者二次差分不为0 但该字段是作为delta IPv4 ID字段它就不占任何位。如果没有IPv4头正好位于UDP头之前, 则I位必须为0且不应存在delta IPv4 ID字段。 3.3.3. COMPRESSED_UDP包格式 如果RTP头中任何一般情况下应为常量的字段(如负载类型字段)发生了变化,则必须发 送一个非压缩RTP头。如果IP和UDP头不需要更新,则该RTP头可以用COMPRESSED_UDP包携带, 而不必用FULL_HEADER包。除了M,S和T为为常数0以及没有相应的delta字段以外, COMPRESSED_UDP包同COMPRESSED_RTP格式相同: 0 1 2 3 4 5 6 7 +...............................+ : 会话环境ID的msb : (如果使用16位CID) +-------------------------------+ | 会话环境ID的lsb | +---+---+---+---+---+---+---+---+ | 0 | 0 | 0 | I | 链路顺序号 | +---+---+---+---+---+---+---+---+ : : + UDP 校验和 + (如果环境中校验和非0) : : +...............................+ : : + "RANDOM" 字段 + (如果被封装) : : +...............................+ : delta IPv4 ID : (如果I = 1) +-------------------------------+ | UDP 数据 | : (非压缩RTP ) : 请注意,这里IP/UDP头的压缩形式和[3]中定义的COMPRESSED_NON_TCP包类型不同。其目 的是象IPv4所允许的那样,当禁用UDP校验和时使压缩目标达到2字节。[3]中定义的协议没 有使用UDP包的差分编码,所以在用于IPv4时,除了前面的两个压缩字节,还有两个字节的 IP ID和两个字节的非0 UDP校验和都要进行传输。对于IPv6,可使用COMPRESSED_NON_TCP包 类型来替代。 3.3.4.差分编码Encoding of differences COMPRESSED_RTP和COMPRESSED_UDP包的delta字段为变长编码,可将压缩数据映射到更多 的通常使用值。下面规定了一种优化的哈夫曼编码作为缺省编码,推荐在实现表驱动delta 编/解码器来为会话进行面向表协商时使用。针对一定范围内数据的测试表明,在合理的表 规模下基于对位流进行顺序解释的编码执行速度比非表驱动的实现要快,这种缺省表和哈夫 曼编码就是例子。缺省delta编码规范见下表。该编码在IP ID和RTP顺序号变化很小的情况 下可高效编码,此时压缩器发出的包丢失,但仍能将大多数音视频deltas保持为2字节。左 边的列是要编码的10进制数,右边的列是16进制显示的编码后按发送顺序排列(网络字节顺 序)的字节序列。其中显示了相临范围的首尾值,其余均省略: 十进制 16进制 -16384 C0 00 00 : : -129 C0 3F 7F -128 80 00 : : -1 80 7F 0 00 : : 127 7F 128 80 80 : : 16383 BF FF 16384 C0 40 00 : : 4194303 FF FF FF 对于正数,在一个字节内直接以0到127表示。如果该字节的最高两位是10或者11,则表示 分别表示要扩展到2或3个字节。低6位按照降序同后面紧跟的1到2个字节联合表示一个14或 22位值。 当包出现乱序或者在MPEG视频的RTP时间戳故意被打乱时可能会出现负数的delta值。这 种情况很少见,所以负数值编码范围更小,仅使用表中正数值剩余的部分。 RTP时间戳值中小于-16384或大于4194303的改变都会导致强制发送未压缩的 FULL_HEADER, COMPRESSED_NON_TCP或COMPRESSED_UDP类型RTP头。IP ID和RTP顺序号字段都 只有16位,所以这些字段的负数delta都掩蔽为16位再进行编码(作为16位正数)。 3.3.5.错误恢复 除了由FULL_HEADER和COMPRESSED_NON_TCP包设置外,当特定环境的4位顺序号增量不为1 时,解压器必须将环境置为无效并发送CONTEXT_STATE包回压缩器表示环境已经无效。无效 环境的所有当前包都必须丢弃,直到收到一个FULL_HEADER或COMPRESSED_NON_TCP重建稳定 状态为止(除非使用了本节后面将描述的"twice"算法。)。由于在这一过渡时期可能会有 多个压缩包到达,解压器应该为每个收到的压缩包重新传输CONTEXT_STATE包,但应该限制 重传输率以避免反向通道的溢出。 当链路中出现错误时,链路层通常将放弃损坏的包,但可以提供一个错误指示。在相同 环境的另一个包传输前可能会消耗一些时间,然后该包将被解压器发现乱序而抛弃,造成至 少两个包丢失。链路提供显示地错误指示是为了快速恢复,解压器可以有选择地发送一个咨 询CONTEXT_STATE包为最近的一个或多个活动环境(没必要为所有环境)列出最近有效的顺 序号和generation号。对于给定的环境,如果压缩器还没有发送更高顺序号的压缩包,并且 generation号和当前号一致,则不需要任何校正动作。否则压缩器就得选择标志环境为无效 以便下一个包以FULL_HEADER或COMPRESSED_NON_TCP模式(如果generation号不一致则需要 FULL_HEADER)发送。不过可以注意到,如果链路层RTT时间比包间隙很大,这时已经有多个 不同环境的包沿链路发送了,这使得在压缩器收到CONTEXT_STATE包时顺序号可能已经增大。 其结果就是有些环境被没必要地变为无效,导致额外地消耗了带宽。 下图所示为CONTEXT_STATE包的格式。第一个字节是类型码,允许CONTEXT_STATE包类型 被[3]中定义的通用压缩框架中的多个压缩方案共享。包其余部分的内容取决于具体的压缩 方案。在本文的IP/UDP/RTP压缩方案中,其余部分组织为一个块的列表,可以为多个环境指 示状态,前面为一个字节表示的块数目。 IP/UDP/RTP压缩方案中使用了两个类型码值。1表示采用8位会话环境: 0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 1 = IP/UDP/RTP 如CID为8位 | +---+---+---+---+---+---+---+---+ | 会话计数 | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | 会话环境ID | +---+---+---+---+---+---+---+---+ | I | 0 | 0 | 0 | 顺序号 | +---+---+---+---+---+---+---+---+ | 0 | 0 | generation | +---+---+---+---+---+---+---+---+ ... +---+---+---+---+---+---+---+---+ | 会话环境 ID | +---+---+---+---+---+---+---+---+ | I | 0 | 0 | 0 | 顺序号 | +---+---+---+---+---+---+---+---+ | 0 | 0 | generation | +---+---+---+---+---+---+---+---+ 2表示使用16位的会话环境ID。 会话环境ID按照网络字节顺序发送(最高位优先): 0 1 2 3 4 5 6 7 +---+---+---+---+---+---+---+---+ | 2 = IP/UDP/RTP 如CID为16位 | +---+---+---+---+---+---+---+---+ | 会话数目 | +---+---+---+---+---+---+---+---+ +---+---+---+---+---+---+---+---+ | | + 会话环境ID + | | +---+---+---+---+---+---+---+---+ | I | 0 | 0 | 0 | 顺序号 | +---+---+---+---+---+---+---+---+ | 0 | 0 | generation | +---+---+---+---+---+---+---+---+ ... +---+---+---+---+---+---+---+---+ | | + 会话环境ID + | | +---+---+---+---+---+---+---+---+ | I | 0 | 0 | 0 | 顺序号 | +---+---+---+---+---+---+---+---+ | 0 | 0 | generation | +---+---+---+---+---+---+---+---+ 在标志为无效,要发送COMPRESSED_NON_TCP包或FULL_HEADER的环境中,"I"位应设置为1。 如果I为0,则环境处于咨询状态。I位设为0表示、在链路错误指示后要发送环境咨询状态。 由于CONTEXT_STATE包本身也可能丢失,所以允许对一个或多个块重传输。但希望只有在接 收到另一个包时才触发重传输,如果链路几乎空闲时,可用一个相对较长的计时器来触发重 传输(如定为1秒)。如果给定环境的块被重传输,它可能与用来刷新环境的FULL_HEADER或 COMPRESSED_NON_TCP错过。这时压缩器可以忽略错误指示。 在需要传输UDP校验和的情况下,解压器可以尝试使用[3]的10.1节描述的"twice"算法。 在该算法中,假设delta值与丢失包和随后接收的一个包相同则delta要多次应用。校验和匹 配表示成功。对于这里定义的方案,顺序号的区别说明了delta必须要应用的次数。注意, 一个不正确的正指示可能会带来一些小风险。即便这里"twice"算法应用成功,也建议发送 一个FULL_HEADER或COMPRESSED_NON_TCP包。 有些错误可能无法检测出来,比如一排丢失了16个包且链路层没有提供错误指示。在这 种情况下解压器将产生无效的包。如果UDP校验和正在传输,接收方可能会检测到无效包并 且丢弃他们,但是接收方无法通知解压器。因此,建议解压器周期性地验证UDP校验和,如 每16个包验证一次。如果发现错误,它应将环境置为无效并且用一个CONTEXT_STATE包来通 知压缩器。 3.4. RTCP控制包压缩 按照RTP协议规定,数据通过偶数端口发送,而RTCP包通过下一个奇数号端口进行发送, 因此可以为RTP和RTCP包分别制定压缩方案。对于RTCP,压缩同时针对包头和数据本身,即 不同包类型的内容。SR和RR RTCP包中的数字内容不好压缩,但SDES包中的文本信息可以压 缩到一个屏蔽位表示每个存在并已压缩的项(用于对SDES NOTE项进行计时并允许端系统为 计算间隔而测量平均RTCP包大小)。 然而由于一些原因(尽管压缩应该应用于IP和UDP头),在本压缩方案中并不对RTCP头和 数据进行压缩。RTP协议规范建议应该按比例决定RTCP包间隙,以便所有会话中参与者占用 的RTCP总带宽不超过5%的会话总带宽,所以压缩RTCP并没有太多的好处。压缩SDES项会造成 每个环境ID要存储的共享状态明显增加。并且,当通过一个RTP混合器发送多个源的SDES信 息时,为了允许压缩就必须为每个SSRC标识符维护一个单独的RTCP会话环境。在一个超过255 个参与者的会话中,即使只有一个参与者发送数据也会造成环境缓存中大量的垃圾数据。假 设RTCP包作为COMPRESSED_UDP形式发送,即使不对其进行压缩,多数情况下它所占压缩链路 的比重也不超过5%。鉴于非压缩RTCP包消耗的带宽不超过会话总带宽的5%,对于一个长度为 90字节的典型RTCP包,只要RTP数据包负载长度至少为108字节,则RTCP所占用的压缩带宽比 率也会不超过5%。如果RTP负载长度比较小,该比率会有所提高,但对于负载大小为37字节 的RTP包而言,该比例仍不会超过7%。如果RTP负载数据包很大,则压缩RTCP所占的比例小于 非压缩RTCP(如对1000字节的包该比例为4%)。 3.5.非RTP UDP包压缩 如前所述,COMPRESSED_UDP包可用来压缩未携带RTP信息的UDP包。UDP之头后的任何数据 都不太可能象在RTP头中相应字段一样有恒定不变的值。特别地,SSRC字段就很可能发生改 变。因此为了避免当SSRC字段改变时用光环境槽,很有必要明了这些非RTP的UDP包流(由于 该字段是用来标识特定RTP环境的一部分)。每一个这样的流都可以拥有一个环境,但编码 器只在环境中设置一个标志来表示SSRC字段的变化可被忽略,且将发送COMPRESSED_UDP包而 非COMPRESSED_RTP包。 4.与分片的交互 为了减少延迟,在连接RTP头时使用分片的方法对大的非实时包进行分割,以便允许小的 实时包能利用分割间隙进行发送。由于这样的交错发送会改变解压器的接收到的包顺序,导 致错误出现,我们在此均假定这些大数据包对于压缩器到解压器的通道是旁路的。头压缩对 大数据包而言并不重要,因为其开销所占比重较小。 如果有些来自RTP会话环境的包被选中参加分片(主要取决于大小),而另一些不参加分 片,则可能造成乱序的现象出现。这将导致压缩效率的下降,因为在顺序空间中这些被分割 的大包会被当作是丢失。但是,由于RTP顺序号将在接收方被正确重建且允许应用程序进行 重排序,所以暂时的乱序也不会造成过于严重的问题。就象链路层自己能检测到的链路错误 一样,分片机制使用顺序信息检测到的链路错误可以通过一个CONTEXT_STATE消息指示给压 缩器。 环境ID字节位于COMPRESSED_RTP头的最前面,如果这样可行并经过协商,可以把该字节 分派给分片层。由于压缩器可以强制分配环境ID,其值可设置为和分片层中的环境标识符一 致。 5.压缩协商 在特定链路上使用IP/UDP/RTP压缩属于链路层协议的功能。所以要为具体协议单独定义 协商方式,如为PPP[4]。下面是可能要协商的项: ? 环境ID的大小。 ? 环境中包头栈的最大值。 ? 一个对delta值解码的环境相关表。 6.致谢 很多朋友都为本压缩方案的设计和相关问题的解决付出了努力。1996年3月,Scott Petrack在落山矶的AVT工作组发起了关于RTP头压缩的讨论。Carsten Bormann开发了低速链 路上带传输控制的压缩体系结构,同时对于本文描述的方案也作出了一些特别贡献。David Oran独立开发了一个基于本文类似思想的Note,并建议使用PPP多链路协议进行分片。Mikael Degermark在把本方案同IPv6压缩框架进行集成方面作出了贡献。 7.参考文献 [1] Schulzrinne, H., Casner, S., Frederick, R. and V. Jacobson, "RTP: A Transport Protocol for real-time applications", RFC 1889, January 1996. [2] Jacobson, V., "TCP/IP Compression for Low-Speed Serial Links", RFC 1144, February 1990. [3] Degermark, M., Nordgren, B. and S. Pink, "Header Compression for IPv6", RFC 2507, February 1999. [4] Simpson, W., "The Point-to-Point Protocol (PPP)", STD 51, RFC 1661, July 1994. [5] Hoffman, D., Fernando, G., Goyal, V. and M. Civanlar, "RTP Payload Format for MPEG1/MPEG2 Video", RFC 2250, January 1998. 8.安全性考虑 由于加密会消除本压缩方案所试图实现的冗余性,所以为了在低带宽链路上完成操作我们考 虑可能要放弃加密。不过对于那些需要压缩数据而不是包头的情况,RTP已经规定了另一种可选 的加密方法,它只压缩RTP负载而将包头保持明文。这样压缩依然可以使用。 一个有问题的或是恶意的压缩器可能使解压器重组的包同原始包不一致却有有效的IP, IDP, RTP头,甚至有效的UDP校验和。这样的破坏可通过端到端认证和完整性机制(它不会受到压缩的 影响)检测出来。认证头中的恒定部分可通过[3]所描述的方法进行压缩。 本协议在发送CONTEXT_STATE控制包时没有执行任何认证。有权访问压缩器和解压器之间链路 的攻击者可以通过插入错误的包使压缩效率下降,甚至导致链路拥塞。不过他们还可以通过许多 其他方式来破坏通信。如果使用的压缩技术会造成接收端计算负荷不均衡,系统就有潜在拒绝服 务式攻击的威胁。攻击者可通过插入病态报文造成解压缩复杂性增加,导致接收端过载和处理其 它流的效率降低。然而,本压缩方案并未显示出有任何明显的波动性。 对本协议的安全性回顾并没有发现任何多余的安全性考虑。 9.作者地址 Stephen L. Casner Cisco Systems, Inc. 170 West Tasman Drive San Jose, CA 95134-1706 United States EMail: casner@cisco.com Van Jacobson Cisco Systems, Inc. 170 West Tasman Drive San Jose, CA 95134-1706 United States EMail: van@cisco.com 10.版权声明 Copyright (C) The Internet Society (1999). All Rights Reserved. This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English. The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns. 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. RFC2508 Compressing IP/UDP/RTP Headers for Low-Speed Serial Links 低速串行链 路下IP/UDP/RTP数据包头的压缩 1 RFC文档中文翻译计划