Network Working Group                                       G. Pelletier
Request for Comments: 5225                                   K. Sandlund
Category: Standards Track                                       Ericsson
                                                              April 2008
        
Network Working Group                                       G. Pelletier
Request for Comments: 5225                                   K. Sandlund
Category: Standards Track                                       Ericsson
                                                              April 2008
        

RObust Header Compression Version 2 (ROHCv2): Profiles for RTP, UDP, IP, ESP and UDP-Lite

健壮的头压缩版本2(ROHCv2):RTP、UDP、IP、ESP和UDP Lite的配置文件

Status of This Memo

关于下段备忘

This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited.

本文件规定了互联网社区的互联网标准跟踪协议,并要求进行讨论和提出改进建议。有关本协议的标准化状态和状态,请参考当前版本的“互联网官方协议标准”(STD 1)。本备忘录的分发不受限制。

Abstract

摘要

This document specifies ROHC (Robust Header Compression) profiles that efficiently compress RTP/UDP/IP (Real-Time Transport Protocol, User Datagram Protocol, Internet Protocol), RTP/UDP-Lite/IP (User Datagram Protocol Lite), UDP/IP, UDP-Lite/IP, IP and ESP/IP (Encapsulating Security Payload) headers.

本文档规定了ROHC(鲁棒头压缩)配置文件,可有效压缩RTP/UDP/IP(实时传输协议、用户数据报协议、互联网协议)、RTP/UDP Lite/IP(用户数据报协议Lite)、UDP/IP、UDP Lite/IP、IP和ESP/IP(封装安全有效载荷)头。

This specification defines a second version of the profiles found in RFC 3095, RFC 3843 and RFC 4019; it supersedes their definition, but does not obsolete them.

本规范定义了RFC 3095、RFC 3843和RFC 4019中配置文件的第二个版本;它取代了它们的定义,但并没有使它们过时。

The ROHCv2 profiles introduce a number of simplifications to the rules and algorithms that govern the behavior of the compression endpoints. It also defines robustness mechanisms that may be used by a compressor implementation to increase the probability of decompression success when packets can be lost and/or reordered on the ROHC channel. Finally, the ROHCv2 profiles define their own specific set of header formats, using the ROHC formal notation.

ROHCv2概要文件对控制压缩端点行为的规则和算法进行了大量简化。它还定义了稳健性机制,当数据包在ROHC信道上丢失和/或重新排序时,压缩器实现可以使用这些机制来增加解压缩成功的概率。最后,ROHCv2概要文件使用ROHC形式表示法定义了它们自己特定的头格式集。

Table of Contents

目录

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
   2.  Terminology . . . . . . . . . . . . . . . . . . . . . . . . .   4
   3.  Acronyms  . . . . . . . . . . . . . . . . . . . . . . . . . .   7
   4.  Background (Informative)  . . . . . . . . . . . . . . . . . .   7
     4.1.  Classification of Header Fields . . . . . . . . . . . . .   7
     4.2.  Improvements of ROHCv2 over RFC 3095 Profiles . . . . . .   8
     4.3.  Operational Characteristics of ROHCv2 Profiles  . . . . .  10
   5.  Overview of the ROHCv2 Profiles (Informative) . . . . . . . .  10
     5.1.  Compressor Concepts . . . . . . . . . . . . . . . . . . .  11
       5.1.1.  Optimistic Approach . . . . . . . . . . . . . . . . .  11
       5.1.2.  Tradeoff between Robustness to Losses and to
               Reordering  . . . . . . . . . . . . . . . . . . . . .  11
       5.1.3.  Interactions with the Decompressor Context  . . . . .  13
     5.2.  Decompressor Concepts . . . . . . . . . . . . . . . . . .  14
       5.2.1.  Decompressor State Machine  . . . . . . . . . . . . .  14
       5.2.2.  Decompressor Context Management . . . . . . . . . . .  17
       5.2.3.  Feedback Logic  . . . . . . . . . . . . . . . . . . .  19
   6.  ROHCv2 Profiles (Normative) . . . . . . . . . . . . . . . . .  19
     6.1.  Channel Parameters, Segmentation, and Reordering  . . . .  19
     6.2.  Profile Operation, Per-context  . . . . . . . . . . . . .  20
     6.3.  Control Fields  . . . . . . . . . . . . . . . . . . . . .  21
       6.3.1.  Master Sequence Number (MSN)  . . . . . . . . . . . .  21
       6.3.2.  Reordering Ratio  . . . . . . . . . . . . . . . . . .  21
       6.3.3.  IP-ID Behavior  . . . . . . . . . . . . . . . . . . .  22
       6.3.4.  UDP-Lite Coverage Behavior  . . . . . . . . . . . . .  22
       6.3.5.  Timestamp Stride  . . . . . . . . . . . . . . . . . .  22
       6.3.6.  Time Stride . . . . . . . . . . . . . . . . . . . . .  22
       6.3.7.  CRC-3 for Control Fields  . . . . . . . . . . . . . .  23
     6.4.  Reconstruction and Verification . . . . . . . . . . . . .  23
     6.5.  Compressed Header Chains  . . . . . . . . . . . . . . . .  24
     6.6.  Header Formats and Encoding Methods . . . . . . . . . . .  25
       6.6.1.  baseheader_extension_headers  . . . . . . . . . . . .  26
       6.6.2.  baseheader_outer_headers  . . . . . . . . . . . . . .  26
       6.6.3.  inferred_udp_length . . . . . . . . . . . . . . . . .  26
       6.6.4.  inferred_ip_v4_header_checksum  . . . . . . . . . . .  26
       6.6.5.  inferred_mine_header_checksum . . . . . . . . . . . .  27
       6.6.6.  inferred_ip_v4_length . . . . . . . . . . . . . . . .  28
       6.6.7.  inferred_ip_v6_length . . . . . . . . . . . . . . . .  28
       6.6.8.  Scaled RTP Timestamp Compression  . . . . . . . . . .  29
       6.6.9.  timer_based_lsb . . . . . . . . . . . . . . . . . . .  30
       6.6.10. inferred_scaled_field . . . . . . . . . . . . . . . .  31
       6.6.11. control_crc3_encoding . . . . . . . . . . . . . . . .  32
       6.6.12. inferred_sequential_ip_id . . . . . . . . . . . . . .  33
       6.6.13. list_csrc(cc_value) . . . . . . . . . . . . . . . . .  34
     6.7.  Encoding Methods with External Parameters as Arguments  .  38
     6.8.  Header Formats  . . . . . . . . . . . . . . . . . . . . .  40
        
   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . .   4
   2.  Terminology . . . . . . . . . . . . . . . . . . . . . . . . .   4
   3.  Acronyms  . . . . . . . . . . . . . . . . . . . . . . . . . .   7
   4.  Background (Informative)  . . . . . . . . . . . . . . . . . .   7
     4.1.  Classification of Header Fields . . . . . . . . . . . . .   7
     4.2.  Improvements of ROHCv2 over RFC 3095 Profiles . . . . . .   8
     4.3.  Operational Characteristics of ROHCv2 Profiles  . . . . .  10
   5.  Overview of the ROHCv2 Profiles (Informative) . . . . . . . .  10
     5.1.  Compressor Concepts . . . . . . . . . . . . . . . . . . .  11
       5.1.1.  Optimistic Approach . . . . . . . . . . . . . . . . .  11
       5.1.2.  Tradeoff between Robustness to Losses and to
               Reordering  . . . . . . . . . . . . . . . . . . . . .  11
       5.1.3.  Interactions with the Decompressor Context  . . . . .  13
     5.2.  Decompressor Concepts . . . . . . . . . . . . . . . . . .  14
       5.2.1.  Decompressor State Machine  . . . . . . . . . . . . .  14
       5.2.2.  Decompressor Context Management . . . . . . . . . . .  17
       5.2.3.  Feedback Logic  . . . . . . . . . . . . . . . . . . .  19
   6.  ROHCv2 Profiles (Normative) . . . . . . . . . . . . . . . . .  19
     6.1.  Channel Parameters, Segmentation, and Reordering  . . . .  19
     6.2.  Profile Operation, Per-context  . . . . . . . . . . . . .  20
     6.3.  Control Fields  . . . . . . . . . . . . . . . . . . . . .  21
       6.3.1.  Master Sequence Number (MSN)  . . . . . . . . . . . .  21
       6.3.2.  Reordering Ratio  . . . . . . . . . . . . . . . . . .  21
       6.3.3.  IP-ID Behavior  . . . . . . . . . . . . . . . . . . .  22
       6.3.4.  UDP-Lite Coverage Behavior  . . . . . . . . . . . . .  22
       6.3.5.  Timestamp Stride  . . . . . . . . . . . . . . . . . .  22
       6.3.6.  Time Stride . . . . . . . . . . . . . . . . . . . . .  22
       6.3.7.  CRC-3 for Control Fields  . . . . . . . . . . . . . .  23
     6.4.  Reconstruction and Verification . . . . . . . . . . . . .  23
     6.5.  Compressed Header Chains  . . . . . . . . . . . . . . . .  24
     6.6.  Header Formats and Encoding Methods . . . . . . . . . . .  25
       6.6.1.  baseheader_extension_headers  . . . . . . . . . . . .  26
       6.6.2.  baseheader_outer_headers  . . . . . . . . . . . . . .  26
       6.6.3.  inferred_udp_length . . . . . . . . . . . . . . . . .  26
       6.6.4.  inferred_ip_v4_header_checksum  . . . . . . . . . . .  26
       6.6.5.  inferred_mine_header_checksum . . . . . . . . . . . .  27
       6.6.6.  inferred_ip_v4_length . . . . . . . . . . . . . . . .  28
       6.6.7.  inferred_ip_v6_length . . . . . . . . . . . . . . . .  28
       6.6.8.  Scaled RTP Timestamp Compression  . . . . . . . . . .  29
       6.6.9.  timer_based_lsb . . . . . . . . . . . . . . . . . . .  30
       6.6.10. inferred_scaled_field . . . . . . . . . . . . . . . .  31
       6.6.11. control_crc3_encoding . . . . . . . . . . . . . . . .  32
       6.6.12. inferred_sequential_ip_id . . . . . . . . . . . . . .  33
       6.6.13. list_csrc(cc_value) . . . . . . . . . . . . . . . . .  34
     6.7.  Encoding Methods with External Parameters as Arguments  .  38
     6.8.  Header Formats  . . . . . . . . . . . . . . . . . . . . .  40
        
       6.8.1.  Initialization and Refresh Header Format (IR) . . . .  40
       6.8.2.  Compressed Header Formats (CO)  . . . . . . . . . . .  41
     6.9.  Feedback Formats and Options  . . . . . . . . . . . . . . 100
       6.9.1.  Feedback Formats  . . . . . . . . . . . . . . . . . . 100
       6.9.2.  Feedback Options  . . . . . . . . . . . . . . . . . . 102
   7.  Security Considerations . . . . . . . . . . . . . . . . . . . 104
   8.  IANA Considerations . . . . . . . . . . . . . . . . . . . . . 105
   9.  Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . 105
   10. References  . . . . . . . . . . . . . . . . . . . . . . . . . 106
     10.1. Normative References  . . . . . . . . . . . . . . . . . . 106
     10.2. Informative References  . . . . . . . . . . . . . . . . . 107
   Appendix A.    Detailed Classification of Header Fields . . . . . 108
     A.1.  IPv4 Header Fields  . . . . . . . . . . . . . . . . . . . 109
     A.2.  IPv6 Header Fields  . . . . . . . . . . . . . . . . . . . 112
     A.3.  UDP Header Fields   . . . . . . . . . . . . . . . . . . . 113
     A.4.  UDP-Lite Header Fields  . . . . . . . . . . . . . . . . . 114
     A.5.  RTP Header Fields . . . . . . . . . . . . . . . . . . . . 115
     A.6.  ESP Header Fields . . . . . . . . . . . . . . . . . . . . 117
     A.7.  IPv6 Extension Header Fields  . . . . . . . . . . . . . . 117
     A.8.  GRE Header Fields . . . . . . . . . . . . . . . . . . . . 118
     A.9.  MINE Header Fields  . . . . . . . . . . . . . . . . . . . 119
     A.10. AH Header Fields  . . . . . . . . . . . . . . . . . . . . 120
   Appendix B.    Compressor Implementation Guidelines . . . . . . . 121
     B.1.  Reference Management  . . . . . . . . . . . . . . . . . . 121
     B.2.  Window-based LSB Encoding (W-LSB)  . . .  . . . . . . . . 121
     B.3.  W-LSB Encoding and Timer-based Compression  . . . . . . . 122
        
       6.8.1.  Initialization and Refresh Header Format (IR) . . . .  40
       6.8.2.  Compressed Header Formats (CO)  . . . . . . . . . . .  41
     6.9.  Feedback Formats and Options  . . . . . . . . . . . . . . 100
       6.9.1.  Feedback Formats  . . . . . . . . . . . . . . . . . . 100
       6.9.2.  Feedback Options  . . . . . . . . . . . . . . . . . . 102
   7.  Security Considerations . . . . . . . . . . . . . . . . . . . 104
   8.  IANA Considerations . . . . . . . . . . . . . . . . . . . . . 105
   9.  Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . 105
   10. References  . . . . . . . . . . . . . . . . . . . . . . . . . 106
     10.1. Normative References  . . . . . . . . . . . . . . . . . . 106
     10.2. Informative References  . . . . . . . . . . . . . . . . . 107
   Appendix A.    Detailed Classification of Header Fields . . . . . 108
     A.1.  IPv4 Header Fields  . . . . . . . . . . . . . . . . . . . 109
     A.2.  IPv6 Header Fields  . . . . . . . . . . . . . . . . . . . 112
     A.3.  UDP Header Fields   . . . . . . . . . . . . . . . . . . . 113
     A.4.  UDP-Lite Header Fields  . . . . . . . . . . . . . . . . . 114
     A.5.  RTP Header Fields . . . . . . . . . . . . . . . . . . . . 115
     A.6.  ESP Header Fields . . . . . . . . . . . . . . . . . . . . 117
     A.7.  IPv6 Extension Header Fields  . . . . . . . . . . . . . . 117
     A.8.  GRE Header Fields . . . . . . . . . . . . . . . . . . . . 118
     A.9.  MINE Header Fields  . . . . . . . . . . . . . . . . . . . 119
     A.10. AH Header Fields  . . . . . . . . . . . . . . . . . . . . 120
   Appendix B.    Compressor Implementation Guidelines . . . . . . . 121
     B.1.  Reference Management  . . . . . . . . . . . . . . . . . . 121
     B.2.  Window-based LSB Encoding (W-LSB)  . . .  . . . . . . . . 121
     B.3.  W-LSB Encoding and Timer-based Compression  . . . . . . . 122
        
1. Introduction
1. 介绍

The ROHC WG has developed a header compression framework on top of which various profiles can be defined for different protocol sets or compression requirements. The ROHC framework was first documented in [RFC3095], together with profiles for compression of RTP/UDP/IP (Real-Time Transport Protocol, User Datagram Protocol, Internet Protocol), UDP/IP, IP and ESP/IP (Encapsulating Security Payload) headers. Additional profiles for compression of IP headers [RFC3843] and UDP-Lite (User Datagram Protocol Lite) headers [RFC4019] were later specified to complete the initial set of ROHC profiles.

ROHC工作组开发了一个头部压缩框架,在此框架之上,可以为不同的协议集或压缩需求定义各种概要文件。ROHC框架首先记录在[RFC3095]中,以及RTP/UDP/IP(实时传输协议、用户数据报协议、互联网协议)、UDP/IP、IP和ESP/IP(封装安全有效负载)头的压缩配置文件。随后指定了用于压缩IP头[RFC3843]和UDP Lite(用户数据报协议Lite)头[RFC4019]的其他配置文件,以完成ROHC配置文件的初始设置。

This document defines an updated version for each of the above mentioned profiles, and the definitions depend on the ROHC framework as found in [RFC4995]. The framework is required reading to understand the profile definitions, rules, and their role.

本文件定义了上述每个概要文件的更新版本,定义取决于[RFC4995]中的ROHC框架。需要阅读该框架才能理解概要文件定义、规则及其作用。

Specifically, this document defines header compression schemes for:

具体而言,本文档定义了以下标题压缩方案:

o RTP/UDP/IP : profile 0x0101 o UDP/IP : profile 0x0102 o ESP/IP : profile 0x0103 o IP : profile 0x0104 o RTP/UDP-Lite/IP : profile 0x0107 o UDP-Lite/IP : profile 0x0108

o RTP/UDP/IP:profile 0x0101 o UDP/IP:profile 0x0102 o ESP/IP:profile 0x0103 o IP:profile 0x0104 o RTP/UDP Lite/IP:profile 0x0107 o UDP Lite/IP:profile 0x0108

Each of the profiles above can compress the following type of extension headers:

上述每个配置文件都可以压缩以下类型的扩展标头:

o AH [RFC4302]

o 啊[RFC4302]

o GRE [RFC2784][RFC2890]

o GRE[RFC2784][RFC2890]

o MINE [RFC2004]

o 矿山[RFC2004]

o IPv6 Destination Options header[RFC2460]

o IPv6目标选项标头[RFC2460]

o IPv6 Hop-by-hop Options header[RFC2460]

o IPv6逐跳选项标头[RFC2460]

o IPv6 Routing header [RFC2460]

o IPv6路由头[RFC2460]

2. Terminology
2. 术语

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 RFC 2119 [RFC2119].

本文件中的关键词“必须”、“不得”、“要求”、“应”、“不应”、“应”、“不应”、“建议”、“可”和“可选”应按照RFC 2119[RFC2119]中所述进行解释。

This document is consistent with the terminology found in the ROHC framework [RFC4995] and in the formal notation for ROHC [RFC4997]. In addition, this document uses or defines the following terms:

本文件与ROHC框架[RFC4995]和ROHC正式符号[RFC4997]中的术语一致。此外,本文件使用或定义了以下术语:

Acknowledgment Number

确认号

The Acknowledgment Number identifies what packet is being acknowledged in the RoHCv2 feedback element (See Section 6.9). The value of this field normally corresponds to the Master Sequence Number (MSN) of the header that was last successfully decompressed, for the compression context (CID) for which the feedback information applies.

确认号标识RoHCv2反馈元素中正在确认的数据包(见第6.9节)。对于反馈信息适用的压缩上下文(CID),此字段的值通常对应于上次成功解压缩的报头的主序列号(MSN)。

Chaining of Items

项目链接

A chain of items groups fields based on similar characteristics. ROHCv2 defines chain items for static, dynamic and irregular fields. Chaining is achieved by appending an item to the chain for each header in its order of appearance in the uncompressed packet. Chaining is useful to construct compressed headers from an arbitrary number of any of the protocol headers for which a ROHCv2 profile defines a compressed format.

基于相似特征对字段进行分组的项目链。ROHCv2定义静态、动态和不规则字段的链项目。链接是通过按照未压缩数据包中每个头的出现顺序向链中添加一个项来实现的。链接可用于从任意数量的协议头(ROHCv2概要文件定义了压缩格式)构造压缩头。

CRC-3 Control Fields Validation

CRC-3控制域验证

The CRC-3 control fields validation refers to the validation of the control fields. This validation is performed by the decompressor when it receives a Compressed (CO) header that contains a 3-bit Cyclic Redundancy Check (CRC) calculated over control fields. This 3-bit CRC covers controls fields carried in the CO header as well as specific control fields in the context. In the formal definition of the header formats, this 3-bit CRC is labeled "control_crc3" and uses the control_crc3_encoding (See also Section 6.6.11).

CRC-3控制字段验证是指控制字段的验证。当解压器接收到包含通过控制字段计算的3位循环冗余校验(CRC)的压缩(CO)报头时,该验证由解压器执行。此3位CRC涵盖CO标头中携带的控制字段以及上下文中的特定控制字段。在报头格式的正式定义中,该3位CRC标记为“control_crc3”,并使用control_crc3_编码(另见第6.6.11节)。

Delta

希腊字母表的第4个字母

The delta refers to the difference in the absolute value of a field between two consecutive packets being processed by the same compression endpoint.

增量是指由同一压缩端点处理的两个连续数据包之间字段绝对值的差值。

Reordering Depth

重排深度

The number of packets by which a packet is received late within its sequence due to reordering between the compressor and the decompressor, i.e., reordering between packets associated with the same context (CID). See the definition of sequentially late packet below.

由于压缩器和解压缩器之间的重新排序(即,与相同上下文(CID)相关联的数据包之间的重新排序),在其序列中延迟接收数据包的数据包数。请参阅下面的顺序延迟数据包定义。

ROHCv2 Header Types

ROHCv2头类型

ROHCv2 profiles use two different header types: the Initialization and Refresh (IR) header type, and the Compressed (CO) header type.

ROHCv2配置文件使用两种不同的头类型:初始化和刷新(IR)头类型和压缩(CO)头类型。

Sequentially Early Packet

顺序早包

A packet that reaches the decompressor before one or several packets that were delayed over the channel, where all of the said packets belong to the same header-compressed flow and are associated to the same compression context (CID). At the time of the arrival of a sequentially early packet, the packet(s) delayed on the link cannot be differentiated from lost packet(s).

在通过信道延迟的一个或多个分组之前到达解压缩器的分组,其中所有所述分组属于相同的报头压缩流并且与相同的压缩上下文(CID)相关联。在顺序提前分组到达时,链路上延迟的分组不能与丢失的分组区分开来。

Sequentially Late Packet

顺序延迟数据包

A packet is late within its sequence if it reaches the decompressor after one or several other packets belonging to the same CID have been received, although the sequentially late packet was sent from the compressor before the other packet(s). How the decompressor detects a sequentially late packet is outside the scope of this specification, but it can for example use the MSN for this purpose.

如果一个数据包在接收到属于同一CID的一个或多个其他数据包之后到达解压器,则该数据包在其序列中是延迟的,尽管顺序延迟的数据包是在其他数据包之前从压缩器发送的。解压器如何检测顺序延迟的数据包超出了本规范的范围,但它可以例如为此目的使用MSN。

Timestamp Stride (ts_stride)

时间戳步幅(ts_步幅)

The timestamp stride (ts_stride) is the expected increase in the timestamp value between two RTP packets with consecutive sequence numbers. For example, for a media encoding with a sample rate of 8 kHz producing one frame every 20 ms, the RTP timestamp will typically increase by n * 160 (= 8000 * 0.02), for some integer n.

时间戳步长(ts_步长)是具有连续序列号的两个RTP数据包之间时间戳值的预期增加。例如,对于每20ms产生一帧的采样率为8khz的媒体编码,对于一些整数n,RTP时间戳通常将增加n×160(=8000×0.02)。

Time Stride (time_stride)

时间步长(时间步长)

The time stride (time_stride) is the time interval equivalent to one ts_stride, e.g., 20 ms in the example for the RTP timestamp increment above.

时间步长(time_-stride)是相当于一个ts_步长的时间间隔,例如,在上述RTP时间戳增量的示例中为20ms。

3. Acronyms
3. 缩略词

This section lists most acronyms used for reference, in addition to those defined in [RFC4995].

除[RFC4995]中定义的缩略语外,本节列出了大多数用于参考的缩略语。

AH Authentication Header. ESP Encapsulating Security Payload. GRE Generic Routing Encapsulation. FC Full Context state (decompressor). IP Internet Protocol. LSB Least Significant Bits. MINE Minimal Encapsulation in IP. MSB Most Significant Bits. MSN Master Sequence Number. NC No Context state (decompressor). OA Optimistic Approach. RC Repair Context state (decompressor). ROHC Header compression framework (RFC 4995). ROHCv2 Set of header compression profiles defined in this document. RTP Real-time Transport Protocol. SSRC Synchronization source. Field in RTP header. CSRC Contributing source. The RTP header contains an optional list of contributing sources. TC Traffic Class. Field in the IPv6 header. See also TOS. TOS Type Of Service. Field in the IPv4 header. See also TC. TS RTP Timestamp. TTL Time to Live. Field in the IPv4 header. UDP User Datagram Protocol. UDP-Lite User Datagram Protocol Lite.

认证头。封装安全有效载荷的ESP。GRE通用路由封装。FC完整上下文状态(解压缩器)。IP互联网协议。LSB最低有效位。挖掘IP中的最小封装。最高有效位。MSN主序列号。NC无上下文状态(解压缩器)。乐观的态度。RC修复上下文状态(解压缩器)。ROHC头压缩框架(RFC4995)。ROHCv2本文档中定义的一组标题压缩配置文件。实时传输协议。同步源。RTP标头中的字段。中国证监会消息来源。RTP标题包含一个可选的贡献源列表。TC交通等级。IPv6标头中的字段。另见TOS。TOS服务类型。IPv4标头中的字段。另见TC。TS RTP时间戳。是时候活了。IPv4标头中的字段。UDP用户数据报协议。UDP Lite用户数据报协议Lite。

4. Background (Informative)
4. 背景(资料性)

This section provides background information on the compression profiles defined in this document. The fundamentals of general header compression and of the ROHC framework may be found in sections 3 and 4 of [RFC4995], respectively. The fundamentals of the formal notation for ROHC are defined in [RFC4997]. [RFC4224] describes the impacts of out-of-order delivery on profiles based on [RFC3095].

本节提供本文档中定义的压缩配置文件的背景信息。[RFC4995]第3节和第4节分别介绍了通用报头压缩和ROHC框架的基本原理。[RFC4997]中定义了ROHC形式表示法的基本原理。[RFC4224]根据[RFC3095]描述了无序交付对配置文件的影响。

4.1. Classification of Header Fields
4.1. 标题字段的分类

Section 3.1 of [RFC4995] explains that header compression is possible due to the fact that there is much redundancy between field values within the headers of a packet, especially between the headers of consecutive packets.

[RFC4995]第3.1节解释了由于数据包报头内的字段值之间,特别是连续数据包报头之间存在大量冗余,因此可以进行报头压缩。

Appendix A lists and classifies in detail all the header fields relevant to this document. The appendix concludes with

附录A详细列出并分类了与本文档相关的所有标题字段。附录以

recommendations on how the various fields should be handled by header compression algorithms.

关于如何通过报头压缩算法处理各个字段的建议。

The main conclusion is that most of the header fields can easily be compressed away since they never or seldom change. A small number of fields however need more sophisticated mechanisms.

主要结论是,大多数头字段都很容易被压缩掉,因为它们从未或很少更改。然而,少数领域需要更复杂的机制。

These fields are:

这些字段是:

- IPv4 Identification (16 bits) - IP-ID - ESP Sequence Number (32 bits) - ESP SN - UDP Checksum (16 bits) - Checksum - UDP-Lite Checksum (16 bits) - Checksum - UDP-Lite Checksum Coverage (16 bits) - CCov - RTP Marker ( 1 bit ) - M-bit - RTP Sequence Number (16 bits) - RTP SN - RTP Timestamp (32 bits) - TS

- IPv4标识(16位)—IP-ID—ESP序列号(32位)—ESP序列号—UDP校验和(16位)—校验和—UDP Lite校验和(16位)—校验和—UDP Lite校验和覆盖率(16位)—CCov—RTP标记(1位)—M位—RTP序列号(16位)—RTP序列号—RTP时间戳(32位)—TS

In particular, for RTP, the analysis in Appendix A reveals that the values of the RTP Timestamp (TS) field usually have a strong correlation to the RTP Sequence Number (SN), which increments by one for each packet emitted by an RTP source. The RTP M-bit is expected to have the same value most of the time, but it needs to be communicated explicitly on occasion.

具体而言,对于RTP,附录A中的分析揭示RTP时间戳(TS)字段的值通常与RTP序列号(SN)具有强相关性,RTP序列号(SN)对于RTP源发射的每个数据包递增1。RTP M位在大多数情况下应具有相同的值,但有时需要显式通信。

For UDP, the Checksum field cannot be inferred or recalculated at the receiving end without violating its end-to-end properties, and is thus sent as-is when enabled (mandatory with IPv6). The same applies to the UDP-Lite Checksum (mandatory with both IPv4 and IPv6), while the UDP-Lite Checksum Coverage may in some cases be compressible.

对于UDP,在不违反其端到端属性的情况下,无法在接收端推断或重新计算校验和字段,因此在启用时按原样发送(IPv6强制)。这同样适用于UDP Lite校验和(IPv4和IPv6都是必需的),而UDP Lite校验和覆盖范围在某些情况下可能是可压缩的。

For IPv4, a similar correlation as that of the RTP TS to the RTP SN is often observed between the Identifier field (IP-ID) and the master sequence number (MSN) used for compression (e.g., the RTP SN when compressing RTP headers).

对于IPv4,在标识符字段(IP-ID)和用于压缩的主序列号(MSN)(例如,压缩RTP报头时的RTP SN)之间,通常观察到与RTP TS与RTP SN类似的相关性。

4.2. Improvements of ROHCv2 over RFC 3095 Profiles
4.2. ROHCv2对RFC3095型材的改进

The ROHCv2 profiles can achieve compression efficiency and robustness that are both at least equivalent to RFC 3095 profiles [RFC3095], when used under the same operating conditions. In particular, the size and bit layout of the smallest compressed header (i.e., PT-0 format U/O-0 in RFC 3095, and pt_0_crc3 in ROHCv2) are identical.

当在相同的操作条件下使用时,ROHCv2配置文件可实现压缩效率和鲁棒性,两者至少相当于RFC 3095配置文件[RFC3095]。具体而言,最小压缩头(即RFC 3095中的PT-0格式U/O-0和ROHCv2中的PT_0_crc3)的大小和位布局是相同的。

There are a number of differences and improvements between profiles defined in this document and their earlier version defined in RFC 3095. This section provides an overview of some of the most significant improvements:

本文档中定义的概要文件与RFC 3095中定义的早期版本之间存在许多差异和改进。本节概述了一些最重要的改进:

Tolerance to reordering

对重新排序的容忍度

Profiles defined in RFC 3095 require that the channel between compressor and decompressor provide in-order delivery between compression endpoints. ROHCv2 profiles, however, can handle robustly and efficiently a limited amount of reordering after the compression point as part of the compression algorithm itself. In addition, this improved support for reordering makes it possible for ROHCv2 profiles to handle prelink reordering more efficiently.

RFC 3095中定义的配置文件要求压缩机和解压器之间的通道在压缩端点之间提供顺序传递。然而,作为压缩算法本身的一部分,ROHCv2配置文件可以在压缩点之后稳健有效地处理有限数量的重新排序。此外,这种对重新排序的改进支持使ROHCv2配置文件能够更有效地处理预链接重新排序。

Operational logic

操作逻辑

Profiles in RFC 3095 define multiple operational modes, each with different updating logic and compressed header formats. ROHCv2 profiles operate in unidirectional operation until feedback is first received for a context (CID), at which point bidirectional operation is used; the formats are independent of what operational logic is used.

RFC 3095中的配置文件定义了多种操作模式,每种模式具有不同的更新逻辑和压缩头格式。ROHCv2配置文件在单向操作中运行,直到第一次接收到上下文(CID)的反馈,此时使用双向操作;格式与使用的操作逻辑无关。

IP extension header

IP扩展头

Profiles in RFC 3095 compress IP Extension headers using list compression. ROHCv2 profiles instead treat extension headers in the same manner as other protocol headers, i.e., using the chaining mechanism; it thus assumes that extension headers are not added or removed during the lifetime of a context (CID), otherwise compression has to be restarted for this flow.

RFC3095中的配置文件使用列表压缩压缩IP扩展头。ROHCv2配置文件以与其他协议头相同的方式处理扩展头,即使用链接机制;因此,它假定在上下文(CID)的生存期内未添加或删除扩展头,否则必须为此流重新启动压缩。

IP encapsulation

IP封装

Profiles in RFC 3095 can compress at most two levels of IP headers. ROHCv2 profiles can compress an arbitrary number of IP headers.

RFC3095中的配置文件最多可以压缩两级IP头。ROHCv2配置文件可以压缩任意数量的IP头。

List compression

列表压缩

ROHCv2 profiles do not support reference-based list compression.

ROHCv2配置文件不支持基于引用的列表压缩。

Robustness and repairs

坚固性和修复

ROHCv2 profiles do not define a format for the IR-DYN packet; instead, each profile defines a compressed header that can be used to perform a more robust context repair using a 7-bit CRC verification. This also implies that only the IR header can change the association between a CID and the profile it uses.

ROHCv2配置文件未定义IR-DYN数据包的格式;相反,每个概要文件定义了一个压缩头,可用于使用7位CRC验证执行更健壮的上下文修复。这还意味着只有IR标头可以更改CID与其使用的配置文件之间的关联。

Feedback

反馈

ROHCv2 profiles mandate a CRC in the format of the FEEDBACK-2, while this is optional in RFC 3095. A different set of feedback options is also used in ROHCv2 compared to RFC 3095.

ROHCv2配置文件要求采用反馈-2格式的CRC,而这在RFC 3095中是可选的。与RFC 3095相比,ROHCv2中还使用了一组不同的反馈选项。

4.3. Operational Characteristics of ROHCv2 Profiles
4.3. ROHCv2型材的运行特性

Robust header compression can be used over different link technologies. Section 4.4 of [RFC4995] lists the operational characteristics of the ROHC channel. The ROHCv2 profiles address a wide range of applications, and this section summarizes some of the operational characteristics that are specific to these profiles.

健壮的报头压缩可以在不同的链路技术上使用。[RFC4995]第4.4节列出了ROHC通道的运行特性。ROHCv2配置文件涉及广泛的应用,本节总结了这些配置文件特有的一些操作特性。

Packet length

数据包长度

ROHCv2 profiles assume that the lower layer indicates the length of a compressed packet. ROHCv2 compressed headers do not contain length information for the payload.

ROHCv2配置文件假定较低层表示压缩数据包的长度。ROHCv2压缩头不包含有效负载的长度信息。

Out-of-order delivery between compression endpoints

压缩端点之间的无序传递

The definition of the ROHCv2 profiles places no strict requirement on the delivery sequence between the compression endpoints, i.e., packets may be received in a different order than the compressor has sent them and still have a fair probability of being successfully decompressed.

ROHCv2简档的定义对压缩端点之间的传递顺序没有严格要求,即,可以以不同于压缩器发送的顺序接收数据包,并且仍然具有成功解压缩的公平概率。

However, frequent out-of-order delivery and/or significant reordering depth will negatively impact the compression efficiency. More specifically, if the compressor can operate using a proper estimate of the reordering characteristics of the path between the compression endpoints, larger headers can be sent more often to increase the robustness against decompression failures due to out-of-order delivery. Otherwise, the compression efficiency will be impaired from an increase in the frequency of decompression failures and recovery attempts.

然而,频繁的无序交付和/或显著的重新订购深度将对压缩效率产生负面影响。更具体地说,如果压缩器可以使用对压缩端点之间的路径的重新排序特征的适当估计来操作,则可以更频繁地发送更大的报头,以增加对由于无序交付而导致的解压缩失败的鲁棒性。否则,解压缩失败和恢复尝试频率的增加将影响压缩效率。

5. Overview of the ROHCv2 Profiles (Informative)
5. ROHCv2配置文件概述(资料性)

This section provides an overview of concepts that are important and useful to the ROHCv2 profiles. These concepts may be used as guidelines for implementations but they are not part of the normative definition of the profiles, as these concepts relate to the compression efficiency of the protocol without impacting the interoperability characteristics of an implementation.

本节概述了ROHCv2概要文件中重要且有用的概念。这些概念可以用作实施指南,但它们不是概要文件规范定义的一部分,因为这些概念与协议的压缩效率相关,而不影响实施的互操作性特征。

5.1. Compressor Concepts
5.1. 压缩机概念

Header compression can be conceptually characterized as the interaction of a compressor with a decompressor state machine, one per context. The responsibility of the compressor is to convey the information needed to successfully decompress a packet, based on a certain confidence regarding the state of the decompressor context.

标题压缩在概念上可以描述为压缩器与解压缩器状态机的交互,每个上下文一个。压缩器的职责是基于关于解压器上下文的状态的一定置信度来传递成功解压分组所需的信息。

This confidence is obtained from the frequency and the type of information the compressor sends when updating the decompressor context from the optimistic approach (Section 5.1.1), and optionally from feedback messages (See Section 6.9), received from the decompressor.

该置信度是从压缩机在使用乐观方法(第5.1.1节)更新解压器上下文时发送的频率和信息类型中获得的,也可以从解压器收到的反馈消息(见第6.9节)中获得。

5.1.1. Optimistic Approach
5.1.1. 乐观态度

A compressor always uses the optimistic approach when it performs context updates. The compressor normally repeats the same type of update until it is fairly confident that the decompressor has successfully received the information. If the decompressor successfully receives any of the headers containing this update, the state will be available for the decompressor to process smaller compressed headers.

压缩器在执行上下文更新时始终使用乐观方法。压缩器通常会重复相同类型的更新,直到它确信解压缩器已成功接收到信息为止。如果解压缩程序成功接收到包含此更新的任何标头,则该状态将可供解压缩程序处理较小的压缩标头。

If field X in the uncompressed header changes value, the compressor uses a header type that contains an encoding of field X until it has gained confidence that the decompressor has received at least one packet containing the new value for X. The compressor normally selects a compressed format with the smallest header that can convey the changes needed to achieve confidence.

如果未压缩标头中的字段X更改了值,压缩器使用包含字段X编码的报头类型,直到它确信解压器已收到至少一个包含X新值的数据包。压缩器通常选择具有最小报头的压缩格式,该报头可以传递实现置信度所需的更改。

The number of repetitions that is needed to obtain this confidence is normally related to the packet loss and out-of-order delivery characteristics of the link where header compression is used; it is thus not defined in this document. It is outside the scope of this specification and is left to implementors to decide.

获得该置信度所需的重复次数通常与使用报头压缩的链路的分组丢失和无序交付特性有关;因此,本文件未对其进行定义。它不在本规范的范围内,由实现者决定。

5.1.2. Tradeoff between Robustness to Losses and to Reordering
5.1.2. 损失稳健性和重新排序稳健性之间的权衡

The ability of a header compression algorithm to handle sequentially late packets is mainly limited by two factors: the interpretation interval offset of the sliding window used for lsb encoded fields [RFC4997], and the optimistic approach (See Section 5.1.1) for seldom changing fields.

报头压缩算法处理顺序延迟数据包的能力主要受到两个因素的限制:用于lsb编码字段的滑动窗口的解释间隔偏移量[RFC4997],以及用于很少变化字段的乐观方法(见第5.1.1节)。

lsb encoded fields:

lsb编码字段:

The interpretation interval offset specifies an upper limit for the maximum reordering depth, by which is it possible for the decompressor to recover the original value of a dynamically changing (i.e., sequentially incrementing) field that is encoded using a window-based lsb encoding. Its value is typically bound to the number of lsb compressed bits in the compressed header format, and thus grows with the number of bits transmitted. However, the offset and the lsb encoding only provide robustness for the field that it compresses, and (implicitly) for other sequentially changing fields that are derived from that field.

解释间隔偏移量指定了最大重新排序深度的上限,通过该上限,解压器可以恢复使用基于窗口的lsb编码进行编码的动态变化(即,顺序递增)字段的原始值。其值通常与压缩报头格式中的lsb压缩比特数绑定,因此随着传输比特数的增加而增加。然而,偏移量和lsb编码仅为其压缩的字段提供健壮性,并且(隐式地)为从该字段派生的其他顺序变化的字段提供健壮性。

This is shown in the figure below:

如下图所示:

         <--- interpretation interval (size is 2^k) ---->
         |------------------+---------------------------|
      v_ref-p             v_ref              v_ref + (2^k-1) - p
       Lower                                          Upper
       Bound                                          Bound
         <--- reordering --> <--------- losses --------->
        
         <--- interpretation interval (size is 2^k) ---->
         |------------------+---------------------------|
      v_ref-p             v_ref              v_ref + (2^k-1) - p
       Lower                                          Upper
       Bound                                          Bound
         <--- reordering --> <--------- losses --------->
        

where p is the maximum negative delta, corresponding to the maximum reordering depth for which the lsb encoding can recover the original value of the field;

其中p是最大负增量,对应于lsb编码可以恢复字段原始值的最大重新排序深度;

where (2^k-1) - p is the maximum positive delta, corresponding to the maximum number of consecutive losses for which the lsb encoding can recover the original value of the field;

其中(2^k-1)-p是最大正增量,对应于lsb编码可以恢复字段原始值的最大连续丢失数;

where v_ref is the reference value, as defined in the lsb encoding method in [RFC4997].

其中v_ref是参考值,如[RFC4997]中lsb编码方法中所定义。

There is thus a tradeoff between the robustness against reordering and the robustness against packet losses, with respect to the number of MSN bits needed and the distribution of the interpretation interval between negative and positive deltas in the MSN.

因此,在针对重排序的鲁棒性和针对分组丢失的鲁棒性之间,就所需MSN比特的数量和MSN中负增量和正增量之间的解释间隔的分布而言,存在折衷。

Seldom changing fields

很少变换场地

The optimistic approach (Section 5.1.1) provides the upper limit for the maximum reordering depth for seldom changing fields.

乐观方法(第5.1.1节)为很少变化的字段提供了最大重新排序深度的上限。

There is thus a tradeoff between compression efficiency and robustness. When only information on the MSN needs to be conveyed to the decompressor, the tradeoff relates to the number of compressed

因此,在压缩效率和鲁棒性之间存在折衷。当只需要将MSN上的信息传送到解压缩器时,折衷与压缩数据的数量有关

MSN bits in the compressed header format. Otherwise, the tradeoff relates to the implementation of the optimistic approach.

压缩头格式的MSN位。否则,折衷关系到乐观方法的实施。

In particular, compressor implementations should adjust their optimistic approach strategy to match both packet loss and reordering characteristics of the link over which header compression is applied. For example, the number of repetitions for each update of a non-lsb encoded field can be increased. The compressor can ensure that each update is repeated until it is reasonably confident that at least one packet containing the change has reached the decompressor before the first packet sent after this sequence.

特别是,压缩器实现应该调整其乐观方法策略,以匹配应用报头压缩的链路的丢包和重新排序特性。例如,可以增加非lsb编码字段的每次更新的重复次数。压缩器可以确保重复每次更新,直到它合理地确信在该序列之后发送的第一个数据包之前,至少有一个包含变更的数据包已经到达解压缩器。

5.1.3. Interactions with the Decompressor Context
5.1.3. 与解压缩程序上下文的交互

The compressor normally starts compression with the initial assumption that the decompressor has no useful information to process the new flow, and sends Initialization and Refresh (IR) packets.

压缩机通常在初始假设解压缩器没有处理新流的有用信息的情况下启动压缩,并发送初始化和刷新(IR)数据包。

Initially, when sending the first IR packet for a compressed flow, the compressor does not expect to receive feedback for that flow, until such feedback is first received. At this point, the compressor may then assume that the decompressor will continue to send feedback in order to repair its context when necessary. The former is referred to as unidirectional operation, while the latter is called bidirectional operation.

最初,当发送压缩流的第一IR分组时,压缩器不期望接收该流的反馈,直到第一次接收到该反馈为止。此时,压缩器可能会假设解压器将继续发送反馈,以便在必要时修复其上下文。前者称为单向操作,后者称为双向操作。

The compressor can then adjust the compression level (i.e., what header format it selects) based on its confidence that the decompressor has the necessary information to successfully process the compressed headers that it selects.

然后,压缩器可以基于其对解压缩器具有成功处理其选择的压缩报头所必需的信息的信心来调整压缩级别(即,它选择的报头格式)。

In other words, the responsibilities of the compressor are to ensure that the decompressor operates with state information that is sufficient to successfully decompress the type of compressed header(s) it receives, and to allow the decompressor to successfully recover that state information as soon as possible otherwise. The compressor therefore selects the type of compressed header based on the following factors:

换言之,压缩机的责任是确保减压器使用足以成功解压缩其接收的压缩头类型的状态信息运行,并允许减压器尽快成功恢复该状态信息。因此,压缩机根据以下因素选择压缩集管的类型:

o the outcome of the encoding method applied to each field;

o 应用于每个字段的编码方法的结果;

o the optimistic approach, with respect to the characteristics of the channel;

o 关于渠道特征的乐观方法;

o the type of operation (unidirectional or bidirectional), and if in bidirectional operation, feedback received from the decompressor (ACKs, NACKs, STATIC-NACK, and options).

o 操作类型(单向或双向),以及如果在双向操作中,从解压缩器接收的反馈(ACK、NACK、STATIC-NACK和选项)。

Encoding methods normally use previous value(s) from a history of packets whose headers it has previously compressed. The optimistic approach is meant to ensure that at least one compressed header containing the information to update the state for a field is received. Finally, feedback indicates what actions the decompressor has taken with respect to its assumptions regarding the validity of its context (Section 5.2.2); it indicates what type of compressed header the decompressor can or cannot decompress.

编码方法通常使用以前压缩过的数据包头历史记录中的先前值。乐观方法旨在确保至少收到一个压缩报头,其中包含更新字段状态的信息。最后,反馈表明减压器对其上下文有效性的假设采取了什么行动(第5.2.2节);它指示解压器可以或不能解压的压缩头的类型。

The decompressor has the means to detect decompression failures for any compressed (CO) header format, using the CRC verification. Depending on the frequency and/or on the type of the failure, it might send a negative acknowledgement (NACK) or an explicit request for a complete context update (STATIC-NACK). However, the decompressor does not have the means to identify the cause of the failure, and in particular the decompression of what field(s) is responsible for the failure. The compressor is thus always responsible for determining the most suitable response to a negative acknowledgement, using the confidence it has in the state of the decompressor context, when selecting the type of compressed header it will use when compressing a header.

解压器可以使用CRC验证检测任何压缩(CO)头格式的解压失败。根据故障的频率和/或类型,它可能发送否定确认(NACK)或完整上下文更新的显式请求(STATIC-NACK)。但是,解压器无法确定故障原因,尤其是对导致故障的字段进行解压。因此,当选择压缩报头时将使用的压缩报头类型时,压缩器始终负责使用其在解压缩器上下文的状态中的置信度来确定对否定确认的最合适响应。

5.2. Decompressor Concepts
5.2. 解压器概念

The decompressor normally uses the last received and successfully validated (IR packets) or verified (CO packets) header as the reference for future decompression.

解压器通常使用最后接收并成功验证(IR数据包)或验证(CO数据包)的报头作为将来解压的参考。

The decompressor is responsible for verifying the outcome of every decompression attempt, to update its context when successful, and finally to request context repairs by making coherent usage of feedback once it has started using feedback.

解压器负责验证每次解压尝试的结果,在成功时更新其上下文,并在开始使用反馈后通过一致使用反馈请求上下文修复。

Specifically, the outcome of every decompression attempt is verified using the CRC present in the compressed header; the decompressor updates the context information when this outcome is successfully verified; finally, if the decompressor uses feedback once for a compressed flow, then it will continue to do so for as long as the corresponding context is associated with the same profile.

具体地说,使用压缩报头中存在的CRC来验证每次解压缩尝试的结果;当成功验证此结果时,解压缩程序更新上下文信息;最后,如果解压缩程序对压缩流使用一次反馈,那么只要相应的上下文与相同的概要文件关联,它就会继续这样做。

5.2.1. Decompressor State Machine
5.2.1. 解压器状态机

The decompressor operation may be represented as a state machine defining three states: No Context (NC), Repair Context (RC), and Full Context (FC).

解压器操作可以表示为定义三种状态的状态机:无上下文(NC)、修复上下文(RC)和完整上下文(FC)。

The decompressor starts without a valid context, the NC state. Upon receiving an IR packet, the decompressor validates the integrity of

解压缩程序在没有有效上下文NC状态的情况下启动。在接收到IR数据包后,解压缩程序验证数据包的完整性

its header using the CRC-8 validation. If the IR header is successfully validated, the decompressor updates the context and uses this header as the reference header, and moves to the FC state. Once the decompressor state machine has entered the FC state, it does not normally leave; only repeated decompression failures will force the decompressor to transit downwards to a lower state. When context damage is detected, the decompressor moves to the repair context (RC) state, where it stays until it successfully verifies a decompression attempt for a compressed header with a 7-bit CRC or until it successfully validates an IR header. When static context damage is detected, the decompressor moves back to the NC state.

其标头使用CRC-8验证。如果IR头成功验证,则解压缩程序将更新上下文并将此头用作参考头,并移动到FC状态。一旦解压器状态机进入FC状态,它通常不会离开;只有反复的减压失败才会迫使减压器向下过渡到较低的状态。当检测到上下文损坏时,解压器将移动到修复上下文(RC)状态,在该状态下,解压器将一直保持,直到它使用7位CRC成功验证压缩头的解压尝试,或者直到它成功验证IR头。当检测到静态上下文损坏时,解压缩程序将移回NC状态。

Below is the state machine for the decompressor. Details of the transitions between states and decompression logic are given in the sub-sections following the figure.

下面是解压器的状态机。状态和解压缩逻辑之间转换的详细信息在下图的小节中给出。

  CRC-8(IR) Validation
   +----->----->----->----->----->----->----->----->----->----->----+
   |                                                  CRC-8(IR)     |
   |  !CRC-8(IR) or      CRC-7(CO) or                 or CRC-7(CO)  |
   |  PT not allowed     CRC-8(IR)                    or CRC-3(CO)  |
   |  +--->---+         +--->----->----->----->---+  +--->---->---+ |
   |  |       |         |                         |  |            | |
   |  |       v         |                         v  |            v v
  +-----------------+  +----------------------+  +--------------------+
  | No Context (NC) |  | Repair Context (RC)  |  | Full Context (FC)  |
  +-----------------+  +----------------------+  +--------------------+
    ^ ^ Static Context  | ^ !CRC-7(CO) or  | ^ Context Damage  | |
    | | Damage Detected | | PT not allowed | | Detected        | |
    | +--<-----<-----<--+ +----<------<----+ +--<-----<-----<--+ |
    |                                                            |
    |            Static Context Damage Detected                  |
    +--<-----<-----<-----<-----<-----<-----<-----<-----<---------+
        
  CRC-8(IR) Validation
   +----->----->----->----->----->----->----->----->----->----->----+
   |                                                  CRC-8(IR)     |
   |  !CRC-8(IR) or      CRC-7(CO) or                 or CRC-7(CO)  |
   |  PT not allowed     CRC-8(IR)                    or CRC-3(CO)  |
   |  +--->---+         +--->----->----->----->---+  +--->---->---+ |
   |  |       |         |                         |  |            | |
   |  |       v         |                         v  |            v v
  +-----------------+  +----------------------+  +--------------------+
  | No Context (NC) |  | Repair Context (RC)  |  | Full Context (FC)  |
  +-----------------+  +----------------------+  +--------------------+
    ^ ^ Static Context  | ^ !CRC-7(CO) or  | ^ Context Damage  | |
    | | Damage Detected | | PT not allowed | | Detected        | |
    | +--<-----<-----<--+ +----<------<----+ +--<-----<-----<--+ |
    |                                                            |
    |            Static Context Damage Detected                  |
    +--<-----<-----<-----<-----<-----<-----<-----<-----<---------+
        

where:

哪里:

CRC-8(IR) : Successful CRC-8 validation for the IR header. !CRC-8(IR) : Unsuccessful CRC-8 validation for the IR header. CRC-7(CO) and/or CRC-3(CO) : Successful CRC verification for the decompression of a CO header, based on the number of CRC bits carried in the CO header. !CRC-7(CO) : Failure to CRC verify the decompression of a CO header carrying a 7-bit CRC. PT not allowed : The decompressor has received a packet type (PT) for which the decompressor's current context does not provide enough valid state information to decompress the packet.

CRC-8(IR):IR头的CRC-8验证成功!CRC-8(IR):IR标头的CRC-8验证失败。CRC-7(CO)和/或CRC-3(CO):根据CO报头中携带的CRC比特数,对CO报头解压缩成功进行CRC验证!CRC-7(CO):无法通过CRC验证承载7位CRC的CO报头的解压缩。PT not allowed(不允许):解压器已接收到数据包类型(PT),解压器的当前上下文没有提供足够的有效状态信息来解压该数据包。

Static Context Damage Detected: See definition in Section 5.2.2.

检测到静态环境损坏:见第5.2.2节中的定义。

Context Damage Detected: See definition in Section 5.2.2.

检测到的环境损害:见第5.2.2节中的定义。

5.2.1.1. No Context (NC) State
5.2.1.1. 无上下文(NC)状态

Initially, while working in the No Context (NC) state, the decompressor has not yet successfully validated an IR header.

最初,在无上下文(NC)状态下工作时,解压缩程序尚未成功验证IR头。

Attempting decompression:

正在尝试解压缩:

In the NC state, only packets carrying sufficient information on the static fields (i.e., IR packets) can be decompressed.

在NC状态下,只能解压缩携带关于静态字段的足够信息的分组(即IR分组)。

Upward transition:

向上过渡:

The decompressor can move to the Full Context (FC) state when the CRC validation of an 8-bit CRC in an IR header is successful.

当IR报头中8位CRC的CRC验证成功时,解压器可以移动到完整上下文(FC)状态。

Feedback logic:

反馈逻辑:

In the NC state, the decompressor should send a STATIC-NACK if a packet of a type other than IR is received, or if an IR header has failed the CRC-8 validation, subject to the feedback rate limitation as described in Section 5.2.3.

在NC状态下,如果接收到非IR类型的数据包,或者如果IR报头未通过CRC-8验证,则解压器应发送静态NACK,并遵守第5.2.3节中所述的反馈速率限制。

5.2.1.2. Repair Context (RC) State
5.2.1.2. 修复上下文(RC)状态

In the Repair Context (RC) state, the decompressor has successfully decompressed packets for this context, but does not have confidence that the entire context is valid.

在修复上下文(RC)状态下,解压缩程序已成功解压缩此上下文的数据包,但无法确定整个上下文是否有效。

Attempting decompression:

正在尝试解压缩:

In the RC state, only headers covered by an 8-bit CRC (i.e., IR) or CO headers carrying a 7-bit CRC can be decompressed.

在RC状态下,只能解压缩由8位CRC(即IR)覆盖的报头或携带7位CRC的CO报头。

Upward transition:

向上过渡:

The decompressor can move to the Full Context (FC) state when the CRC verification succeeds for a CO header carrying a 7-bit CRC or when validation of an 8-bit CRC in an IR header succeeds.

当承载7位CRC的CO报头的CRC验证成功时或当IR报头中的8位CRC验证成功时,解压器可以移动到全上下文(FC)状态。

Downward transition:

向下过渡:

The decompressor moves back to the NC state if it assumes static context damage.

如果解压器假定静态上下文损坏,它将返回NC状态。

Feedback logic:

反馈逻辑:

In the RC state, the decompressor should send a STATIC-NACK when CRC-8 validation of an IR header fails, or when a CO header carrying a 7-bit CRC fails and static context damage is assumed, subject to the feedback rate limitation as described in Section 5.2.3. If any other packet type is received, the decompressor should treat it as a CRC verification failure to determine if NACK is to be sent.

在RC状态下,当IR报头的CRC-8验证失败时,或当承载7位CRC的CO报头失败且假设静态上下文损坏时,解压器应发送静态NACK,但需遵守第5.2.3节所述的反馈速率限制。如果收到任何其他数据包类型,解压器应将其视为CRC验证失败,以确定是否发送NACK。

5.2.1.3. Full Context (FC) State
5.2.1.3. 完整上下文(FC)状态

In the Full Context (FC) state, the decompressor assumes that its entire context is valid.

在完整上下文(FC)状态下,解压缩程序假定其整个上下文有效。

Attempting decompression:

正在尝试解压缩:

In the FC state, decompression can be attempted regardless of the type of packet received.

在FC状态下,无论接收的数据包类型如何,都可以尝试解压缩。

Downward transition:

向下过渡:

The decompressor moves back to the RC state if it assumes context damage. If the decompressor assumes static context damage, it moves directly to the NC state.

如果解压器假定上下文损坏,它将返回到RC状态。如果解压缩程序假定静态上下文损坏,它将直接移动到NC状态。

Feedback logic:

反馈逻辑:

In the FC state, the decompressor should send a NACK when CRC-8 validation or CRC verification of any header type fails and if context damage is assumed, or it should send a STATIC-NACK if static context damage is assumed; this is subject to the feedback rate limitation described in Section 5.2.3.

在FC状态下,当任何头类型的CRC-8验证或CRC验证失败且假设上下文损坏时,解压器应发送NACK,或者如果假设静态上下文损坏,解压器应发送静态NACK;这受第5.2.3节所述反馈率限制的约束。

5.2.2. Decompressor Context Management
5.2.2. 解压器上下文管理

All header formats carry a CRC and are context updating. A packet for which the CRC succeeds updates the reference values of all header fields, either explicitly (from the information about a field carried within the compressed header) or implicitly (fields inferred from other fields).

所有报头格式都带有CRC,并且都是上下文更新。CRC成功更新所有报头字段的参考值的数据包,要么显式(根据压缩报头中携带的字段信息)要么隐式(根据其他字段推断的字段)。

The decompressor may assume that some or the entire context is invalid, when it fails to validate or to verify one or more headers using the CRC. Because the decompressor cannot know the exact

当解压缩程序无法使用CRC验证或验证一个或多个头时,它可能会认为部分或整个上下文无效。因为解压器无法知道确切的

reason(s) for a CRC failure or what field caused it, the validity of the context hence does not refer to what specific part(s) of the context is deemed valid or not.

CRC故障的原因或是哪个字段导致的,因此上下文的有效性并不指上下文的哪个特定部分被视为有效或无效。

Validity of the context rather relates to the detection of a problem with the context. The decompressor first assumes that the type of information that most likely caused the failure(s) is the state that normally changes for each packet, i.e., context damage of the dynamic part of the context. Upon repeated decompression failures and unsuccessful repairs, the decompressor then assumes that the entire context, including the static part, needs to be repaired, i.e., static context damage. Failure to validate the 3-bit CRC that protects control fields should be treated as a decompression failure when the decompressor asserts the validity of its context.

上下文的有效性与上下文问题的检测有关。解压器首先假设最有可能导致故障的信息类型是每个数据包通常改变的状态,即上下文动态部分的上下文损坏。在多次解压失败和修复失败后,解压器会假定整个上下文(包括静态部分)需要修复,即静态上下文损坏。当解压缩程序断言其上下文的有效性时,未能验证保护控制字段的3位CRC应视为解压缩失败。

Context Damage Detection

上下文损伤检测

The assumption of context damage means that the decompressor will not attempt decompression of a CO header that carries only a 3-bit CRC, and will only attempt decompression of IR headers or CO headers protected by a CRC-7.

上下文损坏的假设意味着解压器不会尝试解压仅携带3位CRC的CO报头,而只会尝试解压受CRC-7保护的IR报头或CO报头。

Static Context Damage Detection

静态上下文损伤检测

The assumption of static context damage means that the decompressor refrains from attempting decompression of any type of header other than the IR header.

静态上下文损坏的假设意味着解压器不尝试解压除IR头以外的任何类型的头。

How these assumptions are made, i.e., how context damage is detected, is open to implementations. It can be based on the residual error rate, where a low error rate makes the decompressor assume damage more often than on a high rate link.

如何做出这些假设,即如何检测上下文损坏,对实现是开放的。它可以基于剩余错误率,其中低错误率使解压缩器比高速链路更经常地承担损坏。

The decompressor implements these assumptions by selecting the type of compressed header for which it will attempt decompression. In other words, validity of the context refers to the ability of a decompressor to attempt (or not) decompression of specific packet types.

解压器通过选择要尝试解压的压缩头的类型来实现这些假设。换句话说,上下文的有效性是指解压器尝试(或不尝试)解压特定数据包类型的能力。

When ROHCv2 profiles are used over a channel that cannot guarantee in-order delivery, the decompressor may refrain from updating its context with the content of a sequentially late packet that is successfully decompressed. This is to avoid updating the context with information that is older than what the decompressor already has in its context.

当ROHCv2简档在不能保证顺序递送的信道上使用时,解压器可以避免使用成功解压的顺序延迟分组的内容更新其上下文。这是为了避免使用比解压器在其上下文中已有的信息旧的信息更新上下文。

5.2.3. Feedback Logic
5.2.3. 反馈逻辑

ROHCv2 profiles may be used in environments with or without feedback capabilities from decompressor to compressor. ROHCv2 however assumes that if a ROHC feedback channel is available and if this channel is used at least once by the decompressor for a specific context, this channel will be used during the entire compression operation for that context (i.e., bidirectional operation).

ROHCv2配置文件可用于具有或不具有从解压器到压缩机的反馈功能的环境中。然而,ROHCv2假设如果ROHC反馈通道可用,并且如果解压器在特定上下文中至少使用该通道一次,则该通道将在该上下文的整个压缩操作期间使用(即,双向操作)。

The ROHC framework defines 3 types of feedback messages: ACKs, NACKs, and STATIC-NACKs. The semantics of each message is defined in Section 5.2.4.1. of [RFC4995]. What feedback to send is coupled with the context management of the decompressor, i.e., with the implementation of the context damage detection algorithms as described in Section 5.2.2.

ROHC框架定义了3种类型的反馈消息:ACK、NACK和静态NACK。第5.2.4.1节定义了每条消息的语义。属于[RFC4995]。要发送的反馈与解压器的上下文管理相结合,即与第5.2.2节所述的上下文损坏检测算法的实现相结合。

The decompressor should send a NACK when it assumes context damage, and it should send a STATIC-NACK when it assumes static context damage. The decompressor is not strictly expected to send ACK feedback upon successful decompression, other than for the purpose of improving compression efficiency.

解压器在假设上下文损坏时应发送NACK,在假设静态上下文损坏时应发送静态NACK。严格来说,解压缩程序在成功解压缩时不会发送ACK反馈,除非是为了提高压缩效率。

When ROHCv2 profiles are used over a channel that cannot guarantee in-order delivery, the decompressor may refrain from sending ACK feedback for a sequentially late packet that is successfully decompressed.

当ROHCv2简档在不能保证顺序递送的信道上使用时,解压器可以避免为成功解压的顺序延迟分组发送ACK反馈。

The decompressor should limit the rate at which it sends feedback, for both ACKs and STATIC-NACK/NACKs, and should avoid sending unnecessary duplicates of the same type of feedback message that may be associated with the same event.

对于ACK和静态NACK/NACK,解压缩程序应限制其发送反馈的速率,并应避免发送可能与同一事件相关联的同一类型反馈消息的不必要副本。

6. ROHCv2 Profiles (Normative)
6. ROHCv2配置文件(规范性)
6.1. Channel Parameters, Segmentation, and Reordering
6.1. 通道参数、分段和重新排序

The compressor MUST NOT use ROHC segmentation (see Section 5.2.5 of [RFC4995]), i.e., the Maximum Reconstructed Reception Unit (MRRU) MUST be set to 0, if the configuration of the ROHC channel contains at least one ROHCv2 profile in the list of supported profiles (i.e., the PROFILES parameter) and if the channel cannot guarantee in-order delivery of packets between compression endpoints.

压缩机不得使用ROHC分段(见[RFC4995]第5.2.5节),即,如果ROHC通道的配置在支持的配置文件列表中至少包含一个ROHCv2配置文件(即配置文件参数),则最大重构接收单元(MRRU)必须设置为0如果通道不能保证压缩端点之间的数据包按顺序传递。

6.2. Profile Operation, Per-context
6.2. 配置文件操作,按上下文

ROHCv2 profiles operate differently, per context, depending on how the decompressor makes use of the feedback channel, if any. Once the decompressor uses the feedback channel for a context, it establishes the feedback channel for that CID.

ROHCv2配置文件根据上下文的不同而不同,这取决于解压器如何利用反馈通道(如果有的话)。一旦解压缩程序将反馈通道用于上下文,它将为该CID建立反馈通道。

The compressor always starts with the assumption that the decompressor will not send feedback when it initializes a new context (see also the definition of a new context in Section 5.1.1. of [RFC4995], i.e., there is no established feedback channel for the new context. At this point, despite the use of the optimistic approach, decompression failure is still possible because the decompressor may not have received sufficient information to correctly decompress the packets; therefore, until the decompressor has established a feedback channel, the compressor SHOULD periodically send IR packets. The periodicity can be based on timeouts, on the number of compressed packets sent for the flow, or any other strategy the implementer chooses.

压缩器总是假设解压器在初始化新上下文时不会发送反馈(另请参见[RFC4995]第5.1.1节中的新上下文定义),即,没有为新上下文建立反馈通道。在这一点上,尽管使用了乐观方法,但解压失败仍然是可能的,因为解压器可能没有收到足够的信息来正确解压数据包;因此,在解压器建立反馈通道之前压缩器应定期发送IR数据包。周期性可以基于超时、为流发送的压缩数据包的数量或实现者选择的任何其他策略。

The reception of either positive feedback (ACKs) or negative feedback (NACKs or STATIC-NACKs) from the decompressor establishes the feedback channel for the context (CID) for which the feedback was received. Once there is an established feedback channel for a specific context, the compressor can make use of this feedback to estimate the current state of the decompressor. This helps to increase the compression efficiency by providing the information needed for the compressor to achieve the necessary confidence level. When the feedback channel is established, it becomes superfluous for the compressor to send periodic refreshes, and instead it can rely entirely on the optimistic approach and feedback from the decompressor.

从解压缩器接收到正反馈(ACK)或负反馈(NACK或静态NACK),为接收到反馈的上下文(CID)建立反馈通道。一旦针对特定上下文建立了反馈通道,压缩器就可以利用该反馈来估计解压缩器的当前状态。通过提供压缩机达到必要置信水平所需的信息,这有助于提高压缩效率。当反馈通道建立时,压缩机发送定期刷新就变得多余了,相反,它可以完全依赖于乐观方法和来自解压缩器的反馈。

The decompressor MAY send positive feedback (ACKs) to initially establish the feedback channel for a particular flow. Either positive feedback (ACKs) or negative feedback (NACKs or STATIC-NACKs) establishes this channel. Once it has established a feedback channel for a CID, the decompressor is REQUIRED to continue sending feedback for the lifetime of the context (i.e., until it receives an IR packet that associates the CID to a different profile), to send error recovery requests and (optionally) acknowledgments of significant context updates.

解压器可以发送正反馈(ACKs),以最初建立特定流的反馈通道。正反馈(ACKs)或负反馈(NACKs或静态NACKs)建立此通道。一旦为CID建立了反馈通道,解压器就需要在上下文的生命周期内继续发送反馈(即,直到它接收到将CID关联到不同配置文件的IR数据包),以发送错误恢复请求和(可选)重要上下文更新的确认。

Compression without an established feedback channel will be less efficient, because of the periodic refreshes and the lack of feedback to trigger error recovery; there will also be a slightly higher probability of loss propagation compared to the case where the decompressor uses feedback.

由于周期性刷新和缺少触发错误恢复的反馈,没有建立反馈通道的压缩效率较低;与减压器使用反馈的情况相比,损失传播的概率也会稍高一些。

6.3. Control Fields
6.3. 控制场

ROHCv2 defines a number of control fields that are used by the decompressor in its interpretation of the header formats received from the compressor. The control fields listed in the following subsections are defined using the formal notation [RFC4997] in Section 6.8.2.4 of this document.

ROHCv2定义了许多控制字段,解压器在解释从压缩器接收的头格式时使用这些字段。以下小节中列出的控制字段使用本文件第6.8.2.4节中的正式符号[RFC4997]进行定义。

6.3.1. Master Sequence Number (MSN)
6.3.1. 主序列号(MSN)

The Master Sequence Number (MSN) field is either taken from a field that already exists in one of the headers of the protocol that the profile compresses (e.g., RTP SN), or alternatively it is created at the compressor. There is one MSN space per context.

主序列号(MSN)字段要么取自已存在于配置文件压缩的协议头之一中的字段(例如,RTP SN),要么在压缩器处创建。每个上下文有一个MSN空间。

The MSN field has the following two functions:

MSN字段具有以下两个功能:

o Differentiating between reference headers when receiving feedback data;

o 在接收反馈数据时区分参考标题;

o Inferring the value of incrementing fields (e.g., IPv4 Identifier).

o 推断递增字段的值(例如,IPv4标识符)。

There is one MSN field in every ROHCv2 header, i.e., the MSN is always present in each header type sent by the compressor. The MSN is sent in full in IR headers, while it can be lsb encoded within CO header formats. The decompressor always includes LSBs of the MSN in the Acknowledgment Number field in feedback (see Section 6.9). The compressor can later use this field to infer what packet the decompressor is acknowledging.

每个ROHCv2标头中都有一个MSN字段,即压缩机发送的每个标头类型中始终存在MSN。MSN在IR报头中以完整格式发送,而它可以以CO报头格式进行lsb编码。解压器总是在反馈的确认号字段中包含MSN的LSB(参见第6.9节)。压缩器稍后可以使用此字段推断解压器正在确认的数据包。

For profiles for which the MSN is created by the compressor (i.e., 0x0102, 0x0104, and 0x0108), the following applies:

对于由压缩器创建MSN的配置文件(即0x0102、0x0104和0x0108),以下内容适用:

o The compressor only initializes the MSN for a context when that context is first created or when the profile associated with a context changes;

o 压缩器仅在第一次创建上下文或与上下文相关联的概要文件更改时初始化该上下文的MSN;

o When the MSN is initialized, it is initialized to a random value;

o 当MSN被初始化时,它被初始化为随机值;

o The value of the MSN SHOULD be incremented by one for each packet that the compressor sends for a specific CID.

o 对于压缩器针对特定CID发送的每个数据包,MSN的值应增加1。

6.3.2. Reordering Ratio
6.3.2. 再订购率

The control field reorder_ratio specifies how much reordering is handled by the lsb encoding of the MSN. This is useful when header compression is performed over links with varying reordering

控制字段reorder_ratio指定MSN的lsb编码处理的重新排序量。当在具有不同重新排序的链接上执行头压缩时,这非常有用

characteristics. The reorder_ratio control field provides the means for the compressor to adjust the robustness characteristics of the lsb encoding method with respect to reordering and consecutive losses, as described in Section 5.1.2.

特点。如第5.1.2节所述,重新排序比率控制字段为压缩机提供了调整lsb编码方法关于重新排序和连续损失的鲁棒性特征的方法。

6.3.3. IP-ID Behavior
6.3.3. IP-ID行为

The IP-ID field of the IPv4 header can have different change patterns: sequential in network byte order, sequential byte-swapped, random or constant (a constant value of zero, although not conformant with [RFC0791], has been observed in practice). There is one IP-ID behavior control field per IP header. The control field for the IP-ID behavior of the innermost IP header determines which set of header formats is used. The IP-ID behavior control field is also used to determine the contents of the irregular chain item, for each IP header.

IPv4报头的IP-ID字段可以有不同的更改模式:网络字节顺序顺序、顺序字节交换、随机或常量(在实践中观察到常量值为零,但不符合[RFC0791])。每个IP头有一个IP-ID行为控制字段。最内层IP头的IP-ID行为的控制字段确定使用哪一组头格式。IP-ID行为控制字段还用于确定每个IP头的不规则链项的内容。

ROHCv2 profiles MUST NOT assign a sequential behavior (network byte order or byte-swapped) to any IP-ID but the one in the innermost IP header when compressing more than one level of IP headers. This is because only the IP-ID of the innermost IP header is likely to have a sufficiently close correlation with the MSN to compress it as a sequentially changing field. Therefore, a compressor MUST assign either the constant zero IP-ID or the random IP-ID behavior to tunneling headers.

ROHCv2配置文件不得将顺序行为(网络字节顺序或字节交换)分配给任何IP-ID,但压缩多个级别的IP头时,分配给最内层IP头中的IP-ID。这是因为只有最内层IP报头的IP-ID可能与MSN有足够密切的相关性,从而将其压缩为一个顺序变化的字段。因此,压缩器必须将常量零IP-ID或随机IP-ID行为分配给隧道头。

6.3.4. UDP-Lite Coverage Behavior
6.3.4. UDP Lite覆盖行为

The control field coverage_behavior specifies how the checksum coverage field of the UDP-Lite header is compressed with RoHCv2. It can indicate one of the following encoding methods: irregular, static, or inferred encoding.

控制字段覆盖率_行为指定如何使用RoHCv2压缩UDP Lite头的校验和覆盖率字段。它可以指示以下编码方法之一:不规则编码、静态编码或推断编码。

6.3.5. Timestamp Stride
6.3.5. 时间戳步长

The ts_stride control field is used in scaled RTP timestamp encoding (see Section 6.6.8). It defines the expected increase in the RTP timestamp between consecutive RTP sequence numbers.

ts_步幅控制字段用于缩放RTP时间戳编码(见第6.6.8节)。它定义了连续RTP序列号之间RTP时间戳的预期增加。

6.3.6. Time Stride
6.3.6. 时间步长

The time_stride control field is used in timer-based compression encoding (see Section 6.6.9). When timer-based compression is used, time_stride should be set to the expected difference in arrival time between consecutive RTP packets.

时间步长控制字段用于基于定时器的压缩编码(见第6.6.9节)。当使用基于计时器的压缩时,时间步长应设置为连续RTP数据包之间到达时间的预期差异。

6.3.7. CRC-3 for Control Fields
6.3.7. 控制字段的CRC-3

ROHCv2 profiles define a CRC-3 calculated over a number of control fields. This 3-bit CRC protecting the control fields is present in the header format for the co_common and co_repair header types.

ROHCv2配置文件定义了在多个控制字段上计算的CRC-3。这种保护控制字段的3位CRC以co_common和co_repair标头类型的标头格式存在。

The decompressor MUST always validate the integrity of the control fields covered by this 3-bit CRC when processing a co_common or a co_repair compressed header.

在处理co_公共或co_修复压缩头时,解压缩程序必须始终验证此3位CRC覆盖的控制字段的完整性。

Failure to validate the control fields using this CRC should be considered as a decompression failure by the decompressor in the algorithm that assesses the validity of the context. However, if the decompression attempt can be verified using either the CRC-3 or the CRC-7 calculated over the uncompressed header, the decompressor MAY still forward the decompressed header to upper layers. This is because the protected control fields are not always used to decompress the header (i.e., co_common or co_repair) that updates their respective value.

在评估上下文有效性的算法中,未能使用此CRC验证控制字段应被视为解压失败。然而,如果可以使用在未压缩报头上计算的CRC-3或CRC-7来验证解压缩尝试,则解压缩器仍然可以将解压缩报头转发到上层。这是因为受保护的控制字段并不总是用于解压更新其各自值的报头(即co_common或co_repair)。

The CRC polynomial and coverage of this CRC-3 is defined in Section 6.6.11.

本CRC-3的CRC多项式和覆盖范围见第6.6.11节。

6.4. Reconstruction and Verification
6.4. 重建与核查

Validation of the IR header (8-bit CRC)

IR报头的验证(8位CRC)

The decompressor MUST always validate the integrity of the IR header using the 8-bit CRC carried within the IR header. When the header is validated, the decompressor updates the context with the information in the IR header. Otherwise, if the IR cannot be validated, the context MUST NOT be updated and the IR header MUST NOT be delivered to upper layers.

解压器必须始终使用IR报头中携带的8位CRC验证IR报头的完整性。验证标头时,解压缩程序使用IR标头中的信息更新上下文。否则,如果无法验证IR,则不能更新上下文,也不能将IR头传递到上层。

Verification of CO headers (3-bit CRC or 7-bit CRC)

CO报头的验证(3位CRC或7位CRC)

The decompressor MUST always verify the decompression of a CO header using the CRC carried within the compressed header. When the decompression is verified and successful, the decompressor updates the context with the information received in the CO header; otherwise, if the reconstructed header fails the CRC verification, these updates MUST NOT be performed.

解压器必须始终使用压缩头中携带的CRC验证CO头的解压。当解压被验证并成功时,解压器使用在CO报头中接收的信息更新上下文;否则,如果重建的报头未通过CRC验证,则不得执行这些更新。

A packet for which the decompression attempt cannot be verified using the CRC MUST NOT be delivered to upper layers.

不能使用CRC验证解压缩尝试的数据包不得传送到上层。

Decompressor implementations may attempt corrective or repair measures on CO headers prior to performing the above actions, and the result of any decompression attempt MUST be verified using the CRC.

在执行上述操作之前,解压器实现可能会尝试对CO标头采取纠正或修复措施,并且必须使用CRC验证任何解压尝试的结果。

6.5. Compressed Header Chains
6.5. 压缩割台链

Some header types use one or more chains containing sub-header information. The function of a chain is to group fields based on similar characteristics, such as static, dynamic, or irregular fields.

某些标题类型使用一个或多个包含子标题信息的链。链的功能是根据类似的特征(如静态、动态或不规则字段)对字段进行分组。

Chaining is done by appending an item for each header to the chain in their order of appearance in the uncompressed packet, starting from the fields in the outermost header.

链接是通过从最外层的头中的字段开始,按照在未压缩数据包中的出现顺序将每个头的项附加到链中来完成的。

In the text below, the term <protocol_name> is used to identify formal notation names corresponding to different protocol headers. The mapping between these is defined in the following table:

在下文中,术语<protocol_name>用于标识对应于不同协议头的正式符号名称。下表中定义了它们之间的映射:

     +----------------------------------+---------------+
     | Protocol                         | protocol_name |
     +----------------------------------+---------------+
     | IPv4                    RFC 0791 | ipv4          |
     | IPv6                    RFC 2460 | ipv6          |
     | UDP                     RFC 0768 | udp           |
     | RTP                     RFC 3550 | rtp           |
     | ESP                     RFC 4303 | esp           |
     | UDP-Lite                RFC 3828 | udp_lite      |
     | AH                      RFC 4302 | ah            |
     | GRE           RFC 2784, RFC 2890 | gre           |
     | MINE                    RFC 2004 | mine          |
     | IPv6 Destination Option RFC 2460 | dest_opt      |
     | IPv6 Hop-by-hop Options RFC 2460 | hop_opt       |
     | IPv6 Routing Header     RFC 2460 | rout_opt      |
     +----------------------------------+---------------+
        
     +----------------------------------+---------------+
     | Protocol                         | protocol_name |
     +----------------------------------+---------------+
     | IPv4                    RFC 0791 | ipv4          |
     | IPv6                    RFC 2460 | ipv6          |
     | UDP                     RFC 0768 | udp           |
     | RTP                     RFC 3550 | rtp           |
     | ESP                     RFC 4303 | esp           |
     | UDP-Lite                RFC 3828 | udp_lite      |
     | AH                      RFC 4302 | ah            |
     | GRE           RFC 2784, RFC 2890 | gre           |
     | MINE                    RFC 2004 | mine          |
     | IPv6 Destination Option RFC 2460 | dest_opt      |
     | IPv6 Hop-by-hop Options RFC 2460 | hop_opt       |
     | IPv6 Routing Header     RFC 2460 | rout_opt      |
     +----------------------------------+---------------+
        

Static chain:

静态链:

The static chain consists of one item for each header of the chain of protocol headers that is compressed, starting from the outermost IP header. In the formal description of the header formats, this static chain item for each header type is labeled <protocol_name>_static. The static chain is only used in the IR header format.

静态链由压缩的协议头链的每个头的一个项组成,从最外层的IP头开始。在标题格式的正式描述中,每个标题类型的此静态链项标记为<protocol\u name>\u static。静态链仅在IR标头格式中使用。

Dynamic chain:

动态链:

The dynamic chain consists of one item for each header of the chain of protocol headers that is compressed, starting from the outermost IP header. In the formal description of the header formats, the dynamic chain item for each header type is labeled <protocol_name>_dynamic. The dynamic chain is only used in the IR and co_repair header formats.

动态链包括从最外层的IP头开始压缩的协议头链的每个头的一个项。在头格式的正式描述中,每种头类型的动态链项都标记为<protocol\u name>\u dynamic。动态链仅用于IR和co_修复头格式。

Irregular chain:

不规则链:

The structure of the irregular chain is analogous to the structure of the static chain. For each compressed header that uses the general format of Section 6.8, the irregular chain is appended at a specific location in the general format of the compressed headers. In the formal description of the header formats, the irregular chain item for each header type is a format whose name is suffixed by "_irregular". The irregular chain is used in all CO headers, except for the co_repair format.

不规则链的结构类似于静态链的结构。对于使用第6.8节通用格式的每个压缩标题,不规则链附加在压缩标题通用格式的特定位置。在标题格式的正式描述中,每种标题类型的不规则链项是一种格式,其名称后缀为“_unregular”。不规则链用于除CO_修复格式之外的所有CO标头。

The format of the irregular chain for the innermost IP header differs from the format used for the outer IP headers, because the innermost IP header is part of the compressed base header. In the definition of the header formats using the formal notation, the argument "is_innermost", which is passed to the corresponding encoding method (ipv4 or ipv6), determines what irregular chain items to use. The format of the irregular chain item for the outer IP headers is also determined using one flag for TTL/Hop Limit and TOS/TC. This flag is defined in the format of some of the compressed base headers.

最内层IP头的不规则链的格式与外部IP头的格式不同,因为最内层IP头是压缩的基本头的一部分。在使用形式表示法定义标头格式时,参数“is_innerst”(传递给相应的编码方法(ipv4或ipv6))确定要使用的不规则链项。外部IP头的不规则链项的格式也使用TTL/Hop Limit和TOS/TC的一个标志来确定。此标志以某些压缩的基本标头的格式定义。

ROHCv2 profiles compress extension headers as other headers, and thus extension headers have a static chain, a dynamic chain, and an irregular chain.

ROHCv2概要文件将扩展头压缩为其他头,因此扩展头具有静态链、动态链和不规则链。

   ROHCv2 profiles define chains for all headers that can be compressed,
   i.e., RTP [RFC3550], UDP [RFC0768], ESP [RFC4303], UDP-Lite
   [RFC3828], IPv4 [RFC0791], IPv6 [RFC2460], AH [RFC4302], GRE
   [RFC2784][RFC2890], MINE [RFC2004], IPv6 Destination Options header
   [RFC2460], IPv6 Hop-by-hop Options header [RFC2460], and IPv6 Routing
   header [RFC2460].
        
   ROHCv2 profiles define chains for all headers that can be compressed,
   i.e., RTP [RFC3550], UDP [RFC0768], ESP [RFC4303], UDP-Lite
   [RFC3828], IPv4 [RFC0791], IPv6 [RFC2460], AH [RFC4302], GRE
   [RFC2784][RFC2890], MINE [RFC2004], IPv6 Destination Options header
   [RFC2460], IPv6 Hop-by-hop Options header [RFC2460], and IPv6 Routing
   header [RFC2460].
        
6.6. Header Formats and Encoding Methods
6.6. 标题格式和编码方法

The header formats are defined using the ROHC formal notation. Some of the encoding methods used in the header formats are defined in [RFC4997], while other methods are defined in this section.

标题格式使用ROHC形式表示法定义。标题格式中使用的一些编码方法在[RFC4997]中定义,而其他方法在本节中定义。

6.6.1. baseheader_extension_headers
6.6.1. baseheader\u扩展\u头

The baseheader_extension_headers encoding method skips over all fields of the extension headers of the innermost IP header, without encoding any of them. Fields in these extension headers are instead encoded in the irregular chain.

baseheader_extension_headers编码方法跳过最内层IP头的扩展头的所有字段,而不对其中任何字段进行编码。这些扩展标题中的字段改为在不规则链中编码。

This encoding is used in CO headers (see Section 6.8.2). The innermost IP header is combined with other header(s) (i.e., UDP, UDP-Lite, RTP) to create the compressed base header. In this case, there may be a number of extension headers between the IP headers and the other headers.

该编码用于CO头(见第6.8.2节)。最里面的IP报头与其他报头(即UDP、UDP Lite、RTP)组合以创建压缩的基本报头。在这种情况下,在IP头和其他头之间可能有许多扩展头。

The base header defines a representation of the extension headers, to comply with the syntax of the formal notation; this encoding method provides this representation.

基本头定义了扩展头的表示,以符合形式表示法的语法;这种编码方法提供了这种表示。

6.6.2. baseheader_outer_headers
6.6.2. 基本标头\外部标头

The baseheader_outer_headers encoding method skips over all the fields of the extension header(s) that do not belong to the innermost IP header, without encoding any of them. Changing fields in outer headers are instead handled by the irregular chain.

baseheader\u outer\u headers编码方法跳过不属于最内层IP头的扩展头的所有字段,而不对其中任何字段进行编码。外部标题中的更改字段由不规则链处理。

This encoding method, similarly to the baseheader_extension_headers encoding method above, is necessary to keep the definition of the header formats syntactically correct. It describes tunneling IP headers and their respective extension headers (i.e., all headers located before the innermost IP header) for CO headers (see Section 6.8.2).

此编码方法类似于上面的baseheader_extension_headers编码方法,对于保持头格式的定义在语法上正确是必要的。它描述了CO头的隧道IP头及其各自的扩展头(即位于最内层IP头之前的所有头)(见第6.8.2节)。

6.6.3. inferred_udp_length
6.6.3. 推断长度

The decompressor infers the value of the UDP length field as being the sum of the UDP header length and the UDP payload length. The compressor must therefore ensure that the UDP length field is consistent with the length field(s) of preceding subheaders, i.e., there must not be any padding after the UDP payload that is covered by the IP Length.

解压缩程序将UDP长度字段的值推断为UDP报头长度和UDP有效负载长度之和。因此,压缩器必须确保UDP长度字段与前面子标题的长度字段一致,即IP长度覆盖的UDP有效负载后不得有任何填充。

This encoding method is also used for the UDP-Lite Checksum Coverage field when it behaves in the same manner as the UDP length field (i.e., when the checksum always covers the entire UDP-Lite payload).

当UDP Lite校验和覆盖范围字段的行为与UDP长度字段的行为相同时(即,当校验和始终覆盖整个UDP Lite有效负载时),此编码方法也用于UDP Lite校验和覆盖范围字段。

6.6.4. inferred_ip_v4_header_checksum
6.6.4. 推断的\u ip\u v4\u头\u校验和

This encoding method compresses the header checksum field of the IPv4 header. This checksum is defined in RFC 791 [RFC0791] as follows:

此编码方法压缩IPv4标头的标头校验和字段。该校验和在RFC 791[RFC0791]中定义如下:

Header Checksum: 16 bits

报头校验和:16位

A checksum on the header only. Since some header fields change (e.g., time to live), this is recomputed and verified at each point that the internet header is processed.

仅在标头上使用校验和。由于某些报头字段发生更改(例如,生存时间),因此会在处理internet报头的每个点重新计算和验证。

The checksum algorithm is:

校验和算法是:

The checksum field is the 16 bit one's complement of the one's complement sum of all 16 bit words in the header. For purposes of computing the checksum, the value of the checksum field is zero.

校验和字段是报头中所有16位字的补码和的16位一的补码。为了计算校验和,校验和字段的值为零。

As described above, the header checksum protects individual hops from processing a corrupted header. As the data that this checksum protects is mostly compressed away and is instead taken from state stored in the context, this checksum becomes cumulative to the ROHC CRC. When using this encoding method, the checksum is recomputed by the decompressor.

如上所述,报头校验和保护单个跃点不处理损坏的报头。由于该校验和保护的数据大部分被压缩掉,取而代之的是从上下文中存储的状态中获取的数据,因此该校验和将累积到ROHC CRC中。使用此编码方法时,校验和由解压缩程序重新计算。

The inferred_ip_v4_header_checksum encoding method thus compresses the header checksum field of the IPv4 header down to a size of zero bits, i.e., no bits are transmitted in compressed headers for this field. Using this encoding method, the decompressor infers the value of this field using the computation above.

因此,推断出的_ip_v4_报头_校验和编码方法将IPv4报头的报头校验和字段压缩到零位大小,即,在压缩报头中不传输该字段的位。使用此编码方法,解压器使用上述计算推断此字段的值。

The compressor MAY use the header checksum to validate the correctness of the header before compressing it, to avoid processing a corrupted header.

压缩器可以使用报头校验和在压缩报头之前验证报头的正确性,以避免处理损坏的报头。

6.6.5. inferred_mine_header_checksum
6.6.5. 推断的\u挖掘\u标题\u校验和

This encoding method compresses the minimal encapsulation header checksum. This checksum is defined in RFC 2004 [RFC2004] as follows:

此编码方法压缩最小封装头校验和。该校验和在RFC 2004[RFC2004]中定义如下:

Header Checksum

报头校验和

The 16-bit one's complement of the one's complement sum of all 16-bit words in the minimal forwarding header. For purposes of computing the checksum, the value of the checksum field is 0. The IP header and IP payload (after the minimal forwarding header) are not included in this checksum computation.

最小转发报头中所有16位字的补码和的16位补码。为了计算校验和,校验和字段的值为0。IP报头和IP有效负载(在最小转发报头之后)不包括在此校验和计算中。

The inferred_mine_header_checksum encoding method compresses the minimal encapsulation header checksum down to a size of zero bits, i.e., no bits are transmitted in compressed headers for this field. Using this encoding method, the decompressor infers the value of this field using the above computation.

推断的_mine_header_校验和编码方法将最小封装报头校验和压缩到零位大小,即,此字段的压缩报头中不传输任何位。使用此编码方法,解压器使用上述计算推断此字段的值。

The motivations for inferring this checksum are similar to the ones explained above in Section 6.6.4.

推断该校验和的动机与上文第6.6.4节中解释的类似。

The compressor MAY use the minimal encapsulation header checksum to validate the correctness of the header before compressing it, to avoid processing a corrupted header.

压缩器可以使用最小封装标头校验和在压缩标头之前验证标头的正确性,以避免处理损坏的标头。

6.6.6. inferred_ip_v4_length
6.6.6. 推断的\u ip\u v4\u长度

This encoding method compresses the total length field of the IPv4 header. The total length field of the IPv4 header is defined in RFC 791 [RFC0791] as follows:

此编码方法压缩IPv4标头的总长度字段。IPv4报头的总长度字段在RFC 791[RFC0791]中定义如下:

Total Length: 16 bits

总长度:16位

Total Length is the length of the datagram, measured in octets, including internet header and data. This field allows the length of a datagram to be up to 65,535 octets.

Total Length是数据报的长度,以八位字节为单位,包括internet标头和数据。此字段允许数据报的长度最多为65535个八位字节。

The inferred_ip_v4_length encoding method compresses the IPv4 header checksum down to a size of zero bits, i.e., no bits are transmitted in compressed headers for this field. Using this encoding method, the decompressor infers the value of this field by counting in octets the length of the entire packet after decompression.

推断的_ip_v4_长度编码方法将IPv4报头校验和压缩为零位大小,即此字段的压缩报头中不传输任何位。使用这种编码方法,解压器通过以八位字节为单位计算解压后整个数据包的长度来推断此字段的值。

6.6.7. inferred_ip_v6_length
6.6.7. 推断的ip长度

This encoding method compresses the payload length field in the IPv6 header. This length field is defined in RFC 2460 [RFC2460] as follows:

此编码方法压缩IPv6标头中的有效负载长度字段。该长度字段在RFC 2460[RFC2460]中定义如下:

Payload Length: 16-bit unsigned integer

有效负载长度:16位无符号整数

Length of the IPv6 payload, i.e., the rest of the packet following this IPv6 header, in octets. (Note that any extension headers present are considered part of the payload, i.e., included in the length count.)

IPv6有效负载的长度,即该IPv6报头之后的数据包的剩余部分,以八位字节为单位。(请注意,存在的任何扩展标头都被视为有效负载的一部分,即包含在长度计数中。)

The "inferred_ip_v6_length" encoding method compresses the payload length field of the IPv6 header down to a size of zero bits, i.e., no bits are transmitted in compressed headers for this field. Using this encoding method, the decompressor infers the value of this field by counting in octets the length of the entire packet after decompression.

“推断的_ip_v6_长度”编码方法将IPv6报头的有效负载长度字段压缩到零位大小,即,在压缩报头中不传输该字段的任何位。使用这种编码方法,解压器通过以八位字节为单位计算解压后整个数据包的长度来推断此字段的值。

IPv6 headers using the jumbo payload option of RFC 2675 [RFC2675] will not be compressible with this encoding method since the value of the payload length field does not match the length of the packet.

使用RFC 2675[RFC2675]的jumbo payload选项的IPv6报头将无法使用此编码方法进行压缩,因为payload length字段的值与数据包的长度不匹配。

6.6.8. Scaled RTP Timestamp Compression
6.6.8. 缩放RTP时间戳压缩

This section provides additional details on encodings used to scale the RTP timestamp, as defined in the formal notation in Section 6.8.2.4.

本节提供了有关用于缩放RTP时间戳的编码的更多详细信息,如第6.8.2.4节中的正式符号所定义。

The RTP timestamp (TS) usually increases by a multiple of the RTP Sequence Number's (SN's) increase and is therefore a suitable candidate for scaled encoding. This scaling factor is labeled ts_stride in the definition of the profile in the formal notation. The compressor sets the scaling factor based on the change in TS with respect to the change in the RTP SN.

RTP时间戳(TS)通常增加RTP序列号(SN)增加的倍数,因此是缩放编码的合适候选。该比例因子在形式符号中的轮廓定义中标记为ts_stride。压缩器根据TS相对于RTP SN的变化设置比例因子。

The default value of the scaling factor ts_stride is 160, as defined in Section 6.8.2.4. To use a different value for ts_stride, the compressor explicitly updates the value of ts_stride to the decompressor using one of the header formats that can carry this information.

如第6.8.2.4节所述,缩放因子ts_步长的默认值为160。要为ts_stride使用不同的值,压缩器将使用可携带此信息的其中一种标头格式将ts_stride的值显式更新到解压缩器。

When the compressor uses a scaling factor that is different than the default value of ts_stride, it can only use the new scaling factor once it has enough confidence that the decompressor has successfully calculated the residue (ts_offset) of the scaling function for the timestamp. The compressor achieves this by sending unscaled timestamp values, to allow the decompressor to establish the residue based on the current ts_stride. The compressor MAY send the unscaled timestamp in the same compressed header(s) used to establish the value of ts_stride.

当压缩器使用的缩放因子不同于ts_stride的默认值时,只有当压缩器有足够的信心成功计算出时间戳缩放函数的剩余值(ts_offset)时,它才能使用新的缩放因子。压缩器通过发送未标度的时间戳值来实现这一点,以允许解压缩器基于当前ts_步长建立剩余值。压缩器可以在用于建立ts_步长值的相同压缩报头中发送未标度时间戳。

Once the compressor has gained enough confidence that both the value of the scaling factor and the value of the residue have been established in the decompressor, the compressor can start compressing packets using the new scaling factor.

一旦压缩器获得足够的置信度,即在解压缩器中建立了缩放因子的值和剩余值,压缩器就可以使用新的缩放因子开始压缩分组。

When the compressor detects that the residue (ts_offset) value has changed, it MUST NOT select a compressed header format that uses the scaled timestamp encoding before it has re-established the residue as described above.

当压缩器检测到剩余(ts_offset)值已更改时,在如上所述重新建立剩余之前,压缩器不得选择使用缩放时间戳编码的压缩报头格式。

When the value of the timestamp field wraps around, the value of the residue of the scaling function is likely to change. When this occurs, the compressor re-establishes the new residue value as described above.

当timestamp字段的值环绕时,缩放函数的剩余值可能会改变。发生这种情况时,压缩机将重新建立新的残余值,如上所述。

If the decompressor receives a compressed header containing scaled timestamp bits while the ts_stride equals zero, it MUST NOT deliver the packet to upper layers and it SHOULD treat this as a CRC verification failure.

如果解压器在ts_步长等于零的情况下接收到包含缩放时间戳位的压缩报头,则解压器不得将数据包传送到上层,并且应将其视为CRC验证失败。

Whether or not the scaling is applied to the RTP TS field is up to the compressor implementation (i.e., the use of scaling is OPTIONAL), and is indicated by the tsc_indicator control field. In case scaling is applied to the RTP TS field, the value of ts_stride used by the compressor is up to the implementation. A value of ts_stride that is set to the expected increase in the RTP timestamp between consecutive unit increases of the RTP SN will provide the most gain for the scaled encoding. Other values may provide the same gain in some situations, but may reduce the gain in others.

缩放是否应用于RTP TS字段取决于压缩机的实施(即,缩放的使用是可选的),并由tsc_指示器控制字段指示。如果将缩放应用于RTP TS字段,则压缩器使用的TS_步长值取决于实现。设置为RTP SN连续单位增加之间RTP时间戳的预期增加的ts_stride值将为缩放编码提供最大增益。其他值在某些情况下可能提供相同的增益,但在其他情况下可能会降低增益。

When scaled timestamp encoding is used for header formats that do not transmit any lsb-encoded timestamp bits at all, the inferred_scaled_field encoding of Section 6.6.10 is used for encoding the timestamp.

当缩放时间戳编码用于根本不传输任何lsb编码的时间戳位的报头格式时,第6.6.10节中推断的_缩放_字段编码用于编码时间戳。

6.6.9. timer_based_lsb
6.6.9. 基于定时器的lsb

The timer-based compression encoding method, timer_based_lsb, compresses a field whose change pattern approximates a linear function of the time of day.

基于计时器的压缩编码方法,即基于计时器的计时器lsb,压缩其变化模式近似于一天中时间的线性函数的字段。

This encoding uses the local clock to obtain an approximation of the value that it encodes. The approximated value is then used as a reference value together with the num_lsbs_param least-significant bits received as the encoded value, where num_lsbs_param represents a number of bits that is sufficient to uniquely represent the encoded value in the presence of jitter between compression endpoints.

此编码使用本地时钟获得其编码值的近似值。然后将近似值与作为编码值接收的num_lsbs_param最低有效位一起用作参考值,其中num_lsbs_param表示在压缩端点之间存在抖动的情况下足以唯一表示编码值的位数。

     ts_scaled =:= timer_based_lsb(<time_stride_param>,
                                   <num_lsbs_param>, <offset_param>)
        
     ts_scaled =:= timer_based_lsb(<time_stride_param>,
                                   <num_lsbs_param>, <offset_param>)
        

The parameters "num_lsbs_param" and "offset_param" are the parameters to use for the lsb encoding, i.e., the number of least significant bits and the interpretation interval offset, respectively. The parameter "time_stride_param" represents the context value of the control field time_stride.

参数“num_lsbs_param”和“offset_param”分别是用于lsb编码的参数,即最低有效位的数量和解释间隔偏移。参数“time_stride_param”表示控制字段time_stride的上下文值。

This encoding method always uses a scaled version of the field it compresses.

此编码方法始终使用压缩字段的缩放版本。

The value of the field is decoded by calculating an approximation of the scaled value, using:

通过使用以下公式计算缩放值的近似值,对场值进行解码:

tsc_ref_advanced = tsc_ref + (a_n - a_ref) / time_stride.

tsc_ref_advanced=tsc_ref+(a_n-a_ref)/时间步长。

where:

哪里:

- tsc_ref is a reference value of the scaled representation of the field. - a_n is the arrival time associated with the value to decode. - a_ref is the arrival time associated with the reference header. - tsc_ref_advanced is an approximation of the scaled value of the field.

- tsc_ref是字段缩放表示的参考值。-a_n是与要解码的值关联的到达时间。-a_ref是与参考标头关联的到达时间。-tsc_ref_advanced是字段缩放值的近似值。

The lsb encoding is then applied using the num_lsbs_param bits received in the compressed header and the tsc_ref_advanced as "ref_value" (as per Section 4.11.5 of [RFC4997]).

然后,使用压缩报头中接收的num_lsbs_param位和作为“ref_值”的tsc_ref_高级应用lsb编码(根据[RFC4997]第4.11.5节)。

Appendix B.3 provides an example of how the compressor can calculate jitter.

附录B.3提供了压缩机如何计算抖动的示例。

The control field time_stride controls whether or not the timer_based_lsb method is used in the CO header. The decompressor SHOULD send the CLOCK_RESOLUTION option with a zero value, if:

控制字段time_stride控制CO报头中是否使用基于计时器的\u lsb方法。如果出现以下情况,解压器应发送带有零值的时钟分辨率选项:

o it receives a non-zero time_stride value, and

o 它接收非零时间步长值,并且

o it has not previously sent a CLOCK_RESOLUTION feedback with a non-zero value.

o 它以前没有发送非零值的时钟分辨率反馈。

This is to allow compression to recover from the case where a compressor erroneously activates timer-based compression.

这是为了允许压缩从压缩机错误激活基于计时器的压缩的情况下恢复。

The support and usage of timer-based compression is OPTIONAL for both the compressor and the decompressor; the compressor is not required to set the time_stride control field to a non-zero value when it has received a non-zero value for the CLOCK_RESOLUTION option.

基于定时器的压缩的支持和使用对于压缩机和解压缩器都是可选的;当压缩器接收到时钟分辨率选项的非零值时,无需将时间步长控制字段设置为非零值。

6.6.10. inferred_scaled_field
6.6.10. 推断\u缩放\u字段

The inferred_scaled_field encoding method encodes a field that is defined as changing in relation to the MSN, and for which the increase with respect to the MSN can be scaled by some scaling factor. This encoding method is used in compressed header formats that do not contain any bits for the scaled field. In this case, the decompressor infers the unscaled value of the scaled field from the MSN field. The unscaled value is calculated according to the following formula:

推断的_scaled_字段编码方法对定义为相对于MSN改变的字段进行编码,并且对于该字段,相对于MSN的增加可以通过一些缩放因子进行缩放。此编码方法用于不包含缩放字段任何位的压缩头格式。在这种情况下,解压缩器从MSN字段推断缩放字段的未缩放值。未标度值根据以下公式计算:

      unscaled_value = delta_msn * stride + reference_unscaled_value
        
      unscaled_value = delta_msn * stride + reference_unscaled_value
        

where "delta_msn" is the difference in MSN between the reference value of the MSN in the context and the value of the MSN decompressed

其中,“delta_msn”是上下文中msn的参考值和解压缩的msn的值之间的msn差

from this packet, "reference_unscaled_value" is the value of the field being scaled in the context, and "stride" is the scaling value for this field.

从这个数据包中,“reference_unscaled_value”是上下文中正在缩放的字段的值,“stride”是该字段的缩放值。

For example, when this encoding method is applied to the RTP timestamp in the RTP profile, the calculation above becomes:

例如,当此编码方法应用于RTP简档中的RTP时间戳时,上述计算变为:

      timestamp = delta_msn * ts_stride + reference_timestamp
        
      timestamp = delta_msn * ts_stride + reference_timestamp
        
6.6.11. control_crc3_encoding
6.6.11. 控制crc3编码

The control_crc3_encoding method provides a CRC calculated over a number of control fields. The definition of this encoding method is the same as for the "crc" encoding method specified in Section 4.11.6 of [RFC4997], with the difference being that the data covered by the CRC is given by a concatenated list of control fields.

control_crc3_编码方法提供在多个控制字段上计算的CRC。该编码方法的定义与[RFC4997]第4.11.6节中规定的“crc”编码方法的定义相同,不同之处在于,crc覆盖的数据由控制字段的串联列表给出。

In other words, the definition of the control_crc3_encoding method is equivalent to the following definition:

换句话说,control_crc3_编码方法的定义等同于以下定义:

     control_crc_encoding(ctrl_data_value, ctrl_data_length)
     {
       UNCOMPRESSED {
       }
        
     control_crc_encoding(ctrl_data_value, ctrl_data_length)
     {
       UNCOMPRESSED {
       }
        
       COMPRESSED {
         control_crc3 =:=
           crc(3, 0x06, 0x07, ctrl_data_value, ctrl_data_length) [ 3 ];
       }
     }
        
       COMPRESSED {
         control_crc3 =:=
           crc(3, 0x06, 0x07, ctrl_data_value, ctrl_data_length) [ 3 ];
       }
     }
        

where the parameter "ctrl_data_value" binds to the concatenated values of the following control fields, in the order listed below:

其中,参数“ctrl_data_value”按下列顺序绑定到以下控制字段的串联值:

o reorder_ratio, 2 bits padded with 6 MSB of zeroes

o 重新排序_比率,2位填充6 MSB的零

o ts_stride, 32 bits (only for profiles 0x0101 and 0x0107)

o ts_步长,32位(仅适用于配置文件0x0101和0x0107)

o time_stride, 32 bits (only for profiles 0x0101 and 0x0107)

o 时间步长,32位(仅适用于配置文件0x0101和0x0107)

o msn, 16 bits (not applicable for profiles 0x0101, 0x0103, and 0x0107)

o msn,16位(不适用于配置文件0x0101、0x0103和0x0107)

o coverage_behavior, 2 bits padded with 6 MSB of zeroes (only for profiles 0x0107 and 0x0108)

o 覆盖率_行为,2位填充6 MSB的零(仅适用于配置文件0x0107和0x0108)

o ip_id_behavior, one octet for each IP header in the compressible header chain starting from the outermost header. Each octet consists of 2 bits padded with 6 MSBs of zeroes.

o ip_id_行为,在可压缩报头链中,从最外层报头开始的每个ip报头对应一个八位组。每个八位字节由2位组成,并用6个零的MSB填充。

The "ctrl_data_length" binds to the sum of the length of the control field(s) that are applicable to the specific profile.

“ctrl_data_length”绑定到适用于特定配置文件的控制字段的长度总和。

The decompressor uses the resulting 3-bit CRC to validate the control fields that are updated by the co_common and co_repair header formats; this CRC cannot be used to verify the outcome of a decompression attempt.

解压器使用产生的3位CRC来验证由co_公共和co_修复头格式更新的控制字段;此CRC不能用于验证解压缩尝试的结果。

This CRC protects the update of control fields, as the updated values are not always used to decompress the header that carries them and thus are not protected by the CRC-7 verification. This prevents impairments that could occur if the decompression of a co_common or of a co_repair succeeds and the decompressor sends positive feedback, while for some reason the control fields are incorrectly updated.

该CRC保护控制字段的更新,因为更新的值并不总是用于解压携带它们的报头,因此不受CRC-7验证的保护。这可防止在co_公共或co_修复解压缩成功且解压缩器发送正反馈时,由于某种原因控制字段被错误更新时可能发生的损害。

6.6.12. inferred_sequential_ip_id
6.6.12. 推断的\u顺序\u ip\u id

This encoding method is used with a sequential IP-ID behavior (sequential or sequential byte-swapped) and when there are no coded IP-ID bits in the compressed header. In this case, the IP-ID offset from the MSN is constant, and the IP-ID increases by the same amount as the MSN (similar to the inferred_scaled_field encoding method).

此编码方法用于顺序IP-ID行为(顺序或顺序字节交换)以及压缩头中没有编码IP-ID位时。在这种情况下,来自MSN的IP-ID偏移量是恒定的,并且IP-ID的增加量与MSN的增加量相同(类似于推断的_缩放_字段编码方法)。

The decompressor calculates the value for the IP-ID according to the following formula:

解压缩器根据以下公式计算IP-ID的值:

IP-ID = delta_msn + reference_IP_ID_value

IP-ID=增量msn+参考IP-ID值

where "delta_msn" is the difference between the reference value of the MSN in the context and the uncompressed value of the MSN associated to the compressed header, and where "reference_IP_ID_value" is the value of the IP-ID in the context. For swapped IP-ID behavior (i.e., when ip_id_behavior_innermost is set to IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED), "reference_IP_ID_value" and "IP-ID" are byte-swapped with regard to the corresponding fields in the context.

其中,“delta_msn”是上下文中的msn的参考值和与压缩报头相关联的msn的未压缩值之间的差,其中“reference_IP_ID_value”是上下文中的IP-ID的值。对于交换的IP-ID行为(即,当IP_ID_behavior_innerst设置为IP_ID_behavior_SEQUENTIAL_swapped时),“reference_IP_ID_value”和“IP-ID”相对于上下文中的相应字段进行字节交换。

If the IP-ID behavior is random or zero, this encoding method does not update any fields.

如果IP-ID行为为随机或零,则此编码方法不会更新任何字段。

6.6.13. list_csrc(cc_value)
6.6.13. 列表(cc值)

This encoding method compresses the list of RTP CSRC identifiers using list compression. This encoding establishes a content for the different CSRC identifiers (items) and a list describing the order in which they appear.

此编码方法使用列表压缩来压缩RTP CSC标识符列表。该编码为不同的CSC标识符(项目)建立内容,并建立描述其出现顺序的列表。

The compressor passes an argument (cc_value) to this encoding method: this is the value of the CC field taken from the RTP header. The decompressor is required to bind the value of this argument to the number of items in the list, which will allow the decompressor to correctly reconstruct the CC field.

压缩器将一个参数(cc_值)传递给此编码方法:这是从RTP头获取的cc字段的值。解压器需要将此参数的值绑定到列表中的项数,这将允许解压器正确地重建CC字段。

6.6.13.1. List Compression
6.6.13.1. 列表压缩

The CSRC identifiers in the uncompressed packet can be represented as an ordered list, whose order and presence are usually constant between packets. The generic structure of such a list is as follows:

未压缩数据包中的CSC标识符可以表示为有序列表,其顺序和存在通常在数据包之间保持不变。该清单的一般结构如下:

            +--------+--------+--...--+--------+
      list: | item 1 | item 2 |       | item n |
            +--------+--------+--...--+--------+
        
            +--------+--------+--...--+--------+
      list: | item 1 | item 2 |       | item n |
            +--------+--------+--...--+--------+
        

When performing list compression on a CSRC list, each item is the uncompressed value of one CSRC identifier.

在对CSC列表执行列表压缩时,每个项目都是一个CSC标识符的未压缩值。

The basic principles of list-based compression are the following:

基于列表的压缩的基本原理如下:

When initializing the context:

初始化上下文时:

1) The complete representation of the list of CSRC identifiers is transmitted.

1) 传输CSC标识符列表的完整表示。

Then, once the context has been initialized:

然后,在初始化上下文后:

2) When the list is unchanged, a compressed header that does not contain information about the list can be used.

2) 当列表保持不变时,可以使用不包含列表信息的压缩标题。

3) When the list changes, a compressed list is sent in the compressed header, including a representation of its structure and order. Previously unknown items are sent uncompressed in the list, while previously known items are only represented by an index pointing to the item stored in the context.

3) 当列表更改时,将在压缩头中发送压缩列表,包括其结构和顺序的表示。以前未知的项在列表中以未压缩的方式发送,而以前已知的项仅由指向存储在上下文中的项的索引表示。

6.6.13.2. Table-based Item Compression
6.6.13.2. 基于表的项目压缩

The table-based item compression compresses individual items sent in compressed lists. The compressor assigns a unique identifier, "Index", to each item "Item" of a list.

基于表的项压缩压缩压缩在压缩列表中发送的单个项。压缩器为列表中的每个“项”分配唯一标识符“索引”。

Compressor Logic

压缩逻辑

The compressor conceptually maintains an item table containing all items, indexed using "Index". The (Index, Item) pair is sent together in compressed lists until the compressor gains enough confidence that the decompressor has observed the mapping between items and their respective index. Confidence is obtained from the reception of an acknowledgment from the decompressor, or by sending (Index, Item) pairs using the optimistic approach. Once confidence is obtained, the index alone is sent in compressed lists to indicate the presence of the item corresponding to this index.

压缩器概念上维护一个包含所有项的项表,并使用“索引”进行索引。(索引,项)对在压缩列表中一起发送,直到压缩器获得足够的置信度,即解压缩器已观察到项与其各自索引之间的映射。置信度是通过接收来自解压器的确认,或通过使用乐观方法发送(索引、项)对来获得的。一旦获得了置信度,则仅在压缩列表中发送索引,以指示存在与此索引对应的项。

The compressor MAY reset its item table upon receiving a negative acknowledgement.

压缩机可在收到否定确认后重置其项目表。

The compressor MAY reassign an existing index to a new item by re-establishing the mapping using the procedure described above.

压缩器可通过使用上述步骤重新建立映射,将现有索引重新分配给新项。

Decompressor Logic

解压逻辑

The decompressor conceptually maintains an item table that contains all (Index, Item) pairs received. The item table is updated whenever an (Index, Item) pair is received and decompression is successful (CRC verification, or CRC-8 validation). The decompressor retrieves the item from the table whenever an Index is received without an accompanying Item.

从概念上讲,解压缩程序维护一个包含所有接收到的(索引、项)对的项表。每当接收到(索引、项)对且解压缩成功(CRC验证或CRC-8验证)时,项表就会更新。每当收到没有附带项的索引时,解压器就会从表中检索该项。

If an index is received without an accompanying Item and the decompressor does not have any context for this index, the decompressor MUST NOT deliver the packet to upper layers.

如果接收到的索引没有附带项,且解压器没有该索引的任何上下文,则解压器不得将数据包交付给上层。

6.6.13.3. Encoding of Compressed Lists
6.6.13.3. 压缩列表的编码

Each item present in a compressed list is represented by:

压缩列表中的每个项目由以下内容表示:

o an Index into the table of items, and a presence bit indicating if a compressed representation of the item is present in the list.

o 项表中的索引,以及表示列表中是否存在项的压缩表示的存在位。

o an item (if the presence bit is set).

o 项目(如果设置了存在位)。

If the presence bit is not set, the item must already be known by the decompressor.

如果未设置存在位,则解压缩程序必须已经知道该项。

A compressed list of items uses the following encoding:

项目的压缩列表使用以下编码:

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      | Reserved  |PS |       m       |
      +---+---+---+---+---+---+---+---+
      |        XI_1, ..., XI_m        | m octets, or m * 4 bits
      /                --- --- --- ---/
      |               :    Padding    : if PS = 0 and m is odd
      +---+---+---+---+---+---+---+---+
      |                               |
      /      Item_1, ..., Item_n      / variable
      |                               |
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      | Reserved  |PS |       m       |
      +---+---+---+---+---+---+---+---+
      |        XI_1, ..., XI_m        | m octets, or m * 4 bits
      /                --- --- --- ---/
      |               :    Padding    : if PS = 0 and m is odd
      +---+---+---+---+---+---+---+---+
      |                               |
      /      Item_1, ..., Item_n      / variable
      |                               |
      +---+---+---+---+---+---+---+---+
        

Reserved: MUST be set to zero; otherwise, the decompressor MUST discard the packet.

保留:必须设置为零;否则,解压缩程序必须丢弃数据包。

PS: Indicates size of XI fields:

PS:指示席字段的大小:

PS = 0 indicates 4-bit XI fields;

PS=0表示4位席场;

PS = 1 indicates 8-bit XI fields.

PS=1表示8位席场。

m: Number of XI item(s) in the compressed list. Also, the value of the cc_value argument of the list_csrc encoding (see Section 6.6.13).

M:压缩列表中的席项数。此外,列表编码的cc_值参数的值(见第6.6.13节)。

XI_1, ..., XI_m: m XI items. Each XI represents one item in the list of items of the uncompressed header, in the same order as they appear in the uncompressed header.

西席1,…,XIIm:MXI项目。每席XI表示未压缩标头的项目列表中的一个项目,其顺序与未压缩标头中出现的顺序相同。

The format of an XI item is as follows:

一席项目的格式如下:

                   0   1   2   3
                 +---+---+---+---+
         PS = 0: | X |   Index   |
                 +---+---+---+---+
        
                   0   1   2   3
                 +---+---+---+---+
         PS = 0: | X |   Index   |
                 +---+---+---+---+
        
                   0   1   2   3   4   5   6   7
                 +---+---+---+---+---+---+---+---+
         PS = 1: | X | Reserved  |     Index     |
                 +---+---+---+---+---+---+---+---+
        
                   0   1   2   3   4   5   6   7
                 +---+---+---+---+---+---+---+---+
         PS = 1: | X | Reserved  |     Index     |
                 +---+---+---+---+---+---+---+---+
        

X: Indicates whether the item is present in the list:

X:指示该项是否存在于列表中:

X = 1 indicates that the item corresponding to the Index is sent in the Item_1, ..., Item_n list;

X=1表示与索引对应的项在项列表中发送;

X = 0 indicates that the item corresponding to the Index is not sent.

X=0表示未发送与索引对应的项。

Reserved: MUST be set to zero; otherwise, the decompressor MUST discard the packet.

保留:必须设置为零;否则,解压缩程序必须丢弃数据包。

Index: An index into the item table. See Section 6.6.13.4

索引:项表中的索引。见第6.6.13.4节

When 4-bit XI items are used, the XI items are placed in octets in the following manner:

当使用4位席项目时,席项目以八种方式放置在八位位组中:

           0   1   2   3   4   5   6   7
         +---+---+---+---+---+---+---+---+
         |     XI_k      |    XI_k + 1   |
         +---+---+---+---+---+---+---+---+
        
           0   1   2   3   4   5   6   7
         +---+---+---+---+---+---+---+---+
         |     XI_k      |    XI_k + 1   |
         +---+---+---+---+---+---+---+---+
        

Padding: A 4-bit Padding field is present when PS = 0 and the number of XIs is odd. The Padding field MUST be set to zero; otherwise, the decompressor MUST discard the packet.

填充:当PS=0且XIs的数量为奇数时,会出现一个4位填充字段。填充字段必须设置为零;否则,解压缩程序必须丢弃数据包。

Item 1, ..., item n: Each item corresponds to an XI with X = 1 in XI 1, ..., XI m. Each entry in the Item list is the uncompressed representation of one CSRC identifier.

项目1,…,项目n:每个项目对应于席席1,XI=1,席,…项目列表中的每个条目都是一个CSC标识符的未压缩表示。

6.6.13.4. Item Table Mappings
6.6.13.4. 项表映射

The item table for list compression is limited to 16 different items, since the RTP header can only carry at most 15 simultaneous CSRC identifiers. The effect of having more than 16 items in the item table will only cause a slight overhead to the compressor when items are swapped in/out of the item table.

列表压缩的项目表限制为16个不同的项目,因为RTP头最多只能携带15个同时的CSC标识符。在项目表中有超过16个项目的效果,只会在项目在项目表中交换时对压缩器造成轻微的开销。

6.6.13.5. Compressed Lists in Dynamic Chain
6.6.13.5. 动态链中的压缩列表

A compressed list that is part of the dynamic chain must have all of its list items present, i.e., all X-bits in the XI list MUST be set. All items previously established in the item table that are not present in the list decompressed from this packet MUST also be retained in the decompressor context.

作为动态链的一部分的压缩列表必须具有其所有列表项,即必须设置席列表中的所有X位。以前在item表中建立的、从该数据包解压的列表中不存在的所有项也必须保留在解压器上下文中。

6.7. Encoding Methods with External Parameters as Arguments
6.7. 使用外部参数作为参数的编码方法

A number of encoding methods in Section 6.8.2.4 have one or more arguments for which the derivation of the parameter's value is outside the scope of the ROHC-FN [RFC4997] specification of the header formats.

第6.8.2.4节中的许多编码方法有一个或多个参数,其参数值的推导超出了头格式的ROHC-FN[RFC4997]规范的范围。

The following is a list of encoding methods with external parameters as arguments, from Section 6.8.2.4:

以下是第6.8.2.4节中以外部参数为参数的编码方法列表:

o udp(profile_value, reorder_ratio_value)

o udp(配置文件值、重新排序比率值)

o udp_lite(profile_value, reorder_ratio_value, coverage_behavior_value)

o udp_lite(配置文件_值、重新排序_比率_值、覆盖率_行为_值)

o esp(profile_value, reorder_ratio_value)

o esp(配置文件值、重新排序比率值)

o rtp(profile_value, ts_stride_value, time_stride_value, reorder_ratio_value)

o rtp(外形值、ts步长值、时间步长值、重新排序比率值)

o ipv4(profile_value, is_innermost, outer_ip_flag, ip_id_behavior_value, reorder_ratio_value))

o ipv4(配置文件\u值、最内层、外层\u ip\u标志、ip\u id\u行为\u值、重新排序\u比率\u值))

o ipv6(profile_value, is_innermost, outer_ip_flag, reorder_ratio_value))

o ipv6(配置文件值、最内层、外层ip标志、重新排序比率值))

o iponly_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value, reorder_ratio_value)

o i仅\u基头(配置文件\u值、外部\u ip\u标志、ip\u id\u行为\u值、重新排序\u比率\u值)

o udp_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value, reorder_ratio_value)

o udp_baseheader(配置文件_值、外部_ip_标志、ip_id_行为_值、重新排序比率_值)

o udplite_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value, reorder_ratio_value)

o udplite\u baseheader(配置文件\u值、外部\u ip\u标志、ip\u id\u行为\u值、重新排序\u比率\u值)

o esp_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value, reorder_ratio_value)

o esp_baseheader(配置文件_值、外部_ip_标志、ip_id_行为_值、重新排序比率_值)

o rtp_baseheader(profile_value, ts_stride_value, time_stride_value, outer_ip_flag, ip_id_behavior_value, reorder_ratio_value)

o rtp_baseheader(配置文件_值、ts_步长值、时间_步长值、外部_ip_标志、ip_id_行为_值、重新排序比率_值)

o udplite_rtp_baseheader(profile_value, ts_stride_value, time_stride_value, outer_ip_flag, ip_id_behavior_value, reorder_ratio_value, coverage_behavior_value)

o udplite\u rtp\u baseheader(配置文件\u值、ts\u步长\u值、时间\u步长\u值、外部\u ip\u标志、ip\u id\u行为\u值、重新排序\u比率\u值、覆盖率\u行为\u值)

The following applies for all parameters listed below: At the compressor, the value of the parameter is set according to the recommendations for each parameter. At the decompressor, the value

以下适用于以下列出的所有参数:在压缩机上,参数值根据每个参数的建议进行设置。在解压缩程序中,值

of the parameter is set to undefined and will get bound by encoding methods, except where otherwise noted.

除非另有说明,否则参数的值设置为未定义,并将由编码方法绑定。

The following is a list of external arguments with their respective definition:

以下是外部参数及其各自定义的列表:

o profile_value:

o 配置文件_值:

Set to the 16-bit number that identifies the profile used to compress this packet. When processing the static chain at the decompressor, this parameter is set to the value of the profile field in the IR header (see Section 6.8.1).

设置为识别用于压缩此数据包的配置文件的16位数字。在解压器处处理静态链时,该参数设置为IR标题中的profile字段值(见第6.8.1节)。

o reorder_ratio_value:

o 重新排序比率值:

Set to a 2-bit integer value, using one of the constants whose name begins with the prefix REORDERING_ and as defined in Section 6.8.2.4.

使用名称以前缀REORDERING_u开头的常数之一,并按照第6.8.2.4节的定义,将其设置为2位整数值。

o ip_id_behavior_value:

o ip_id_行为_值:

Set to a 2-bit integer value, using one of the constants whose name begins with the prefix IP_ID_BEHAVIOR_ and as defined in Section 6.8.2.4.

使用名称以前缀IP_ID_BEHAVIOR_开头的常数之一,并按照第6.8.2.4节的定义,将其设置为2位整数值。

o coverage_behavior_value:

o 覆盖率\行为\价值:

Set to a 2-bit integer value, using one of the constants whose name begins with the prefix UDP_LITE_COVERAGE_ and as defined in Section 6.8.2.4.

使用名称以前缀UDP_LITE_COVERAGE_开头的常数之一,并按照第6.8.2.4节的定义,将其设置为2位整数值。

o outer_ip_flag:

o 外部_ip_标志:

This parameter is set to 1 if at least one of the TOS/TC or TTL/Hop Limit fields in outer IP headers has changed compared to their reference values in the context; otherwise, it is set to 0. This flag may only be set to 1 for the "co_common" header format in the different profiles.

如果外部IP头中的TOS/TC或TTL/Hop限制字段中至少有一个与上下文中的参考值相比发生了更改,则此参数设置为1;否则,它将设置为0。对于不同配置文件中的“co_common”头格式,此标志只能设置为1。

o is_innermost:

o 最里面的是什么

This boolean flag is set to 1 when processing the innermost of the compressible IP headers; otherwise, it is set to 0.

当处理最内层的可压缩IP头时,此布尔标志设置为1;否则,它将设置为0。

o ts_stride_value

o t__值

The value of this parameter should be set to the expected increase in the RTP Timestamp between consecutive RTP sequence numbers. The value selected is implementation-specific. See also Section 6.6.8.

此参数的值应设置为连续RTP序列号之间RTP时间戳的预期增加。所选的值是特定于实现的。另见第6.6.8节。

o time_stride_value

o 时间步长值

The value of this parameter should be set to the expected inter-arrival time between consecutive packets for the flow. The value selected is implementation-specific. This parameter MUST be set to zero, unless the compressor has received a feedback message with the CLOCK_RESOLUTION option set to a non-zero value. See also Section 6.6.9.

此参数的值应设置为流的连续数据包之间的预期到达时间。所选的值是特定于实现的。此参数必须设置为零,除非压缩器已收到反馈消息,且时钟分辨率选项设置为非零值。另见第6.6.9节。

6.8. Header Formats
6.8. 标题格式

ROHCv2 profiles use two different header types: the Initialization and Refresh (IR) header type, and the Compressed header type (CO).

ROHCv2配置文件使用两种不同的头类型:初始化和刷新(IR)头类型和压缩头类型(CO)。

The CO header type defines a number of header formats: there are two sets of base header formats, with a few additional formats that are common to both sets.

CO头类型定义了许多头格式:有两组基本头格式,还有一些附加格式是两组通用的。

6.8.1. Initialization and Refresh Header Format (IR)
6.8.1. 初始化和刷新标头格式(IR)

The IR header format uses the structure of the ROHC IR header as defined in Section 5.2.2.1 of [RFC4995].

IR标头格式使用[RFC4995]第5.2.2.1节中定义的ROHC IR标头结构。

Header type: IR

标题类型:IR

This header format communicates the static part and the dynamic part of the context.

此标题格式传递上下文的静态部分和动态部分。

The ROHCv2 IR header has the following format:

ROHCv2 IR标头具有以下格式:

        0   1   2   3   4   5   6   7
       --- --- --- --- --- --- --- ---
      :        Add-CID octet          : if for small CIDs and (CID != 0)
      +---+---+---+---+---+---+---+---+
      | 1   1   1   1   1   1   0   1 | IR type octet
      +---+---+---+---+---+---+---+---+
      :                               :
      /       0-2 octets of CID       / 1-2 octets if for large CIDs
      :                               :
      +---+---+---+---+---+---+---+---+
      |            Profile            | 1 octet
      +---+---+---+---+---+---+---+---+
      |              CRC              | 1 octet
      +---+---+---+---+---+---+---+---+
      |                               |
      /         Static chain          / variable length
      |                               |
       - - - - - - - - - - - - - - - -
      |                               |
      /         Dynamic chain         / variable length
      |                               |
       - - - - - - - - - - - - - - - -
        
        0   1   2   3   4   5   6   7
       --- --- --- --- --- --- --- ---
      :        Add-CID octet          : if for small CIDs and (CID != 0)
      +---+---+---+---+---+---+---+---+
      | 1   1   1   1   1   1   0   1 | IR type octet
      +---+---+---+---+---+---+---+---+
      :                               :
      /       0-2 octets of CID       / 1-2 octets if for large CIDs
      :                               :
      +---+---+---+---+---+---+---+---+
      |            Profile            | 1 octet
      +---+---+---+---+---+---+---+---+
      |              CRC              | 1 octet
      +---+---+---+---+---+---+---+---+
      |                               |
      /         Static chain          / variable length
      |                               |
       - - - - - - - - - - - - - - - -
      |                               |
      /         Dynamic chain         / variable length
      |                               |
       - - - - - - - - - - - - - - - -
        

CRC: 8-bit CRC over the entire IR-header, including any CID fields and up until the end of the dynamic chain, using the polynomial defined in [RFC4995]. For purposes of computing the CRC, the CRC field is zero.

CRC:使用[RFC4995]中定义的多项式,对整个IR报头(包括任何CID字段)执行8位CRC,直至动态链结束。为了计算CRC,CRC字段为零。

Static chain: See Section 6.5.

静态链:见第6.5节。

Dynamic chain: See Section 6.5.

动态链:见第6.5节。

6.8.2. Compressed Header Formats (CO)
6.8.2. 压缩头格式(CO)
6.8.2.1. Design Rationale for Compressed Base Headers
6.8.2.1. 压缩基头的设计原理

The compressed header formats are defined as two separate sets for each profile: one set for the headers where the innermost IP header contains a sequential IP-ID (either network byte order or byte-swapped), and one set for the headers without sequential IP-ID (either random, zero, or no IP-ID). There are also a number of common header formats shared between both sets. In the description below, the naming convention used for header formats that belong to the sequential set is to include "seq" in the name of the format, while similarly "rnd" is used for those that belong to the non-sequential set.

压缩头格式被定义为每个配置文件的两个独立集:一个用于最内层IP头包含顺序IP-ID(网络字节顺序或字节交换)的头,另一个用于不包含顺序IP-ID(随机、零或无IP-ID)的头。两个集合之间还共享许多常见的头格式。在下面的描述中,用于属于顺序集的标题格式的命名约定是在格式名称中包含“seq”,而类似地,“rnd”用于属于非顺序集的标题格式。

The design of the header formats is derived from the field behavior analysis found in Appendix A.

标题格式的设计源自附录A中的字段行为分析。

All of the compressed base headers transmit lsb-encoded MSN bits and a CRC.

所有压缩的基本报头都传输lsb编码的MSN位和CRC。

The following header formats exist for all profiles defined in this document, and are common to both the sequential and the random header format sets:

以下标题格式适用于本文档中定义的所有配置文件,并且是顺序和随机标题格式集的通用格式:

o co_common: This format can be used to update the context when the established change pattern of a dynamic field changes, for any of the dynamic fields. However, not all dynamic fields are updated by conveying their uncompressed value; some fields can only be transmitted using a compressed representation. This format is especially useful when a rarely changing field needs to be updated. This format contains a set of flags to indicate what fields are present in the header, and its size can vary accordingly. This format is protected by a 7-bit CRC. It can update control fields, and it thus also carries a 3-bit CRC to protect those fields. This format is similar in purpose to the UOR-2-extension 3 format of [RFC3095].

o co_common:此格式可用于在任何动态字段的已建立更改模式更改时更新上下文。然而,并不是所有的动态字段都通过传递其未压缩的值来更新;某些字段只能使用压缩表示进行传输。当需要更新很少更改的字段时,此格式特别有用。此格式包含一组标志,用于指示标头中存在哪些字段,其大小可以相应地变化。此格式受7位CRC保护。它可以更新控制字段,因此还携带3位CRC来保护这些字段。该格式在用途上与[RFC3095]的UOR-2-扩展3格式类似。

o co_repair: This format can be used to update the context of all the dynamic fields by conveying their uncompressed value. This is especially useful when context damage is assumed (e.g., from the reception of a NACK) and a context repair is performed. This format is protected by a 7-bit CRC. It also carries a 3-bit CRC over the control fields that it can update. This format is similar in purpose to the IR-DYN format of [RFC3095] when performing context repairs.

o co_repair:此格式可用于通过传递未压缩的值来更新所有动态字段的上下文。当假定环境损害(例如,从接收NACK)并且执行环境修复时,这尤其有用。此格式受7位CRC保护。它还通过控制字段携带3位CRC,可以进行更新。在执行上下文修复时,此格式的用途与[RFC3095]的IR-DYN格式类似。

o pt_0_crc3: This format conveys only the MSN; it can therefore only update the MSN and fields that are derived from the MSN, such as IP-ID and the RTP Timestamp (for applicable profiles). It is protected by a 3-bit CRC. This format is equivalent to the UO-0 header format in [RFC3095].

o pt_0_crc3:此格式仅传送MSN;因此,它只能更新MSN和从MSN派生的字段,例如IP-ID和RTP时间戳(对于适用的配置文件)。它由3位CRC保护。此格式相当于[RFC3095]中的UO-0标头格式。

o pt_0_crc7: This format has the same properties as pt_0_crc3, but is instead protected by a 7-bit CRC and contains a larger amount of lsb-encoded MSN bits. This format is useful in environments where a high amount of reordering or a high-residual error rate can occur.

o pt_0_crc7:此格式与pt_0_crc3具有相同的属性,但受7位CRC保护,并包含大量lsb编码的MSN位。此格式在可能发生大量重新排序或高剩余错误率的环境中非常有用。

The following header format descriptions apply to profiles 0x0101 and 0x0107.

以下标题格式说明适用于配置文件0x0101和0x0107。

o pt_1_rnd: This format can convey changes to the MSN and to the RTP Marker bit, and it can update the RTP timestamp using scaled timestamp encoding. It is protected by a 3-bit CRC. It is similar in purpose to the UO-1 format in [RFC3095].

o pt_1_rnd:此格式可以将更改传递给MSN和RTP标记位,并且可以使用缩放时间戳编码更新RTP时间戳。它由3位CRC保护。其用途与[RFC3095]中的UO-1格式类似。

o pt_1_seq_id: This format can convey changes to the MSN and to the IP-ID. It is protected by a 3-bit CRC. It is similar in purpose to the UO-1-ID format in [RFC3095].

o pt_1_seq_id:此格式可以将更改传送到MSN和IP-id。它受3位CRC保护。其用途与[RFC3095]中的UO-1-ID格式类似。

o pt_1_seq_ts: This format can convey changes to the MSN and to the RTP Marker bit, and it can update the RTP Timestamp using scaled timestamp encoding. It is protected by a 3-bit CRC. It is similar in purpose to the UO-1-TS format in [RFC3095].

o pt_1_seq_ts:此格式可以将更改传递给MSN和RTP标记位,并且可以使用缩放时间戳编码更新RTP时间戳。它由3位CRC保护。其用途与[RFC3095]中的UO-1-TS格式类似。

o pt_2_rnd: This format can convey changes to the MSN, to the RTP Marker bit, and to the RTP Timestamp. It is protected by a 7-bit CRC. It is similar in purpose to the UOR-2 format in [RFC3095].

o pt_2_rnd:此格式可以将更改传递到MSN、RTP标记位和RTP时间戳。它由7位CRC保护。其用途与[RFC3095]中的UOR-2格式类似。

o pt_2_seq_id: This format can convey changes to the MSN and to the IP-ID. It is protected by a 7-bit CRC. It is similar in purpose to the UO-2-ID format in [RFC3095].

o pt_2_seq_id:此格式可将更改传送到MSN和IP-id。它受7位CRC保护。其用途与[RFC3095]中的UO-2-ID格式类似。

o pt_2_seq_ts: This format can convey changes to the MSN, to the RTP Marker bit and it can update the RTP Timestamp using scaled timestamp encoding. It is protected by a 7-bit CRC. It is similar in purpose to the UO-2-TS format in [RFC3095].

o pt_2_seq_ts:此格式可以将更改传递到MSN、RTP标记位,并且可以使用缩放时间戳编码更新RTP时间戳。它由7位CRC保护。其用途与[RFC3095]中的UO-2-TS格式类似。

o pt_2_seq_both: This format can convey changes to both the RTP Timestamp and the IP-ID, in addition to the MSN and to the Marker bit. It is protected by a 7-bit CRC. It is similar in purpose to the UOR-2-ID extension 1 format in [RFC3095].

o pt_2_seq_两者:除了MSN和标记位之外,该格式还可以传递对RTP时间戳和IP-ID的更改。它由7位CRC保护。其用途与[RFC3095]中的UOR-2-ID扩展1格式类似。

The following header format descriptions apply to profiles 0x0102, 0x0103, 0x0104, and 0x0108.

以下标题格式说明适用于配置文件0x0102、0x0103、0x0104和0x0108。

o pt_1_seq_id: This format can convey changes to the MSN and to the IP-ID. It is protected by a 7-bit CRC. It is similar in purpose to the UO-1-ID format in [RFC3095].

o pt_1_seq_id:此格式可以将更改传送到MSN和IP-id。它受7位CRC保护。其用途与[RFC3095]中的UO-1-ID格式类似。

o pt_2_seq_id: This format can convey changes to the MSN and to the IP-ID. It is protected by a 7-bit CRC. It is similar in purpose to the UO-2-ID format in [RFC3095].

o pt_2_seq_id:此格式可将更改传送到MSN和IP-id。它受7位CRC保护。其用途与[RFC3095]中的UO-2-ID格式类似。

6.8.2.2. co_repair Header Format
6.8.2.2. co_修复头格式

The ROHCv2 co_repair header has the following format:

ROHCv2 co_维修标题的格式如下:

        0   1   2   3   4   5   6   7
       --- --- --- --- --- --- --- ---
      :         Add-CID octet         : if for small CIDs and CID 1-15
      +---+---+---+---+---+---+---+---+
      | 1   1   1   1   1   0   1   1 | discriminator
      +---+---+---+---+---+---+---+---+
      :                               :
      /   0, 1, or 2 octets of CID    / 1-2 octets if large CIDs
      :                               :
      +---+---+---+---+---+---+---+---+
      |r1 |         CRC-7             |
      +---+---+---+---+---+---+---+---+
      |        r2         |   CRC-3   |
      +---+---+---+---+---+---+---+---+
      |                               |
      /         Dynamic chain         / variable length
      |                               |
       - - - - - - - - - - - - - - - -
        
        0   1   2   3   4   5   6   7
       --- --- --- --- --- --- --- ---
      :         Add-CID octet         : if for small CIDs and CID 1-15
      +---+---+---+---+---+---+---+---+
      | 1   1   1   1   1   0   1   1 | discriminator
      +---+---+---+---+---+---+---+---+
      :                               :
      /   0, 1, or 2 octets of CID    / 1-2 octets if large CIDs
      :                               :
      +---+---+---+---+---+---+---+---+
      |r1 |         CRC-7             |
      +---+---+---+---+---+---+---+---+
      |        r2         |   CRC-3   |
      +---+---+---+---+---+---+---+---+
      |                               |
      /         Dynamic chain         / variable length
      |                               |
       - - - - - - - - - - - - - - - -
        

r1: MUST be set to zero; otherwise, the decompressor MUST discard the packet.

r1:必须设置为零;否则,解压缩程序必须丢弃数据包。

CRC-7: A 7-bit CRC over the entire uncompressed header, computed using the crc7 (data_value, data_length) encoding method defined in Section 6.8.2.4, where data_value corresponds to the entire uncompressed header chain and where data_length corresponds to the length of this header chain.

CRC-7:整个未压缩头上的7位CRC,使用第6.8.2.4节中定义的crc7(数据_值,数据_长度)编码方法计算,其中数据_值对应于整个未压缩头链,数据_长度对应于此头链的长度。

r2: MUST be set to zero; otherwise, the decompressor MUST discard the packet.

r2:必须设置为零;否则,解压缩程序必须丢弃数据包。

CRC-3: Encoded using the control_crc3_encoding method defined in Section 6.6.11.

CRC-3:使用第6.6.11节中定义的控制crc3编码方法进行编码。

Dynamic chain: See Section 6.5.

动态链:见第6.5节。

6.8.2.3. General CO Header Format
6.8.2.3. 通用CO头格式

The CO header format communicates irregularities in the packet header. All CO formats carry a CRC and can update the context. All CO header formats use the general format defined in this section, with the exception of the co_repair format, which is defined in Section 6.8.2.2.

CO报头格式传递数据包报头中的异常情况。所有CO格式都带有CRC,可以更新上下文。除第6.8.2.2节中定义的CO_维修格式外,所有CO标题格式均使用本节中定义的通用格式。

The general format for a compressed header is as follows:

压缩头的一般格式如下所示:

        0   1   2   3   4   5   6   7
       --- --- --- --- --- --- --- ---
      :         Add-CID octet         : if for small CIDs and CID 1-15
      +---+---+---+---+---+---+---+---+
      |  first octet of base header   | (with type indication)
      +---+---+---+---+---+---+---+---+
      :                               :
      /   0, 1, or 2 octets of CID    / 1-2 octets if large CIDs
      :                               :
      +---+---+---+---+---+---+---+---+
      /   remainder of base header    / variable length
      +---+---+---+---+---+---+---+---+
      :                               :
      /        Irregular Chain        / variable length
      :                               :
       --- --- --- --- --- --- --- ---
        
        0   1   2   3   4   5   6   7
       --- --- --- --- --- --- --- ---
      :         Add-CID octet         : if for small CIDs and CID 1-15
      +---+---+---+---+---+---+---+---+
      |  first octet of base header   | (with type indication)
      +---+---+---+---+---+---+---+---+
      :                               :
      /   0, 1, or 2 octets of CID    / 1-2 octets if large CIDs
      :                               :
      +---+---+---+---+---+---+---+---+
      /   remainder of base header    / variable length
      +---+---+---+---+---+---+---+---+
      :                               :
      /        Irregular Chain        / variable length
      :                               :
       --- --- --- --- --- --- --- ---
        

The base header in the figure above is the compressed representation of the innermost IP header and other header(s), if any, in the uncompressed packet. The base header formats are defined in Section 6.8.2.4. In the formal description of the header formats, the base header for each profile is labeled <profile_name>_baseheader, where <profile_name> is defined in the following table:

上图中的基本报头是未压缩数据包中最内层IP报头和其他报头(如果有)的压缩表示。第6.8.2.4节定义了基本标题格式。在标题格式的正式描述中,每个概要文件的基本标题都标记为<profile\u name>\u baseheader,其中<profile\u name>在下表中定义:

      +------------------+----------------+
      | Profile number   | profile_name   |
      +------------------+----------------+
      | 0x0101           | rtp            |
      | 0x0102           | udp            |
      | 0x0103           | esp            |
      | 0x0104           | ip             |
      | 0x0107           | udplite_rtp    |
      | 0x0108           | udplite        |
      +------------------+----------------+
        
      +------------------+----------------+
      | Profile number   | profile_name   |
      +------------------+----------------+
      | 0x0101           | rtp            |
      | 0x0102           | udp            |
      | 0x0103           | esp            |
      | 0x0104           | ip             |
      | 0x0107           | udplite_rtp    |
      | 0x0108           | udplite        |
      +------------------+----------------+
        
6.8.2.4. Header Formats in ROHC-FN
6.8.2.4. ROHC-FN中的标题格式

This section defines the complete set of base header formats for ROHCv2 profiles. The base header formats are defined using the ROHC Formal Notation [RFC4997].

本节定义了ROHCv2配置文件的一整套基本标题格式。基本标头格式使用ROHC形式表示法[RFC4997]定义。

// NOTE: The irregular, static, and dynamic chains (see Section 6.5)
// are defined across multiple encoding methods and are embodied
// in the correspondingly named formats within those encoding
// methods.  In particular, note that the static and dynamic
// chains ordinarily go together.  The uncompressed fields are
// defined across these two formats combined, rather than in one
// or the other of them.  The irregular chain items are likewise
// combined with a baseheader format.
        
// NOTE: The irregular, static, and dynamic chains (see Section 6.5)
// are defined across multiple encoding methods and are embodied
// in the correspondingly named formats within those encoding
// methods.  In particular, note that the static and dynamic
// chains ordinarily go together.  The uncompressed fields are
// defined across these two formats combined, rather than in one
// or the other of them.  The irregular chain items are likewise
// combined with a baseheader format.
        
////////////////////////////////////////////
// Constants
////////////////////////////////////////////
        
////////////////////////////////////////////
// Constants
////////////////////////////////////////////
        
// IP-ID behavior constants
IP_ID_BEHAVIOR_SEQUENTIAL         = 0;
IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED = 1;
IP_ID_BEHAVIOR_RANDOM             = 2;
IP_ID_BEHAVIOR_ZERO               = 3;
        
// IP-ID behavior constants
IP_ID_BEHAVIOR_SEQUENTIAL         = 0;
IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED = 1;
IP_ID_BEHAVIOR_RANDOM             = 2;
IP_ID_BEHAVIOR_ZERO               = 3;
        
// UDP-lite checksum coverage behavior constants
UDP_LITE_COVERAGE_INFERRED  = 0;
UDP_LITE_COVERAGE_STATIC    = 1;
UDP_LITE_COVERAGE_IRREGULAR = 2;
// The value 3 is reserved and cannot be used for coverage behavior
        
// UDP-lite checksum coverage behavior constants
UDP_LITE_COVERAGE_INFERRED  = 0;
UDP_LITE_COVERAGE_STATIC    = 1;
UDP_LITE_COVERAGE_IRREGULAR = 2;
// The value 3 is reserved and cannot be used for coverage behavior
        
// Variable reordering offset
REORDERING_NONE          = 0;
REORDERING_QUARTER       = 1;
REORDERING_HALF          = 2;
REORDERING_THREEQUARTERS = 3;
        
// Variable reordering offset
REORDERING_NONE          = 0;
REORDERING_QUARTER       = 1;
REORDERING_HALF          = 2;
REORDERING_THREEQUARTERS = 3;
        
// Profile names and versions
PROFILE_RTP_0101     = 0x0101;
PROFILE_UDP_0102     = 0x0102;
PROFILE_ESP_0103     = 0x0103;
PROFILE_IP_0104      = 0x0104;
PROFILE_RTP_0107     = 0x0107; // With UDP-LITE
PROFILE_UDPLITE_0108 = 0x0108; // Without RTP
        
// Profile names and versions
PROFILE_RTP_0101     = 0x0101;
PROFILE_UDP_0102     = 0x0102;
PROFILE_ESP_0103     = 0x0103;
PROFILE_IP_0104      = 0x0104;
PROFILE_RTP_0107     = 0x0107; // With UDP-LITE
PROFILE_UDPLITE_0108 = 0x0108; // Without RTP
        
// Default values for RTP timestamp encoding
TS_STRIDE_DEFAULT    = 160;
TIME_STRIDE_DEFAULT  = 0;
        
// Default values for RTP timestamp encoding
TS_STRIDE_DEFAULT    = 160;
TIME_STRIDE_DEFAULT  = 0;
        
////////////////////////////////////////////
// Global control fields
////////////////////////////////////////////
        
////////////////////////////////////////////
// Global control fields
////////////////////////////////////////////
        

CONTROL {

控制{

  profile                                    [ 16 ];
  msn                                        [ 16 ];
  reorder_ratio                              [  2 ];
  // ip_id fields are for innermost IP header only
  ip_id_offset                               [ 16 ];
  ip_id_behavior_innermost                   [  2 ];
  // The following are only used in RTP-based profiles
  ts_stride                                  [ 32 ];
  time_stride                                [ 32 ];
  ts_scaled                                  [ 32 ];
  ts_offset                                  [ 32 ];
  // UDP-lite-based profiles only
  coverage_behavior                          [  2 ];
}
        
  profile                                    [ 16 ];
  msn                                        [ 16 ];
  reorder_ratio                              [  2 ];
  // ip_id fields are for innermost IP header only
  ip_id_offset                               [ 16 ];
  ip_id_behavior_innermost                   [  2 ];
  // The following are only used in RTP-based profiles
  ts_stride                                  [ 32 ];
  time_stride                                [ 32 ];
  ts_scaled                                  [ 32 ];
  ts_offset                                  [ 32 ];
  // UDP-lite-based profiles only
  coverage_behavior                          [  2 ];
}
        
///////////////////////////////////////////////
// Encoding methods not specified in FN syntax:
///////////////////////////////////////////////
        
///////////////////////////////////////////////
// Encoding methods not specified in FN syntax:
///////////////////////////////////////////////
        
baseheader_extension_headers       "defined in Section 6.6.1";
baseheader_outer_headers           "defined in Section 6.6.2";
control_crc3_encoding              "defined in Section 6.6.11";
inferred_ip_v4_header_checksum     "defined in Section 6.6.4";
inferred_ip_v4_length              "defined in Section 6.6.6";
inferred_ip_v6_length              "defined in Section 6.6.7";
inferred_mine_header_checksum      "defined in Section 6.6.5";
inferred_scaled_field              "defined in Section 6.6.10";
inferred_sequential_ip_id          "defined in Section 6.6.12";
inferred_udp_length                "defined in Section 6.6.3";
list_csrc(cc_value)                "defined in Section 6.6.13";
timer_based_lsb(time_stride, k, p) "defined in Section 6.6.9";
        
baseheader_extension_headers       "defined in Section 6.6.1";
baseheader_outer_headers           "defined in Section 6.6.2";
control_crc3_encoding              "defined in Section 6.6.11";
inferred_ip_v4_header_checksum     "defined in Section 6.6.4";
inferred_ip_v4_length              "defined in Section 6.6.6";
inferred_ip_v6_length              "defined in Section 6.6.7";
inferred_mine_header_checksum      "defined in Section 6.6.5";
inferred_scaled_field              "defined in Section 6.6.10";
inferred_sequential_ip_id          "defined in Section 6.6.12";
inferred_udp_length                "defined in Section 6.6.3";
list_csrc(cc_value)                "defined in Section 6.6.13";
timer_based_lsb(time_stride, k, p) "defined in Section 6.6.9";
        
////////////////////////////////////////////
// General encoding methods
////////////////////////////////////////////
        
////////////////////////////////////////////
// General encoding methods
////////////////////////////////////////////
        
static_or_irreg(flag, width)
{
  UNCOMPRESSED {
    field [ width ];
  }
        
static_or_irreg(flag, width)
{
  UNCOMPRESSED {
    field [ width ];
  }
        
  COMPRESSED irreg_enc {
    ENFORCE(flag == 1);
    field =:= irregular(width) [ width ];
  }
        
  COMPRESSED irreg_enc {
    ENFORCE(flag == 1);
    field =:= irregular(width) [ width ];
  }
        

COMPRESSED static_enc {

压缩静态加密{

    ENFORCE(flag == 0);
    field =:= static [ 0 ];
  }
}
        
    ENFORCE(flag == 0);
    field =:= static [ 0 ];
  }
}
        
optional_32(flag)
{
  UNCOMPRESSED {
    item [ 0, 32 ];
  }
        
optional_32(flag)
{
  UNCOMPRESSED {
    item [ 0, 32 ];
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    item =:= irregular(32) [ 32 ];
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    item =:= irregular(32) [ 32 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    item =:= compressed_value(0, 0) [ 0 ];
  }
}
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    item =:= compressed_value(0, 0) [ 0 ];
  }
}
        
// Send the entire value, or keep previous value
sdvl_or_static(flag)
{
  UNCOMPRESSED {
    field [ 32 ];
  }
        
// Send the entire value, or keep previous value
sdvl_or_static(flag)
{
  UNCOMPRESSED {
    field [ 32 ];
  }
        
  COMPRESSED present_7bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^7);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '0' [ 1 ];
    field                 [ 7 ];
  }
        
  COMPRESSED present_7bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^7);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '0' [ 1 ];
    field                 [ 7 ];
  }
        
  COMPRESSED present_14bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^14);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '10'   [  2 ];
    field                    [ 14 ];
  }
        
  COMPRESSED present_14bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^14);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '10'   [  2 ];
    field                    [ 14 ];
  }
        
  COMPRESSED present_21bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^21);
        
  COMPRESSED present_21bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^21);
        
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '110'  [  3 ];
    field                    [ 21 ];
  }
        
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '110'  [  3 ];
    field                    [ 21 ];
  }
        
  COMPRESSED present_28bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^28);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '1110'  [  4 ];
    field                     [ 28 ];
  }
        
  COMPRESSED present_28bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^28);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '1110'  [  4 ];
    field                     [ 28 ];
  }
        
  COMPRESSED present_32bit {
    ENFORCE(flag == 1);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '11111111'  [  8 ];
    field                         [ 32 ];
  }
        
  COMPRESSED present_32bit {
    ENFORCE(flag == 1);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '11111111'  [  8 ];
    field                         [ 32 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    field =:= static;
  }
}
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    field =:= static;
  }
}
        
// Send the entire value, or revert to default value
sdvl_or_default(flag, default_value)
{
  UNCOMPRESSED {
    field [ 32 ];
  }
        
// Send the entire value, or revert to default value
sdvl_or_default(flag, default_value)
{
  UNCOMPRESSED {
    field [ 32 ];
  }
        
  COMPRESSED present_7bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^7);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '0' [ 1 ];
    field                 [ 7 ];
  }
        
  COMPRESSED present_7bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^7);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '0' [ 1 ];
    field                 [ 7 ];
  }
        
  COMPRESSED present_14bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^14);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '10'   [  2 ];
    field                    [ 14 ];
  }
        
  COMPRESSED present_14bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^14);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '10'   [  2 ];
    field                    [ 14 ];
  }
        
  COMPRESSED present_21bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^21);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '110'  [  3 ];
    field                    [ 21 ];
  }
        
  COMPRESSED present_21bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^21);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '110'  [  3 ];
    field                    [ 21 ];
  }
        
  COMPRESSED present_28bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^28);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '1110'  [  4 ];
    field                     [ 28 ];
  }
        
  COMPRESSED present_28bit {
    ENFORCE(flag == 1);
    ENFORCE(field.UVALUE < 2^28);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '1110'  [  4 ];
    field                     [ 28 ];
  }
        
  COMPRESSED present_32bit {
    ENFORCE(flag == 1);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '11111111'  [  8 ];
    field                         [ 32 ];
  }
        
  COMPRESSED present_32bit {
    ENFORCE(flag == 1);
    ENFORCE(field.CVALUE == field.UVALUE);
    discriminator =:= '11111111'  [  8 ];
    field                         [ 32 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    field =:= uncompressed_value(32, default_value);
  }
}
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    field =:= uncompressed_value(32, default_value);
  }
}
        
lsb_7_or_31
{
  UNCOMPRESSED {
    item [ 32 ];
  }
        
lsb_7_or_31
{
  UNCOMPRESSED {
    item [ 32 ];
  }
        
  COMPRESSED lsb_7 {
    discriminator =:= '0'                       [  1 ];
    item          =:= lsb(7, ((2^7) / 4) - 1)   [  7 ];
  }
        
  COMPRESSED lsb_7 {
    discriminator =:= '0'                       [  1 ];
    item          =:= lsb(7, ((2^7) / 4) - 1)   [  7 ];
  }
        
  COMPRESSED lsb_31 {
    discriminator =:= '1'                       [  1 ];
    item          =:= lsb(31, ((2^31) / 4) - 1) [ 31 ];
  }
}
        
  COMPRESSED lsb_31 {
    discriminator =:= '1'                       [  1 ];
    item          =:= lsb(31, ((2^31) / 4) - 1) [ 31 ];
  }
}
        

crc3(data_value, data_length) {

crc3(数据值、数据长度){

  UNCOMPRESSED {
  }
  COMPRESSED {
    crc_value =:= crc(3, 0x06, 0x07, data_value, data_length) [ 3 ];
  }
}
        
  UNCOMPRESSED {
  }
  COMPRESSED {
    crc_value =:= crc(3, 0x06, 0x07, data_value, data_length) [ 3 ];
  }
}
        
crc7(data_value, data_length)
{
  UNCOMPRESSED {
  }
        
crc7(data_value, data_length)
{
  UNCOMPRESSED {
  }
        
  COMPRESSED {
    crc_value =:= crc(7, 0x79, 0x7f, data_value, data_length) [ 7 ];
  }
}
        
  COMPRESSED {
    crc_value =:= crc(7, 0x79, 0x7f, data_value, data_length) [ 7 ];
  }
}
        
// Encoding method for updating a scaled field and its associated
// control fields.  Should be used both when the value is scaled
// or unscaled in a compressed format.
// Does not have an uncompressed side.
field_scaling(stride_value, scaled_value, unscaled_value, residue_value)
{
  UNCOMPRESSED {
    // Nothing
  }
        
// Encoding method for updating a scaled field and its associated
// control fields.  Should be used both when the value is scaled
// or unscaled in a compressed format.
// Does not have an uncompressed side.
field_scaling(stride_value, scaled_value, unscaled_value, residue_value)
{
  UNCOMPRESSED {
    // Nothing
  }
        
  COMPRESSED no_scaling {
    ENFORCE(stride_value == 0);
    ENFORCE(residue_value == unscaled_value);
    ENFORCE(scaled_value == 0);
  }
        
  COMPRESSED no_scaling {
    ENFORCE(stride_value == 0);
    ENFORCE(residue_value == unscaled_value);
    ENFORCE(scaled_value == 0);
  }
        
  COMPRESSED scaling_used {
    ENFORCE(stride_value != 0);
    ENFORCE(residue_value == (unscaled_value % stride_value));
    ENFORCE(unscaled_value ==
            scaled_value * stride_value + residue_value);
  }
}
        
  COMPRESSED scaling_used {
    ENFORCE(stride_value != 0);
    ENFORCE(residue_value == (unscaled_value % stride_value));
    ENFORCE(unscaled_value ==
            scaled_value * stride_value + residue_value);
  }
}
        
////////////////////////////////////////////
// IPv6 Destination options header
////////////////////////////////////////////
        
////////////////////////////////////////////
// IPv6 Destination options header
////////////////////////////////////////////
        
ip_dest_opt
{
  UNCOMPRESSED {
        
ip_dest_opt
{
  UNCOMPRESSED {
        
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
        
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
        
  DEFAULT {
    length      =:= static;
    next_header =:= static;
    value       =:= static;
  }
        
  DEFAULT {
    length      =:= static;
    next_header =:= static;
    value       =:= static;
  }
        
  COMPRESSED dest_opt_static {
    next_header =:= irregular(8) [ 8 ];
    length      =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED dest_opt_static {
    next_header =:= irregular(8) [ 8 ];
    length      =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED dest_opt_dynamic {
    value =:=
      irregular(length.UVALUE * 64 + 48) [ length.UVALUE * 64 + 48 ];
  }
        
  COMPRESSED dest_opt_dynamic {
    value =:=
      irregular(length.UVALUE * 64 + 48) [ length.UVALUE * 64 + 48 ];
  }
        
  COMPRESSED dest_opt_irregular {
  }
        
  COMPRESSED dest_opt_irregular {
  }
        

}

}

////////////////////////////////////////////
// IPv6 Hop-by-Hop options header
////////////////////////////////////////////
        
////////////////////////////////////////////
// IPv6 Hop-by-Hop options header
////////////////////////////////////////////
        
ip_hop_opt
{
  UNCOMPRESSED {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
        
ip_hop_opt
{
  UNCOMPRESSED {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
        
  DEFAULT {
    length      =:= static;
    next_header =:= static;
    value       =:= static;
  }
        
  DEFAULT {
    length      =:= static;
    next_header =:= static;
    value       =:= static;
  }
        
  COMPRESSED hop_opt_static {
    next_header =:= irregular(8) [ 8 ];
    length      =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED hop_opt_static {
    next_header =:= irregular(8) [ 8 ];
    length      =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED hop_opt_dynamic {
    value =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }
        
  COMPRESSED hop_opt_dynamic {
    value =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }
        
  COMPRESSED hop_opt_irregular {
  }
        
  COMPRESSED hop_opt_irregular {
  }
        

}

}

////////////////////////////////////////////
// IPv6 Routing header
////////////////////////////////////////////
        
////////////////////////////////////////////
// IPv6 Routing header
////////////////////////////////////////////
        
ip_rout_opt
{
  UNCOMPRESSED {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
        
ip_rout_opt
{
  UNCOMPRESSED {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
        
  DEFAULT {
    length      =:= static;
    next_header =:= static;
    value       =:= static;
  }
        
  DEFAULT {
    length      =:= static;
    next_header =:= static;
    value       =:= static;
  }
        
  COMPRESSED rout_opt_static {
    next_header =:= irregular(8)                   [ 8 ];
    length      =:= irregular(8)                   [ 8 ];
    value       =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }
        
  COMPRESSED rout_opt_static {
    next_header =:= irregular(8)                   [ 8 ];
    length      =:= irregular(8)                   [ 8 ];
    value       =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }
        
  COMPRESSED rout_opt_dynamic {
  }
        
  COMPRESSED rout_opt_dynamic {
  }
        
  COMPRESSED rout_opt_irregular {
  }
}
        
  COMPRESSED rout_opt_irregular {
  }
}
        
////////////////////////////////////////////
// GRE Header
////////////////////////////////////////////
        
////////////////////////////////////////////
// GRE Header
////////////////////////////////////////////
        

optional_lsb_7_or_31(flag) {

可选_lsb_7_或_31(标志){

  UNCOMPRESSED {
    item [ 0, 32 ];
  }
        
  UNCOMPRESSED {
    item [ 0, 32 ];
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    item =:= lsb_7_or_31 [ 8, 32 ];
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    item =:= lsb_7_or_31 [ 8, 32 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    item =:= compressed_value(0, 0) [ 0 ];
  }
}
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    item =:= compressed_value(0, 0) [ 0 ];
  }
}
        
optional_checksum(flag_value)
{
  UNCOMPRESSED {
    value     [ 0, 16 ];
    reserved1 [ 0, 16 ];
  }
        
optional_checksum(flag_value)
{
  UNCOMPRESSED {
    value     [ 0, 16 ];
    reserved1 [ 0, 16 ];
  }
        
  COMPRESSED cs_present {
    ENFORCE(flag_value == 1);
    value     =:= irregular(16)             [ 16 ];
    reserved1 =:= uncompressed_value(16, 0) [  0 ];
  }
        
  COMPRESSED cs_present {
    ENFORCE(flag_value == 1);
    value     =:= irregular(16)             [ 16 ];
    reserved1 =:= uncompressed_value(16, 0) [  0 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag_value == 0);
    value     =:= compressed_value(0, 0) [ 0 ];
    reserved1 =:= compressed_value(0, 0) [ 0 ];
  }
}
        
  COMPRESSED not_present {
    ENFORCE(flag_value == 0);
    value     =:= compressed_value(0, 0) [ 0 ];
    reserved1 =:= compressed_value(0, 0) [ 0 ];
  }
}
        
gre_proto
{
  UNCOMPRESSED {
    protocol [ 16 ];
  }
        
gre_proto
{
  UNCOMPRESSED {
    protocol [ 16 ];
  }
        
  COMPRESSED ether_v4 {
    discriminator =:= '0'                            [ 1 ];
    protocol      =:= uncompressed_value(16, 0x0800) [ 0 ];
  }
        
  COMPRESSED ether_v4 {
    discriminator =:= '0'                            [ 1 ];
    protocol      =:= uncompressed_value(16, 0x0800) [ 0 ];
  }
        
  COMPRESSED ether_v6 {
    discriminator =:= '1'                            [ 1 ];
        
  COMPRESSED ether_v6 {
    discriminator =:= '1'                            [ 1 ];
        
    protocol      =:= uncompressed_value(16, 0x86DD) [ 0 ];
  }
}
        
    protocol      =:= uncompressed_value(16, 0x86DD) [ 0 ];
  }
}
        
gre
{
  UNCOMPRESSED {
    c_flag                                 [  1 ];
    r_flag    =:= uncompressed_value(1, 0) [  1 ];
    k_flag                                 [  1 ];
    s_flag                                 [  1 ];
    reserved0 =:= uncompressed_value(9, 0) [  9 ];
    version   =:= uncompressed_value(3, 0) [  3 ];
    protocol                               [ 16 ];
    checksum_and_res                       [ 0, 32 ];
    key                                    [ 0, 32 ];
    sequence_number                        [ 0, 32 ];
  }
        
gre
{
  UNCOMPRESSED {
    c_flag                                 [  1 ];
    r_flag    =:= uncompressed_value(1, 0) [  1 ];
    k_flag                                 [  1 ];
    s_flag                                 [  1 ];
    reserved0 =:= uncompressed_value(9, 0) [  9 ];
    version   =:= uncompressed_value(3, 0) [  3 ];
    protocol                               [ 16 ];
    checksum_and_res                       [ 0, 32 ];
    key                                    [ 0, 32 ];
    sequence_number                        [ 0, 32 ];
  }
        
  DEFAULT {
    c_flag           =:= static;
    k_flag           =:= static;
    s_flag           =:= static;
    protocol         =:= static;
    key              =:= static;
    sequence_number  =:= static;
  }
        
  DEFAULT {
    c_flag           =:= static;
    k_flag           =:= static;
    s_flag           =:= static;
    protocol         =:= static;
    key              =:= static;
    sequence_number  =:= static;
  }
        
  COMPRESSED gre_static {
    ENFORCE((c_flag.UVALUE == 1 && checksum_and_res.ULENGTH == 32)
            || checksum_and_res.ULENGTH == 0);
    ENFORCE((s_flag.UVALUE == 1 && sequence_number.ULENGTH == 32)
            || sequence_number.ULENGTH == 0);
    protocol =:= gre_proto                  [ 1 ];
    c_flag   =:= irregular(1)               [ 1 ];
    k_flag   =:= irregular(1)               [ 1 ];
    s_flag   =:= irregular(1)               [ 1 ];
    padding  =:= compressed_value(4, 0)     [ 4 ];
    key      =:= optional_32(k_flag.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED gre_static {
    ENFORCE((c_flag.UVALUE == 1 && checksum_and_res.ULENGTH == 32)
            || checksum_and_res.ULENGTH == 0);
    ENFORCE((s_flag.UVALUE == 1 && sequence_number.ULENGTH == 32)
            || sequence_number.ULENGTH == 0);
    protocol =:= gre_proto                  [ 1 ];
    c_flag   =:= irregular(1)               [ 1 ];
    k_flag   =:= irregular(1)               [ 1 ];
    s_flag   =:= irregular(1)               [ 1 ];
    padding  =:= compressed_value(4, 0)     [ 4 ];
    key      =:= optional_32(k_flag.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED gre_dynamic {
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE)              [ 0, 16 ];
    sequence_number  =:= optional_32(s_flag.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED gre_dynamic {
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE)              [ 0, 16 ];
    sequence_number  =:= optional_32(s_flag.UVALUE) [ 0, 32 ];
  }
        

COMPRESSED gre_irregular {

压缩gre_不规则{

    checksum_and_res =:= optional_checksum(c_flag.UVALUE) [ 0, 16 ];
    sequence_number  =:=
      optional_lsb_7_or_31(s_flag.UVALUE)           [ 0, 8, 32 ];
  }
        
    checksum_and_res =:= optional_checksum(c_flag.UVALUE) [ 0, 16 ];
    sequence_number  =:=
      optional_lsb_7_or_31(s_flag.UVALUE)           [ 0, 8, 32 ];
  }
        

}

}

/////////////////////////////////////////////
// MINE header
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// MINE header
/////////////////////////////////////////////
        
mine
{
  UNCOMPRESSED {
    next_header [  8 ];
    s_bit       [  1 ];
    res_bits    [  7 ];
    checksum    [ 16 ];
    orig_dest   [ 32 ];
    orig_src    [ 0, 32 ];
  }
        
mine
{
  UNCOMPRESSED {
    next_header [  8 ];
    s_bit       [  1 ];
    res_bits    [  7 ];
    checksum    [ 16 ];
    orig_dest   [ 32 ];
    orig_src    [ 0, 32 ];
  }
        
  DEFAULT {
    next_header =:= static;
    s_bit       =:= static;
    res_bits    =:= static;
    checksum    =:= inferred_mine_header_checksum;
    orig_dest   =:= static;
    orig_src    =:= static;
  }
        
  DEFAULT {
    next_header =:= static;
    s_bit       =:= static;
    res_bits    =:= static;
    checksum    =:= inferred_mine_header_checksum;
    orig_dest   =:= static;
    orig_src    =:= static;
  }
        
  COMPRESSED mine_static {
    next_header =:= irregular(8)              [  8 ];
    s_bit       =:= irregular(1)              [  1 ];
    // Reserved bits are included to achieve byte-alignment
    res_bits    =:= irregular(7)              [  7 ];
    orig_dest   =:= irregular(32)             [ 32 ];
    orig_src    =:= optional_32(s_bit.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED mine_static {
    next_header =:= irregular(8)              [  8 ];
    s_bit       =:= irregular(1)              [  1 ];
    // Reserved bits are included to achieve byte-alignment
    res_bits    =:= irregular(7)              [  7 ];
    orig_dest   =:= irregular(32)             [ 32 ];
    orig_src    =:= optional_32(s_bit.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED mine_dynamic {
  }
        
  COMPRESSED mine_dynamic {
  }
        
  COMPRESSED mine_irregular {
  }
}
        
  COMPRESSED mine_irregular {
  }
}
        
/////////////////////////////////////////////
        
/////////////////////////////////////////////
        
// Authentication Header (AH)
/////////////////////////////////////////////
        
// Authentication Header (AH)
/////////////////////////////////////////////
        
ah
{
  UNCOMPRESSED {
    next_header                            [  8 ];
    length                                 [  8 ];
    res_bits =:= uncompressed_value(16, 0) [ 16 ];
    spi                                    [ 32 ];
    sequence_number                        [ 32 ];
    icv                   [ length.UVALUE*32-32 ];
  }
        
ah
{
  UNCOMPRESSED {
    next_header                            [  8 ];
    length                                 [  8 ];
    res_bits =:= uncompressed_value(16, 0) [ 16 ];
    spi                                    [ 32 ];
    sequence_number                        [ 32 ];
    icv                   [ length.UVALUE*32-32 ];
  }
        
  DEFAULT {
    next_header     =:= static;
    length          =:= static;
    spi             =:= static;
    sequence_number =:= static;
  }
        
  DEFAULT {
    next_header     =:= static;
    length          =:= static;
    spi             =:= static;
    sequence_number =:= static;
  }
        
  COMPRESSED ah_static {
    next_header =:= irregular(8)      [  8 ];
    length      =:= irregular(8)      [  8 ];
    spi         =:= irregular(32)     [ 32 ];
  }
        
  COMPRESSED ah_static {
    next_header =:= irregular(8)      [  8 ];
    length      =:= irregular(8)      [  8 ];
    spi         =:= irregular(32)     [ 32 ];
  }
        
  COMPRESSED ah_dynamic {
    sequence_number =:= irregular(32) [ 32 ];
    icv       =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        
  COMPRESSED ah_dynamic {
    sequence_number =:= irregular(32) [ 32 ];
    icv       =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        
  COMPRESSED ah_irregular {
    sequence_number =:= lsb_7_or_31   [ 8, 32 ];
    icv       =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        
  COMPRESSED ah_irregular {
    sequence_number =:= lsb_7_or_31   [ 8, 32 ];
    icv       =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        

}

}

/////////////////////////////////////////////
// IPv6 Header
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// IPv6 Header
/////////////////////////////////////////////
        
fl_enc
{
  UNCOMPRESSED {
        
fl_enc
{
  UNCOMPRESSED {
        
    flow_label [ 20 ];
  }
        
    flow_label [ 20 ];
  }
        
  COMPRESSED fl_zero {
    discriminator =:= '0'                       [ 1 ];
    flow_label    =:= uncompressed_value(20, 0) [ 0 ];
    reserved      =:= '0000'                    [ 4 ];
  }
        
  COMPRESSED fl_zero {
    discriminator =:= '0'                       [ 1 ];
    flow_label    =:= uncompressed_value(20, 0) [ 0 ];
    reserved      =:= '0000'                    [ 4 ];
  }
        
  COMPRESSED fl_non_zero {
    discriminator =:= '1'           [  1 ];
    flow_label    =:= irregular(20) [ 20 ];
  }
}
        
  COMPRESSED fl_non_zero {
    discriminator =:= '1'           [  1 ];
    flow_label    =:= irregular(20) [ 20 ];
  }
}
        
ipv6(profile_value, is_innermost, outer_ip_flag, reorder_ratio_value)
{
  UNCOMPRESSED {
    version         =:= uncompressed_value(4, 6) [   4 ];
    tos_tc                                       [   8 ];
    flow_label                                   [  20 ];
    payload_length                               [  16 ];
    next_header                                  [   8 ];
    ttl_hopl                                     [   8 ];
    src_addr                                     [ 128 ];
    dst_addr                                     [ 128 ];
  }
        
ipv6(profile_value, is_innermost, outer_ip_flag, reorder_ratio_value)
{
  UNCOMPRESSED {
    version         =:= uncompressed_value(4, 6) [   4 ];
    tos_tc                                       [   8 ];
    flow_label                                   [  20 ];
    payload_length                               [  16 ];
    next_header                                  [   8 ];
    ttl_hopl                                     [   8 ];
    src_addr                                     [ 128 ];
    dst_addr                                     [ 128 ];
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(innermost_ip.UVALUE == is_innermost);
    innermost_ip [ 1 ];
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(innermost_ip.UVALUE == is_innermost);
    innermost_ip [ 1 ];
  }
        
  DEFAULT {
    tos_tc         =:= static;
    flow_label     =:= static;
    payload_length =:= inferred_ip_v6_length;
    next_header    =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    dst_addr       =:= static;
  }
        
  DEFAULT {
    tos_tc         =:= static;
    flow_label     =:= static;
    payload_length =:= inferred_ip_v6_length;
    next_header    =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    dst_addr       =:= static;
  }
        
  COMPRESSED ipv6_static {
    version_flag        =:= '1'              [   1 ];
    innermost_ip        =:= irregular(1)     [   1 ];
        
  COMPRESSED ipv6_static {
    version_flag        =:= '1'              [   1 ];
    innermost_ip        =:= irregular(1)     [   1 ];
        
    reserved            =:= '0'              [   1 ];
    flow_label          =:= fl_enc           [ 5, 21 ];
    next_header         =:= irregular(8)     [   8 ];
    src_addr            =:= irregular(128)   [ 128 ];
    dst_addr            =:= irregular(128)   [ 128 ];
  }
        
    reserved            =:= '0'              [   1 ];
    flow_label          =:= fl_enc           [ 5, 21 ];
    next_header         =:= irregular(8)     [   8 ];
    src_addr            =:= irregular(128)   [ 128 ];
    dst_addr            =:= irregular(128)   [ 128 ];
  }
        
  COMPRESSED ipv6_endpoint_dynamic {
    ENFORCE((is_innermost == 1) &&
            (profile_value == PROFILE_IP_0104));
    tos_tc        =:= irregular(8)           [  8 ];
    ttl_hopl      =:= irregular(8)           [  8 ];
    reserved      =:= compressed_value(6, 0) [  6 ];
    reorder_ratio =:= irregular(2)           [  2 ];
    msn           =:= irregular(16)          [ 16 ];
  }
        
  COMPRESSED ipv6_endpoint_dynamic {
    ENFORCE((is_innermost == 1) &&
            (profile_value == PROFILE_IP_0104));
    tos_tc        =:= irregular(8)           [  8 ];
    ttl_hopl      =:= irregular(8)           [  8 ];
    reserved      =:= compressed_value(6, 0) [  6 ];
    reorder_ratio =:= irregular(2)           [  2 ];
    msn           =:= irregular(16)          [ 16 ];
  }
        
  COMPRESSED ipv6_regular_dynamic {
    ENFORCE((is_innermost == 0) ||
            (profile_value != PROFILE_IP_0104));
    tos_tc       =:= irregular(8) [ 8 ];
    ttl_hopl     =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED ipv6_regular_dynamic {
    ENFORCE((is_innermost == 0) ||
            (profile_value != PROFILE_IP_0104));
    tos_tc       =:= irregular(8) [ 8 ];
    ttl_hopl     =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED ipv6_outer_irregular {
    ENFORCE(is_innermost == 0);
    tos_tc       =:=
        static_or_irreg(outer_ip_flag, 8) [ 0, 8 ];
    ttl_hopl     =:=
        static_or_irreg(outer_ip_flag, 8) [ 0, 8 ];
  }
        
  COMPRESSED ipv6_outer_irregular {
    ENFORCE(is_innermost == 0);
    tos_tc       =:=
        static_or_irreg(outer_ip_flag, 8) [ 0, 8 ];
    ttl_hopl     =:=
        static_or_irreg(outer_ip_flag, 8) [ 0, 8 ];
  }
        
  COMPRESSED ipv6_innermost_irregular {
    ENFORCE(is_innermost == 1);
  }
        
  COMPRESSED ipv6_innermost_irregular {
    ENFORCE(is_innermost == 1);
  }
        

}

}

/////////////////////////////////////////////
// IPv4 Header
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// IPv4 Header
/////////////////////////////////////////////
        
ip_id_enc_dyn(behavior)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
ip_id_enc_dyn(behavior)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
  COMPRESSED ip_id_seq {
    ENFORCE((behavior == IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    ENFORCE(ip_id_offset.UVALUE == ip_id.UVALUE - msn.UVALUE);
    ip_id =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED ip_id_seq {
    ENFORCE((behavior == IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    ENFORCE(ip_id_offset.UVALUE == ip_id.UVALUE - msn.UVALUE);
    ip_id =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED ip_id_random {
    ENFORCE(behavior == IP_ID_BEHAVIOR_RANDOM);
    ip_id =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED ip_id_random {
    ENFORCE(behavior == IP_ID_BEHAVIOR_RANDOM);
    ip_id =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED ip_id_zero {
    ENFORCE(behavior == IP_ID_BEHAVIOR_ZERO);
    ip_id =:= uncompressed_value(16, 0) [ 0 ];
  }
}
        
  COMPRESSED ip_id_zero {
    ENFORCE(behavior == IP_ID_BEHAVIOR_ZERO);
    ip_id =:= uncompressed_value(16, 0) [ 0 ];
  }
}
        
ip_id_enc_irreg(behavior)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
ip_id_enc_irreg(behavior)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
  COMPRESSED ip_id_seq {
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL);
  }
        
  COMPRESSED ip_id_seq {
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL);
  }
        
  COMPRESSED ip_id_seq_swapped {
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED);
  }
        
  COMPRESSED ip_id_seq_swapped {
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED);
  }
        
  COMPRESSED ip_id_rand {
    ENFORCE(behavior == IP_ID_BEHAVIOR_RANDOM);
    ip_id =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED ip_id_rand {
    ENFORCE(behavior == IP_ID_BEHAVIOR_RANDOM);
    ip_id =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED ip_id_zero {
    ENFORCE(behavior == IP_ID_BEHAVIOR_ZERO);
    ip_id =:= uncompressed_value(16, 0) [ 0 ];
  }
}
        
  COMPRESSED ip_id_zero {
    ENFORCE(behavior == IP_ID_BEHAVIOR_ZERO);
    ip_id =:= uncompressed_value(16, 0) [ 0 ];
  }
}
        
ipv4(profile_value, is_innermost, outer_ip_flag, ip_id_behavior_value,
  reorder_ratio_value)
{
  UNCOMPRESSED {
    version     =:= uncompressed_value(4, 4)       [  4 ];
        
ipv4(profile_value, is_innermost, outer_ip_flag, ip_id_behavior_value,
  reorder_ratio_value)
{
  UNCOMPRESSED {
    version     =:= uncompressed_value(4, 4)       [  4 ];
        
    hdr_length  =:= uncompressed_value(4, 5)       [  4 ];
    tos_tc                                         [  8 ];
    length      =:= inferred_ip_v4_length          [ 16 ];
    ip_id                                          [ 16 ];
    rf          =:= uncompressed_value(1, 0)       [  1 ];
    df                                             [  1 ];
    mf          =:= uncompressed_value(1, 0)       [  1 ];
    frag_offset =:= uncompressed_value(13, 0)      [ 13 ];
    ttl_hopl                                       [  8 ];
    protocol                                       [  8 ];
    checksum    =:= inferred_ip_v4_header_checksum [ 16 ];
    src_addr                                       [ 32 ];
    dst_addr                                       [ 32 ];
  }
        
    hdr_length  =:= uncompressed_value(4, 5)       [  4 ];
    tos_tc                                         [  8 ];
    length      =:= inferred_ip_v4_length          [ 16 ];
    ip_id                                          [ 16 ];
    rf          =:= uncompressed_value(1, 0)       [  1 ];
    df                                             [  1 ];
    mf          =:= uncompressed_value(1, 0)       [  1 ];
    frag_offset =:= uncompressed_value(13, 0)      [ 13 ];
    ttl_hopl                                       [  8 ];
    protocol                                       [  8 ];
    checksum    =:= inferred_ip_v4_header_checksum [ 16 ];
    src_addr                                       [ 32 ];
    dst_addr                                       [ 32 ];
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(innermost_ip.UVALUE == is_innermost);
    ip_id_behavior_outer [ 2 ];
    innermost_ip [ 1 ];
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(innermost_ip.UVALUE == is_innermost);
    ip_id_behavior_outer [ 2 ];
    innermost_ip [ 1 ];
  }
        
  DEFAULT {
    tos_tc               =:= static;
    df                   =:= static;
    ttl_hopl             =:= static;
    protocol             =:= static;
    src_addr             =:= static;
    dst_addr             =:= static;
    ip_id_behavior_outer =:= static;
  }
        
  DEFAULT {
    tos_tc               =:= static;
    df                   =:= static;
    ttl_hopl             =:= static;
    protocol             =:= static;
    src_addr             =:= static;
    dst_addr             =:= static;
    ip_id_behavior_outer =:= static;
  }
        
  COMPRESSED ipv4_static {
    version_flag        =:= '0'                    [  1 ];
    innermost_ip        =:= irregular(1)           [  1 ];
    reserved            =:= '000000'               [  6 ];
    protocol            =:= irregular(8)           [  8 ];
    src_addr            =:= irregular(32)          [ 32 ];
    dst_addr            =:= irregular(32)          [ 32 ];
  }
        
  COMPRESSED ipv4_static {
    version_flag        =:= '0'                    [  1 ];
    innermost_ip        =:= irregular(1)           [  1 ];
    reserved            =:= '000000'               [  6 ];
    protocol            =:= irregular(8)           [  8 ];
    src_addr            =:= irregular(32)          [ 32 ];
    dst_addr            =:= irregular(32)          [ 32 ];
  }
        
  COMPRESSED ipv4_endpoint_innermost_dynamic {
    ENFORCE((is_innermost == 1) && (profile_value == PROFILE_IP_0104));
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    reserved       =:= '000'                                 [  3 ];
    reorder_ratio  =:= irregular(2)                          [  2 ];
    df             =:= irregular(1)                          [  1 ];
        
  COMPRESSED ipv4_endpoint_innermost_dynamic {
    ENFORCE((is_innermost == 1) && (profile_value == PROFILE_IP_0104));
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    reserved       =:= '000'                                 [  3 ];
    reorder_ratio  =:= irregular(2)                          [  2 ];
    df             =:= irregular(1)                          [  1 ];
        
    ip_id_behavior_innermost =:= irregular(2)                [  2 ];
    tos_tc         =:= irregular(8)                          [  8 ];
    ttl_hopl       =:= irregular(8)                          [  8 ];
    ip_id =:= ip_id_enc_dyn(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
    msn            =:= irregular(16)                         [ 16 ];
  }
        
    ip_id_behavior_innermost =:= irregular(2)                [  2 ];
    tos_tc         =:= irregular(8)                          [  8 ];
    ttl_hopl       =:= irregular(8)                          [  8 ];
    ip_id =:= ip_id_enc_dyn(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
    msn            =:= irregular(16)                         [ 16 ];
  }
        
  COMPRESSED ipv4_regular_innermost_dynamic {
    ENFORCE((is_innermost == 1) && (profile_value != PROFILE_IP_0104));
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    reserved       =:= '00000'                               [ 5 ];
    df             =:= irregular(1)                          [ 1 ];
    ip_id_behavior_innermost =:= irregular(2)                [ 2 ];
    tos_tc         =:= irregular(8)                          [ 8 ];
    ttl_hopl       =:= irregular(8)                          [ 8 ];
    ip_id =:= ip_id_enc_dyn(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
  }
        
  COMPRESSED ipv4_regular_innermost_dynamic {
    ENFORCE((is_innermost == 1) && (profile_value != PROFILE_IP_0104));
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    reserved       =:= '00000'                               [ 5 ];
    df             =:= irregular(1)                          [ 1 ];
    ip_id_behavior_innermost =:= irregular(2)                [ 2 ];
    tos_tc         =:= irregular(8)                          [ 8 ];
    ttl_hopl       =:= irregular(8)                          [ 8 ];
    ip_id =:= ip_id_enc_dyn(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
  }
        
  COMPRESSED ipv4_outer_dynamic {
    ENFORCE(is_innermost == 0);
    ENFORCE(ip_id_behavior_outer.UVALUE == ip_id_behavior_value);
    reserved       =:= '00000'                             [ 5 ];
    df             =:= irregular(1)                        [ 1 ];
    ip_id_behavior_outer =:=     irregular(2)              [ 2 ];
    tos_tc         =:= irregular(8)                        [ 8 ];
    ttl_hopl       =:= irregular(8)                        [ 8 ];
    ip_id =:= ip_id_enc_dyn(ip_id_behavior_outer.UVALUE)   [ 0, 16 ];
  }
        
  COMPRESSED ipv4_outer_dynamic {
    ENFORCE(is_innermost == 0);
    ENFORCE(ip_id_behavior_outer.UVALUE == ip_id_behavior_value);
    reserved       =:= '00000'                             [ 5 ];
    df             =:= irregular(1)                        [ 1 ];
    ip_id_behavior_outer =:=     irregular(2)              [ 2 ];
    tos_tc         =:= irregular(8)                        [ 8 ];
    ttl_hopl       =:= irregular(8)                        [ 8 ];
    ip_id =:= ip_id_enc_dyn(ip_id_behavior_outer.UVALUE)   [ 0, 16 ];
  }
        
  COMPRESSED ipv4_outer_irregular {
    ENFORCE(is_innermost == 0);
    ip_id    =:=
      ip_id_enc_irreg(ip_id_behavior_outer.UVALUE)      [ 0, 16 ];
    tos_tc   =:= static_or_irreg(outer_ip_flag, 8)      [  0, 8 ];
    ttl_hopl =:= static_or_irreg(outer_ip_flag, 8)      [  0, 8 ];
  }
        
  COMPRESSED ipv4_outer_irregular {
    ENFORCE(is_innermost == 0);
    ip_id    =:=
      ip_id_enc_irreg(ip_id_behavior_outer.UVALUE)      [ 0, 16 ];
    tos_tc   =:= static_or_irreg(outer_ip_flag, 8)      [  0, 8 ];
    ttl_hopl =:= static_or_irreg(outer_ip_flag, 8)      [  0, 8 ];
  }
        
  COMPRESSED ipv4_innermost_irregular {
    ENFORCE(is_innermost == 1);
    ip_id =:=
      ip_id_enc_irreg(ip_id_behavior_innermost.UVALUE)  [ 0, 16 ];
  }
        
  COMPRESSED ipv4_innermost_irregular {
    ENFORCE(is_innermost == 1);
    ip_id =:=
      ip_id_enc_irreg(ip_id_behavior_innermost.UVALUE)  [ 0, 16 ];
  }
        

}

}

/////////////////////////////////////////////
// UDP Header
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// UDP Header
/////////////////////////////////////////////
        
udp(profile_value, reorder_ratio_value)
{
  UNCOMPRESSED {
    ENFORCE((profile_value == PROFILE_RTP_0101) ||
            (profile_value == PROFILE_UDP_0102));
    src_port                           [ 16 ];
    dst_port                           [ 16 ];
    udp_length =:= inferred_udp_length [ 16 ];
    checksum                           [ 16 ];
  }
        
udp(profile_value, reorder_ratio_value)
{
  UNCOMPRESSED {
    ENFORCE((profile_value == PROFILE_RTP_0101) ||
            (profile_value == PROFILE_UDP_0102));
    src_port                           [ 16 ];
    dst_port                           [ 16 ];
    udp_length =:= inferred_udp_length [ 16 ];
    checksum                           [ 16 ];
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    checksum_used [ 1 ];
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    checksum_used [ 1 ];
  }
        
  DEFAULT {
    src_port      =:= static;
    dst_port      =:= static;
    checksum_used =:= static;
  }
        
  DEFAULT {
    src_port      =:= static;
    dst_port      =:= static;
    checksum_used =:= static;
  }
        
  COMPRESSED udp_static {
    src_port   =:= irregular(16) [ 16 ];
    dst_port   =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED udp_static {
    src_port   =:= irregular(16) [ 16 ];
    dst_port   =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED udp_endpoint_dynamic {
    ENFORCE(profile_value == PROFILE_UDP_0102);
    ENFORCE(profile == PROFILE_UDP_0102);
    ENFORCE(checksum_used.UVALUE == (checksum.UVALUE != 0));
    checksum      =:= irregular(16)          [ 16 ];
    msn           =:= irregular(16)          [ 16 ];
    reserved      =:= compressed_value(6, 0) [  6 ];
    reorder_ratio =:= irregular(2)           [  2 ];
  }
        
  COMPRESSED udp_endpoint_dynamic {
    ENFORCE(profile_value == PROFILE_UDP_0102);
    ENFORCE(profile == PROFILE_UDP_0102);
    ENFORCE(checksum_used.UVALUE == (checksum.UVALUE != 0));
    checksum      =:= irregular(16)          [ 16 ];
    msn           =:= irregular(16)          [ 16 ];
    reserved      =:= compressed_value(6, 0) [  6 ];
    reorder_ratio =:= irregular(2)           [  2 ];
  }
        
  COMPRESSED udp_regular_dynamic {
    ENFORCE(profile_value == PROFILE_RTP_0101);
    ENFORCE(checksum_used.UVALUE == (checksum.UVALUE != 0));
    checksum =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED udp_regular_dynamic {
    ENFORCE(profile_value == PROFILE_RTP_0101);
    ENFORCE(checksum_used.UVALUE == (checksum.UVALUE != 0));
    checksum =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED udp_zero_checksum_irregular {
    ENFORCE(checksum_used.UVALUE == 0);
    checksum =:= uncompressed_value(16, 0)   [ 0 ];
  }
        
  COMPRESSED udp_zero_checksum_irregular {
    ENFORCE(checksum_used.UVALUE == 0);
    checksum =:= uncompressed_value(16, 0)   [ 0 ];
  }
        
  COMPRESSED udp_with_checksum_irregular {
    ENFORCE(checksum_used.UVALUE == 1);
    checksum =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED udp_with_checksum_irregular {
    ENFORCE(checksum_used.UVALUE == 1);
    checksum =:= irregular(16) [ 16 ];
  }
        

}

}

/////////////////////////////////////////////
// RTP Header
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// RTP Header
/////////////////////////////////////////////
        
csrc_list_dynchain(presence, cc_value)
{
  UNCOMPRESSED {
    csrc_list;
  }
        
csrc_list_dynchain(presence, cc_value)
{
  UNCOMPRESSED {
    csrc_list;
  }
        
  COMPRESSED no_list {
    ENFORCE(cc_value == 0);
    ENFORCE(presence == 0);
    csrc_list =:= uncompressed_value(0, 0) [ 0 ];
  }
        
  COMPRESSED no_list {
    ENFORCE(cc_value == 0);
    ENFORCE(presence == 0);
    csrc_list =:= uncompressed_value(0, 0) [ 0 ];
  }
        
  COMPRESSED list_present {
    ENFORCE(presence == 1);
    csrc_list =:= list_csrc(cc_value) [ VARIABLE ];
  }
}
        
  COMPRESSED list_present {
    ENFORCE(presence == 1);
    csrc_list =:= list_csrc(cc_value) [ VARIABLE ];
  }
}
        
rtp(profile_value, ts_stride_value, time_stride_value,
    reorder_ratio_value)
{
  UNCOMPRESSED {
    ENFORCE((profile_value == PROFILE_RTP_0101) ||
            (profile_value == PROFILE_RTP_0107));
    rtp_version =:= uncompressed_value(2, 0) [  2 ];
    pad_bit                                  [  1 ];
    extension                                [  1 ];
    cc                                       [  4 ];
    marker                                   [  1 ];
    payload_type                             [  7 ];
    sequence_number                          [ 16 ];
    timestamp                                [ 32 ];
    ssrc                                     [ 32 ];
    csrc_list                                [ cc.UVALUE * 32 ];
  }
        
rtp(profile_value, ts_stride_value, time_stride_value,
    reorder_ratio_value)
{
  UNCOMPRESSED {
    ENFORCE((profile_value == PROFILE_RTP_0101) ||
            (profile_value == PROFILE_RTP_0107));
    rtp_version =:= uncompressed_value(2, 0) [  2 ];
    pad_bit                                  [  1 ];
    extension                                [  1 ];
    cc                                       [  4 ];
    marker                                   [  1 ];
    payload_type                             [  7 ];
    sequence_number                          [ 16 ];
    timestamp                                [ 32 ];
    ssrc                                     [ 32 ];
    csrc_list                                [ cc.UVALUE * 32 ];
  }
        

CONTROL {

控制{

    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(time_stride_value == time_stride.UVALUE);
    ENFORCE(ts_stride_value == ts_stride.UVALUE);
    dummy_field =:= field_scaling(ts_stride.UVALUE,
      ts_scaled.UVALUE, timestamp.UVALUE, ts_offset.UVALUE) [ 0 ];
  }
        
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(time_stride_value == time_stride.UVALUE);
    ENFORCE(ts_stride_value == ts_stride.UVALUE);
    dummy_field =:= field_scaling(ts_stride.UVALUE,
      ts_scaled.UVALUE, timestamp.UVALUE, ts_offset.UVALUE) [ 0 ];
  }
        
  INITIAL {
    ts_stride     =:= uncompressed_value(32, TS_STRIDE_DEFAULT);
    time_stride   =:= uncompressed_value(32, TIME_STRIDE_DEFAULT);
  }
        
  INITIAL {
    ts_stride     =:= uncompressed_value(32, TS_STRIDE_DEFAULT);
    time_stride   =:= uncompressed_value(32, TIME_STRIDE_DEFAULT);
  }
        
  DEFAULT {
    ENFORCE(msn.UVALUE == sequence_number.UVALUE);
    pad_bit         =:= static;
    extension       =:= static;
    cc              =:= static;
    marker          =:= static;
    payload_type    =:= static;
    sequence_number =:= static;
    timestamp       =:= static;
    ssrc            =:= static;
    csrc_list       =:= static;
    ts_stride       =:= static;
    time_stride     =:= static;
    ts_scaled       =:= static;
    ts_offset       =:= static;
  }
        
  DEFAULT {
    ENFORCE(msn.UVALUE == sequence_number.UVALUE);
    pad_bit         =:= static;
    extension       =:= static;
    cc              =:= static;
    marker          =:= static;
    payload_type    =:= static;
    sequence_number =:= static;
    timestamp       =:= static;
    ssrc            =:= static;
    csrc_list       =:= static;
    ts_stride       =:= static;
    time_stride     =:= static;
    ts_scaled       =:= static;
    ts_offset       =:= static;
  }
        
  COMPRESSED rtp_static {
    ssrc            =:= irregular(32)  [ 32 ];
  }
        
  COMPRESSED rtp_static {
    ssrc            =:= irregular(32)  [ 32 ];
  }
        
  COMPRESSED rtp_dynamic {
    reserved        =:= compressed_value(1, 0)       [  1 ];
    reorder_ratio   =:= irregular(2)                 [  2 ];
    list_present    =:= irregular(1)                 [  1 ];
    tss_indicator   =:= irregular(1)                 [  1 ];
    tis_indicator   =:= irregular(1)                 [  1 ];
    pad_bit         =:= irregular(1)                 [  1 ];
    extension       =:= irregular(1)                 [  1 ];
    marker          =:= irregular(1)                 [  1 ];
    payload_type    =:= irregular(7)                 [  7 ];
    sequence_number =:= irregular(16)                [ 16 ];
    timestamp       =:= irregular(32)                [ 32 ];
    ts_stride       =:= sdvl_or_default(tss_indicator.CVALUE,
      TS_STRIDE_DEFAULT)                             [ VARIABLE ];
        
  COMPRESSED rtp_dynamic {
    reserved        =:= compressed_value(1, 0)       [  1 ];
    reorder_ratio   =:= irregular(2)                 [  2 ];
    list_present    =:= irregular(1)                 [  1 ];
    tss_indicator   =:= irregular(1)                 [  1 ];
    tis_indicator   =:= irregular(1)                 [  1 ];
    pad_bit         =:= irregular(1)                 [  1 ];
    extension       =:= irregular(1)                 [  1 ];
    marker          =:= irregular(1)                 [  1 ];
    payload_type    =:= irregular(7)                 [  7 ];
    sequence_number =:= irregular(16)                [ 16 ];
    timestamp       =:= irregular(32)                [ 32 ];
    ts_stride       =:= sdvl_or_default(tss_indicator.CVALUE,
      TS_STRIDE_DEFAULT)                             [ VARIABLE ];
        
    time_stride     =:= sdvl_or_default(tis_indicator.CVALUE,
      TIME_STRIDE_DEFAULT)                           [ VARIABLE ];
    csrc_list   =:= csrc_list_dynchain(list_present.CVALUE,
      cc.UVALUE)                                     [ VARIABLE ];
  }
        
    time_stride     =:= sdvl_or_default(tis_indicator.CVALUE,
      TIME_STRIDE_DEFAULT)                           [ VARIABLE ];
    csrc_list   =:= csrc_list_dynchain(list_present.CVALUE,
      cc.UVALUE)                                     [ VARIABLE ];
  }
        
  COMPRESSED rtp_irregular {
  }
}
        
  COMPRESSED rtp_irregular {
  }
}
        
/////////////////////////////////////////////
// UDP-Lite Header
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// UDP-Lite Header
/////////////////////////////////////////////
        
checksum_coverage_dynchain(behavior)
{
  UNCOMPRESSED {
    checksum_coverage [ 16 ];
  }
        
checksum_coverage_dynchain(behavior)
{
  UNCOMPRESSED {
    checksum_coverage [ 16 ];
  }
        
  COMPRESSED inferred_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_INFERRED);
    checksum_coverage =:= inferred_udp_length [  0 ];
  }
        
  COMPRESSED inferred_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_INFERRED);
    checksum_coverage =:= inferred_udp_length [  0 ];
  }
        
  COMPRESSED static_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_STATIC);
    checksum_coverage =:= irregular(16)       [ 16 ];
  }
        
  COMPRESSED static_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_STATIC);
    checksum_coverage =:= irregular(16)       [ 16 ];
  }
        
  COMPRESSED irregular_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_IRREGULAR);
    checksum_coverage =:= irregular(16)       [ 16 ];
  }
}
        
  COMPRESSED irregular_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_IRREGULAR);
    checksum_coverage =:= irregular(16)       [ 16 ];
  }
}
        
checksum_coverage_irregular(behavior)
{
  UNCOMPRESSED {
    checksum_coverage [ 16 ];
  }
        
checksum_coverage_irregular(behavior)
{
  UNCOMPRESSED {
    checksum_coverage [ 16 ];
  }
        
  COMPRESSED inferred_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_INFERRED);
    checksum_coverage =:= inferred_udp_length [  0 ];
  }
        
  COMPRESSED inferred_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_INFERRED);
    checksum_coverage =:= inferred_udp_length [  0 ];
  }
        

COMPRESSED static_coverage {

压缩静态覆盖{

    ENFORCE(behavior == UDP_LITE_COVERAGE_STATIC);
    checksum_coverage =:= static              [  0 ];
  }
        
    ENFORCE(behavior == UDP_LITE_COVERAGE_STATIC);
    checksum_coverage =:= static              [  0 ];
  }
        
  COMPRESSED irregular_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_IRREGULAR);
    checksum_coverage =:= irregular(16)       [ 16 ];
  }
}
        
  COMPRESSED irregular_coverage {
    ENFORCE(behavior == UDP_LITE_COVERAGE_IRREGULAR);
    checksum_coverage =:= irregular(16)       [ 16 ];
  }
}
        
udp_lite(profile_value, reorder_ratio_value, coverage_behavior_value)
{
  UNCOMPRESSED {
    ENFORCE((profile_value == PROFILE_RTP_0107) ||
            (profile_value == PROFILE_UDPLITE_0108));
    src_port          [ 16 ];
    dst_port          [ 16 ];
    checksum_coverage [ 16 ];
    checksum          [ 16 ];
  }
        
udp_lite(profile_value, reorder_ratio_value, coverage_behavior_value)
{
  UNCOMPRESSED {
    ENFORCE((profile_value == PROFILE_RTP_0107) ||
            (profile_value == PROFILE_UDPLITE_0108));
    src_port          [ 16 ];
    dst_port          [ 16 ];
    checksum_coverage [ 16 ];
    checksum          [ 16 ];
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(coverage_behavior.UVALUE == coverage_behavior_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(coverage_behavior.UVALUE == coverage_behavior_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
  }
        
  DEFAULT {
    src_port          =:= static;
    dst_port          =:= static;
    coverage_behavior =:= static;
  }
        
  DEFAULT {
    src_port          =:= static;
    dst_port          =:= static;
    coverage_behavior =:= static;
  }
        
  COMPRESSED udp_lite_static {
    src_port   =:= irregular(16) [ 16 ];
    dst_port   =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED udp_lite_static {
    src_port   =:= irregular(16) [ 16 ];
    dst_port   =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED udp_lite_endpoint_dynamic {
    ENFORCE(profile_value == PROFILE_UDPLITE_0108);
    reserved =:= compressed_value(4, 0)                      [  4 ];
    coverage_behavior =:= irregular(2)                       [  2 ];
    reorder_ratio     =:= irregular(2)                       [  2 ];
    checksum_coverage =:=
      checksum_coverage_dynchain(coverage_behavior.UVALUE)   [ 16 ];
    checksum          =:= irregular(16)                      [ 16 ];
    msn               =:= irregular(16)                      [ 16 ];
  }
        
  COMPRESSED udp_lite_endpoint_dynamic {
    ENFORCE(profile_value == PROFILE_UDPLITE_0108);
    reserved =:= compressed_value(4, 0)                      [  4 ];
    coverage_behavior =:= irregular(2)                       [  2 ];
    reorder_ratio     =:= irregular(2)                       [  2 ];
    checksum_coverage =:=
      checksum_coverage_dynchain(coverage_behavior.UVALUE)   [ 16 ];
    checksum          =:= irregular(16)                      [ 16 ];
    msn               =:= irregular(16)                      [ 16 ];
  }
        
  COMPRESSED udp_lite_regular_dynamic {
    ENFORCE(profile_value == PROFILE_RTP_0107);
    coverage_behavior =:= irregular(2)                       [  2 ];
    reserved =:= compressed_value(6, 0)                      [  6 ];
    checksum_coverage =:=
        checksum_coverage_dynchain(coverage_behavior.UVALUE) [ 16 ];
    checksum =:= irregular(16)                               [ 16 ];
  }
        
  COMPRESSED udp_lite_regular_dynamic {
    ENFORCE(profile_value == PROFILE_RTP_0107);
    coverage_behavior =:= irregular(2)                       [  2 ];
    reserved =:= compressed_value(6, 0)                      [  6 ];
    checksum_coverage =:=
        checksum_coverage_dynchain(coverage_behavior.UVALUE) [ 16 ];
    checksum =:= irregular(16)                               [ 16 ];
  }
        
  COMPRESSED udp_lite_irregular {
    checksum_coverage =:=
      checksum_coverage_irregular(coverage_behavior.UVALUE) [ 0, 16 ];
    checksum          =:= irregular(16)                     [ 16 ];
  }
}
        
  COMPRESSED udp_lite_irregular {
    checksum_coverage =:=
      checksum_coverage_irregular(coverage_behavior.UVALUE) [ 0, 16 ];
    checksum          =:= irregular(16)                     [ 16 ];
  }
}
        
/////////////////////////////////////////////
// ESP Header
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// ESP Header
/////////////////////////////////////////////
        
esp(profile_value, reorder_ratio_value)
{
  UNCOMPRESSED {
    ENFORCE(profile_value == PROFILE_ESP_0103);
    ENFORCE(msn.UVALUE == sequence_number.UVALUE % 65536);
    spi             [ 32 ];
    sequence_number [ 32 ];
  }
        
esp(profile_value, reorder_ratio_value)
{
  UNCOMPRESSED {
    ENFORCE(profile_value == PROFILE_ESP_0103);
    ENFORCE(msn.UVALUE == sequence_number.UVALUE % 65536);
    spi             [ 32 ];
    sequence_number [ 32 ];
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
  }
        
  CONTROL {
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
  }
        
  DEFAULT {
    spi             =:= static;
    sequence_number =:= static;
  }
        
  DEFAULT {
    spi             =:= static;
    sequence_number =:= static;
  }
        
  COMPRESSED esp_static {
    spi =:= irregular(32)                         [ 32 ];
  }
        
  COMPRESSED esp_static {
    spi =:= irregular(32)                         [ 32 ];
  }
        
  COMPRESSED esp_dynamic {
    sequence_number =:= irregular(32)             [ 32 ];
    reserved        =:= compressed_value(6, 0)    [  6 ];
    reorder_ratio   =:= irregular(2)              [  2 ];
  }
        
  COMPRESSED esp_dynamic {
    sequence_number =:= irregular(32)             [ 32 ];
    reserved        =:= compressed_value(6, 0)    [  6 ];
    reorder_ratio   =:= irregular(2)              [  2 ];
  }
        
  COMPRESSED esp_irregular {
  }
}
        
  COMPRESSED esp_irregular {
  }
}
        
///////////////////////////////////////////////////
// Encoding methods used in the profiles' CO headers
///////////////////////////////////////////////////
        
///////////////////////////////////////////////////
// Encoding methods used in the profiles' CO headers
///////////////////////////////////////////////////
        
// Variable reordering offset used for MSN
msn_lsb(k)
{
  UNCOMPRESSED {
    master [ VARIABLE ];
  }
        
// Variable reordering offset used for MSN
msn_lsb(k)
{
  UNCOMPRESSED {
    master [ VARIABLE ];
  }
        
  COMPRESSED none {
    ENFORCE(reorder_ratio.UVALUE == REORDERING_NONE);
    master =:= lsb(k, 1);
  }
        
  COMPRESSED none {
    ENFORCE(reorder_ratio.UVALUE == REORDERING_NONE);
    master =:= lsb(k, 1);
  }
        
  COMPRESSED quarter {
    ENFORCE(reorder_ratio.UVALUE == REORDERING_QUARTER);
    master =:= lsb(k, ((2^k) / 4) - 1);
  }
        
  COMPRESSED quarter {
    ENFORCE(reorder_ratio.UVALUE == REORDERING_QUARTER);
    master =:= lsb(k, ((2^k) / 4) - 1);
  }
        
  COMPRESSED half {
    ENFORCE(reorder_ratio.UVALUE == REORDERING_HALF);
    master =:= lsb(k, ((2^k) / 2) - 1);
  }
        
  COMPRESSED half {
    ENFORCE(reorder_ratio.UVALUE == REORDERING_HALF);
    master =:= lsb(k, ((2^k) / 2) - 1);
  }
        
  COMPRESSED threequarters {
    ENFORCE(reorder_ratio.UVALUE == REORDERING_THREEQUARTERS);
    master =:= lsb(k, (((2^k) * 3) / 4) - 1);
  }
}
        
  COMPRESSED threequarters {
    ENFORCE(reorder_ratio.UVALUE == REORDERING_THREEQUARTERS);
    master =:= lsb(k, (((2^k) * 3) / 4) - 1);
  }
}
        
ip_id_lsb(behavior, k)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
ip_id_lsb(behavior, k)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
  CONTROL {
    ip_id_nbo    [ 16 ];
  }
        
  CONTROL {
    ip_id_nbo    [ 16 ];
  }
        
  COMPRESSED nbo {
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL);
        
  COMPRESSED nbo {
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL);
        
    ENFORCE(ip_id_offset.UVALUE == ip_id.UVALUE - msn.UVALUE);
    ip_id_offset =:= lsb(k, ((2^k) / 4) - 1) [ k ];
  }
        
    ENFORCE(ip_id_offset.UVALUE == ip_id.UVALUE - msn.UVALUE);
    ip_id_offset =:= lsb(k, ((2^k) / 4) - 1) [ k ];
  }
        
  COMPRESSED non_nbo {
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED);
    ENFORCE(ip_id_nbo.UVALUE ==
            (ip_id.UVALUE / 256) + (ip_id.UVALUE % 256) * 256);
    ENFORCE(ip_id_nbo.ULENGTH == 16);
    ENFORCE(ip_id_offset.UVALUE == ip_id_nbo.UVALUE - msn.UVALUE);
    ip_id_offset =:= lsb(k, ((2^k) / 4) - 1) [ k ];
  }
}
        
  COMPRESSED non_nbo {
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED);
    ENFORCE(ip_id_nbo.UVALUE ==
            (ip_id.UVALUE / 256) + (ip_id.UVALUE % 256) * 256);
    ENFORCE(ip_id_nbo.ULENGTH == 16);
    ENFORCE(ip_id_offset.UVALUE == ip_id_nbo.UVALUE - msn.UVALUE);
    ip_id_offset =:= lsb(k, ((2^k) / 4) - 1) [ k ];
  }
}
        
ip_id_sequential_variable(behavior, indicator)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
ip_id_sequential_variable(behavior, indicator)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
  COMPRESSED short {
    ENFORCE((behavior == IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    ENFORCE(indicator == 0);
    ip_id =:= ip_id_lsb(behavior, 8) [ 8 ];
  }
        
  COMPRESSED short {
    ENFORCE((behavior == IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    ENFORCE(indicator == 0);
    ip_id =:= ip_id_lsb(behavior, 8) [ 8 ];
  }
        
  COMPRESSED long {
    ENFORCE((behavior == IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    ENFORCE(indicator == 1);
    ENFORCE(ip_id_offset.UVALUE == ip_id.UVALUE - msn.UVALUE);
    ip_id =:= irregular(16)  [ 16 ];
  }
        
  COMPRESSED long {
    ENFORCE((behavior == IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    ENFORCE(indicator == 1);
    ENFORCE(ip_id_offset.UVALUE == ip_id.UVALUE - msn.UVALUE);
    ip_id =:= irregular(16)  [ 16 ];
  }
        
  COMPRESSED not_present {
    ENFORCE((behavior == IP_ID_BEHAVIOR_RANDOM) ||
            (behavior == IP_ID_BEHAVIOR_ZERO));
  }
}
        
  COMPRESSED not_present {
    ENFORCE((behavior == IP_ID_BEHAVIOR_RANDOM) ||
            (behavior == IP_ID_BEHAVIOR_ZERO));
  }
}
        
dont_fragment(version)
{
  UNCOMPRESSED {
    df [ 0, 1 ];
  }
        
dont_fragment(version)
{
  UNCOMPRESSED {
    df [ 0, 1 ];
  }
        

COMPRESSED v4 {

压缩v4{

    ENFORCE(version == 4);
    df =:= irregular(1) [ 1 ];
  }
        
    ENFORCE(version == 4);
    df =:= irregular(1) [ 1 ];
  }
        
  COMPRESSED v6 {
    ENFORCE(version == 6);
    unused =:= compressed_value(1, 0) [ 1 ];
  }
}
        
  COMPRESSED v6 {
    ENFORCE(version == 6);
    unused =:= compressed_value(1, 0) [ 1 ];
  }
}
        
pt_irr_or_static(flag)
{
  UNCOMPRESSED {
    payload_type [ 7 ];
  }
        
pt_irr_or_static(flag)
{
  UNCOMPRESSED {
    payload_type [ 7 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    payload_type =:= static [ 0 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    payload_type =:= static [ 0 ];
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    reserved     =:= compressed_value(1, 0) [ 1 ];
    payload_type =:= irregular(7)           [ 7 ];
  }
}
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    reserved     =:= compressed_value(1, 0) [ 1 ];
    payload_type =:= irregular(7)           [ 7 ];
  }
}
        
csrc_list_presence(presence, cc_value)
{
  UNCOMPRESSED {
    csrc_list;
  }
        
csrc_list_presence(presence, cc_value)
{
  UNCOMPRESSED {
    csrc_list;
  }
        
  COMPRESSED no_list {
    ENFORCE(presence == 0);
    csrc_list =:= static [ 0 ];
  }
        
  COMPRESSED no_list {
    ENFORCE(presence == 0);
    csrc_list =:= static [ 0 ];
  }
        
  COMPRESSED list_present {
    ENFORCE(presence == 1);
    csrc_list =:= list_csrc(cc_value) [ VARIABLE ];
  }
}
        
  COMPRESSED list_present {
    ENFORCE(presence == 1);
    csrc_list =:= list_csrc(cc_value) [ VARIABLE ];
  }
}
        
scaled_ts_lsb(time_stride_value, k)
{
  UNCOMPRESSED {
        
scaled_ts_lsb(time_stride_value, k)
{
  UNCOMPRESSED {
        
    timestamp [ 32 ];
  }
        
    timestamp [ 32 ];
  }
        
  COMPRESSED timerbased {
    ENFORCE(time_stride_value != 0);
    timestamp =:= timer_based_lsb(time_stride_value, k,
                                  ((2^k) / 2) - 1);
  }
        
  COMPRESSED timerbased {
    ENFORCE(time_stride_value != 0);
    timestamp =:= timer_based_lsb(time_stride_value, k,
                                  ((2^k) / 2) - 1);
  }
        
  COMPRESSED regular {
    ENFORCE(time_stride_value == 0);
    timestamp =:= lsb(k, ((2^k) / 4) - 1);
  }
}
        
  COMPRESSED regular {
    ENFORCE(time_stride_value == 0);
    timestamp =:= lsb(k, ((2^k) / 4) - 1);
  }
}
        
// Self-describing variable length encoding with reordering offset
sdvl_sn_lsb(field_width)
{
  UNCOMPRESSED {
    field [ field_width ];
  }
        
// Self-describing variable length encoding with reordering offset
sdvl_sn_lsb(field_width)
{
  UNCOMPRESSED {
    field [ field_width ];
  }
        
  COMPRESSED lsb7 {
    discriminator =:= '0'   [ 1 ];
    field =:= msn_lsb(7)    [ 7 ];
  }
        
  COMPRESSED lsb7 {
    discriminator =:= '0'   [ 1 ];
    field =:= msn_lsb(7)    [ 7 ];
  }
        
  COMPRESSED lsb14 {
    discriminator =:= '10'  [  2 ];
    field =:= msn_lsb(14)   [ 14 ];
  }
        
  COMPRESSED lsb14 {
    discriminator =:= '10'  [  2 ];
    field =:= msn_lsb(14)   [ 14 ];
  }
        
  COMPRESSED lsb21 {
    discriminator =:= '110'  [  3 ];
    field =:= msn_lsb(21)    [ 21 ];
  }
        
  COMPRESSED lsb21 {
    discriminator =:= '110'  [  3 ];
    field =:= msn_lsb(21)    [ 21 ];
  }
        
  COMPRESSED lsb28 {
    discriminator =:= '1110' [  4 ];
    field =:= msn_lsb(28)    [ 28 ];
  }
        
  COMPRESSED lsb28 {
    discriminator =:= '1110' [  4 ];
    field =:= msn_lsb(28)    [ 28 ];
  }
        
  COMPRESSED lsb32 {
    discriminator =:= '11111111'        [  8 ];
    field =:= irregular(field_width)    [ field_width ];
  }
}
        
  COMPRESSED lsb32 {
    discriminator =:= '11111111'        [  8 ];
    field =:= irregular(field_width)    [ field_width ];
  }
}
        
// Self-describing variable length encoding
sdvl_lsb(field_width)
{
  UNCOMPRESSED {
    field [ field_width ];
  }
        
// Self-describing variable length encoding
sdvl_lsb(field_width)
{
  UNCOMPRESSED {
    field [ field_width ];
  }
        
  COMPRESSED lsb7 {
    discriminator =:= '0'               [ 1 ];
    field =:= lsb(7, ((2^7) / 4) - 1)   [ 7 ];
  }
        
  COMPRESSED lsb7 {
    discriminator =:= '0'               [ 1 ];
    field =:= lsb(7, ((2^7) / 4) - 1)   [ 7 ];
  }
        
  COMPRESSED lsb14 {
    discriminator =:= '10'              [  2 ];
    field =:= lsb(14, ((2^14) / 4) - 1) [ 14 ];
  }
        
  COMPRESSED lsb14 {
    discriminator =:= '10'              [  2 ];
    field =:= lsb(14, ((2^14) / 4) - 1) [ 14 ];
  }
        
  COMPRESSED lsb21 {
    discriminator =:= '110'             [  3 ];
    field =:= lsb(21, ((2^21) / 4) - 1) [ 21 ];
  }
        
  COMPRESSED lsb21 {
    discriminator =:= '110'             [  3 ];
    field =:= lsb(21, ((2^21) / 4) - 1) [ 21 ];
  }
        
  COMPRESSED lsb28 {
    discriminator =:= '1110'            [  4 ];
    field =:= lsb(28, ((2^28) / 4) - 1) [ 28 ];
  }
        
  COMPRESSED lsb28 {
    discriminator =:= '1110'            [  4 ];
    field =:= lsb(28, ((2^28) / 4) - 1) [ 28 ];
  }
        
  COMPRESSED lsb32 {
    discriminator =:= '11111111'        [  8 ];
    field =:= irregular(field_width)    [ field_width ];
  }
}
        
  COMPRESSED lsb32 {
    discriminator =:= '11111111'        [  8 ];
    field =:= irregular(field_width)    [ field_width ];
  }
}
        
sdvl_scaled_ts_lsb(time_stride)
{
   UNCOMPRESSED {
     field [ 32 ];
   }
        
sdvl_scaled_ts_lsb(time_stride)
{
   UNCOMPRESSED {
     field [ 32 ];
   }
        
   COMPRESSED lsb7 {
     discriminator =:= '0'                     [  1 ];
     field =:= scaled_ts_lsb(time_stride, 7)   [  7 ];
   }
        
   COMPRESSED lsb7 {
     discriminator =:= '0'                     [  1 ];
     field =:= scaled_ts_lsb(time_stride, 7)   [  7 ];
   }
        
   COMPRESSED lsb14 {
     discriminator =:= '10'                    [  2 ];
     field =:= scaled_ts_lsb(time_stride, 14)  [ 14 ];
   }
        
   COMPRESSED lsb14 {
     discriminator =:= '10'                    [  2 ];
     field =:= scaled_ts_lsb(time_stride, 14)  [ 14 ];
   }
        
   COMPRESSED lsb21 {
     discriminator =:= '110'                   [  3 ];
     field =:= scaled_ts_lsb(time_stride, 21)  [ 21 ];
   }
        
   COMPRESSED lsb21 {
     discriminator =:= '110'                   [  3 ];
     field =:= scaled_ts_lsb(time_stride, 21)  [ 21 ];
   }
        
   COMPRESSED lsb28 {
     discriminator =:= '1110'                  [  4 ];
     field =:= scaled_ts_lsb(time_stride, 28)  [ 28 ];
   }
        
   COMPRESSED lsb28 {
     discriminator =:= '1110'                  [  4 ];
     field =:= scaled_ts_lsb(time_stride, 28)  [ 28 ];
   }
        
   COMPRESSED lsb32 {
     discriminator =:= '11111111'              [  8 ];
     field =:= irregular(32)                   [ 32 ];
   }
}
        
   COMPRESSED lsb32 {
     discriminator =:= '11111111'              [  8 ];
     field =:= irregular(32)                   [ 32 ];
   }
}
        
variable_scaled_timestamp(tss_flag, tsc_flag, ts_stride, time_stride)
{
  UNCOMPRESSED {
    scaled_value [ 32 ];
  }
        
variable_scaled_timestamp(tss_flag, tsc_flag, ts_stride, time_stride)
{
  UNCOMPRESSED {
    scaled_value [ 32 ];
  }
        
  COMPRESSED present {
    ENFORCE((tss_flag == 0) && (tsc_flag == 1));
    ENFORCE(ts_stride != 0);
    scaled_value =:= sdvl_scaled_ts_lsb(time_stride) [ VARIABLE ];
  }
        
  COMPRESSED present {
    ENFORCE((tss_flag == 0) && (tsc_flag == 1));
    ENFORCE(ts_stride != 0);
    scaled_value =:= sdvl_scaled_ts_lsb(time_stride) [ VARIABLE ];
  }
        
  COMPRESSED not_present {
    ENFORCE(((tss_flag == 1) && (tsc_flag == 0)) ||
            ((tss_flag == 0) && (tsc_flag == 0)));
  }
}
        
  COMPRESSED not_present {
    ENFORCE(((tss_flag == 1) && (tsc_flag == 0)) ||
            ((tss_flag == 0) && (tsc_flag == 0)));
  }
}
        
variable_unscaled_timestamp(tss_flag, tsc_flag)
{
  UNCOMPRESSED {
    timestamp [ 32 ];
  }
        
variable_unscaled_timestamp(tss_flag, tsc_flag)
{
  UNCOMPRESSED {
    timestamp [ 32 ];
  }
        
  COMPRESSED present {
    ENFORCE(((tss_flag == 1) && (tsc_flag == 0)) ||
            ((tss_flag == 0) && (tsc_flag == 0)));
    timestamp =:= sdvl_lsb(32);
  }
        
  COMPRESSED present {
    ENFORCE(((tss_flag == 1) && (tsc_flag == 0)) ||
            ((tss_flag == 0) && (tsc_flag == 0)));
    timestamp =:= sdvl_lsb(32);
  }
        
  COMPRESSED not_present {
    ENFORCE((tss_flag == 0) && (tsc_flag == 1));
        
  COMPRESSED not_present {
    ENFORCE((tss_flag == 0) && (tsc_flag == 1));
        
  }
}
        
  }
}
        
profile_1_7_flags1_enc(flag, ip_version)
{
  UNCOMPRESSED {
    ip_outer_indicator  [ 1 ];
    ttl_hopl_indicator  [ 1 ];
    tos_tc_indicator    [ 1 ];
    df                  [ 0, 1 ];
    ip_id_behavior      [ 2 ];
    reorder_ratio       [ 2 ];
  }
        
profile_1_7_flags1_enc(flag, ip_version)
{
  UNCOMPRESSED {
    ip_outer_indicator  [ 1 ];
    ttl_hopl_indicator  [ 1 ];
    tos_tc_indicator    [ 1 ];
    df                  [ 0, 1 ];
    ip_id_behavior      [ 2 ];
    reorder_ratio       [ 2 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    ENFORCE(ip_outer_indicator.CVALUE == 0);
    ENFORCE(ttl_hopl_indicator.CVALUE == 0);
    ENFORCE(tos_tc_indicator.CVALUE == 0);
    df                   =:= static;
    ip_id_behavior       =:= static;
    reorder_ratio        =:= static;
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    ENFORCE(ip_outer_indicator.CVALUE == 0);
    ENFORCE(ttl_hopl_indicator.CVALUE == 0);
    ENFORCE(tos_tc_indicator.CVALUE == 0);
    df                   =:= static;
    ip_id_behavior       =:= static;
    reorder_ratio        =:= static;
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    ip_outer_indicator  =:= irregular(1)                [ 1 ];
    ttl_hopl_indicator  =:= irregular(1)                [ 1 ];
    tos_tc_indicator    =:= irregular(1)                [ 1 ];
    df                  =:= dont_fragment(ip_version)   [ 1 ];
    ip_id_behavior      =:= irregular(2)                [ 2 ];
    reorder_ratio       =:= irregular(2)                [ 2 ];
  }
}
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    ip_outer_indicator  =:= irregular(1)                [ 1 ];
    ttl_hopl_indicator  =:= irregular(1)                [ 1 ];
    tos_tc_indicator    =:= irregular(1)                [ 1 ];
    df                  =:= dont_fragment(ip_version)   [ 1 ];
    ip_id_behavior      =:= irregular(2)                [ 2 ];
    reorder_ratio       =:= irregular(2)                [ 2 ];
  }
}
        
profile_1_flags2_enc(flag)
{
  UNCOMPRESSED {
    list_indicator        [ 1 ];
    pt_indicator          [ 1 ];
    time_stride_indicator [ 1 ];
    pad_bit               [ 1 ];
    extension             [ 1 ];
  }
        
profile_1_flags2_enc(flag)
{
  UNCOMPRESSED {
    list_indicator        [ 1 ];
    pt_indicator          [ 1 ];
    time_stride_indicator [ 1 ];
    pad_bit               [ 1 ];
    extension             [ 1 ];
  }
        
  COMPRESSED not_present{
    ENFORCE(flag == 0);
    ENFORCE(list_indicator.UVALUE == 0);
        
  COMPRESSED not_present{
    ENFORCE(flag == 0);
    ENFORCE(list_indicator.UVALUE == 0);
        
    ENFORCE(pt_indicator.UVALUE == 0);
    ENFORCE(time_stride_indicator.UVALUE == 0);
    pad_bit      =:= static;
    extension    =:= static;
  }
        
    ENFORCE(pt_indicator.UVALUE == 0);
    ENFORCE(time_stride_indicator.UVALUE == 0);
    pad_bit      =:= static;
    extension    =:= static;
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    list_indicator =:= irregular(1)                  [ 1 ];
    pt_indicator   =:= irregular(1)                  [ 1 ];
    time_stride_indicator =:= irregular(1)           [ 1 ];
    pad_bit        =:= irregular(1)                  [ 1 ];
    extension      =:= irregular(1)                  [ 1 ];
    reserved       =:= compressed_value(3, 0)        [ 3 ];
  }
}
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    list_indicator =:= irregular(1)                  [ 1 ];
    pt_indicator   =:= irregular(1)                  [ 1 ];
    time_stride_indicator =:= irregular(1)           [ 1 ];
    pad_bit        =:= irregular(1)                  [ 1 ];
    extension      =:= irregular(1)                  [ 1 ];
    reserved       =:= compressed_value(3, 0)        [ 3 ];
  }
}
        
profile_2_3_4_flags_enc(flag, ip_version)
{
  UNCOMPRESSED {
    ip_outer_indicator [ 1 ];
    df                 [ 0, 1 ];
    ip_id_behavior     [ 2 ];
  }
        
profile_2_3_4_flags_enc(flag, ip_version)
{
  UNCOMPRESSED {
    ip_outer_indicator [ 1 ];
    df                 [ 0, 1 ];
    ip_id_behavior     [ 2 ];
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    ENFORCE(ip_outer_indicator.CVALUE == 0);
    df                 =:= static;
    ip_id_behavior     =:= static;
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    ENFORCE(ip_outer_indicator.CVALUE == 0);
    df                 =:= static;
    ip_id_behavior     =:= static;
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    ip_outer_indicator =:= irregular(1)              [ 1 ];
    df                 =:= dont_fragment(ip_version) [ 1 ];
    ip_id_behavior     =:= irregular(2)              [ 2 ];
    reserved           =:= compressed_value(4, 0)    [ 4 ];
  }
}
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    ip_outer_indicator =:= irregular(1)              [ 1 ];
    df                 =:= dont_fragment(ip_version) [ 1 ];
    ip_id_behavior     =:= irregular(2)              [ 2 ];
    reserved           =:= compressed_value(4, 0)    [ 4 ];
  }
}
        
profile_8_flags_enc(flag, ip_version)
{
  UNCOMPRESSED {
    ip_outer_indicator  [ 1 ];
    df                  [ 0, 1 ];
    ip_id_behavior      [ 2 ];
    coverage_behavior   [ 2 ];
        
profile_8_flags_enc(flag, ip_version)
{
  UNCOMPRESSED {
    ip_outer_indicator  [ 1 ];
    df                  [ 0, 1 ];
    ip_id_behavior      [ 2 ];
    coverage_behavior   [ 2 ];
        

}

}

  COMPRESSED not_present {
    ENFORCE(flag == 0);
    ENFORCE(ip_outer_indicator.CVALUE == 0);
    df                  =:= static;
    ip_id_behavior      =:= static;
    coverage_behavior   =:= static;
  }
        
  COMPRESSED not_present {
    ENFORCE(flag == 0);
    ENFORCE(ip_outer_indicator.CVALUE == 0);
    df                  =:= static;
    ip_id_behavior      =:= static;
    coverage_behavior   =:= static;
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    reserved            =:= compressed_value(2, 0)      [ 2 ];
    ip_outer_indicator  =:= irregular(1)                [ 1 ];
    df                  =:= dont_fragment(ip_version)   [ 1 ];
    ip_id_behavior      =:= irregular(2)                [ 2 ];
    coverage_behavior   =:= irregular(2)                [ 2 ];
  }
}
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    reserved            =:= compressed_value(2, 0)      [ 2 ];
    ip_outer_indicator  =:= irregular(1)                [ 1 ];
    df                  =:= dont_fragment(ip_version)   [ 1 ];
    ip_id_behavior      =:= irregular(2)                [ 2 ];
    coverage_behavior   =:= irregular(2)                [ 2 ];
  }
}
        
profile_7_flags2_enc(flag)
{
  UNCOMPRESSED {
    list_indicator          [ 1 ];
    pt_indicator            [ 1 ];
    time_stride_indicator   [ 1 ];
    pad_bit                 [ 1 ];
    extension               [ 1 ];
    coverage_behavior       [ 2 ];
  }
        
profile_7_flags2_enc(flag)
{
  UNCOMPRESSED {
    list_indicator          [ 1 ];
    pt_indicator            [ 1 ];
    time_stride_indicator   [ 1 ];
    pad_bit                 [ 1 ];
    extension               [ 1 ];
    coverage_behavior       [ 2 ];
  }
        
  COMPRESSED not_present{
    ENFORCE(flag == 0);
    ENFORCE(list_indicator.CVALUE == 0);
    ENFORCE(pt_indicator.CVALUE == 0);
    ENFORCE(time_stride_indicator.CVALUE == 0);
    pad_bit             =:= static;
    extension           =:= static;
    coverage_behavior   =:= static;
  }
        
  COMPRESSED not_present{
    ENFORCE(flag == 0);
    ENFORCE(list_indicator.CVALUE == 0);
    ENFORCE(pt_indicator.CVALUE == 0);
    ENFORCE(time_stride_indicator.CVALUE == 0);
    pad_bit             =:= static;
    extension           =:= static;
    coverage_behavior   =:= static;
  }
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    reserved       =:= compressed_value(1, 0)      [ 1 ];
    list_indicator =:= irregular(1)                [ 1 ];
    pt_indicator   =:= irregular(1)                [ 1 ];
    time_stride_indicator =:= irregular(1)         [ 1 ];
    pad_bit        =:= irregular(1)                [ 1 ];
        
  COMPRESSED present {
    ENFORCE(flag == 1);
    reserved       =:= compressed_value(1, 0)      [ 1 ];
    list_indicator =:= irregular(1)                [ 1 ];
    pt_indicator   =:= irregular(1)                [ 1 ];
    time_stride_indicator =:= irregular(1)         [ 1 ];
    pad_bit        =:= irregular(1)                [ 1 ];
        
    extension      =:= irregular(1)                [ 1 ];
    coverage_behavior =:= irregular(2)             [ 2 ];
  }
}
        
    extension      =:= irregular(1)                [ 1 ];
    coverage_behavior =:= irregular(2)             [ 2 ];
  }
}
        
////////////////////////////////////////////
// RTP profile
////////////////////////////////////////////
        
////////////////////////////////////////////
// RTP profile
////////////////////////////////////////////
        
rtp_baseheader(profile_value, ts_stride_value, time_stride_value,
               outer_ip_flag, ip_id_behavior_value,
               reorder_ratio_value)
{
  UNCOMPRESSED v4 {
    ENFORCE(msn.UVALUE == sequence_number.UVALUE);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    udp_length  =:= inferred_udp_length                [ 16 ];
    udp_checksum                                       [ 16 ];
    rtp_version =:= uncompressed_value(2, 2)           [  2 ];
    pad_bit                                            [  1 ];
    extension                                          [  1 ];
    cc                                                 [  4 ];
    marker                                             [  1 ];
    payload_type                                       [  7 ];
    sequence_number                                    [ 16 ];
    timestamp                                          [ 32 ];
    ssrc                                               [ 32 ];
    csrc_list                                          [ VARIABLE ];
  }
        
rtp_baseheader(profile_value, ts_stride_value, time_stride_value,
               outer_ip_flag, ip_id_behavior_value,
               reorder_ratio_value)
{
  UNCOMPRESSED v4 {
    ENFORCE(msn.UVALUE == sequence_number.UVALUE);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    udp_length  =:= inferred_udp_length                [ 16 ];
    udp_checksum                                       [ 16 ];
    rtp_version =:= uncompressed_value(2, 2)           [  2 ];
    pad_bit                                            [  1 ];
    extension                                          [  1 ];
    cc                                                 [  4 ];
    marker                                             [  1 ];
    payload_type                                       [  7 ];
    sequence_number                                    [ 16 ];
    timestamp                                          [ 32 ];
    ssrc                                               [ 32 ];
    csrc_list                                          [ VARIABLE ];
  }
        

UNCOMPRESSED v6 {

未压缩v6{

    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    ENFORCE(msn.UVALUE == sequence_number.UVALUE);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length =:= inferred_ip_v6_length           [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [  16 ];
    dst_port                                           [  16 ];
    udp_length     =:= inferred_udp_length             [  16 ];
    udp_checksum                                       [  16 ];
    rtp_version    =:= uncompressed_value(2, 2)        [   2 ];
    pad_bit                                            [   1 ];
    extension                                          [   1 ];
    cc                                                 [   4 ];
    marker                                             [   1 ];
    payload_type                                       [   7 ];
    sequence_number                                    [  16 ];
    timestamp                                          [  32 ];
    ssrc                                               [  32 ];
    csrc_list                                          [ VARIABLE ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    ENFORCE(msn.UVALUE == sequence_number.UVALUE);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length =:= inferred_ip_v6_length           [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [  16 ];
    dst_port                                           [  16 ];
    udp_length     =:= inferred_udp_length             [  16 ];
    udp_checksum                                       [  16 ];
    rtp_version    =:= uncompressed_value(2, 2)        [   2 ];
    pad_bit                                            [   1 ];
    extension                                          [   1 ];
    cc                                                 [   4 ];
    marker                                             [   1 ];
    payload_type                                       [   7 ];
    sequence_number                                    [  16 ];
    timestamp                                          [  32 ];
    ssrc                                               [  32 ];
    csrc_list                                          [ VARIABLE ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_RTP_0101);
    ENFORCE(profile == profile_value);
    ENFORCE(time_stride.UVALUE == time_stride_value);
    ENFORCE(ts_stride.UVALUE == ts_stride_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    dummy_field =:= field_scaling(ts_stride.UVALUE,
      ts_scaled.UVALUE, timestamp.UVALUE, ts_offset.UVALUE) [ 0 ];
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_RTP_0101);
    ENFORCE(profile == profile_value);
    ENFORCE(time_stride.UVALUE == time_stride_value);
    ENFORCE(ts_stride.UVALUE == ts_stride_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    dummy_field =:= field_scaling(ts_stride.UVALUE,
      ts_scaled.UVALUE, timestamp.UVALUE, ts_offset.UVALUE) [ 0 ];
  }
        
  INITIAL {
    ts_stride     =:= uncompressed_value(32, TS_STRIDE_DEFAULT);
    time_stride   =:= uncompressed_value(32, TIME_STRIDE_DEFAULT);
  }
        
  INITIAL {
    ts_stride     =:= uncompressed_value(32, TS_STRIDE_DEFAULT);
    time_stride   =:= uncompressed_value(32, TIME_STRIDE_DEFAULT);
  }
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
        
    tos_tc          =:= static;
    dest_addr       =:= static;
    ttl_hopl        =:= static;
    src_addr        =:= static;
    df              =:= static;
    flow_label      =:= static;
    next_header     =:= static;
    src_port        =:= static;
    dst_port        =:= static;
    pad_bit         =:= static;
    extension       =:= static;
    cc              =:= static;
    // When marker not present in packets, it is assumed 0
    marker          =:= uncompressed_value(1, 0);
    payload_type    =:= static;
    sequence_number =:= static;
    timestamp       =:= static;
    ssrc            =:= static;
    csrc_list       =:= static;
    ts_stride       =:= static;
    time_stride     =:= static;
    ts_scaled       =:= static;
    ts_offset       =:= static;
    reorder_ratio   =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
    tos_tc          =:= static;
    dest_addr       =:= static;
    ttl_hopl        =:= static;
    src_addr        =:= static;
    df              =:= static;
    flow_label      =:= static;
    next_header     =:= static;
    src_port        =:= static;
    dst_port        =:= static;
    pad_bit         =:= static;
    extension       =:= static;
    cc              =:= static;
    // When marker not present in packets, it is assumed 0
    marker          =:= uncompressed_value(1, 0);
    payload_type    =:= static;
    sequence_number =:= static;
    timestamp       =:= static;
    ssrc            =:= static;
    csrc_list       =:= static;
    ts_stride       =:= static;
    time_stride     =:= static;
    ts_scaled       =:= static;
    ts_offset       =:= static;
    reorder_ratio   =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    marker               =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags1_indicator     =:= irregular(1)                  [ 1 ];
    flags2_indicator     =:= irregular(1)                  [ 1 ];
    tsc_indicator        =:= irregular(1)                  [ 1 ];
    tss_indicator        =:= irregular(1)                  [ 1 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    marker               =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags1_indicator     =:= irregular(1)                  [ 1 ];
    flags2_indicator     =:= irregular(1)                  [ 1 ];
    tsc_indicator        =:= irregular(1)                  [ 1 ];
    tss_indicator        =:= irregular(1)                  [ 1 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
        
    outer_ip_indicator : ttl_hopl_indicator :
      tos_tc_indicator : df : ip_id_behavior_innermost : reorder_ratio
      =:= profile_1_7_flags1_enc(flags1_indicator.CVALUE,
        ip_version.UVALUE)                                 [ 0, 8 ];
    list_indicator : pt_indicator : tis_indicator : pad_bit :
      extension =:= profile_1_flags2_enc(
        flags2_indicator.CVALUE)                           [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
        
    outer_ip_indicator : ttl_hopl_indicator :
      tos_tc_indicator : df : ip_id_behavior_innermost : reorder_ratio
      =:= profile_1_7_flags1_enc(flags1_indicator.CVALUE,
        ip_version.UVALUE)                                 [ 0, 8 ];
    list_indicator : pt_indicator : tis_indicator : pad_bit :
      extension =:= profile_1_flags2_enc(
        flags2_indicator.CVALUE)                           [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
        
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    payload_type =:= pt_irr_or_static(pt_indicator)        [ 0, 8 ];
    sequence_number =:=
      sdvl_sn_lsb(sequence_number.ULENGTH)                [ VARIABLE ];
    ip_id =:= ip_id_sequential_variable(
      ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE) [ 0, 8, 16 ];
    ts_scaled =:= variable_scaled_timestamp(tss_indicator.CVALUE,
      tsc_indicator.CVALUE, ts_stride.UVALUE,
      time_stride.UVALUE)                                 [ VARIABLE ];
    timestamp =:= variable_unscaled_timestamp(tss_indicator.CVALUE,
      tsc_indicator.CVALUE)                               [ VARIABLE ];
    ts_stride =:= sdvl_or_static(tss_indicator.CVALUE)    [ VARIABLE ];
    time_stride =:= sdvl_or_static(tis_indicator.CVALUE)  [ VARIABLE ];
    csrc_list =:= csrc_list_presence(list_indicator.CVALUE,
      cc.UVALUE)                                          [ VARIABLE ];
  }
        
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    payload_type =:= pt_irr_or_static(pt_indicator)        [ 0, 8 ];
    sequence_number =:=
      sdvl_sn_lsb(sequence_number.ULENGTH)                [ VARIABLE ];
    ip_id =:= ip_id_sequential_variable(
      ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE) [ 0, 8, 16 ];
    ts_scaled =:= variable_scaled_timestamp(tss_indicator.CVALUE,
      tsc_indicator.CVALUE, ts_stride.UVALUE,
      time_stride.UVALUE)                                 [ VARIABLE ];
    timestamp =:= variable_unscaled_timestamp(tss_indicator.CVALUE,
      tsc_indicator.CVALUE)                               [ VARIABLE ];
    ts_stride =:= sdvl_or_static(tss_indicator.CVALUE)    [ VARIABLE ];
    time_stride =:= sdvl_or_static(tis_indicator.CVALUE)  [ VARIABLE ];
    csrc_list =:= csrc_list_presence(list_indicator.CVALUE,
      cc.UVALUE)                                          [ VARIABLE ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    timestamp     =:= inferred_scaled_field           [ 0 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    timestamp     =:= inferred_scaled_field           [ 0 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator =:= '1000'                          [ 4 ];
    msn           =:= msn_lsb(5)                      [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    timestamp     =:= inferred_scaled_field           [ 0 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator =:= '1000'                          [ 4 ];
    msn           =:= msn_lsb(5)                      [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    timestamp     =:= inferred_scaled_field           [ 0 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-1 replacement
  COMPRESSED pt_1_rnd {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
    discriminator =:= '101'                                [ 3 ];
    marker        =:= irregular(1)                         [ 1 ];
    msn           =:= msn_lsb(4)                           [ 4 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)      [ 3 ];
        
  // UO-1 replacement
  COMPRESSED pt_1_rnd {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
    discriminator =:= '101'                                [ 3 ];
    marker        =:= irregular(1)                         [ 1 ];
    msn           =:= msn_lsb(4)                           [ 4 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)      [ 3 ];
        

}

}

  // UO-1-ID replacement
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '1001'                                [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
    msn           =:= msn_lsb(5)                            [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    timestamp     =:= inferred_scaled_field                 [ 0 ];
  }
        
  // UO-1-ID replacement
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '1001'                                [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
    msn           =:= msn_lsb(5)                            [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    timestamp     =:= inferred_scaled_field                 [ 0 ];
  }
        
  // UO-1-TS replacement
  COMPRESSED pt_1_seq_ts {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                [ 3 ];
    marker        =:= irregular(1)                         [ 1 ];
    msn           =:= msn_lsb(4)                           [ 4 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)      [ 3 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-1-TS replacement
  COMPRESSED pt_1_seq_ts {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                [ 3 ];
    marker        =:= irregular(1)                         [ 1 ];
    msn           =:= msn_lsb(4)                           [ 4 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)      [ 3 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UOR-2 replacement
  COMPRESSED pt_2_rnd {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
    discriminator =:= '110'                                [ 3 ];
    msn           =:= msn_lsb(7)                           [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 6) [ 6 ];
    marker        =:= irregular(1)                         [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)      [ 7 ];
  }
        
  // UOR-2 replacement
  COMPRESSED pt_2_rnd {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
    discriminator =:= '110'                                [ 3 ];
    msn           =:= msn_lsb(7)                           [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 6) [ 6 ];
    marker        =:= irregular(1)                         [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)      [ 7 ];
  }
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
        
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '11000'                               [ 5 ];
    msn           =:= msn_lsb(7)                            [ 7 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5) [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    timestamp     =:= inferred_scaled_field                 [ 0 ];
  }
        
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '11000'                               [ 5 ];
    msn           =:= msn_lsb(7)                            [ 7 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5) [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    timestamp     =:= inferred_scaled_field                 [ 0 ];
  }
        
  // UOR-2-ID-ext1 replacement (both TS and IP-ID)
  COMPRESSED pt_2_seq_both {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '11001'                               [ 5 ];
    msn           =:= msn_lsb(7)                            [ 7 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5) [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 7)  [ 7 ];
    marker        =:= irregular(1)                          [ 1 ];
  }
        
  // UOR-2-ID-ext1 replacement (both TS and IP-ID)
  COMPRESSED pt_2_seq_both {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '11001'                               [ 5 ];
    msn           =:= msn_lsb(7)                            [ 7 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5) [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 7)  [ 7 ];
    marker        =:= irregular(1)                          [ 1 ];
  }
        
  // UOR-2-TS replacement
  COMPRESSED pt_2_seq_ts {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '1101'                               [ 4 ];
    msn           =:= msn_lsb(7)                           [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    marker        =:= irregular(1)                         [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)      [ 7 ];
    ip_id         =:= inferred_sequential_ip_id            [ 0 ];
  }
}
        
  // UOR-2-TS replacement
  COMPRESSED pt_2_seq_ts {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '1101'                               [ 4 ];
    msn           =:= msn_lsb(7)                           [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    marker        =:= irregular(1)                         [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)      [ 7 ];
    ip_id         =:= inferred_sequential_ip_id            [ 0 ];
  }
}
        
////////////////////////////////////////////
// UDP profile
////////////////////////////////////////////
        
////////////////////////////////////////////
// UDP profile
////////////////////////////////////////////
        
udp_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value,
               reorder_ratio_value)
{
  UNCOMPRESSED v4 {
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
        
udp_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value,
               reorder_ratio_value)
{
  UNCOMPRESSED v4 {
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
        
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    udp_length     =:= inferred_udp_length             [ 16 ];
    udp_checksum                                       [ 16 ];
  }
        
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    udp_length     =:= inferred_udp_length             [ 16 ];
    udp_checksum                                       [ 16 ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [  4 ];
    tos_tc                                             [  8 ];
    flow_label                                         [ 20 ];
    payload_length =:= inferred_ip_v6_length           [ 16 ];
    next_header                                        [  8 ];
    ttl_hopl                                           [  8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    udp_length     =:= inferred_udp_length             [ 16 ];
    udp_checksum                                       [ 16 ];
    df    =:= uncompressed_value(0,0)                  [  0 ];
    ip_id =:= uncompressed_value(0,0)                  [  0 ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [  4 ];
    tos_tc                                             [  8 ];
    flow_label                                         [ 20 ];
    payload_length =:= inferred_ip_v6_length           [ 16 ];
    next_header                                        [  8 ];
    ttl_hopl                                           [  8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    udp_length     =:= inferred_udp_length             [ 16 ];
    udp_checksum                                       [ 16 ];
    df    =:= uncompressed_value(0,0)                  [  0 ];
    ip_id =:= uncompressed_value(0,0)                  [  0 ];
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_UDP_0102);
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_UDP_0102);
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
  }
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
    tos_tc         =:= static;
    dest_addr      =:= static;
    ip_version     =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    df             =:= static;
    flow_label     =:= static;
    next_header    =:= static;
    src_port       =:= static;
    dst_port       =:= static;
    reorder_ratio  =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
    tos_tc         =:= static;
    dest_addr      =:= static;
    ip_version     =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    df             =:= static;
    flow_label     =:= static;
    next_header    =:= static;
    src_port       =:= static;
    dst_port       =:= static;
    reorder_ratio  =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags_indicator      =:= irregular(1)                  [ 1 ];
    ttl_hopl_indicator   =:= irregular(1)                  [ 1 ];
    tos_tc_indicator     =:= irregular(1)                  [ 1 ];
    reorder_ratio        =:= irregular(2)                  [ 2 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
    outer_ip_indicator : df : ip_id_behavior_innermost =:=
      profile_2_3_4_flags_enc(
      flags_indicator.CVALUE, ip_version.UVALUE)           [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    msn                  =:= msn_lsb(8)                    [ 8 ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                          [ 0, 8, 16 ];
  }
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags_indicator      =:= irregular(1)                  [ 1 ];
    ttl_hopl_indicator   =:= irregular(1)                  [ 1 ];
    tos_tc_indicator     =:= irregular(1)                  [ 1 ];
    reorder_ratio        =:= irregular(2)                  [ 2 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
    outer_ip_indicator : df : ip_id_behavior_innermost =:=
      profile_2_3_4_flags_enc(
      flags_indicator.CVALUE, ip_version.UVALUE)           [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    msn                  =:= msn_lsb(8)                    [ 8 ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                          [ 0, 8, 16 ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        

// New format, Type 0 with strong CRC and more SN bits COMPRESSED pt_0_crc7 {

//新格式,类型0,具有强CRC和更多SN位压缩pt_0_crc7{

    discriminator =:= '100'                           [ 3 ];
    msn           =:= msn_lsb(6)                      [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
    discriminator =:= '100'                           [ 3 ];
    msn           =:= msn_lsb(6)                      [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-1-ID replacement (PT-1 only used for sequential)
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                 [ 3 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    msn           =:= msn_lsb(6)                            [ 6 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
  }
        
  // UO-1-ID replacement (PT-1 only used for sequential)
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                 [ 3 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    msn           =:= msn_lsb(6)                            [ 6 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
  }
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '110'                                 [ 3 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 6) [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    msn           =:= msn_lsb(8)                            [ 8 ];
  }
}
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '110'                                 [ 3 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 6) [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    msn           =:= msn_lsb(8)                            [ 8 ];
  }
}
        
////////////////////////////////////////////
// ESP profile
////////////////////////////////////////////
        
////////////////////////////////////////////
// ESP profile
////////////////////////////////////////////
        
esp_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value,
               reorder_ratio_value)
{
  UNCOMPRESSED v4 {
    ENFORCE(msn.UVALUE == sequence_number.UVALUE % 65536);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
        
esp_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value,
               reorder_ratio_value)
{
  UNCOMPRESSED v4 {
    ENFORCE(msn.UVALUE == sequence_number.UVALUE % 65536);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
        
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    spi                                                [ 32 ];
    sequence_number                                    [ 32 ];
  }
        
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    spi                                                [ 32 ];
    sequence_number                                    [ 32 ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(msn.UVALUE == (sequence_number.UVALUE % 65536));
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length =:= inferred_ip_v6_length           [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    spi                                                [  32 ];
    sequence_number                                    [  32 ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(msn.UVALUE == (sequence_number.UVALUE % 65536));
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length =:= inferred_ip_v6_length           [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    spi                                                [  32 ];
    sequence_number                                    [  32 ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_ESP_0103);
    ENFORCE(profile == profile_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_ESP_0103);
    ENFORCE(profile == profile_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
  }
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
    tos_tc          =:= static;
    dest_addr       =:= static;
    ttl_hopl        =:= static;
    src_addr        =:= static;
    df              =:= static;
    flow_label      =:= static;
    next_header     =:= static;
    spi             =:= static;
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
    tos_tc          =:= static;
    dest_addr       =:= static;
    ttl_hopl        =:= static;
    src_addr        =:= static;
    df              =:= static;
    flow_label      =:= static;
    next_header     =:= static;
    spi             =:= static;
        
    sequence_number =:= static;
    reorder_ratio   =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
    sequence_number =:= static;
    reorder_ratio   =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags_indicator      =:= irregular(1)                  [ 1 ];
    ttl_hopl_indicator   =:= irregular(1)                  [ 1 ];
    tos_tc_indicator     =:= irregular(1)                  [ 1 ];
    reorder_ratio        =:= irregular(2)                  [ 2 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags_indicator      =:= irregular(1)                  [ 1 ];
    ttl_hopl_indicator   =:= irregular(1)                  [ 1 ];
    tos_tc_indicator     =:= irregular(1)                  [ 1 ];
    reorder_ratio        =:= irregular(2)                  [ 2 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
        
    outer_ip_indicator : df : ip_id_behavior_innermost =:=
      profile_2_3_4_flags_enc(
      flags_indicator.CVALUE, ip_version.UVALUE)           [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    sequence_number =:=
      sdvl_sn_lsb(sequence_number.ULENGTH)             [ VARIABLE ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                          [ 0, 8, 16 ];
  }
        
    outer_ip_indicator : df : ip_id_behavior_innermost =:=
      profile_2_3_4_flags_enc(
      flags_indicator.CVALUE, ip_version.UVALUE)           [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    sequence_number =:=
      sdvl_sn_lsb(sequence_number.ULENGTH)             [ VARIABLE ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                          [ 0, 8, 16 ];
  }
        
  // Sequence number sent instead of MSN due to field length
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator   =:= '0'                             [ 1 ];
    sequence_number =:= msn_lsb(4)                      [ 4 ];
    header_crc      =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ip_id           =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // Sequence number sent instead of MSN due to field length
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator   =:= '0'                             [ 1 ];
    sequence_number =:= msn_lsb(4)                      [ 4 ];
    header_crc      =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ip_id           =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator   =:= '100'                           [ 3 ];
    sequence_number =:= msn_lsb(6)                      [ 6 ];
    header_crc      =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    ip_id           =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator   =:= '100'                           [ 3 ];
    sequence_number =:= msn_lsb(6)                      [ 6 ];
    header_crc      =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    ip_id           =:= inferred_sequential_ip_id       [ 0 ];
  }
        

// UO-1-ID replacement (PT-1 only used for sequential) COMPRESSED pt_1_seq_id {

//UO-1-ID替换(PT-1仅用于顺序)压缩PT_1_seq_ID{

    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator   =:= '101'                               [ 3 ];
    header_crc      =:= crc3(THIS.UVALUE, THIS.ULENGTH)     [ 3 ];
    sequence_number =:= msn_lsb(6)                          [ 6 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
  }
        
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator   =:= '101'                               [ 3 ];
    header_crc      =:= crc3(THIS.UVALUE, THIS.ULENGTH)     [ 3 ];
    sequence_number =:= msn_lsb(6)                          [ 6 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
  }
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator   =:= '110'                               [ 3 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 6) [ 6 ];
    header_crc      =:= crc7(THIS.UVALUE, THIS.ULENGTH)     [ 7 ];
    sequence_number =:= msn_lsb(8)                          [ 8 ];
  }
}
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator   =:= '110'                               [ 3 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 6) [ 6 ];
    header_crc      =:= crc7(THIS.UVALUE, THIS.ULENGTH)     [ 7 ];
    sequence_number =:= msn_lsb(8)                          [ 8 ];
  }
}
        
////////////////////////////////////////////
// IP-only profile
////////////////////////////////////////////
        
////////////////////////////////////////////
// IP-only profile
////////////////////////////////////////////
        
iponly_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value,
                  reorder_ratio_value)
{
  UNCOMPRESSED v4 {
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
  }
        
iponly_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value,
                  reorder_ratio_value)
{
  UNCOMPRESSED v4 {
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers     =:= baseheader_outer_headers     [ VARIABLE ];
    ip_version        =:= uncompressed_value(4, 6)     [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length    =:= inferred_ip_v6_length        [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers     =:= baseheader_outer_headers     [ VARIABLE ];
    ip_version        =:= uncompressed_value(4, 6)     [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length    =:= inferred_ip_v6_length        [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_IP_0104);
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_IP_0104);
    ENFORCE(profile == profile_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
  }
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
    tos_tc         =:= static;
    dest_addr      =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    df             =:= static;
    flow_label     =:= static;
    next_header    =:= static;
    reorder_ratio  =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
    tos_tc         =:= static;
    dest_addr      =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    df             =:= static;
    flow_label     =:= static;
    next_header    =:= static;
    reorder_ratio  =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags_indicator      =:= irregular(1)                  [ 1 ];
    ttl_hopl_indicator   =:= irregular(1)                  [ 1 ];
    tos_tc_indicator     =:= irregular(1)                  [ 1 ];
    reorder_ratio        =:= irregular(2)                  [ 2 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
    outer_ip_indicator : df : ip_id_behavior_innermost =:=
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags_indicator      =:= irregular(1)                  [ 1 ];
    ttl_hopl_indicator   =:= irregular(1)                  [ 1 ];
    tos_tc_indicator     =:= irregular(1)                  [ 1 ];
    reorder_ratio        =:= irregular(2)                  [ 2 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
    outer_ip_indicator : df : ip_id_behavior_innermost =:=
        
      profile_2_3_4_flags_enc(
      flags_indicator.CVALUE, ip_version.UVALUE)           [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    msn                  =:= msn_lsb(8)                    [ 8 ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                          [ 0, 8, 16 ];
  }
        
      profile_2_3_4_flags_enc(
      flags_indicator.CVALUE, ip_version.UVALUE)           [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    msn                  =:= msn_lsb(8)                    [ 8 ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                          [ 0, 8, 16 ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator =:= '100'                           [ 3 ];
    msn           =:= msn_lsb(6)                      [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator =:= '100'                           [ 3 ];
    msn           =:= msn_lsb(6)                      [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-1-ID replacement (PT-1 only used for sequential)
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                 [ 3 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    msn           =:= msn_lsb(6)                            [ 6 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
  }
        
  // UO-1-ID replacement (PT-1 only used for sequential)
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                 [ 3 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    msn           =:= msn_lsb(6)                            [ 6 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
  }
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '110'                                 [ 3 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 6) [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    msn           =:= msn_lsb(8)                            [ 8 ];
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '110'                                 [ 3 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 6) [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    msn           =:= msn_lsb(8)                            [ 8 ];
        
  }
}
        
  }
}
        
////////////////////////////////////////////
// UDP-lite/RTP profile
////////////////////////////////////////////
        
////////////////////////////////////////////
// UDP-lite/RTP profile
////////////////////////////////////////////
        
udplite_rtp_baseheader(profile_value, ts_stride_value,
                       time_stride_value, outer_ip_flag,
                       ip_id_behavior_value, reorder_ratio_value,
                       coverage_behavior_value)
{
  UNCOMPRESSED v4 {
    ENFORCE(msn.UVALUE == sequence_number.UVALUE);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    checksum_coverage                                  [ 16 ];
    udp_checksum                                       [ 16 ];
    rtp_version    =:= uncompressed_value(2, 2)        [  2 ];
    pad_bit                                            [  1 ];
    extension                                          [  1 ];
    cc                                                 [  4 ];
    marker                                             [  1 ];
    payload_type                                       [  7 ];
    sequence_number                                    [ 16 ];
    timestamp                                          [ 32 ];
    ssrc                                               [ 32 ];
    csrc_list                                          [ VARIABLE ];
  }
        
udplite_rtp_baseheader(profile_value, ts_stride_value,
                       time_stride_value, outer_ip_flag,
                       ip_id_behavior_value, reorder_ratio_value,
                       coverage_behavior_value)
{
  UNCOMPRESSED v4 {
    ENFORCE(msn.UVALUE == sequence_number.UVALUE);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    checksum_coverage                                  [ 16 ];
    udp_checksum                                       [ 16 ];
    rtp_version    =:= uncompressed_value(2, 2)        [  2 ];
    pad_bit                                            [  1 ];
    extension                                          [  1 ];
    cc                                                 [  4 ];
    marker                                             [  1 ];
    payload_type                                       [  7 ];
    sequence_number                                    [ 16 ];
    timestamp                                          [ 32 ];
    ssrc                                               [ 32 ];
    csrc_list                                          [ VARIABLE ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
        
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length =:= inferred_ip_v6_length           [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [  16 ];
    dst_port                                           [  16 ];
    checksum_coverage                                  [  16 ];
    udp_checksum                                       [  16 ];
    rtp_version =:= uncompressed_value(2, 2)           [   2 ];
    pad_bit                                            [   1 ];
    extension                                          [   1 ];
    cc                                                 [   4 ];
    marker                                             [   1 ];
    payload_type                                       [   7 ];
    sequence_number                                    [  16 ];
    timestamp                                          [  32 ];
    ssrc                                               [  32 ];
    csrc_list                                          [ VARIABLE ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length =:= inferred_ip_v6_length           [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [  16 ];
    dst_port                                           [  16 ];
    checksum_coverage                                  [  16 ];
    udp_checksum                                       [  16 ];
    rtp_version =:= uncompressed_value(2, 2)           [   2 ];
    pad_bit                                            [   1 ];
    extension                                          [   1 ];
    cc                                                 [   4 ];
    marker                                             [   1 ];
    payload_type                                       [   7 ];
    sequence_number                                    [  16 ];
    timestamp                                          [  32 ];
    ssrc                                               [  32 ];
    csrc_list                                          [ VARIABLE ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_RTP_0107);
    ENFORCE(profile == profile_value);
    ENFORCE(time_stride.UVALUE == time_stride_value);
    ENFORCE(ts_stride.UVALUE == ts_stride_value);
    ENFORCE(coverage_behavior.UVALUE == coverage_behavior_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    dummy_field =:= field_scaling(ts_stride.UVALUE,
      ts_scaled.UVALUE, timestamp.UVALUE, ts_offset.UVALUE) [ 0 ];
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_RTP_0107);
    ENFORCE(profile == profile_value);
    ENFORCE(time_stride.UVALUE == time_stride_value);
    ENFORCE(ts_stride.UVALUE == ts_stride_value);
    ENFORCE(coverage_behavior.UVALUE == coverage_behavior_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    dummy_field =:= field_scaling(ts_stride.UVALUE,
      ts_scaled.UVALUE, timestamp.UVALUE, ts_offset.UVALUE) [ 0 ];
  }
        
  INITIAL {
    ts_stride     =:= uncompressed_value(32, TS_STRIDE_DEFAULT);
    time_stride   =:= uncompressed_value(32, TIME_STRIDE_DEFAULT);
  }
        
  INITIAL {
    ts_stride     =:= uncompressed_value(32, TS_STRIDE_DEFAULT);
    time_stride   =:= uncompressed_value(32, TIME_STRIDE_DEFAULT);
  }
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
    tos_tc            =:= static;
        
  DEFAULT {
    ENFORCE(outer_ip_flag == 0);
    tos_tc            =:= static;
        
    dest_addr         =:= static;
    ttl_hopl          =:= static;
    src_addr          =:= static;
    df                =:= static;
    flow_label        =:= static;
    next_header       =:= static;
    src_port          =:= static;
    dst_port          =:= static;
    pad_bit           =:= static;
    extension         =:= static;
    cc                =:= static;
    // When marker not present in packets, it is assumed 0
    marker            =:= uncompressed_value(1, 0);
    payload_type      =:= static;
    sequence_number   =:= static;
    timestamp         =:= static;
    ssrc              =:= static;
    csrc_list         =:= static;
    ts_stride         =:= static;
    time_stride       =:= static;
    ts_scaled         =:= static;
    ts_offset         =:= static;
    reorder_ratio     =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
    dest_addr         =:= static;
    ttl_hopl          =:= static;
    src_addr          =:= static;
    df                =:= static;
    flow_label        =:= static;
    next_header       =:= static;
    src_port          =:= static;
    dst_port          =:= static;
    pad_bit           =:= static;
    extension         =:= static;
    cc                =:= static;
    // When marker not present in packets, it is assumed 0
    marker            =:= uncompressed_value(1, 0);
    payload_type      =:= static;
    sequence_number   =:= static;
    timestamp         =:= static;
    ssrc              =:= static;
    csrc_list         =:= static;
    ts_stride         =:= static;
    time_stride       =:= static;
    ts_scaled         =:= static;
    ts_offset         =:= static;
    reorder_ratio     =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    marker               =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags1_indicator     =:= irregular(1)                  [ 1 ];
    flags2_indicator     =:= irregular(1)                  [ 1 ];
    tsc_indicator        =:= irregular(1)                  [ 1 ];
    tss_indicator        =:= irregular(1)                  [ 1 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    marker               =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags1_indicator     =:= irregular(1)                  [ 1 ];
    flags2_indicator     =:= irregular(1)                  [ 1 ];
    tsc_indicator        =:= irregular(1)                  [ 1 ];
    tss_indicator        =:= irregular(1)                  [ 1 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
        
    outer_ip_indicator : ttl_hopl_indicator :
      tos_tc_indicator : df : ip_id_behavior_innermost : reorder_ratio
      =:= profile_1_7_flags1_enc(flags1_indicator.CVALUE,
        ip_version.UVALUE)                                 [ 0, 8 ];
    list_indicator : pt_indicator : tis_indicator : pad_bit :
      extension : coverage_behavior =:=
      profile_7_flags2_enc(flags2_indicator.CVALUE)        [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:=
        
    outer_ip_indicator : ttl_hopl_indicator :
      tos_tc_indicator : df : ip_id_behavior_innermost : reorder_ratio
      =:= profile_1_7_flags1_enc(flags1_indicator.CVALUE,
        ip_version.UVALUE)                                 [ 0, 8 ];
    list_indicator : pt_indicator : tis_indicator : pad_bit :
      extension : coverage_behavior =:=
      profile_7_flags2_enc(flags2_indicator.CVALUE)        [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:=
        
      static_or_irreg(ttl_hopl_indicator.CVALUE, 8)        [ 0, 8 ];
    payload_type =:= pt_irr_or_static(pt_indicator.CVALUE) [ 0, 8 ];
    sequence_number =:=
      sdvl_sn_lsb(sequence_number.ULENGTH)               [ VARIABLE ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                            [ 0, 8, 16 ];
    ts_scaled =:= variable_scaled_timestamp(tss_indicator.CVALUE,
      tsc_indicator.CVALUE, ts_stride.UVALUE,
      time_stride.UVALUE)                                [ VARIABLE ];
    timestamp =:= variable_unscaled_timestamp(tss_indicator.CVALUE,
      tsc_indicator.CVALUE)                              [ VARIABLE ];
    ts_stride =:= sdvl_or_static(tss_indicator.CVALUE)   [ VARIABLE ];
    time_stride =:= sdvl_or_static(tis_indicator.CVALUE) [ VARIABLE ];
    csrc_list            =:=
        csrc_list_presence(list_indicator.CVALUE,
          cc.UVALUE)                                     [ VARIABLE ];
  }
        
      static_or_irreg(ttl_hopl_indicator.CVALUE, 8)        [ 0, 8 ];
    payload_type =:= pt_irr_or_static(pt_indicator.CVALUE) [ 0, 8 ];
    sequence_number =:=
      sdvl_sn_lsb(sequence_number.ULENGTH)               [ VARIABLE ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                            [ 0, 8, 16 ];
    ts_scaled =:= variable_scaled_timestamp(tss_indicator.CVALUE,
      tsc_indicator.CVALUE, ts_stride.UVALUE,
      time_stride.UVALUE)                                [ VARIABLE ];
    timestamp =:= variable_unscaled_timestamp(tss_indicator.CVALUE,
      tsc_indicator.CVALUE)                              [ VARIABLE ];
    ts_stride =:= sdvl_or_static(tss_indicator.CVALUE)   [ VARIABLE ];
    time_stride =:= sdvl_or_static(tis_indicator.CVALUE) [ VARIABLE ];
    csrc_list            =:=
        csrc_list_presence(list_indicator.CVALUE,
          cc.UVALUE)                                     [ VARIABLE ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    timestamp     =:= inferred_scaled_field           [ 0 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    timestamp     =:= inferred_scaled_field           [ 0 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator =:= '1000'                          [ 4 ];
    msn           =:= msn_lsb(5)                      [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    timestamp     =:= inferred_scaled_field           [ 0 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator =:= '1000'                          [ 4 ];
    msn           =:= msn_lsb(5)                      [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    timestamp     =:= inferred_scaled_field           [ 0 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-1 replacement
  COMPRESSED pt_1_rnd {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
    discriminator =:= '101'                                [ 3 ];
    marker        =:= irregular(1)                         [ 1 ];
    msn           =:= msn_lsb(4)                           [ 4 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)      [ 3 ];
  }
        
  // UO-1 replacement
  COMPRESSED pt_1_rnd {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
    discriminator =:= '101'                                [ 3 ];
    marker        =:= irregular(1)                         [ 1 ];
    msn           =:= msn_lsb(4)                           [ 4 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)      [ 3 ];
  }
        
  // UO-1-ID replacement
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '1001'                                [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
    msn           =:= msn_lsb(5)                            [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    timestamp     =:= inferred_scaled_field                 [ 0 ];
  }
        
  // UO-1-ID replacement
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '1001'                                [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
    msn           =:= msn_lsb(5)                            [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    timestamp     =:= inferred_scaled_field                 [ 0 ];
  }
        
  // UO-1-TS replacement
  COMPRESSED pt_1_seq_ts {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                [ 3 ];
    marker        =:= irregular(1)                         [ 1 ];
    msn           =:= msn_lsb(4)                           [ 4 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)      [ 3 ];
    ip_id         =:= inferred_sequential_ip_id            [ 0 ];
  }
        
  // UO-1-TS replacement
  COMPRESSED pt_1_seq_ts {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                [ 3 ];
    marker        =:= irregular(1)                         [ 1 ];
    msn           =:= msn_lsb(4)                           [ 4 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)      [ 3 ];
    ip_id         =:= inferred_sequential_ip_id            [ 0 ];
  }
        
  // UOR-2 replacement
  COMPRESSED pt_2_rnd {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
    discriminator =:= '110'                                [ 3 ];
    msn           =:= msn_lsb(7)                           [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 6) [ 6 ];
    marker        =:= irregular(1)                         [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)      [ 7 ];
  }
        
  // UOR-2 replacement
  COMPRESSED pt_2_rnd {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
    discriminator =:= '110'                                [ 3 ];
    msn           =:= msn_lsb(7)                           [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 6) [ 6 ];
    marker        =:= irregular(1)                         [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)      [ 7 ];
  }
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '11000'                               [ 5 ];
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '11000'                               [ 5 ];
        
    msn           =:= msn_lsb(7)                            [ 7 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5) [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    timestamp     =:= inferred_scaled_field                 [ 0 ];
  }
        
    msn           =:= msn_lsb(7)                            [ 7 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5) [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    timestamp     =:= inferred_scaled_field                 [ 0 ];
  }
        
  // UOR-2-ID-ext1 replacement (both TS and IP-ID)
  COMPRESSED pt_2_seq_both {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '11001'                               [ 5 ];
    msn           =:= msn_lsb(7)                            [ 7 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5) [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 7)  [ 7 ];
    marker        =:= irregular(1)                          [ 1 ];
  }
        
  // UOR-2-ID-ext1 replacement (both TS and IP-ID)
  COMPRESSED pt_2_seq_both {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '11001'                               [ 5 ];
    msn           =:= msn_lsb(7)                            [ 7 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5) [ 5 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 7)  [ 7 ];
    marker        =:= irregular(1)                          [ 1 ];
  }
        
  // UOR-2-TS replacement
  COMPRESSED pt_2_seq_ts {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '1101'                               [ 4 ];
    msn           =:= msn_lsb(7)                           [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    marker        =:= irregular(1)                         [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)      [ 7 ];
    ip_id         =:= inferred_sequential_ip_id            [ 0 ];
  }
}
        
  // UOR-2-TS replacement
  COMPRESSED pt_2_seq_ts {
    ENFORCE(ts_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '1101'                               [ 4 ];
    msn           =:= msn_lsb(7)                           [ 7 ];
    ts_scaled     =:= scaled_ts_lsb(time_stride.UVALUE, 5) [ 5 ];
    marker        =:= irregular(1)                         [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)      [ 7 ];
    ip_id         =:= inferred_sequential_ip_id            [ 0 ];
  }
}
        
////////////////////////////////////////////
// UDP-lite profile
////////////////////////////////////////////
        
////////////////////////////////////////////
// UDP-lite profile
////////////////////////////////////////////
        
udplite_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value,
                   reorder_ratio_value, coverage_behavior_value)
{
  UNCOMPRESSED v4 {
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
        
udplite_baseheader(profile_value, outer_ip_flag, ip_id_behavior_value,
                   reorder_ratio_value, coverage_behavior_value)
{
  UNCOMPRESSED v4 {
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 4)        [  4 ];
    header_length  =:= uncompressed_value(4, 5)        [  4 ];
        
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    checksum_coverage                                  [ 16 ];
    udp_checksum                                       [ 16 ];
  }
        
    tos_tc                                             [  8 ];
    length         =:= inferred_ip_v4_length           [ 16 ];
    ip_id                                              [ 16 ];
    rf             =:= uncompressed_value(1, 0)        [  1 ];
    df                                                 [  1 ];
    mf             =:= uncompressed_value(1, 0)        [  1 ];
    frag_offset    =:= uncompressed_value(13, 0)       [ 13 ];
    ttl_hopl                                           [  8 ];
    next_header                                        [  8 ];
    ip_checksum =:= inferred_ip_v4_header_checksum     [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dst_port                                           [ 16 ];
    checksum_coverage                                  [ 16 ];
    udp_checksum                                       [ 16 ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length =:= inferred_ip_v6_length           [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [  16 ];
    dst_port                                           [  16 ];
    checksum_coverage                                  [  16 ];
    udp_checksum                                       [  16 ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    ip_version     =:= uncompressed_value(4, 6)        [   4 ];
    tos_tc                                             [   8 ];
    flow_label                                         [  20 ];
    payload_length =:= inferred_ip_v6_length           [  16 ];
    next_header                                        [   8 ];
    ttl_hopl                                           [   8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [  16 ];
    dst_port                                           [  16 ];
    checksum_coverage                                  [  16 ];
    udp_checksum                                       [  16 ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_UDPLITE_0108);
    ENFORCE(profile == profile_value);
    ENFORCE(coverage_behavior.UVALUE == coverage_behavior_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
  }
        
  CONTROL {
    ENFORCE(profile_value == PROFILE_UDPLITE_0108);
    ENFORCE(profile == profile_value);
    ENFORCE(coverage_behavior.UVALUE == coverage_behavior_value);
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
  }
        

DEFAULT {

违约{

    ENFORCE(outer_ip_flag == 0);
    tos_tc            =:= static;
    dest_addr         =:= static;
    ttl_hopl          =:= static;
    src_addr          =:= static;
    df                =:= static;
    flow_label        =:= static;
    next_header       =:= static;
    src_port          =:= static;
    dst_port          =:= static;
    reorder_ratio     =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
    ENFORCE(outer_ip_flag == 0);
    tos_tc            =:= static;
    dest_addr         =:= static;
    ttl_hopl          =:= static;
    src_addr          =:= static;
    df                =:= static;
    flow_label        =:= static;
    next_header       =:= static;
    src_port          =:= static;
    dst_port          =:= static;
    reorder_ratio     =:= static;
    ip_id_behavior_innermost =:= static;
  }
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags_indicator      =:= irregular(1)                  [ 1 ];
    ttl_hopl_indicator   =:= irregular(1)                  [ 1 ];
    tos_tc_indicator     =:= irregular(1)                  [ 1 ];
    reorder_ratio        =:= irregular(2)                  [ 2 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
    outer_ip_indicator : df : ip_id_behavior_innermost :
      coverage_behavior  =:=
      profile_8_flags_enc(flags_indicator.CVALUE,
      ip_version.UVALUE)                                   [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    msn                  =:= msn_lsb(8)                    [ 8 ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                          [ 0, 8, 16 ];
  }
        
  // Replacement for UOR-2-ext3
  COMPRESSED co_common {
    ENFORCE(outer_ip_flag == outer_ip_indicator.CVALUE);
    discriminator        =:= '11111010'                    [ 8 ];
    ip_id_indicator      =:= irregular(1)                  [ 1 ];
    header_crc   =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    flags_indicator      =:= irregular(1)                  [ 1 ];
    ttl_hopl_indicator   =:= irregular(1)                  [ 1 ];
    tos_tc_indicator     =:= irregular(1)                  [ 1 ];
    reorder_ratio        =:= irregular(2)                  [ 2 ];
    control_crc3         =:= control_crc3_encoding         [ 3 ];
    outer_ip_indicator : df : ip_id_behavior_innermost :
      coverage_behavior  =:=
      profile_8_flags_enc(flags_indicator.CVALUE,
      ip_version.UVALUE)                                   [ 0, 8 ];
    tos_tc =:= static_or_irreg(tos_tc_indicator.CVALUE, 8) [ 0, 8 ];
    ttl_hopl =:= static_or_irreg(ttl_hopl_indicator.CVALUE,
      ttl_hopl.ULENGTH)                                    [ 0, 8 ];
    msn                  =:= msn_lsb(8)                    [ 8 ];
    ip_id =:= ip_id_sequential_variable(ip_id_behavior_innermost.UVALUE,
      ip_id_indicator.CVALUE)                          [ 0, 8, 16 ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-0
  COMPRESSED pt_0_crc3 {
    discriminator =:= '0'                             [ 1 ];
    msn           =:= msn_lsb(4)                      [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator =:= '100'                           [ 3 ];
        
  // New format, Type 0 with strong CRC and more SN bits
  COMPRESSED pt_0_crc7 {
    discriminator =:= '100'                           [ 3 ];
        
    msn           =:= msn_lsb(6)                      [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
    msn           =:= msn_lsb(6)                      [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    ip_id         =:= inferred_sequential_ip_id       [ 0 ];
  }
        
  // UO-1-ID replacement (PT-1 only used for sequential)
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                 [ 3 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    msn           =:= msn_lsb(6)                            [ 6 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
  }
        
  // UO-1-ID replacement (PT-1 only used for sequential)
  COMPRESSED pt_1_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '101'                                 [ 3 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)       [ 3 ];
    msn           =:= msn_lsb(6)                            [ 6 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4) [ 4 ];
  }
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '110'                                 [ 3 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 6) [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    msn           =:= msn_lsb(8)                            [ 8 ];
  }
}
        
  // UOR-2-ID replacement
  COMPRESSED pt_2_seq_id {
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    discriminator =:= '110'                                 [ 3 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 6) [ 6 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)       [ 7 ];
    msn           =:= msn_lsb(8)                            [ 8 ];
  }
}
        
6.9. Feedback Formats and Options
6.9. 反馈格式和选项
6.9.1. Feedback Formats
6.9.1. 反馈格式

This section describes the feedback format for ROHCv2 profiles, using the formats described in Section 5.2.3 of [RFC4995].

本节使用[RFC4995]第5.2.3节中所述的格式描述了ROHCv2配置文件的反馈格式。

The Acknowledgment Number field of the feedback formats contains the least significant bits of the MSN (see Section 6.3.1) that corresponds to the reference header that is being acknowledged. A reference header is a header that has been successfully CRC-8 validated or CRC verified. If there is no reference header available, the feedback MUST carry an ACKNUMBER-NOT-VALID option. FEEDBACK-1

反馈格式的确认号字段包含MSN的最低有效位(见第6.3.1节),该位对应于正在确认的参考标头。参考标头是已成功通过CRC-8验证或CRC验证的标头。如果没有可用的参考标头,则反馈必须带有ACKNUMBER-NOT-VALID选项。反馈-1

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |     Acknowledgment Number     |
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |     Acknowledgment Number     |
      +---+---+---+---+---+---+---+---+
        

Acknowledgment Number: The eight least significant bits of the MSN.

确认号:MSN的八个最低有效位。

A FEEDBACK-1 is an ACK. In order to send a NACK or a STATIC-NACK, FEEDBACK-2 must be used.

反馈-1表示确认。为了发送NACK或静态NACK,必须使用反馈-2。

FEEDBACK-2

反馈-2

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |Acktype| Acknowledgment Number |
      +---+---+---+---+---+---+---+---+
      |     Acknowledgment Number     |
      +---+---+---+---+---+---+---+---+
      |              CRC              |
      +---+---+---+---+---+---+---+---+
      /       Feedback options        /
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |Acktype| Acknowledgment Number |
      +---+---+---+---+---+---+---+---+
      |     Acknowledgment Number     |
      +---+---+---+---+---+---+---+---+
      |              CRC              |
      +---+---+---+---+---+---+---+---+
      /       Feedback options        /
      +---+---+---+---+---+---+---+---+
        

Acktype:

确认类型:

         0 = ACK
        
         0 = ACK
        
         1 = NACK
        
         1 = NACK
        
         2 = STATIC-NACK
        
         2 = STATIC-NACK
        

3 is reserved (MUST NOT be used for parsability)

3已保留(不得用于可解析性)

Acknowledgment Number: The least significant bits of the MSN.

确认号:MSN的最低有效位。

CRC: 8-bit CRC computed over the entire feedback payload including any CID fields but excluding the feedback type, the 'Size' field, and the 'Code' octet, using the polynomial defined in Section 5.3.1.1 of [RFC4995]. If the CID is given with an Add-CID octet, the Add-CID octet immediately precedes the FEEDBACK-1 or FEEDBACK-2 format. For purposes of computing the CRC, the CRC field is zero.

CRC:使用[RFC4995]第5.3.1.1节中定义的多项式,在整个反馈有效载荷(包括任何CID字段,但不包括反馈类型、“大小”字段和“代码”八位字节)上计算的8位CRC。如果CID带有Add CID八位字节,则Add CID八位字节紧跟在反馈-1或反馈-2格式之前。为了计算CRC,CRC字段为零。

Feedback options: A variable number of feedback options, see Section 6.9.2. Options may appear in any order.

反馈选项:数量可变的反馈选项,见第6.9.2节。选项可以以任何顺序出现。

A FEEDBACK-2 of type NACK or STATIC-NACK is always implicitly an acknowledgment for a successfully decompressed packet, which corresponds to a packet whose LSBs match the Acknowledgment Number of the feedback element, unless the ACKNUMBER-NOT-VALID option (see Section 6.9.2.2) appears in the feedback element.

NACK或STATIC-NACK类型的FEEDBACK-2始终隐式表示对已成功解压缩数据包的确认,该数据包对应于其LSB与反馈元素的确认号匹配的数据包,除非Acknownumber-NOT-VALID选项(见第6.9.2.2节)出现在反馈元素中。

The FEEDBACK-2 format always carries a CRC and is thus more robust than the FEEDBACK-1 format. When receiving FEEDBACK-2, the compressor MUST verify the information by computing the CRC and comparing the result with the CRC carried in the feedback format. If the two are not identical, the feedback element MUST be discarded.

FEEDBACK-2格式始终携带CRC,因此比FEEDBACK-1格式更健壮。当接收反馈-2时,压缩机必须通过计算CRC并将结果与反馈格式中携带的CRC进行比较来验证信息。如果两者不相同,则必须丢弃反馈元素。

6.9.2. Feedback Options
6.9.2. 反馈选项

A feedback option has variable length and the following general format:

反馈选项具有可变长度和以下通用格式:

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |   Opt Type    |    Opt Len    |
      +---+---+---+---+---+---+---+---+
      /          Option Data          /  Opt Len (octets)
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |   Opt Type    |    Opt Len    |
      +---+---+---+---+---+---+---+---+
      /          Option Data          /  Opt Len (octets)
      +---+---+---+---+---+---+---+---+
        

Opt Type: Unsigned integer that represents the type of the feedback option. Section 6.9.2.1 through Section 6.9.2.4 describes the ROHCv2 feedback options.

Opt Type:表示反馈选项类型的无符号整数。第6.9.2.1节至第6.9.2.4节描述了ROHCv2反馈选项。

Opt Len: Unsigned integer that represents the length of the Option Data field, in octets.

Opt Len:表示选项数据字段长度的无符号整数,以八位字节为单位。

Option Data: Feedback type specific data. Present if the value of the Opt Len field is set to a non-zero value.

选项数据:反馈类型特定的数据。如果Opt Len字段的值设置为非零值,则显示。

6.9.2.1. The REJECT Option
6.9.2.1. 拒绝选项

The REJECT option informs the compressor that the decompressor does not have sufficient resources to handle the flow.

拒绝选项通知压缩机减压器没有足够的资源来处理流量。

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |  Opt Type = 2 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |  Opt Type = 2 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        

When receiving a REJECT option, the compressor MUST stop compressing the packet flow, and SHOULD refrain from attempting to increase the number of compressed packet flows for some time. The REJECT option

当接收到拒绝选项时,压缩器必须停止压缩数据包流,并且应在一段时间内避免尝试增加压缩数据包流的数量。拒绝选项

MUST NOT appear more than once in the FEEDBACK-2 format; otherwise, the compressor MUST discard the entire feedback element.

不得以反馈-2格式出现多次;否则,压缩机必须丢弃整个反馈元件。

6.9.2.2. The ACKNUMBER-NOT-VALID Option
6.9.2.2. ACKNUMBER-NOT-VALID选项无效

The ACKNUMBER-NOT-VALID option indicates that the Acknowledgment Number field of the feedback is not valid.

AcknowledgeNumber-NOT-VALID选项表示反馈的确认号字段无效。

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |  Opt Type = 3 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |  Opt Type = 3 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        

A compressor MUST NOT use the Acknowledgment Number of the feedback to find the corresponding sent header when this option is present. When this option is used, the Acknowledgment Number field of the FEEDBACK-2 format is set to zero. Consequently, a NACK or a STATIC-NACK feedback type sent with the ACKNUMBER-NOT-VALID option is equivalent to a STATIC-NACK with respect to the type of context repair requested by the decompressor.

当存在此选项时,压缩器不得使用反馈的确认号来查找相应的发送头。使用此选项时,FEEDBACK-2格式的确认号字段设置为零。因此,与ACKNUMBER-NOT-VALID选项一起发送的NACK或STATIC-NACK反馈类型在解压器请求的上下文修复类型方面等同于STATIC-NACK。

The ACKNUMBER-NOT-VALID option MUST NOT appear more than once in the FEEDBACK-2 format; otherwise, the compressor MUST discard the entire feedback element.

ACKNUMBER-NOT-VALID选项不得以FEEDBACK-2格式出现多次;否则,压缩机必须丢弃整个反馈元件。

6.9.2.3. The CONTEXT_MEMORY Option
6.9.2.3. 上下文存储选项

The CONTEXT_MEMORY option informs the compressor that the decompressor does not have sufficient memory resources to handle the context of the packet flow, as the flow is currently compressed.

CONTEXT_MEMORY选项通知压缩器,解压缩器没有足够的内存资源来处理数据包流的上下文,因为数据流当前已被压缩。

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |  Opt Type = 9 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |  Opt Type = 9 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        

When receiving a CONTEXT_MEMORY option, the compressor SHOULD take actions to compress the packet flow in a way that requires less decompressor memory resources or stop compressing the packet flow. The CONTEXT_MEMORY option MUST NOT appear more than once in the FEEDBACK-2 format; otherwise, the compressor MUST discard the entire feedback element.

当接收到CONTEXT_MEMORY选项时,压缩器应采取措施以减少解压缩器内存资源的方式压缩数据包流,或停止压缩数据包流。在反馈-2格式中,上下文记忆选项不得出现多次;否则,压缩机必须丢弃整个反馈元件。

6.9.2.4. The CLOCK_RESOLUTION Option
6.9.2.4. 时钟分辨率选项

The CLOCK_RESOLUTION option informs the compressor of the clock resolution of the decompressor. It also informs whether or not the decompressor supports timer-based compression of the RTP TS timestamp

时钟分辨率选项通知压缩器解压缩器的时钟分辨率。它还通知解压器是否支持基于计时器的RTP TS时间戳压缩

(see Section 6.6.9). The CLOCK_RESOLUTION option is applicable per channel, i.e., it applies to any context associated with a profile for which the option is relevant between a compressor and decompressor pair.

(见第6.6.9节)。CLOCK_RESOLUTION(时钟分辨率)选项适用于每个通道,即,它适用于与配置文件相关联的任何上下文,对于该配置文件,该选项在压缩器和解压缩器对之间是相关的。

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      | Opt Type = 10 |  Opt Len = 1  |
      +---+---+---+---+---+---+---+---+
      |     Clock resolution (ms)     |
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      | Opt Type = 10 |  Opt Len = 1  |
      +---+---+---+---+---+---+---+---+
      |     Clock resolution (ms)     |
      +---+---+---+---+---+---+---+---+
        

Clock resolution: Unsigned integer that represents the clock resolution of the decompressor expressed in milliseconds.

时钟分辨率:无符号整数,表示解压缩程序的时钟分辨率,以毫秒为单位。

The smallest clock resolution that can be indicated is 1 millisecond. The value zero has a special meaning: it indicates that the decompressor cannot do timer-based compression of the RTP Timestamp. The CLOCK_RESOLUTION option MUST NOT appear more than once in the FEEDBACK-2 format; otherwise, the compressor MUST discard the entire feedback element.

可指示的最小时钟分辨率为1毫秒。值0有一个特殊的含义:它表示解压缩程序无法对RTP时间戳进行基于计时器的压缩。时钟分辨率选项不得以反馈-2格式出现多次;否则,压缩机必须丢弃整个反馈元件。

6.9.2.5. Unknown Option Types
6.9.2.5. 未知选项类型

If an option type other than those defined in this document is encountered, the compressor MUST discard the entire feedback element.

如果遇到与本文档中定义的选项类型不同的选项类型,则压缩器必须丢弃整个反馈元素。

7. Security Considerations
7. 安全考虑

Impairments such as bit errors on the received compressed headers, missing packets, and reordering between packets could cause the header decompressor to reconstitute erroneous packets, i.e., packets that do not match the original packet, but still have a valid IP, UDP (or UDP-Lite), and RTP headers, and possibly also valid UDP (or UDP-Lite) checksums.

接收到的压缩报头上的位错误、丢失的数据包以及数据包之间的重新排序等损害可能会导致报头解压缩器重新生成错误的数据包,即与原始数据包不匹配的数据包,但仍然具有有效的IP、UDP(或UDP Lite)和RTP报头,并且可能还具有有效的UDP(或UDP Lite)校验和。

The header compression profiles defined herein use an internal checksum for verification of reconstructed headers. This reduces the probability that a header decompressor delivers erroneous packets to upper layers without the error being noticed. In particular, the probability that consecutive erroneous packets are not detected by the internal checksum is close to zero.

本文定义的报头压缩配置文件使用内部校验和来验证重构的报头。这降低了报头解压缩器向上层发送错误数据包而不注意错误的可能性。特别地,内部校验和未检测到连续错误分组的概率接近于零。

This small but non-zero probability remains unchanged when integrity protection is applied after compression and verified before decompression, in the case where an attacker could discard or reorder packets between the compression endpoints.

当完整性保护在压缩后应用并在解压缩前验证时,如果攻击者可以在压缩端点之间丢弃或重新排序数据包,则这种小但非零的概率保持不变。

The impairments mentioned above could be caused by a malfunctioning or malicious header compressor. Such corruption may be detected with end-to-end integrity mechanisms that will not be affected by the compression. Moreover, the internal checksum can also be useful in the case of malfunctioning compressors.

上述损害可能是由故障或恶意割台压缩机造成的。这种损坏可以通过不受压缩影响的端到端完整性机制来检测。此外,内部校验和在压缩机出现故障的情况下也很有用。

Denial-of-service attacks are possible if an intruder can introduce (for example) bogus IR or FEEDBACK packets onto the link and thereby cause compression efficiency to be reduced. However, an intruder having the ability to inject arbitrary packets at the link layer in this manner raises additional security issues that dwarf those related to the use of header compression.

如果入侵者能够(例如)在链路上引入虚假的IR或反馈数据包,从而导致压缩效率降低,则可能发生拒绝服务攻击。然而,能够以这种方式在链路层注入任意数据包的入侵者会引发额外的安全问题,使与使用报头压缩相关的安全问题相形见绌。

8. IANA Considerations
8. IANA考虑

The following ROHC profile identifiers have been assigned by the IANA for the profiles defined in this document:

IANA为本文件中定义的配置文件分配了以下ROHC配置文件标识符:

     Identifier        Profile
     ----------        -------
     0x0101            ROHCv2 RTP
     0x0102            ROHCv2 UDP
     0x0103            ROHCv2 ESP
     0x0104            ROHCv2 IP
     0x0107            ROHCv2 RTP/UDP-Lite
     0x0108            ROHCv2 UDP-Lite
        
     Identifier        Profile
     ----------        -------
     0x0101            ROHCv2 RTP
     0x0102            ROHCv2 UDP
     0x0103            ROHCv2 ESP
     0x0104            ROHCv2 IP
     0x0107            ROHCv2 RTP/UDP-Lite
     0x0108            ROHCv2 UDP-Lite
        
9. Acknowledgements
9. 致谢

The authors would like to thank Mark West, Robert Finking, Haipeng Jin, and Rohit Kapoor for serving as committed document reviewers, and also for constructive discussions during the development of this document. Thanks to Carl Knutsson for his extensive contribution to this specification, as well as to Jani Juvan and Anders Edqvist for useful comments and feedback. Thanks also to Elwyn Davies for his review as the General Area Review Team (Gen-ART) reviewer, and to Stephen Kent for his review on behalf of the IETF security directorate, during IETF last-call. Finally, thanks to the many people who have contributed to previous ROHC specifications and supported this effort.

作者要感谢Mark West、Robert Finking、Jin Haipeng和Rohit Kapoor,感谢他们作为忠实的文档审阅者,以及在本文档开发过程中进行的建设性讨论。感谢Carl Knutsson对本规范的广泛贡献,以及Jani Juvan和Anders Edqvist的有用评论和反馈。还感谢Elwyn Davies作为一般区域审查小组(Gen ART)审查员进行的审查,以及Stephen Kent在IETF最后一次通话期间代表IETF安全理事会进行的审查。最后,感谢许多为之前的ROHC规范做出贡献并支持这项工作的人。

10. References
10. 工具书类
10.1. Normative References
10.1. 规范性引用文件

[RFC0768] Postel, J., "User Datagram Protocol", STD 6, RFC 768, August 1980.

[RFC0768]Postel,J.,“用户数据报协议”,STD 6,RFC 768,1980年8月。

[RFC0791] Postel, J., "Internet Protocol", STD 5, RFC 791, September 1981.

[RFC0791]Postel,J.,“互联网协议”,STD 5,RFC 7911981年9月。

[RFC2004] Perkins, C., "Minimal Encapsulation within IP", RFC 2004, October 1996.

[RFC2004]Perkins,C.,“IP内的最小封装”,RFC 2004,1996年10月。

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

[RFC2119]Bradner,S.,“RFC中用于表示需求水平的关键词”,BCP 14,RFC 2119,1997年3月。

[RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6 (IPv6) Specification", RFC 2460, December 1998.

[RFC2460]Deering,S.和R.Hinden,“互联网协议,第6版(IPv6)规范”,RFC 2460,1998年12月。

[RFC2784] Farinacci, D., Li, T., Hanks, S., Meyer, D., and P. Traina, "Generic Routing Encapsulation (GRE)", RFC 2784, March 2000.

[RFC2784]Farinaci,D.,Li,T.,Hanks,S.,Meyer,D.,和P.Traina,“通用路由封装(GRE)”,RFC 27842000年3月。

[RFC2890] Dommety, G., "Key and Sequence Number Extensions to GRE", RFC 2890, September 2000.

[RFC2890]Dommety,G.“GRE的密钥和序列号扩展”,RFC 28902000年9月。

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

[RFC3550]Schulzrinne,H.,Casner,S.,Frederick,R.,和V.Jacobson,“RTP:实时应用的传输协议”,STD 64,RFC 35502003年7月。

[RFC3828] Larzon, L-A., Degermark, M., Pink, S., Jonsson, L-E., and G. Fairhurst, "The Lightweight User Datagram Protocol (UDP-Lite)", RFC 3828, July 2004.

[RFC3828]Larzon,L-A.,Degermark,M.,Pink,S.,Jonsson,L-E.,和G.Fairhurst,“轻量级用户数据报协议(UDP Lite)”,RFC 38282004年7月。

[RFC4019] Pelletier, G., "RObust Header Compression (ROHC): Profiles for User Datagram Protocol (UDP) Lite", RFC 4019, April 2005.

[RFC4019]Pelletier,G.,“鲁棒头压缩(ROHC):用户数据报协议(UDP)Lite的配置文件”,RFC40119,2005年4月。

[RFC4302] Kent, S., "IP Authentication Header", RFC 4302, December 2005.

[RFC4302]Kent,S.,“IP认证头”,RFC43022005年12月。

[RFC4303] Kent, S., "IP Encapsulating Security Payload (ESP)", RFC 4303, December 2005.

[RFC4303]Kent,S.,“IP封装安全有效载荷(ESP)”,RFC 4303,2005年12月。

[RFC4995] Jonsson, L-E., Pelletier, G., and K. Sandlund, "The RObust Header Compression (ROHC) Framework", RFC 4995, July 2007.

[RFC4995]Jonsson,L-E.,Pelletier,G.和K.Sandlund,“鲁棒头压缩(ROHC)框架”,RFC 49952007年7月。

[RFC4997] Finking, R. and G. Pelletier, "Formal Notation for RObust Header Compression (ROHC-FN)", RFC 4997, July 2007.

[RFC4997]Finking,R.和G.Pelletier,“鲁棒头压缩的形式表示法(ROHC-FN)”,RFC 4997,2007年7月。

10.2. Informative References
10.2. 资料性引用

[RFC2675] Borman, D., Deering, S., and R. Hinden, "IPv6 Jumbograms", RFC 2675, August 1999.

[RFC2675]Borman,D.,Deering,S.,和R.Hinden,“IPv6巨型程序”,RFC 26751999年8月。

[RFC3095] Bormann, C., Burmeister, C., Degermark, M., Fukushima, H., Hannu, H., Jonsson, L-E., 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.

[RFC3095]Bormann,C.,Burmeister,C.,Degermark,M.,Fukushima,H.,Hannu,H.,Jonsson,L-E.,Hakenberg,R.,Koren,T.,Le,K.,Liu,Z.,Martenson,A.,Miyazaki,A.,Svanbro,K.,Wiebke,T.,Yoshimura,T.,和H.Zheng,“鲁棒头压缩(ROHC):框架和四个配置文件:RTP,UDP,ESP,和未压缩”,RFC 3095,2001年7月。

[RFC3843] Jonsson, L-E. and G. Pelletier, "RObust Header Compression (ROHC): A Compression Profile for IP", RFC 3843, June 2004.

[RFC3843]Jonsson,L-E.和G.Pelletier,“鲁棒头压缩(ROHC):IP的压缩配置文件”,RFC 38432004年6月。

[RFC4224] Pelletier, G., Jonsson, L-E., and K. Sandlund, "RObust Header Compression (ROHC): ROHC over Channels That Can Reorder Packets", RFC 4224, January 2006.

[RFC4224]Pelletier,G.,Jonsson,L-E.,和K.Sandlund,“鲁棒报头压缩(ROHC):可以重新排序数据包的信道上的ROHC”,RFC 42242006年1月。

Appendix A. Detailed Classification of Header Fields
附录A.标题字段的详细分类

Header compression is possible due to the fact that most header fields do not vary randomly from packet to packet. Many of the fields exhibit static behavior or change in a more or less predictable way. When designing a header compression scheme, it is of fundamental importance to understand the behavior of the fields in detail.

由于大多数报头字段不会随数据包随机变化,因此可以进行报头压缩。许多字段以或多或少可预测的方式显示静态行为或更改。在设计报头压缩方案时,详细了解字段的行为非常重要。

In this appendix, all fields in the headers compressible by these profiles are classified and analyzed. The analysis is based on behavior for the types of traffic that are expected to be the most frequently compressed (e.g., RTP field behavior is based on voice and/or video traffic behavior).

在本附录中,对这些剖面可压缩的标题中的所有字段进行了分类和分析。分析基于预期最频繁压缩的流量类型的行为(例如,RTP字段行为基于语音和/或视频流量行为)。

Fields are classified as belonging to one of the following classes:

字段被分类为属于以下类别之一:

INFERRED - These fields contain values that can be inferred from other values, for example the size of the frame carrying the packet, and thus do not have to be included in compressed packets.

推断-这些字段包含可以从其他值推断的值,例如承载数据包的帧的大小,因此不必包含在压缩数据包中。

STATIC - These fields are expected to be constant throughout the lifetime of the flow; in general, it is sufficient to design a compressed format so that these fields are only updated by IR packets.

静态-预计这些场在流量的整个生命周期内保持不变;一般来说,设计一种压缩格式,使这些字段仅由IR数据包更新就足够了。

STATIC-DEF - These fields are expected to be constant throughout the lifetime of the flow and their values can be used to define a flow. They are only sent in IR packets.

STATIC-DEF-这些字段在流的整个生命周期内保持不变,其值可用于定义流。它们仅以红外数据包的形式发送。

STATIC-KNOWN - These fields are expected to have well-known values and therefore do not need to be communicated at all.

静态-已知-这些字段应具有已知值,因此根本不需要通信。

SEMISTATIC - These fields are unchanged most of the time. However, occasionally the value changes but will revert to its original value. For ROHCv2, the values of such fields do not need to be possible to change with the smallest compressed packet formats, but should be possible to change via slightly larger compressed packets.

半静态-这些字段大部分时间不变。但是,该值偶尔会更改,但会恢复为其原始值。对于ROHCv2,这些字段的值不需要能够通过最小的压缩数据包格式进行更改,但应该能够通过稍大的压缩数据包进行更改。

RARELY CHANGING (RACH) - These are fields that change their values occasionally and then keep their new values. For ROHCv2, the values of such fields do not need to be possible to change with the smallest compressed packet formats, but should be possible to change via slightly larger compressed packets.

很少更改(RACH)-这些字段偶尔更改其值,然后保留其新值。对于ROHCv2,这些字段的值不需要能够通过最小的压缩数据包格式进行更改,但应该能够通过稍大的压缩数据包进行更改。

IRREGULAR - These are the fields for which no useful change pattern can be identified and should be transmitted uncompressed in all compressed packets.

不规则-这些字段无法识别有用的更改模式,应在所有压缩数据包中以未压缩方式传输。

PATTERN - These are fields that change between each packet, but change in a predictable pattern.

模式-这些字段在每个数据包之间更改,但以可预测的模式更改。

A.1. IPv4 Header Fields
A.1. IPv4标头字段
   +------------------------+----------------+
   | Field                  | Class          |
   +------------------------+----------------+
   | Version                | STATIC-KNOWN   |
   | Header Length          | STATIC-KNOWN   |
   | Type Of Service        | RACH           |
   | Packet Length          | INFERRED       |
   | Identification         |                |
   |             Sequential | PATTERN        |
   |             Seq. swap  | PATTERN        |
   |             Random     | IRREGULAR      |
   |             Zero       | STATIC         |
   | Reserved flag          | STATIC-KNOWN   |
   | Don't Fragment flag    | RACH           |
   | More Fragments flag    | STATIC-KNOWN   |
   | Fragment Offset        | STATIC-KNOWN   |
   | Time To Live           | RACH           |
   | Protocol               | STATIC-DEF     |
   | Header Checksum        | INFERRED       |
   | Source Address         | STATIC-DEF     |
   | Destination Address    | STATIC-DEF     |
   +------------------------+----------------+
        
   +------------------------+----------------+
   | Field                  | Class          |
   +------------------------+----------------+
   | Version                | STATIC-KNOWN   |
   | Header Length          | STATIC-KNOWN   |
   | Type Of Service        | RACH           |
   | Packet Length          | INFERRED       |
   | Identification         |                |
   |             Sequential | PATTERN        |
   |             Seq. swap  | PATTERN        |
   |             Random     | IRREGULAR      |
   |             Zero       | STATIC         |
   | Reserved flag          | STATIC-KNOWN   |
   | Don't Fragment flag    | RACH           |
   | More Fragments flag    | STATIC-KNOWN   |
   | Fragment Offset        | STATIC-KNOWN   |
   | Time To Live           | RACH           |
   | Protocol               | STATIC-DEF     |
   | Header Checksum        | INFERRED       |
   | Source Address         | STATIC-DEF     |
   | Destination Address    | STATIC-DEF     |
   +------------------------+----------------+
        

Version

版本

The version field states which IP version is used and is set to the value four.

版本字段说明使用哪个IP版本,并将其设置为值4。

Header Length

包头长度

As long as no options are present in the IP header, the header length is constant with the value five. If there are options, the field could be RACH or STATIC-DEF, but only option-less headers are compressed by ROHCv2 profiles. The field is therefore classified as STATIC-KNOWN.

只要IP报头中不存在任何选项,报头长度就保持不变,值为5。如果有选项,该字段可以是RACH或STATIC-DEF,但ROHCv2配置文件仅压缩无选项标题。因此,该字段被归类为静态-已知字段。

Type Of Service

服务类型

For the type of flows compressed by the ROHCv2 profiles, the DSCP (Differentiated Services Code Point) and ECN (Explicit Congestion Notification) fields are expected to change relatively seldom.

对于ROHCv2配置文件压缩的流类型,预计DSCP(区分服务代码点)和ECN(显式拥塞通知)字段的更改相对较少。

Packet Length

数据包长度

Information about packet length is expected to be provided by the link layer. The field is therefore classified as INFERRED.

有关数据包长度的信息预计将由链路层提供。因此,该字段被归类为推断字段。

IPv4 Identification

IPv4标识

The Identification field (IP-ID) is used to identify what fragments constitute a datagram when reassembling fragmented datagrams. The IPv4 specification does not specify exactly how this field is to be assigned values, only that each packet should get an IP-ID that is unique for the source-destination pair and protocol for the time the datagram (or any of its fragments) could be alive in the network. This means that assignment of IP-ID values can be done in various ways, but the expected behaviors have been separated into four classes.

标识字段(IP-ID)用于在重新组装碎片数据报时标识构成数据报的碎片。IPv4规范没有明确指定如何分配此字段的值,只是每个数据包应获得一个IP-ID,该IP-ID在数据报(或其任何片段)可能在网络中处于活动状态时对于源-目标对和协议是唯一的。这意味着IP-ID值的分配可以通过各种方式完成,但是预期的行为被分为四类。

Sequential

顺序的

In this behavior, the IP-ID is expected to increment by one for most packets, but may increment by a value larger than one, depending on the behavior of the transmitting IPv4 stack.

在此行为中,对于大多数数据包,IP-ID预计会增加1,但可能会增加大于1的值,具体取决于传输IPv4堆栈的行为。

Sequential Swapped

顺序交换

When using this behavior, the IP-ID behaves as in the Sequential behavior, but the two bytes of IP-ID are byte-swapped. Therefore, the IP-ID can be swapped before compression to make it behave exactly as the Sequential behavior.

使用此行为时,IP-ID的行为与顺序行为相同,但IP-ID的两个字节是字节交换的。因此,可以在压缩之前交换IP-ID,使其与顺序行为完全相同。

Random

随机的

Some IP stacks assign IP-ID values using a pseudo-random number generator. There is thus no correlation between the ID values of subsequent datagrams, and therefore there is no way to predict the IP-ID value for the next datagram. For header compression purposes, this means that the IP-ID field needs to be sent uncompressed with each datagram, resulting in two extra octets of header.

某些IP堆栈使用伪随机数生成器分配IP-ID值。因此,后续数据报的ID值之间没有相关性,因此无法预测下一个数据报的IP-ID值。出于报头压缩的目的,这意味着IP-ID字段需要与每个数据报一起未压缩发送,从而导致报头的两个额外八位字节。

Zero

This behavior, although not a legal implementation of IPv4, is sometimes seen in existing IPv4 stacks. When this behavior is used, all IP packets have the IP-ID value set to zero.

这种行为虽然不是IPv4的合法实现,但有时会出现在现有IPv4协议栈中。使用此行为时,所有IP数据包的IP-ID值都设置为零。

Flags

旗帜

The Reserved flag must be set to zero and is therefore classified as STATIC-KNOWN. The Don't Fragment (DF) flag changes rarely and is therefore classified as RACH. Finally, the More Fragments (MF) flag is expected to be zero because IP fragments will not be compressed by ROHC and is therefore classified as STATIC-KNOWN.

保留标志必须设置为零,因此分类为静态-已知。Don't Fragment(DF)标志很少更改,因此被归类为RACH。最后,More Fragments(MF)标志预计为零,因为IP片段不会被ROHC压缩,因此被归类为静态已知。

Fragment Offset

碎片偏移量

Under the assumption that no fragmentation occurs, the fragment offset is always zero and is therefore classified as STATIC-KNOWN.

在假设不发生碎片的情况下,碎片偏移量始终为零,因此分类为静态-已知。

Time To Live

活下去的时间

The Time To Live field is expected to be constant during the lifetime of a flow or to alternate between a limited number of values due to route changes.

预计生存时间字段在流的生命周期内保持不变,或因路线变化而在有限数量的值之间交替。

Protocol

协议

This field will have the same value in all packets of a flow and is therefore classified as STATIC-DEF.

此字段在流的所有数据包中具有相同的值,因此被分类为STATIC-DEF。

Header Checksum

报头校验和

The header checksum protects individual hops from processing a corrupted header. When almost all IP header information is compressed away, there is no point in having this additional checksum; instead, it can be regenerated at the decompressor side. The field is therefore classified as INFERRED.

标头校验和保护单个跃点不处理损坏的标头。当几乎所有的IP报头信息都被压缩掉时,没有必要再增加这个校验和;相反,它可以在减压器侧重新生成。因此,该字段被归类为推断字段。

Source and Destination addresses

源地址和目标地址

These fields are part of the definition of a flow and must thus be constant for all packets in the flow.

这些字段是流定义的一部分,因此对于流中的所有数据包都必须是常量。

A.2. IPv6 Header Fields
A.2. IPv6头字段
   +----------------------+----------------+
   | Field                | Class          |
   +----------------------+----------------+
   | Version              | STATIC-KNOWN   |
   | Traffic Class        | RACH           |
   | Flow Label           | STATIC-DEF     |
   | Payload Length       | INFERRED       |
   | Next Header          | STATIC-DEF     |
   | Hop Limit            | RACH           |
   | Source Address       | STATIC-DEF     |
   | Destination Address  | STATIC-DEF     |
   +----------------------+----------------+
        
   +----------------------+----------------+
   | Field                | Class          |
   +----------------------+----------------+
   | Version              | STATIC-KNOWN   |
   | Traffic Class        | RACH           |
   | Flow Label           | STATIC-DEF     |
   | Payload Length       | INFERRED       |
   | Next Header          | STATIC-DEF     |
   | Hop Limit            | RACH           |
   | Source Address       | STATIC-DEF     |
   | Destination Address  | STATIC-DEF     |
   +----------------------+----------------+
        

Version

版本

The version field states which IP version is used and is set to the value six.

版本字段说明使用哪个IP版本,并将其设置为值6。

Traffic Class

交通等级

For the type of flows compressed by the ROHCv2 profiles, the DSCP and ECN fields are expected to change relatively seldom.

对于ROHCv2配置文件压缩的流量类型,预计DSCP和ECN字段变化相对较少。

Flow Label

流标签

This field may be used to identify packets belonging to a specific flow. If it is not used, the value should be set to zero. Otherwise, all packets belonging to the same flow must have the same value in this field. The field is therefore classified as STATIC-DEF.

This field may be used to identify packets belonging to a specific flow. If it is not used, the value should be set to zero. Otherwise, all packets belonging to the same flow must have the same value in this field. The field is therefore classified as STATIC-DEF.translate error, please retry

Payload Length

净荷长度

Information about packet length (and, consequently, payload length) is expected to be provided by the link layer. The field is therefore classified as INFERRED.

关于分组长度(以及因此有效负载长度)的信息预期由链路层提供。因此,该字段被归类为推断字段。

Next Header

下一包头

This field will have the same value in all packets of a flow and is therefore classified as STATIC-DEF.

此字段在流的所有数据包中具有相同的值,因此被分类为STATIC-DEF。

Hop Limit

跳数限制

The Hop Limit field is expected to be constant during the lifetime of a flow or to alternate between a limited number of values due to route changes.

在流的生命周期内,跃点限制字段应保持不变,或因路由更改而在有限数量的值之间交替。

Source and Destination addresses

源地址和目标地址

These fields are part of the definition of a flow and must thus be constant for all packets in the flow. The fields are therefore classified as STATIC-DEF.

这些字段是流定义的一部分,因此对于流中的所有数据包都必须是常量。因此,这些字段被分类为STATIC-DEF。

A.3. UDP Header Fields
A.3. UDP头字段
   +------------------+-------------+
   | Field            | Class       |
   +------------------+-------------+
   | Source Port      | STATIC-DEF  |
   | Destination Port | STATIC-DEF  |
   | Length           | INFERRED    |
   | Checksum         |             |
   |         Disabled | STATIC      |
   |         Enabled  | IRREGULAR   |
   +------------------+-------------+
        
   +------------------+-------------+
   | Field            | Class       |
   +------------------+-------------+
   | Source Port      | STATIC-DEF  |
   | Destination Port | STATIC-DEF  |
   | Length           | INFERRED    |
   | Checksum         |             |
   |         Disabled | STATIC      |
   |         Enabled  | IRREGULAR   |
   +------------------+-------------+
        

Source and Destination ports

源端口和目标端口

These fields are part of the definition of a flow and must thus be constant for all packets in the flow.

这些字段是流定义的一部分,因此对于流中的所有数据包都必须是常量。

Length

Information about packet length is expected to be provided by the link layer. The field is therefore classified as INFERRED.

有关数据包长度的信息预计将由链路层提供。因此,该字段被归类为推断字段。

Checksum

校验和

The checksum can be optional. If disabled, its value is constantly zero and can be compressed away. If enabled, its value depends on the payload, which for compression purposes is equivalent to it changing randomly with every packet.

校验和可以是可选的。如果禁用,其值将始终为零,并且可以被压缩。如果启用,其值取决于有效负载,出于压缩目的,有效负载相当于它随每个数据包随机变化。

A.4. UDP-Lite Header Fields
A.4. UDP Lite头字段
   +--------------------+-------------+
   | Field              | Class       |
   +--------------------+-------------+
   | Source Port        | STATIC-DEF  |
   | Destination Port   | STATIC-DEF  |
   | Checksum Coverage  |             |
   |        Zero        | STATIC-DEF  |
   |        Constant    | INFERRED    |
   |        Variable    | IRREGULAR   |
   | Checksum           | IRREGULAR   |
   +--------------------+-------------+
        
   +--------------------+-------------+
   | Field              | Class       |
   +--------------------+-------------+
   | Source Port        | STATIC-DEF  |
   | Destination Port   | STATIC-DEF  |
   | Checksum Coverage  |             |
   |        Zero        | STATIC-DEF  |
   |        Constant    | INFERRED    |
   |        Variable    | IRREGULAR   |
   | Checksum           | IRREGULAR   |
   +--------------------+-------------+
        

Source and Destination Port

源和目标端口

These fields are part of the definition of a flow and must thus be constant for all packets in the flow.

这些字段是流定义的一部分,因此对于流中的所有数据包都必须是常量。

Checksum Coverage

校验和覆盖率

The Checksum Coverage field may behave in different ways: it may have a value of zero, it may be equal to the datagram length, or it may have any value between eight octets and the length of the datagram. From a compression perspective, this field is expected to either be entirely predictable (for the cases where it follows the same behavior as the UDP Length field or where it takes on a constant value) or to change randomly for each packet (making the value unpredictable from a header-compression perspective). For all cases, the behavior itself is not expected to change for this field during the lifetime of a packet flow, or to change relatively seldom.

校验和覆盖率字段可能以不同的方式运行:它可能有一个值为零,它可能等于数据报长度,或者它可能有八个八位组和数据报长度之间的任何值。从压缩的角度来看,该字段应该是完全可预测的(对于它遵循与UDP长度字段相同的行为或具有常量值的情况),或者对于每个数据包随机更改(从报头压缩的角度来看,该值是不可预测的)。对于所有情况,在数据包流的生命周期内,该字段的行为本身预计不会改变,或者变化相对较少。

Checksum

校验和

The information used for the calculation of the UDP-Lite checksum is governed by the value of the checksum coverage and minimally includes the UDP-Lite header. The checksum is a changing field that must always be sent as-is.

用于计算UDP Lite校验和的信息由校验和覆盖率的值控制,并且至少包括UDP Lite头。校验和是一个不断变化的字段,必须始终按原样发送。

A.5. RTP Header Fields
A.5. RTP头字段
   +----------------+----------------+
   | Field          | Class          |
   +----------------+----------------+
   | Version        | STATIC-KNOWN   |
   | Padding        | RACH           |
   | Extension      | RACH           |
   | CSRC Counter   | RACH           |
   | Marker         | SEMISTATIC     |
   | Payload Type   | RACH           |
   | Sequence Number| PATTERN        |
   | Timestamp      | PATTERN        |
   | SSRC           | STATIC-DEF     |
   | CSRC           | RACH           |
   +----------------+----------------+
        
   +----------------+----------------+
   | Field          | Class          |
   +----------------+----------------+
   | Version        | STATIC-KNOWN   |
   | Padding        | RACH           |
   | Extension      | RACH           |
   | CSRC Counter   | RACH           |
   | Marker         | SEMISTATIC     |
   | Payload Type   | RACH           |
   | Sequence Number| PATTERN        |
   | Timestamp      | PATTERN        |
   | SSRC           | STATIC-DEF     |
   | CSRC           | RACH           |
   +----------------+----------------+
        

Version

版本

This field is expected to have the value two and the field is therefore classified as STATIC-KNOWN.

该字段的值应为2,因此该字段被分类为STATIC-KNOWN。

Padding

衬料

The use of this field is application-dependent, but when payload padding is used, it is likely to be present in most or all packets. The field is classified as RACH to allow for the case where the value of this field changes.

此字段的使用取决于应用程序,但当使用有效负载填充时,它可能出现在大多数或所有数据包中。该字段被分类为RACH,以考虑该字段值发生变化的情况。

Extension

扩大

If RTP extensions are used by the application, these extensions are often present in all packets, although the use of extensions is infrequent. To allow efficient compression of a flow using extensions in only a few packets, this field is classified as RACH.

如果应用程序使用RTP扩展,这些扩展通常出现在所有数据包中,尽管很少使用扩展。为了允许仅在少数数据包中使用扩展有效压缩流,此字段被分类为RACH。

CSRC Count

中国证监会计数

This field indicates the number of CSRC items present in the CSRC list. This number is expected to be mostly constant on a packet-to-packet basis and when it changes, change by small amounts. As long as no RTP mixer is used, the value of this field will be zero.

此字段表示中国证监会列表中存在的中国证监会项目的数量。这个数字在包到包的基础上基本上是恒定的,当它改变时,会有少量的改变。只要不使用RTP混频器,此字段的值将为零。

Marker

标记

For audio, the marker bit should be set only in the first packet of a talkspurt, while for video, it should be set in the last packet of every picture. This means that in both cases the RTP marker is classified as SEMISTATIC.

对于音频,标记位应仅在TalkSport的第一个数据包中设置,而对于视频,标记位应在每个图片的最后一个数据包中设置。这意味着在这两种情况下,RTP标记都被归类为半静态标记。

Payload Type

有效载荷类型

Applications could adapt to congestion by changing payload type and/or frame sizes, but that is not expected to happen frequently, so this field is classified as RACH.

应用程序可以通过改变有效负载类型和/或帧大小来适应拥塞,但这种情况预计不会经常发生,因此该字段被归类为RACH。

RTP Sequence Number

RTP序列号

The RTP Sequence Number will be incremented by one for each packet sent.

对于发送的每个数据包,RTP序列号将增加1。

Timestamp

时间戳

In the audio case:

在音频情况下:

As long as there are no pauses in the audio stream, the RTP Timestamp will be incremented by a constant value, which corresponds to the number of samples in the speech frame. It will thus mostly follow the RTP Sequence Number. When there has been a silent period and a new talkspurt begins, the timestamp will jump in proportion to the length of the silent period. However, the increment will probably be within a relatively limited range.

只要音频流中没有暂停,RTP时间戳就会增加一个常量值,该常量值对应于语音帧中的样本数。因此,它将主要遵循RTP序列号。当有一个静默期并且新的talkspurt开始时,时间戳将与静默期的长度成比例跳跃。然而,增量可能在相对有限的范围内。

In the video case:

在视频案例中:

Between two consecutive packets, the timestamp will either be unchanged or increase by a multiple of a fixed value corresponding to the picture clock frequency. The timestamp can also decrease by a multiple of the fixed value for certain coding schemes. The change in timestamp value, expressed as a multiple of the picture clock frequency, is in most cases within a limited range.

在两个连续分组之间,时间戳将保持不变或增加与图片时钟频率相对应的固定值的倍数。对于某些编码方案,时间戳还可以减少固定值的倍数。时间戳值的变化(表示为图片时钟频率的倍数)在大多数情况下在有限范围内。

SSRC

SSRC

This field is part of the definition of a flow and must thus be constant for all packets in the flow. The field is therefore classified as STATIC-DEF.

此字段是流定义的一部分,因此对于流中的所有数据包必须是常量。因此,该字段被分类为STATIC-DEF。

Contributing Sources (CSRC)

贡献来源(中国证监会)

The participants in a session, who are identified by the CSRC fields, are usually expected to be unchanged on a packet-to-packet basis, but will infrequently change by a few additions and/or removals.

由中国证监会字段确定的会议参与者通常在分组对分组的基础上保持不变,但很少通过添加和/或删除进行更改。

A.6. ESP Header Fields
A.6. ESP标题字段
   +------------------+-------------+
   | Field            | Class       |
   +------------------+-------------+
   | SPI              | STATIC-DEF  |
   | Sequence Number  | PATTERN     |
   +------------------+-------------+
        
   +------------------+-------------+
   | Field            | Class       |
   +------------------+-------------+
   | SPI              | STATIC-DEF  |
   | Sequence Number  | PATTERN     |
   +------------------+-------------+
        

SPI

SPI

This field is used to identify a distinct flow between two IPsec peers and it changes rarely; therefore, it is classified as STATIC-DEF.

此字段用于标识两个IPsec对等方之间的不同流,并且很少更改;因此,它被归类为静态DEF。

ESP Sequence Number

ESP序列号

The ESP Sequence Number will be incremented by one for each packet sent.

对于发送的每个数据包,ESP序列号将增加1。

A.7. IPv6 Extension Header Fields
A.7. IPv6扩展头字段
   +-----------------------+---------------+
   | Field                 | Class         |
   +-----------------------+---------------+
   | Next Header           | STATIC-DEF    |
   | Ext Hdr Len           |               |
   |      Routing          | STATIC-DEF    |
   |      Hop-by-hop       | STATIC        |
   |      Destination      | STATIC        |
   | Options               |               |
   |      Routing          | STATIC-DEF    |
   |      Hop-by-hop       | RACH          |
   |      Destination      | RACH          |
   +-----------------------+---------------+
        
   +-----------------------+---------------+
   | Field                 | Class         |
   +-----------------------+---------------+
   | Next Header           | STATIC-DEF    |
   | Ext Hdr Len           |               |
   |      Routing          | STATIC-DEF    |
   |      Hop-by-hop       | STATIC        |
   |      Destination      | STATIC        |
   | Options               |               |
   |      Routing          | STATIC-DEF    |
   |      Hop-by-hop       | RACH          |
   |      Destination      | RACH          |
   +-----------------------+---------------+
        

Next Header

下一包头

This field will have the same value in all packets of a flow and is therefore classified as STATIC-DEF.

此字段在流的所有数据包中具有相同的值,因此被分类为STATIC-DEF。

Ext Hdr Len

外部Hdr透镜

For the Routing header, it is expected that the length will remain constant for the duration of the flow, and that a change in the length should be classified as a new flow by the ROHC compressor. For Hop-by-hop and Destination options headers, the length is expected to remain static, but can be updated by an IR packet.

对于路由头,预计在流量持续期间长度将保持不变,且长度的变化应被ROHC压缩机归类为新流量。对于逐跳和目的地选项标头,长度应保持静态,但可通过IR数据包进行更新。

Options

选择权

For the Routing header, it is expected that the option content will remain constant for the duration of the flow, and that a change in the routing information should be classified as a new flow by the ROHC compressor. For Hop-by-hop and Destination options headers, the options are expected to remain static, but can be updated by an IR packet.

对于路由标头,预计选项内容将在流的持续时间内保持不变,并且路由信息的变化应由ROHC压缩器归类为新流。对于逐跳和目的地选项标头,选项应保持静态,但可通过IR数据包进行更新。

A.8. GRE Header Fields
A.8. GRE头字段
   +--------------------+---------------+
   | Field              | Class         |
   +--------------------+---------------+
   | C flag             | STATIC        |
   | K flag             | STATIC        |
   | S flag             | STATIC        |
   | R flag             | STATIC-KNOWN  |
   | Reserved0, Version | STATIC-KNOWN  |
   | Protocol           | STATIC-DEF    |
   | Checksum           | IRREGULAR     |
   | Reserved           | STATIC-KNOWN  |
   | Sequence Number    | PATTERN       |
   | Key                | STATIC-DEF    |
   +--------------------+---------------+
        
   +--------------------+---------------+
   | Field              | Class         |
   +--------------------+---------------+
   | C flag             | STATIC        |
   | K flag             | STATIC        |
   | S flag             | STATIC        |
   | R flag             | STATIC-KNOWN  |
   | Reserved0, Version | STATIC-KNOWN  |
   | Protocol           | STATIC-DEF    |
   | Checksum           | IRREGULAR     |
   | Reserved           | STATIC-KNOWN  |
   | Sequence Number    | PATTERN       |
   | Key                | STATIC-DEF    |
   +--------------------+---------------+
        

Flags

旗帜

The four flag bits are not expected to change for the duration of the flow, and the R flag is expected to always be set to zero.

在流的持续时间内,四个标志位预计不会改变,并且R标志预计始终设置为零。

Reserved0, Version

保留版本

Both of these fields are expected to be set to zero for the duration of any flow.

在任何流的持续时间内,这两个字段都应设置为零。

Protocol

协议

This field will have the same value in all packets of a flow and is therefore classified as STATIC-DEF.

此字段在流的所有数据包中具有相同的值,因此被分类为STATIC-DEF。

Checksum

校验和

When the checksum field is present, it is expected to behave unpredictably.

当校验和字段存在时,预期其行为不可预测。

Reserved

含蓄的

When present, this field is expected to be set to zero.

出现时,该字段应设置为零。

Sequence Number

序列号

When present, the Sequence Number increases by one for each packet.

当存在时,序列号为每个分组增加一个。

Key

钥匙

When present, the Key field is used to define the flow and does not change.

存在时,键字段用于定义流,不会更改。

A.9. MINE Header Fields
A.9. 矿井掘进机字段
   +---------------------+----------------+
   | Field               | Class          |
   +---------------------+----------------+
   | Protocol            | STATIC-DEF     |
   | S bit               | STATIC-DEF     |
   | Reserved            | STATIC-KNOWN   |
   | Checksum            | INFERRED       |
   | Source Address      | STATIC-DEF     |
   | Destination Address | STATIC-DEF     |
   +---------------------+----------------+
        
   +---------------------+----------------+
   | Field               | Class          |
   +---------------------+----------------+
   | Protocol            | STATIC-DEF     |
   | S bit               | STATIC-DEF     |
   | Reserved            | STATIC-KNOWN   |
   | Checksum            | INFERRED       |
   | Source Address      | STATIC-DEF     |
   | Destination Address | STATIC-DEF     |
   +---------------------+----------------+
        

Protocol

协议

This field will have the same value in all packets of a flow and is therefore classified as STATIC-DEF.

此字段在流的所有数据包中具有相同的值,因此被分类为STATIC-DEF。

S bit

S位

The S bit is not expected to change during a flow.

在流期间,S位预计不会改变。

Reserved

含蓄的

The reserved field is expected to be set to zero.

保留字段应设置为零。

Checksum

校验和

The header checksum protects individual routing hops from processing a corrupted header. Since all fields of this header are compressed away, there is no need to include this checksum in compressed packets and it can be regenerated at the decompressor side.

报头校验和保护单个路由跃点不处理损坏的报头。由于该报头的所有字段都被压缩掉了,因此不需要在压缩包中包含该校验和,它可以在解压缩器端重新生成。

Source and Destination Addresses

源地址和目标地址

These fields can be used to define the flow and are not expected to change.

这些字段可用于定义流,预计不会更改。

A.10. AH Header Fields
A.10. AH头字段
   +---------------------+----------------+
   | Field               | Class          |
   +---------------------+----------------+
   | Next Header         | STATIC-DEF     |
   | Payload Length      | STATIC         |
   | Reserved            | STATIC-KNOWN   |
   | SPI                 | STATIC-DEF     |
   | Sequence Number     | PATTERN        |
   | ICV                 | IRREGULAR      |
   +---------------------+----------------+
        
   +---------------------+----------------+
   | Field               | Class          |
   +---------------------+----------------+
   | Next Header         | STATIC-DEF     |
   | Payload Length      | STATIC         |
   | Reserved            | STATIC-KNOWN   |
   | SPI                 | STATIC-DEF     |
   | Sequence Number     | PATTERN        |
   | ICV                 | IRREGULAR      |
   +---------------------+----------------+
        

Next Header

下一包头

This field will have the same value in all packets of a flow and is therefore classified as STATIC-DEF.

此字段在流的所有数据包中具有相同的值,因此被分类为STATIC-DEF。

Payload Length

净荷长度

It is expected that the length of the header is constant for the duration of the flow.

预计在流量持续期间,收割台的长度是恒定的。

Reserved

含蓄的

The value of this field will be set to zero.

此字段的值将设置为零。

SPI

SPI

This field is used to identify a specific flow and only changes when the sequence number wraps around, and is therefore classified as STATIC-DEF.

此字段用于识别特定流,仅当序列号环绕时才会更改,因此分类为STATIC-DEF。

Sequence Number

序列号

The Sequence Number will be incremented by one for each packet sent.

对于发送的每个数据包,序列号将增加1。

ICV

ICV

The ICV is expected to behave unpredictably and is therefore classified as IRREGULAR.

预计ICV的行为不可预测,因此被归类为不规则。

Appendix B. Compressor Implementation Guidelines
附录B.压缩机实施指南

This section describes some guiding principles for implementing a ROHCv2 compressor with focus on how to efficiently select appropriate packet formats. The text in this appendix should be considered guidelines; it does not define any normative requirement on how ROHCv2 profiles are implemented.

本节介绍了实现ROHCv2压缩器的一些指导原则,重点介绍了如何有效地选择适当的数据包格式。本附录中的文本应视为指南;它没有定义关于如何实施ROHCv2配置文件的任何规范性要求。

B.1. Reference Management
B.1. 参考资料管理

The compressor usually maintains a sliding window of reference headers, which contains as many references as needed for the optimistic approach. Each reference contains a description of which changes occurred in the flow between two consecutive headers in the flow, and a new reference is inserted into the window each time a packet is compressed by this context. A reference may for example be implemented as a stored copy of the uncompressed header being represented. When the compressor is confident that a specific reference is no longer used by the decompressor (for example by using the optimistic approach or feedback received), the reference is removed from the sliding window.

压缩器通常维护引用头的滑动窗口,其中包含乐观方法所需的尽可能多的引用。每个引用都包含流中两个连续头之间的流中发生了哪些更改的描述,并且每次数据包被该上下文压缩时,都会在窗口中插入一个新的引用。例如,可以将引用实现为所表示的未压缩报头的存储副本。当压缩机确信减压器不再使用特定参考时(例如,通过使用乐观方法或接收到的反馈),参考将从滑动窗口中移除。

B.2. Window-based LSB Encoding (W-LSB)
B.2. 基于窗口的LSB编码(W-LSB)

Section 5.1.1 describes how the optimistic approach impacts the packet format selection for the compressor. Exactly how the compressor selects a packet format is up to the implementation to decide, but the following is an example of how this process can be performed for lsb-encoded fields through the use of Window-based LSB encoding (W-LSB).

第5.1.1节描述了乐观方法如何影响压缩器的数据包格式选择。压缩器选择数据包格式的具体方式由实现决定,但以下是如何通过使用基于窗口的lsb编码(W-lsb)对lsb编码字段执行此过程的示例。

With W-LSB encoding, the compressor uses a number of references (a window) from its context. What references to use is determined by its optimistic approach. The compressor extracts the value of the field to be W-LSB encoded from each reference in the window, and finds the maximum and minimum values. Once it determines these values, the compressor uses the assumption that the decompressor has a value for this field within the range given by these boundaries

对于W-LSB编码,压缩器使用来自其上下文的大量引用(一个窗口)。使用什么样的参照物取决于它的乐观态度。压缩器从窗口中的每个引用中提取要进行W-LSB编码的字段的值,并查找最大值和最小值。一旦确定了这些值,压缩器将使用以下假设,即解压缩器的此字段值在这些边界给定的范围内

(inclusively) as its reference. The compressor can then select a number of LSBs from the value to be compressed, so that the LSBs can be decompressed regardless of whether the decompressor uses the minimum value, the maximum value or any other value in the range of possible references.

(包括)作为其参考。然后,压缩器可以从要压缩的值中选择多个lsb,以便可以对lsb进行解压缩,而不管解压缩器使用的是最小值、最大值还是可能参考范围内的任何其他值。

B.3. W-LSB Encoding and Timer-based Compression
B.3. W-LSB编码和基于定时器的压缩

Section 6.6.9 defines decompressor behavior for timer-based RTP timestamp compression. This section gives guidelines on how the compressor should determine the number of LSB bits it should send for the timestamp field. When using timer-based compression, this number depends on the sum of the jitter before the compressor and the jitter between the compressor and decompressor.

第6.6.9节定义了基于计时器的RTP时间戳压缩的解压器行为。本节给出了压缩器应如何确定其应为时间戳字段发送的LSB位数的指南。当使用基于计时器的压缩时,此数字取决于压缩机前的抖动和压缩机与解压缩器之间的抖动之和。

The jitter before the compressor can be estimated using the following computation:

压缩机前的抖动可通过以下计算进行估算:

       Max_Jitter_BC =
            max {|(T_n - T_j) - ((a_n - a_j) / time_stride)|,
               for all headers j in the sliding window}
        
       Max_Jitter_BC =
            max {|(T_n - T_j) - ((a_n - a_j) / time_stride)|,
               for all headers j in the sliding window}
        

where (T_n - T_j) is the difference in the timestamp between the currently compressed header and a reference header and (a_n - a_j) is the difference in arrival time between those same two headers.

其中(T_n-T_j)是当前压缩的报头和参考报头之间的时间戳差,(a_n-a_j)是这两个报头之间的到达时间差。

In addition to this, the compressor needs to estimate an upper bound for the jitter between the compressor and decompressor (Max_Jitter_CD). This information may for example come from lower layers.

除此之外,压缩器还需要估计压缩器和解压缩器之间抖动的上限(Max_jitter_CD)。例如,该信息可能来自较低的层。

A compressor implementation can determine whether the difference in clock resolution between the compressor and decompressor induces an error when performing integer arithmetics; it can then treat this error as additional jitter.

压缩器实现可以确定在执行整数算术时压缩器和解压缩器之间的时钟分辨率的差异是否导致错误;然后,它可以将此错误视为附加抖动。

After obtaining estimates for the jitters, the number of bits needed to transmit is obtained using the following calculation:

获得抖动估计值后,使用以下计算获得传输所需的位数:

       ceiling(log2(2 * (Max_Jitter_BC + Max_Jitter_CD + 2) + 1))
        
       ceiling(log2(2 * (Max_Jitter_BC + Max_Jitter_CD + 2) + 1))
        

This number is then used to select a packet format that contains at least this many scaled timestamp bits.

然后,该数字用于选择至少包含这么多缩放时间戳位的数据包格式。

Authors' Addresses

作者地址

Ghyslain Pelletier Ericsson Box 920 Lulea SE-971 28 Sweden

Ghyslain Pelletier Ericsson信箱920 Lulea SE-971 28瑞典

   Phone: +46 (0) 8 404 29 43
   EMail: ghyslain.pelletier@ericsson.com
        
   Phone: +46 (0) 8 404 29 43
   EMail: ghyslain.pelletier@ericsson.com
        

Kristofer Sandlund Ericsson Box 920 Lulea SE-971 28 Sweden

Kristofer Sandlund Ericsson信箱920 Lulea SE-971 28瑞典

   Phone: +46 (0) 8 404 41 58
   EMail: kristofer.sandlund@ericsson.com
        
   Phone: +46 (0) 8 404 41 58
   EMail: kristofer.sandlund@ericsson.com
        

Full Copyright Statement

完整版权声明

Copyright (C) The IETF Trust (2008).

版权所有(C)IETF信托基金(2008年)。

This document is subject to the rights, licenses and restrictions contained in BCP 78, and except as set forth therein, the authors retain all their rights.

本文件受BCP 78中包含的权利、许可和限制的约束,除其中规定外,作者保留其所有权利。

This document and the information contained herein are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND THE INTERNET ENGINEERING TASK FORCE DISCLAIM 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.

本文件及其包含的信息以“原样”为基础提供,贡献者、他/她所代表或赞助的组织(如有)、互联网协会、IETF信托基金和互联网工程任务组不承担任何明示或暗示的担保,包括但不限于任何保证,即使用本文中的信息不会侵犯任何权利,或对适销性或特定用途适用性的任何默示保证。

Intellectual Property

知识产权

The IETF takes no position regarding the validity or scope of any Intellectual Property Rights or other rights that might be claimed to pertain to the implementation or use of the technology described in this document or the extent to which any license under such rights might or might not be available; nor does it represent that it has made any independent effort to identify any such rights. Information on the procedures with respect to rights in RFC documents can be found in BCP 78 and BCP 79.

IETF对可能声称与本文件所述技术的实施或使用有关的任何知识产权或其他权利的有效性或范围,或此类权利下的任何许可可能或可能不可用的程度,不采取任何立场;它也不表示它已作出任何独立努力来确定任何此类权利。有关RFC文件中权利的程序信息,请参见BCP 78和BCP 79。

Copies of IPR disclosures made to the IETF Secretariat and any assurances of licenses to be made available, or the result of an attempt made to obtain a general license or permission for the use of such proprietary rights by implementers or users of this specification can be obtained from the IETF on-line IPR repository at http://www.ietf.org/ipr.

向IETF秘书处披露的知识产权副本和任何许可证保证,或本规范实施者或用户试图获得使用此类专有权利的一般许可证或许可的结果,可从IETF在线知识产权存储库获取,网址为http://www.ietf.org/ipr.

The IETF invites any interested party to bring to its attention any copyrights, patents or patent applications, or other proprietary rights that may cover technology that may be required to implement this standard. Please address the information to the IETF at ietf-ipr@ietf.org.

IETF邀请任何相关方提请其注意任何版权、专利或专利申请,或其他可能涵盖实施本标准所需技术的专有权利。请将信息发送至IETF的IETF-ipr@ietf.org.