Internet Engineering Task Force (IETF)                      G. Pelletier
Request for Comments: 6846                   InterDigital Communications
Obsoletes: 4996                                              K. Sandlund
Category: Standards Track                                       Ericsson
ISSN: 2070-1721                                             L-E. Jonsson
        
Internet Engineering Task Force (IETF)                      G. Pelletier
Request for Comments: 6846                   InterDigital Communications
Obsoletes: 4996                                              K. Sandlund
Category: Standards Track                                       Ericsson
ISSN: 2070-1721                                             L-E. Jonsson
        

M. West Siemens/Roke Manor January 2013

M.西西门子/罗克庄园2013年1月

RObust Header Compression (ROHC): A Profile for TCP/IP (ROHC-TCP)

健壮的报头压缩(ROHC):TCP/IP的配置文件(ROHC-TCP)

Abstract

摘要

This document specifies a RObust Header Compression (ROHC) profile for compression of TCP/IP packets. The profile, called ROHC-TCP, provides efficient and robust compression of TCP headers, including frequently used TCP options such as selective acknowledgments (SACKs) and Timestamps.

本文档指定了用于压缩TCP/IP数据包的健壮标头压缩(ROHC)配置文件。该配置文件称为ROHC-TCP,它提供了对TCP头的高效和健壮的压缩,包括常用的TCP选项,如选择性确认(SACK)和时间戳。

ROHC-TCP works well when used over links with significant error rates and long round-trip times. For many bandwidth-limited links where header compression is essential, such characteristics are common.

ROHC-TCP在错误率高、往返时间长的链路上使用时效果良好。对于许多带宽有限的链路,报头压缩是必不可少的,这样的特性很常见。

This specification obsoletes RFC 4996. It fixes a technical issue with the SACK compression and clarifies other compression methods used.

本规范淘汰RFC 4996。它修复了SACK压缩的一个技术问题,并澄清了使用的其他压缩方法。

Status of This Memo

关于下段备忘

This is an Internet Standards Track document.

这是一份互联网标准跟踪文件。

This document is a product of the Internet Engineering Task Force (IETF). It represents the consensus of the IETF community. It has received public review and has been approved for publication by the Internet Engineering Steering Group (IESG). Further information on Internet Standards is available in Section 2 of RFC 5741.

本文件是互联网工程任务组(IETF)的产品。它代表了IETF社区的共识。它已经接受了公众审查,并已被互联网工程指导小组(IESG)批准出版。有关互联网标准的更多信息,请参见RFC 5741第2节。

Information about the current status of this document, any errata, and how to provide feedback on it may be obtained at http://www.rfc-editor.org/info/rfc6846.

有关本文件当前状态、任何勘误表以及如何提供反馈的信息,请访问http://www.rfc-editor.org/info/rfc6846.

Copyright Notice

版权公告

Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.

版权所有(c)2013 IETF信托基金和确定为文件作者的人员。版权所有。

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (http://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Simplified BSD License.

本文件受BCP 78和IETF信托有关IETF文件的法律规定的约束(http://trustee.ietf.org/license-info)自本文件出版之日起生效。请仔细阅读这些文件,因为它们描述了您对本文件的权利和限制。从本文件中提取的代码组件必须包括信托法律条款第4.e节中所述的简化BSD许可证文本,并提供简化BSD许可证中所述的无担保。

Table of Contents

目录

   1. Introduction ....................................................5
   2. Terminology .....................................................5
   3. Background ......................................................7
      3.1. Existing TCP/IP Header Compression Schemes .................7
      3.2. Classification of TCP/IP Header Fields .....................8
   4. Overview of the TCP/IP Profile (Informative) ...................10
      4.1. General Concepts ..........................................10
      4.2. Compressor and Decompressor Interactions ..................10
           4.2.1. Compressor Operation ...............................10
           4.2.2. Decompressor Feedback ..............................11
      4.3. Packet Formats and Encoding Methods .......................11
           4.3.1. Compressing TCP Options ............................11
           4.3.2. Compressing Extension Headers ......................11
      4.4. Expected Compression Ratios with ROHC-TCP .................12
   5. Compressor and Decompressor Logic (Normative) ..................13
      5.1. Context Initialization ....................................13
      5.2. Compressor Operation ......................................13
           5.2.1. Compression Logic ..................................13
                  5.2.1.1. Optimistic Approach .......................14
                  5.2.1.2. Periodic Context Refreshes ................14
           5.2.2. Feedback Logic .....................................14
                  5.2.2.1. Optional Acknowledgments (ACKs) ...........14
                  5.2.2.2. Negative Acknowledgments (NACKs) ..........15
           5.2.3. Context Replication ................................15
      5.3. Decompressor Operation ....................................16
           5.3.1. Decompressor States and Logic ......................16
                  5.3.1.1. Reconstruction and Verification ...........16
                  5.3.1.2. Detecting Context Damage ..................17
                  5.3.1.3. No Context (NC) State .....................18
                  5.3.1.4. Static Context (SC) State .................18
                  5.3.1.5. Full Context (FC) State ...................19
           5.3.2. Feedback Logic .....................................19
           5.3.3. Context Replication ................................20
   6. Encodings in ROHC-TCP (Normative) ..............................20
      6.1. Control Fields in ROHC-TCP ................................20
           6.1.1. Master Sequence Number (MSN) .......................20
           6.1.2. IP-ID Behavior .....................................21
           6.1.3. Explicit Congestion Notification (ECN) .............22
      6.2. Compressed Header Chains ..................................22
      6.3. Compressing TCP Options with List Compression .............24
           6.3.1. List Compression ...................................25
           6.3.2. Table-Based Item Compression .......................26
           6.3.3. Encoding of Compressed Lists .......................26
           6.3.4. Item Table Mappings ................................28
           6.3.5. Compressed Lists in Dynamic Chain ..................30
           6.3.6. Irregular Chain Items for TCP Options ..............30
        
   1. Introduction ....................................................5
   2. Terminology .....................................................5
   3. Background ......................................................7
      3.1. Existing TCP/IP Header Compression Schemes .................7
      3.2. Classification of TCP/IP Header Fields .....................8
   4. Overview of the TCP/IP Profile (Informative) ...................10
      4.1. General Concepts ..........................................10
      4.2. Compressor and Decompressor Interactions ..................10
           4.2.1. Compressor Operation ...............................10
           4.2.2. Decompressor Feedback ..............................11
      4.3. Packet Formats and Encoding Methods .......................11
           4.3.1. Compressing TCP Options ............................11
           4.3.2. Compressing Extension Headers ......................11
      4.4. Expected Compression Ratios with ROHC-TCP .................12
   5. Compressor and Decompressor Logic (Normative) ..................13
      5.1. Context Initialization ....................................13
      5.2. Compressor Operation ......................................13
           5.2.1. Compression Logic ..................................13
                  5.2.1.1. Optimistic Approach .......................14
                  5.2.1.2. Periodic Context Refreshes ................14
           5.2.2. Feedback Logic .....................................14
                  5.2.2.1. Optional Acknowledgments (ACKs) ...........14
                  5.2.2.2. Negative Acknowledgments (NACKs) ..........15
           5.2.3. Context Replication ................................15
      5.3. Decompressor Operation ....................................16
           5.3.1. Decompressor States and Logic ......................16
                  5.3.1.1. Reconstruction and Verification ...........16
                  5.3.1.2. Detecting Context Damage ..................17
                  5.3.1.3. No Context (NC) State .....................18
                  5.3.1.4. Static Context (SC) State .................18
                  5.3.1.5. Full Context (FC) State ...................19
           5.3.2. Feedback Logic .....................................19
           5.3.3. Context Replication ................................20
   6. Encodings in ROHC-TCP (Normative) ..............................20
      6.1. Control Fields in ROHC-TCP ................................20
           6.1.1. Master Sequence Number (MSN) .......................20
           6.1.2. IP-ID Behavior .....................................21
           6.1.3. Explicit Congestion Notification (ECN) .............22
      6.2. Compressed Header Chains ..................................22
      6.3. Compressing TCP Options with List Compression .............24
           6.3.1. List Compression ...................................25
           6.3.2. Table-Based Item Compression .......................26
           6.3.3. Encoding of Compressed Lists .......................26
           6.3.4. Item Table Mappings ................................28
           6.3.5. Compressed Lists in Dynamic Chain ..................30
           6.3.6. Irregular Chain Items for TCP Options ..............30
        
           6.3.7. Replication of TCP Options .........................30
      6.4. Profile-Specific Encoding Methods .........................31
           6.4.1. inferred_ip_v4_header_checksum .....................31
           6.4.2. inferred_mine_header_checksum ......................31
           6.4.3. inferred_ip_v4_length ..............................32
           6.4.4. inferred_ip_v6_length ..............................32
           6.4.5. inferred_offset ....................................33
           6.4.6. baseheader_extension_headers .......................33
           6.4.7. baseheader_outer_headers ...........................34
           6.4.8. Scaled Encoding of Fields ..........................34
                  6.4.8.1. Scaled TCP Sequence Number Encoding .......35
                  6.4.8.2. Scaled Acknowledgment Number Encoding .....35
      6.5. Encoding Methods with External Parameters .................36
   7. Packet Types (Normative) .......................................38
      7.1. Initialization and Refresh (IR) Packets ...................38
      7.2. Context Replication (IR-CR) Packets .......................40
      7.3. Compressed (CO) Packets ...................................42
   8. Header Formats (Normative) .....................................43
      8.1. Design Rationale for Compressed Base Headers ..............44
      8.2. Formal Definition of Header Formats .......................47
      8.3. Feedback Formats and Options ..............................88
           8.3.1. Feedback Formats ...................................88
           8.3.2. Feedback Options ...................................89
                  8.3.2.1. The REJECT Option .........................89
                  8.3.2.2. The MSN-NOT-VALID Option ..................90
                  8.3.2.3. The MSN Option ............................90
                  8.3.2.4. The CONTEXT_MEMORY Feedback Option ........91
                  8.3.2.5. Unknown Option Types ......................91
   9. Changes from RFC 4996 ..........................................91
      9.1. Functional Changes ........................................91
      9.2. Non-functional Changes ....................................92
   10. Security Considerations .......................................92
   11. IANA Considerations ...........................................93
   12. Acknowledgments ...............................................93
   13. References ....................................................93
      13.1. Normative References .....................................93
      13.2. Informative References ...................................94
        
           6.3.7. Replication of TCP Options .........................30
      6.4. Profile-Specific Encoding Methods .........................31
           6.4.1. inferred_ip_v4_header_checksum .....................31
           6.4.2. inferred_mine_header_checksum ......................31
           6.4.3. inferred_ip_v4_length ..............................32
           6.4.4. inferred_ip_v6_length ..............................32
           6.4.5. inferred_offset ....................................33
           6.4.6. baseheader_extension_headers .......................33
           6.4.7. baseheader_outer_headers ...........................34
           6.4.8. Scaled Encoding of Fields ..........................34
                  6.4.8.1. Scaled TCP Sequence Number Encoding .......35
                  6.4.8.2. Scaled Acknowledgment Number Encoding .....35
      6.5. Encoding Methods with External Parameters .................36
   7. Packet Types (Normative) .......................................38
      7.1. Initialization and Refresh (IR) Packets ...................38
      7.2. Context Replication (IR-CR) Packets .......................40
      7.3. Compressed (CO) Packets ...................................42
   8. Header Formats (Normative) .....................................43
      8.1. Design Rationale for Compressed Base Headers ..............44
      8.2. Formal Definition of Header Formats .......................47
      8.3. Feedback Formats and Options ..............................88
           8.3.1. Feedback Formats ...................................88
           8.3.2. Feedback Options ...................................89
                  8.3.2.1. The REJECT Option .........................89
                  8.3.2.2. The MSN-NOT-VALID Option ..................90
                  8.3.2.3. The MSN Option ............................90
                  8.3.2.4. The CONTEXT_MEMORY Feedback Option ........91
                  8.3.2.5. Unknown Option Types ......................91
   9. Changes from RFC 4996 ..........................................91
      9.1. Functional Changes ........................................91
      9.2. Non-functional Changes ....................................92
   10. Security Considerations .......................................92
   11. IANA Considerations ...........................................93
   12. Acknowledgments ...............................................93
   13. References ....................................................93
      13.1. Normative References .....................................93
      13.2. Informative References ...................................94
        
1. Introduction
1. 介绍

There are several reasons to perform header compression on low- or medium-speed links for TCP/IP traffic, and these have already been discussed in [RFC2507]. Additional considerations that make robustness an important objective for a TCP [RFC0793] compression scheme are introduced in [RFC4163]. Finally, existing TCP/IP header compression schemes ([RFC1144], [RFC2507]) are limited in their handling of the TCP options field and cannot compress the headers of handshaking packets (SYNs and FINs).

在TCP/IP流量的低速或中速链路上执行报头压缩有几个原因,这些原因已经在[RFC2507]中讨论过。[RFC4163]中介绍了使健壮性成为TCP[RFC0793]压缩方案重要目标的其他注意事项。最后,现有的TCP/IP报头压缩方案([RFC1144]、[RFC2507])在处理TCP选项字段时受到限制,无法压缩握手数据包(SYN和FINs)的报头。

It is thus desirable for a header compression scheme to be able to handle loss on the link between the compression and decompression points as well as loss before the compression point. The header compression scheme also needs to consider how to efficiently compress short-lived TCP transfers and TCP options, such as selective acknowledgments (SACK) ([RFC2018], [RFC2883]) and Timestamps ([RFC1323]). TCP options that may be less frequently used do not necessarily need to be compressed by the protocol, and instead can be passed transparently without reducing the overall compression efficiency of other parts of the TCP header.

因此,期望报头压缩方案能够处理压缩和解压缩点之间的链路上的丢失以及压缩点之前的丢失。报头压缩方案还需要考虑如何有效地压缩短命TCP传输和TCP选项,例如选择性确认(SAK)([RCF2018]、[RCF2683])和时间戳([RCF1323 ])。使用频率较低的TCP选项不一定需要通过协议进行压缩,而是可以透明地传递,而不会降低TCP报头其他部分的整体压缩效率。

The Robust Header Compression (ROHC) Working Group has developed a header compression framework on top of which various profiles can be defined for different protocol sets, or for different compression strategies. This document defines a TCP/IP compression profile for the ROHC framework [RFC5795], compliant with the requirements listed in [RFC4163].

鲁棒头压缩(ROHC)工作组开发了一个头压缩框架,在此框架之上,可以为不同的协议集或不同的压缩策略定义各种概要文件。本文件定义了ROHC框架[RFC5795]的TCP/IP压缩配置文件,符合[RFC4163]中列出的要求。

Specifically, it describes a header compression scheme for TCP/IP header compression (ROHC-TCP) that is robust against packet loss and that offers enhanced capabilities, in particular for the compression of header fields including TCP options. The profile identifier for TCP/IP compression is 0x0006.

具体来说,它描述了一种用于TCP/IP报头压缩(ROHC-TCP)的报头压缩方案,该方案对数据包丢失具有鲁棒性,并提供了增强的功能,特别是用于压缩包括TCP选项在内的报头字段。TCP/IP压缩的配置文件标识符为0x0006。

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

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

This document reuses some of the terminology found in [RFC5795]. In addition, this document uses or defines the following terms:

本文档重用了[RFC5795]中的一些术语。此外,本文件使用或定义了以下术语:

Base context

基本上下文

The base context is a context that has been validated by both the compressor and the decompressor. A base context can be used as the reference when building a new context using replication.

基本上下文是一个已由压缩器和解压缩器验证的上下文。在使用复制构建新上下文时,可以将基本上下文用作引用。

Base Context Identifier (Base CID)

基本上下文标识符(基本CID)

The Base CID is the CID that identifies the base context, from which information needed for context replication can be extracted.

基本CID是标识基本上下文的CID,可以从中提取上下文复制所需的信息。

Base header

基头

The Base header is a compressed representation of the innermost IP and TCP headers of the uncompressed packet.

基本报头是未压缩数据包的最内层IP和TCP报头的压缩表示。

Chaining of items

项目链接

A chain groups fields based on similar characteristics. ROHC-TCP defines chain items for static, dynamic, replicable, or irregular fields. Chaining is done by appending an item for each header, e.g., to the chain in their 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 ROHC-TCP defines a compressed format.

链根据相似的特征对字段进行分组。ROHC-TCP为静态、动态、可复制或不规则字段定义链项。链接是通过为每个头添加一个项目来完成的,例如,按照未压缩数据包中的出现顺序将项目添加到链中。链接对于从任意数量的ROHC-TCP定义压缩格式的任何协议头构造压缩头非常有用。

Context Replication (CR)

上下文复制(CR)

Context replication is the mechanism that establishes and initializes a new context based on another existing valid context (a base context). This mechanism is introduced to reduce the overhead of the context establishment procedure, and is especially useful for compression of multiple short-lived TCP connections that may be occurring simultaneously or near-simultaneously.

上下文复制是一种基于另一个现有有效上下文(基本上下文)建立和初始化新上下文的机制。引入此机制是为了减少上下文建立过程的开销,尤其适用于压缩可能同时或几乎同时发生的多个短期TCP连接。

ROHC-TCP packet types

ROHC-TCP数据包类型

ROHC-TCP uses three different packet types: the Initialization and Refresh (IR) packet type, the Context Replication (IR-CR) packet type, and the Compressed packet (CO) type.

ROHC-TCP使用三种不同的数据包类型:初始化和刷新(IR)数据包类型、上下文复制(IR-CR)数据包类型和压缩数据包(CO)类型。

Short-lived TCP transfer

短寿命TCP传输

Short-lived TCP transfers refer to TCP connections transmitting only small amounts of packets for each single connection.

短寿命TCP传输是指TCP连接仅为每个连接传输少量数据包。

3. Background
3. 出身背景

This section provides some background information on TCP/IP header compression. The fundamentals of general header compression can be found in [RFC5795]. In the following subsections, two existing TCP/IP header compression schemes are first described along with a discussion of their limitations, followed by the classification of TCP/IP header fields. Finally, some of the characteristics of short-lived TCP transfers are summarized.

本节提供有关TCP/IP头压缩的一些背景信息。一般报头压缩的基本原理可在[RFC5795]中找到。在以下小节中,首先介绍了两种现有的TCP/IP报头压缩方案,并讨论了它们的局限性,然后介绍了TCP/IP报头字段的分类。最后,总结了短命TCP传输的一些特点。

A behavior analysis of TCP/IP header fields is found in [RFC4413].

TCP/IP头字段的行为分析见[RFC4413]。

3.1. Existing TCP/IP Header Compression Schemes
3.1. 现有的TCP/IP报头压缩方案

Compressed TCP (CTCP) and IP Header Compression (IPHC) are two different schemes that may be used to compress TCP/IP headers. Both schemes transmit only the differences from the previous header in order to reduce the size of the TCP/IP header.

压缩TCP(CTCP)和IP报头压缩(IPHC)是可用于压缩TCP/IP报头的两种不同方案。两种方案仅传输与前一个报头的差异,以减小TCP/IP报头的大小。

The CTCP [RFC1144] compressor detects transport-level retransmissions and sends a header that updates the context completely when they occur. While CTCP works well over reliable links, it is vulnerable when used over less reliable links as even a single packet loss results in loss of synchronization between the compressor and the decompressor. This in turn leads to the TCP receiver discarding all remaining packets in the current window because of a checksum error. This effectively prevents the TCP fast retransmit algorithm [RFC5681] from being triggered. In such a case, the compressor must wait until TCP times out and retransmits a packet to resynchronize.

CTCP[RFC1144]压缩器检测传输级别的重传,并在重传发生时发送一个完全更新上下文的报头。虽然CTCP在可靠链路上运行良好,但在不太可靠的链路上使用时,它很容易受到攻击,因为即使单个数据包丢失也会导致压缩机和解压缩器之间的同步丢失。这进而导致TCP接收器由于校验和错误而丢弃当前窗口中所有剩余的数据包。这有效地防止了TCP快速重传算法[RFC5681]被触发。在这种情况下,压缩器必须等待TCP超时并重新传输数据包以重新同步。

To reduce the errors due to the inconsistent contexts between compressor and decompressor when compressing TCP, IPHC [RFC2507] improves somewhat on CTCP by augmenting the repair mechanism of CTCP with a local repair mechanism called TWICE and with a link-layer mechanism based on negative acknowledgments to request a header that updates the context.

为了减少压缩TCP时由于压缩程序和解压缩程序之间的上下文不一致而导致的错误,IPHC[RFC2507]通过使用两次调用的本地修复机制和基于否定确认的链路层机制来请求更新上下文的报头,对CTCP的修复机制进行了一些改进。

The TWICE algorithm assumes that only the Sequence Number field of TCP segments is changing with the deltas between consecutive packets being constant in most cases. This assumption is, however, not always true, especially when TCP Timestamps and SACK options are used.

两次算法假设只有TCP段的序列号字段在变化,并且在大多数情况下,连续数据包之间的增量保持不变。然而,这种假设并不总是正确的,尤其是在使用TCP时间戳和SACK选项时。

The full header request mechanism requires a feedback channel that may be unavailable in some circumstances. This channel is used to explicitly request that the next packet be sent with an uncompressed header to allow resynchronization without waiting for a TCP timeout.

完整报头请求机制需要反馈通道,在某些情况下可能不可用。此通道用于显式请求下一个数据包使用未压缩的报头发送,以允许在不等待TCP超时的情况下重新同步。

In addition, this mechanism does not perform well on links with long round-trip times.

此外,这种机制在往返时间较长的链路上表现不佳。

Both CTCP and IPHC are also limited in their handling of the TCP options field. For IPHC, any change in the options field (caused by Timestamps or SACK, for example) renders the entire field uncompressible, while for CTCP, such a change in the options field effectively disables TCP/IP header compression altogether.

CTCP和IPHC在处理TCP选项字段方面也受到限制。对于IPHC,选项字段中的任何更改(例如,由时间戳或SACK引起)都会使整个字段不可压缩,而对于CTCP,选项字段中的此类更改实际上会完全禁用TCP/IP报头压缩。

Finally, existing TCP/IP compression schemes do not compress the headers of handshaking packets (SYNs and FINs). Compressing these packets may greatly improve the overall header compression ratio for the cases where many short-lived TCP connections share the same channel.

最后,现有的TCP/IP压缩方案不压缩握手数据包(SYN和FINs)的报头。对于许多短寿命TCP连接共享同一信道的情况,压缩这些数据包可以极大地提高整体报头压缩比。

3.2. Classification of TCP/IP Header Fields
3.2. TCP/IP头字段的分类

Header compression is possible due to the fact that there is much redundancy between header field values within packets, especially between consecutive packets. To utilize these properties for TCP/IP header compression, it is important to understand the change patterns of the various header fields.

报头压缩是可能的,因为在数据包内的报头字段值之间,特别是在连续数据包之间,存在大量冗余。要将这些属性用于TCP/IP报头压缩,必须了解各种报头字段的更改模式。

All fields of the TCP/IP packet header have been classified in detail in [RFC4413]. The main conclusion is that most of the header fields can easily be compressed away since they seldom or never change. The following fields do, however, require more sophisticated mechanisms:

[RFC4413]中对TCP/IP数据包头的所有字段进行了详细分类。主要结论是,大多数头字段很容易被压缩掉,因为它们很少或从未更改。但是,以下字段确实需要更复杂的机制:

- IPv4 Identification (16 bits) - IP-ID - TCP Sequence Number (32 bits) - SN - TCP Acknowledgment Number (32 bits) - TCP Reserved ( 4 bits) - TCP ECN flags ( 2 bits) - ECN - TCP Window (16 bits) - TCP Options o Maximum Segment Size (32 bits) - MSS o Window Scale (24 bits) - WSCALE o SACK Permitted (16 bits) o TCP SACK (80, 144, 208, or 272 bits) - SACK o TCP Timestamp (80 bits) - TS

- IPv4标识(16位)—IP-ID—TCP序列号(32位)—SN—TCP确认号(32位)—TCP保留(4位)—TCP ECN标志(2位)—ECN—TCP窗口(16位)—TCP选项o最大段大小(32位)—MSS o窗口缩放(24位)—WSCALE o允许的SACK(16位)o TCP SACK(80、144、208或272位)-SACK o TCP时间戳(80位)-TS

The assignment of IP-ID values can be done in various ways, usually one of sequential, sequential jump, or random, as described in Section 4.1.3 of [RFC4413]. Some IPv4 stacks do use a sequential assignment when generating IP-ID values but do not transmit the contents of this field in network byte order; instead, it is sent with the two octets reversed. In this case, the compressor can

IP-ID值的分配可以通过多种方式完成,通常是顺序、顺序跳转或随机方式,如[RFC4413]第4.1.3节所述。某些IPv4堆栈在生成IP-ID值时使用顺序分配,但不按网络字节顺序传输此字段的内容;相反,它是在两个八位字节颠倒的情况下发送的。在这种情况下,压缩机可以

compress the IP-ID field after swapping the bytes. Consequently, the decompressor also swaps the bytes of the IP-ID after decompression to regenerate the original IP-ID. With respect to TCP compression, the analysis in [RFC4413] reveals that there is no obvious candidate among the TCP fields suitable to infer the IP-ID.

交换字节后压缩IP-ID字段。因此,解压器还交换解压后IP-ID的字节以重新生成原始IP-ID。关于TCP压缩,[RFC4413]中的分析表明,TCP字段中没有明显的候选字段适合推断IP-ID。

The change pattern of several TCP fields (Sequence Number, Acknowledgment Number, Window, etc.) is very hard to predict. Of particular importance to a TCP/IP header compression scheme is the understanding of the sequence and acknowledgment numbers [RFC4413].

几个TCP字段(序列号、确认号、窗口等)的变化模式很难预测。对于TCP/IP报头压缩方案来说,理解序列号和确认号尤为重要[RFC4413]。

Specifically, the TCP Sequence Number can be anywhere within a range defined by the TCP Window at any point on the path (i.e., wherever a compressor might be deployed). Missing packets or retransmissions can cause the TCP Sequence Number to fluctuate within the limits of this window. The TCP Window also bounds the jumps in acknowledgment number.

具体而言,TCP序列号可以在路径上任何点(即,可能部署压缩器的位置)的TCP窗口定义的范围内的任何位置。丢失的数据包或重新传输可能会导致TCP序列号在此窗口范围内波动。TCP窗口还限制确认号中的跳转。

Another important behavior of the TCP/IP header is the dependency between the sequence number and the acknowledgment number. TCP connections can be either near-symmetrical or show a strong asymmetrical bias with respect to the data traffic. In the latter case, the TCP connections mainly have one-way traffic (Web browsing and file downloading, for example). This means that on the forward path (from server to client), only the sequence number is changing while the acknowledgment number remains constant for most packets; on the backward path (from client to server), only the acknowledgment number is changing and the sequence number remains constant for most packets. A compression scheme for TCP should thus have packet formats suitable for either cases, i.e., packet formats that can carry either only sequence number bits, only acknowledgment number bits, or both.

TCP/IP报头的另一个重要行为是序列号和确认号之间的依赖关系。TCP连接可以是近似对称的,或者相对于数据流量显示出强烈的不对称偏差。在后一种情况下,TCP连接主要具有单向流量(例如,Web浏览和文件下载)。这意味着在转发路径(从服务器到客户端)上,只有序列号在变化,而大多数数据包的确认号保持不变;在反向路径(从客户机到服务器)上,只有确认号在更改,并且大多数数据包的序列号保持不变。因此,TCP的压缩方案应具有适合任一情况的数据包格式,即,只能携带序列号位、确认号位或两者兼有的数据包格式。

In addition, TCP flows can be short-lived transfers. Short-lived TCP transfers will degrade the performance of header compression schemes that establish a new context by initially sending full headers. Multiple simultaneous or near simultaneous TCP connections may exhibit much similarity in header field values and context values among each other, which would make it possible to reuse information between flows when initializing a new context. A mechanism to this end, context replication [RFC4164], makes the context establishment step faster and more efficient, by replicating part of an existing context to a new flow. The conclusion from [RFC4413] is that part of the IP sub-context, some TCP fields, and some context values can be replicated since they seldom change or change with only a small jump.

此外,TCP流可以是短期传输。短暂的TCP传输会降低报头压缩方案的性能,这些方案通过最初发送完整的报头来建立新的上下文。多个同时或接近同时的TCP连接在头字段值和上下文值之间可能表现出很大的相似性,这使得在初始化新上下文时在流之间重用信息成为可能。为此目的,上下文复制[RFC4164]机制通过将现有上下文的一部分复制到新的流中,使上下文建立步骤更快、更高效。[RFC4413]得出的结论是,部分IP子上下文、一些TCP字段和一些上下文值可以复制,因为它们很少改变,或者只需一个小的跳跃就可以改变。

ROHC-TCP also compresses the following headers: IPv6 Destination Options header [RFC2460], IPv6 Routing header [RFC2460], IPv6 Hop-by-Hop Options header [RFC2460], Authentication Header (AH) [RFC4302], Generic Routing Encapsulation (GRE) [RFC2784][RFC2890], and the Minimal Encapsulation (MINE) header [RFC2004].

ROHC-TCP还压缩以下标头:IPv6目标选项标头[RFC2460]、IPv6路由标头[RFC2460]、IPv6逐跳选项标头[RFC2460]、身份验证标头(AH)[RFC4302]、通用路由封装(GRE)[RFC2784][RFC2890]和最小封装(MINE)标头[RFC2004]。

Headers specific to Mobile IP (for IPv4 or IPv6) do not receive any special treatment in this document, for reasons similar to those described in [RFC3095].

由于与[RFC3095]中所述类似的原因,本文档中未对特定于移动IP(IPv4或IPv6)的标头进行任何特殊处理。

4. Overview of the TCP/IP Profile (Informative)
4. TCP/IP配置文件概述(资料性)
4.1. General Concepts
4.1. 一般概念

ROHC-TCP uses the ROHC protocol as described in [RFC5795]. ROHC-TCP supports context replication as defined in [RFC4164]. Context replication can be particularly useful for short-lived TCP flows [RFC4413].

ROHC-TCP使用[RFC5795]中所述的ROHC协议。ROHC-TCP支持[RFC4164]中定义的上下文复制。上下文复制对于短期TCP流特别有用[RFC4413]。

4.2. Compressor and Decompressor Interactions
4.2. 压缩机和减压器的相互作用
4.2.1. Compressor Operation
4.2.1. 压缩机操作

Header compression with ROHC can be conceptually characterized as the interaction of a compressor with a decompressor state machine. The compressor's task is to minimally send the information needed to successfully decompress a packet, based on a certain confidence regarding the state of the decompressor context.

ROHC的报头压缩在概念上可以描述为压缩机与解压缩器状态机的交互。压缩器的任务是根据关于解压器上下文状态的一定置信度,最小限度地发送成功解压数据包所需的信息。

For ROHC-TCP compression, 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. Alternatively, the compressor may also support Context Replication (CR) and use IR-CR packets [RFC4164], which attempts to reuse context information related to another flow.

对于ROHC-TCP压缩,压缩器通常在初始假设解压缩器没有处理新流的有用信息的情况下启动压缩,并发送初始化和刷新(IR)数据包。或者,压缩器还可以支持上下文复制(CR)并使用IR-CR分组[RFC4164],其尝试重用与另一个流相关的上下文信息。

The compressor can then adjust the compression level based on its confidence that the decompressor has the necessary information to successfully process the Compressed (CO) packets that it selects. In other words, the task of the compressor is to ensure that the decompressor operates in the state that allows decompression of the most efficient CO packet(s), and to allow the decompressor to move to that state as soon as possible otherwise.

然后,压缩器可以基于其确信解压缩器具有成功处理其选择的压缩(CO)分组所需的信息来调整压缩级别。换句话说,压缩器的任务是确保解压缩器在允许对最有效的CO分组进行解压缩的状态下工作,并允许解压缩器尽快移动到该状态,否则。

4.2.2. Decompressor Feedback
4.2.2. 减压器反馈

The ROHC-TCP profile can be used in environments with or without feedback capabilities from decompressor to compressor. ROHC-TCP, 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 ROHC-TCP context, this channel will be used during the entire compression operation for that context. If the feedback channel disappears, compression should be restarted.

ROHC-TCP配置文件可用于具有或不具有从解压器到压缩器的反馈功能的环境中。然而,ROHC-TCP假定,如果ROHC反馈通道可用,并且如果解压器对特定ROHC-TCP上下文至少使用一次该通道,则该通道将在该上下文的整个压缩操作期间使用。如果反馈通道消失,则应重新开始压缩。

The reception of either positive acknowledgments (ACKs) or negative acknowledgments (NACKs) establishes the feedback channel from the decompressor for the context for which the feedback was received. Once there is an established feedback channel for a specific context, the compressor should make use of this feedback to estimate the current state of the decompressor. This helps in increasing the compression efficiency by providing the information needed for the compressor to achieve the necessary confidence level.

正确认(ACKs)或负确认(NACK)的接收为接收反馈的上下文建立来自解压缩器的反馈通道。一旦为特定上下文建立了反馈通道,压缩器应利用该反馈来估计解压器的当前状态。通过提供压缩机达到必要置信水平所需的信息,这有助于提高压缩效率。

The ROHC-TCP feedback mechanism is limited in its applicability by the number of (least significant bit (LSB) encoded) master sequence number (MSN) (see Section 6.1.1) bits used in the FEEDBACK-2 format (see Section 8.3). It is not suitable for a decompressor to use feedback altogether where the MSN bits in the feedback could wrap around within one round-trip time. Instead, unidirectional operation -- where the compressor periodically sends larger context-updating packets -- is more appropriate.

ROHC-TCP反馈机制的适用性受到反馈-2格式(见第8.3节)中使用的(最低有效位(LSB)编码)主序列号(MSN)(见第6.1.1节)位数的限制。如果反馈中的MSN位可以在一个往返时间内环绕,那么解压器不适合同时使用反馈。相反,单向操作(压缩器定期发送较大的上下文更新数据包)更合适。

4.3. Packet Formats and Encoding Methods
4.3. 数据包格式和编码方法

The packet formats and encoding methods used for ROHC-TCP are defined using the formal notation [RFC4997]. The formal notation is used to provide an unambiguous representation of the packet formats and a clear definition of the encoding methods.

ROHC-TCP使用的数据包格式和编码方法使用形式符号[RFC4997]定义。形式表示法用于提供数据包格式的明确表示和编码方法的明确定义。

4.3.1. Compressing TCP Options
4.3.1. 压缩TCP选项

The TCP options in ROHC-TCP are compressed using a list compression encoding that allows option content to be established so that TCP options can be added to the context without having to send all TCP options uncompressed.

ROHC-TCP中的TCP选项使用列表压缩编码进行压缩,该编码允许建立选项内容,以便可以将TCP选项添加到上下文中,而无需发送未压缩的所有TCP选项。

4.3.2. Compressing Extension Headers
4.3.2. 压缩扩展头

ROHC-TCP compresses the extension headers as listed in Section 3.2. These headers are treated exactly as other headers and thus have a static chain, a dynamic chain, an irregular chain, and a chain for context replication (Section 6.2).

ROHC-TCP压缩第3.2节中列出的扩展头。这些标头与其他标头完全相同,因此具有静态链、动态链、不规则链和上下文复制链(第6.2节)。

This means that headers appearing in or disappearing from the flow being compressed will lead to changes to the static chain. However, the change pattern of extension headers is not deemed to impair compression efficiency with respect to this design strategy.

这意味着在被压缩的流中出现或消失的头将导致对静态链的更改。然而,根据该设计策略,扩展头的变化模式不被视为损害压缩效率。

4.4. Expected Compression Ratios with ROHC-TCP
4.4. ROHC-TCP的预期压缩比

The following table illustrates typical compression ratios that can be expected when using ROHC-TCP and IPHC [RFC2507].

下表说明了使用ROHC-TCP和IPHC[RFC2507]时可预期的典型压缩比。

The figures in the table assume that the compression context has already been properly initialized. For the TS option, the Timestamp is assumed to change with small values. All TCP options include a suitable number of No Operation (NOP) options [RFC0793] for padding and/or alignment. Finally, in the examples for IPv4, a sequential IP-ID behavior is assumed.

表中的图假定压缩上下文已经正确初始化。对于TS选项,假定时间戳随小值变化。所有TCP选项包括适当数量的无操作(NOP)选项[RFC0793],用于填充和/或对齐。最后,在IPv4的示例中,假定了顺序IP-ID行为。

                             Total Header Size (octets)
                              ROHC-TCP          IPHC
                     Unc.   DATA    ACK      DATA    ACK
   IPv4+TCP+TS       52       8      8        18     18
   IPv4+TCP+TS       52       7      6        16     16   (1)
   IPv6+TCP+TS       72       8      7        18     18
   IPv6+TCP+no opt   60       6      5         6      6
   IPv6+TCP+SACK     80       -     15         -     80   (2)
   IPv6+TCP+SACK     80       -      9         -     26   (3)
        
                             Total Header Size (octets)
                              ROHC-TCP          IPHC
                     Unc.   DATA    ACK      DATA    ACK
   IPv4+TCP+TS       52       8      8        18     18
   IPv4+TCP+TS       52       7      6        16     16   (1)
   IPv6+TCP+TS       72       8      7        18     18
   IPv6+TCP+no opt   60       6      5         6      6
   IPv6+TCP+SACK     80       -     15         -     80   (2)
   IPv6+TCP+SACK     80       -      9         -     26   (3)
        

(1) The payload size of the data stream is constant. (2) The SACK option appears in the header, but was not present in the previous packet. Two SACK blocks are assumed. (3) The SACK option appears in the header, and was also present in the previous packet (with different SACK blocks). Two SACK blocks are assumed.

(1) 数据流的有效负载大小是恒定的。(2) SACK选项出现在标头中,但在上一个数据包中不存在。假设有两个SACK块。(3) SACK选项出现在报头中,并且也出现在前一个数据包中(具有不同的SACK块)。假设有两个SACK块。

The table below illustrates the typical initial compression ratios for ROHC-TCP and IPHC. The data stream in the example is assumed to be IPv4+TCP, with a sequential behavior for the IP-ID. The following options are assumed present in the SYN packet: TS, MSS, and WSCALE, with an appropriate number of NOP options.

下表说明了ROHC-TCP和IPHC的典型初始压缩比。本例中的数据流假定为IPv4+TCP,IP-ID具有顺序行为。假定SYN数据包中存在以下选项:TS、MSS和WSCALE,以及适当数量的NOP选项。

Total Header Size (octets) Unc. ROHC-TCP IPHC 1st packet (SYN) 60 49 60 2nd packet 52 12 52

总头大小(八位字节)Unc。ROHC-TCP IPHC第一数据包(SYN)60 49 60第二数据包52 12 52

The figures in the table assume that the compressor has received an acknowledgment from the decompressor before compressing the second packet, which can be expected when feedback is used in ROHC-TCP.

表中的数字假设压缩器在压缩第二个数据包之前已收到来自解压器的确认,这在ROHC-TCP中使用反馈时是可以预期的。

This is because in the most common case, the TCP ACKs are expected to take the same return path, and because TCP does not send more packets until the TCP SYN packet has been acknowledged.

这是因为在最常见的情况下,TCP ACK预期采用相同的返回路径,并且因为TCP在确认TCP SYN数据包之前不会发送更多数据包。

5. Compressor and Decompressor Logic (Normative)
5. 压缩机和减压器逻辑(标准)
5.1. Context Initialization
5.1. 上下文初始化

The static context of ROHC-TCP flows can be initialized in either of two ways:

ROHC-TCP流的静态上下文可以通过以下两种方式之一进行初始化:

1. By using an IR packet as in Section 7.1, where the profile number is 0x06 and the static chain ends with the static part of a TCP header.

1. 通过使用第7.1节中的IR数据包,其中配置文件编号为0x06,静态链以TCP头的静态部分结束。

2. By replicating an existing context using the mechanism defined by [RFC4164]. This is done with the IR-CR packet defined in Section 7.2, where the profile number is 0x06.

2. 通过使用[RFC4164]定义的机制复制现有上下文。这是通过第7.2节中定义的IR-CR数据包完成的,其中配置文件编号为0x06。

5.2. Compressor Operation
5.2. 压缩机操作
5.2.1. Compression Logic
5.2.1. 压缩逻辑

The task of the compressor is to determine what data must be sent when compressing a TCP/IP packet, so that the decompressor can successfully reconstruct the original packet based on its current state. The selection of the type of compressed header to send thus depends on a number of factors, including:

压缩器的任务是确定在压缩TCP/IP数据包时必须发送哪些数据,以便解压缩器能够根据其当前状态成功地重构原始数据包。因此,要发送的压缩报头类型的选择取决于许多因素,包括:

o The change behavior of header fields in the flow, e.g., conveying the necessary information within the restrictions of the set of available packet formats.

o 流中报头字段的更改行为,例如,在一组可用数据包格式的限制范围内传送必要的信息。

o The compressor's level of confidence regarding decompressor state, e.g., by selecting header formats updating the same type of information for a number of consecutive packets or from the reception of decompressor feedback (ACKs and/or NACKs).

o 压缩器关于解压缩器状态的置信水平,例如,通过选择报头格式来更新多个连续分组的相同类型的信息,或者通过接收解压缩器反馈(ack和/或nack)。

o Additional robustness required for the flow, e.g., periodic refreshes of static and dynamic information using IR and IR-DYN packets when decompressor feedback is not expected.

o 流所需的额外鲁棒性,例如,当不期望解压缩器反馈时,使用IR和IR-DYN数据包定期刷新静态和动态信息。

The impact of these factors on the compressor's packet type selection is described in more detail in the following subsections.

这些因素对压缩器分组类型选择的影响将在以下小节中更详细地描述。

In this section, a "higher compression state" means that less data will be sent in compressed packets, i.e., smaller compressed headers are used, while a lower compression state means that a larger amount of data will be sent using larger compressed headers.

在本节中,“较高压缩状态”意味着在压缩分组中发送的数据较少,即使用较小的压缩报头,而较低压缩状态意味着使用较大的压缩报头发送的数据量较大。

5.2.1.1. Optimistic Approach
5.2.1.1. 乐观态度

The optimistic approach is the principle by which a compressor sends the same type of information for a number of packets (consecutively or not) until it is fairly confident that the decompressor has received the information. The optimistic approach is useful to ensure robustness when ROHC-TCP is used to compress packets over lossy links.

乐观方法是一种原理,根据该原理,压缩器为多个数据包(连续或不连续)发送相同类型的信息,直到相当确信解压器已接收到该信息。当ROHC-TCP用于在有损链路上压缩数据包时,乐观方法有助于确保健壮性。

Therefore, if field X in the uncompressed packet changes value, the compressor MUST use a packet type that contains an encoding for field X until it has gained confidence that the decompressor has received at least one packet containing the new value for X. The compressor SHOULD choose a compressed format with the smallest header that can convey the changes needed to fulfill the optimistic approach condition used.

因此,如果未压缩数据包中的字段X改变值,压缩器必须使用包含字段X编码的数据包类型,直到确信解压器已收到至少一个包含X新值的数据包。压缩器应选择具有最小报头的压缩格式,该格式可传达满足乐观逼近条件所需的更改习惯于

5.2.1.2. Periodic Context Refreshes
5.2.1.2. 定期刷新上下文

When the optimistic approach is used, there will always be a possibility of decompression failures since the decompressor may not have received sufficient information for correct decompression.

当使用乐观方法时,减压失败的可能性总是存在的,因为减压器可能没有收到足够的信息进行正确的减压。

Therefore, until the decompressor has established a feedback channel, the compressor SHOULD periodically move to a lower compression state and send IR and/or IR-DYN packets. These refreshes can be based on timeouts, on the number of compressed packets sent for the flow, or any other strategy specific to the implementation. Once the feedback channel is established, the decompressor MAY stop performing periodic refreshes.

因此,在解压器建立反馈信道之前,压缩器应周期性地移动到较低的压缩状态并发送IR和/或IR-DYN分组。这些刷新可以基于超时、为流发送的压缩数据包的数量或特定于实现的任何其他策略。一旦建立反馈通道,解压缩器可停止执行定期刷新。

5.2.2. Feedback Logic
5.2.2. 反馈逻辑

The semantics of feedback messages, acknowledgments (ACKs) and negative acknowledgments (NACKs or STATIC-NACKs), are defined in Section 5.2.4.1 of [RFC5795].

[RFC5795]第5.2.4.1节定义了反馈消息、确认(ACKs)和否定确认(NACK或静态NACK)的语义。

5.2.2.1. Optional Acknowledgments (ACKs)
5.2.2.1. 可选确认(确认)

The compressor MAY use acknowledgment feedback (ACKs) to move to a higher compression state.

压缩器可以使用确认反馈(ACKs)移动到更高的压缩状态。

Upon reception of an ACK for a context-updating packet, the compressor obtains confidence that the decompressor has received the acknowledged packet and that it has observed changes in the packet flow up to the acknowledged packet.

在接收到用于上下文更新分组的ACK时,压缩器获得解压缩器已经接收到确认分组并且已经观察到直到确认分组的分组流中的变化的信心。

This functionality is optional, so a compressor MUST NOT expect to get such ACKs, even if a feedback channel is available and has been established for that flow.

此功能是可选的,因此压缩器不得期望获得此类ACK,即使反馈通道可用且已为该流建立。

5.2.2.2. Negative Acknowledgments (NACKs)
5.2.2.2. 否定确认(NACKs)

The compressor uses feedback from the decompressor to move to a lower compression state (NACKs).

压缩机使用来自减压器的反馈移动到较低压缩状态(NACKs)。

On reception of a NACK feedback, the compressor SHOULD:

收到NACK反馈后,压缩机应:

o assume that only the static part of the decompressor is valid, and

o 假设只有解压器的静态部分有效,并且

o re-send all dynamic information (via an IR or IR-DYN packet) the next time it compresses a packet for the indicated flow

o 下次压缩指定流的数据包时,重新发送所有动态信息(通过IR或IR-DYN数据包)

unless it has confidence that information sent after the packet being acknowledged already provides a suitable response to the NACK feedback. In addition, the compressor MAY use a CO packet carrying a 7-bit Cyclic Redundancy Check (CRC) if it can determine with enough confidence what information provides a suitable response to the NACK feedback.

除非它确信在分组被确认之后发送的信息已经提供了对NACK反馈的适当响应。此外,如果压缩器能够以足够的置信度确定哪些信息提供对NACK反馈的适当响应,则压缩器可以使用携带7位循环冗余校验(CRC)的CO分组。

On reception of a STATIC-NACK feedback, the compressor SHOULD:

收到静态NACK反馈后,压缩机应:

o assume that the decompressor has no valid context, and

o 假设解压缩程序没有有效的上下文,并且

o re-send all static and all dynamic information (via an IR packet) the next time it compresses a packet for the indicated flow

o 下次压缩指定流的数据包时,重新发送所有静态和动态信息(通过IR数据包)

unless it has confidence that information sent after the packet that is being acknowledged already provides a suitable response to the STATIC-NACK feedback.

除非它确信在被确认的分组之后发送的信息已经提供了对静态NACK反馈的适当响应。

5.2.3. Context Replication
5.2.3. 上下文复制

A compressor MAY support context replication by implementing the additional compression and feedback logic defined in [RFC4164].

压缩器可以通过实现[RFC4164]中定义的额外压缩和反馈逻辑来支持上下文复制。

5.3. Decompressor Operation
5.3. 减压器操作
5.3.1. Decompressor States and Logic
5.3.1. 解压器状态与逻辑

The three states of the decompressor are No Context (NC), Static Context (SC), and Full Context (FC). The decompressor starts in its lowest compression state, the NC state. Successful decompression will always move the decompressor to the FC state. The decompressor state machine normally never leaves the FC state once it has entered this state; only repeated decompression failures will force the decompressor to transit downwards to a lower state.

解压器的三种状态是无上下文(NC)、静态上下文(SC)和完整上下文(FC)。解压缩程序在其最低压缩状态NC状态下启动。成功解压将始终将解压器移动到FC状态。解压缩器状态机一旦进入FC状态,通常不会离开FC状态;只有反复的减压失败才会迫使减压器向下过渡到较低的状态。

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

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

                                 Success
                +-->------>------>------>------>------>--+
                |                                        |
    No Static   |            No Dynamic        Success   |    Success
     +-->--+    |             +-->--+      +--->----->---+    +-->--+
     |     |    |             |     |      |             |    |     |
     |     v    |             |     v      |             v    |     v
   +-----------------+   +---------------------+   +-------------------+
   | No Context (NC) |   | Static Context (SC) |   | Full Context (FC) |
   +-----------------+   +---------------------+   +-------------------+
      ^                         |        ^                         |
      |  Static Context         |        | Context Damage Assumed  |
      |  Damage Assumed         |        |                         |
      +-----<------<------<-----+        +-----<------<------<-----+
        
                                 Success
                +-->------>------>------>------>------>--+
                |                                        |
    No Static   |            No Dynamic        Success   |    Success
     +-->--+    |             +-->--+      +--->----->---+    +-->--+
     |     |    |             |     |      |             |    |     |
     |     v    |             |     v      |             v    |     v
   +-----------------+   +---------------------+   +-------------------+
   | No Context (NC) |   | Static Context (SC) |   | Full Context (FC) |
   +-----------------+   +---------------------+   +-------------------+
      ^                         |        ^                         |
      |  Static Context         |        | Context Damage Assumed  |
      |  Damage Assumed         |        |                         |
      +-----<------<------<-----+        +-----<------<------<-----+
        
5.3.1.1. Reconstruction and Verification
5.3.1.1. 重建与核查

When decompressing an IR or an IR-DYN packet, the decompressor MUST validate the integrity of the received header using CRC-8 validation [RFC5795]. If validation fails, the packet MUST NOT be delivered to upper layers.

解压IR或IR-DYN数据包时,解压器必须使用CRC-8验证[RFC5795]验证接收到的报头的完整性。如果验证失败,则数据包不得传递到上层。

Upon receiving an IR-CR packet, the decompressor MUST perform the actions as specified in [RFC4164].

收到IR-CR数据包后,解压缩器必须执行[RFC4164]中规定的操作。

When decompressing other packet types (e.g., CO packets), the decompressor MUST validate the outcome of the decompression attempt using CRC verification [RFC5795]. If verification fails, a decompressor implementation MAY attempt corrective or repair measures on the packet, and the result of any attempt MUST be validated using the CRC verification; otherwise, the packet MUST NOT be delivered to upper layers.

当解压缩其他数据包类型(例如CO数据包)时,解压缩器必须使用CRC验证[RFC5795]验证解压缩尝试的结果。如果验证失败,解压器实现可以尝试对数据包采取纠正或修复措施,并且必须使用CRC验证验证任何尝试的结果;否则,数据包不得传送到上层。

When the CRC-8 validation or the CRC verification of the received header is successful, the decompressor SHOULD update its context with the information received in the current header; the decompressor then passes the reconstructed packet to the system's network layer. Otherwise, the decompressor context MUST NOT be updated.

当接收到的报头的CRC-8验证或CRC验证成功时,解压缩器应使用当前报头中接收到的信息更新其上下文;解压器然后将重构的数据包传递到系统的网络层。否则,不得更新解压缩程序上下文。

If the received packet is older than the current reference packet, e.g., based on the master sequence number (MSN) in the compressed packet, the decompressor MAY refrain from updating the context using the information received in the current packet, even if the correctness of its header was successfully verified.

如果接收到的分组早于当前参考分组,例如,基于压缩分组中的主序列号(MSN),则解压缩器可以避免使用在当前分组中接收到的信息更新上下文,即使其报头的正确性已成功验证。

5.3.1.2. Detecting Context Damage
5.3.1.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 that are inferred from other fields).

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

The decompressor may assume that some or the entire context is invalid, following one or more failures to validate or verify a header using the CRC. Because the decompressor cannot know the exact reason(s) for a CRC failure or what field caused it, the validity of the context hence does not refer to what exact context entry is deemed valid or not.

在使用CRC验证或验证报头的一个或多个失败之后,解压缩程序可能会假定某些或整个上下文无效。由于解压缩程序无法知道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 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.

上下文的有效性与上下文问题的检测有关。解压器首先假设最有可能导致故障的信息类型是每个数据包通常改变的状态,即上下文动态部分的上下文损坏。在反复出现故障和修复不成功时,解压器会假定整个上下文(包括静态部分)需要修复,即静态上下文损坏。

Context Damage Detection

上下文损伤检测

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

上下文损坏的假设意味着解压器不会尝试解压缩携带3位CRC的CO报头,而只尝试解压缩IR、IR-DYN或IR-CR报头或受CRC-7保护的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 may attempt decompression. In other words, validity of the context refers to the ability of a decompressor to attempt or not attempt decompression of specific packet types.

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

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

Initially, while working in the No Context (NC) state, the decompressor has not yet successfully decompressed a packet.

最初,在无上下文(NC)状态下工作时,解压缩程序尚未成功解压缩数据包。

Allowing decompression:

允许解压缩:

In the NC state, only packets carrying sufficient information on the static fields (IR and IR-CR packets) can be decompressed; otherwise, the packet MUST NOT be decompressed and MUST NOT be delivered to upper layers.

在NC状态下,只能解压缩携带关于静态字段的足够信息的分组(IR和IR-CR分组);否则,数据包不得解压缩,也不得传送到上层。

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 decompression of an IR packet has failed, subject to the feedback rate limitation as described in Section 5.3.2.

在NC状态下,如果接收到非IR类型的数据包,或者如果IR数据包解压缩失败,则解压器应发送静态NACK,并遵守第5.3.2节中所述的反馈速率限制。

Once a packet has been validated and decompressed correctly, the decompressor MUST transit to the FC state.

一旦数据包被正确验证和解压缩,解压缩程序必须转换到FC状态。

5.3.1.4. Static Context (SC) State
5.3.1.4. 静态上下文(SC)状态

When the decompressor is in the Static Context (SC) state, only the static part of the decompressor context is valid.

当解压缩程序处于静态上下文(SC)状态时,只有解压缩程序上下文的静态部分有效。

From the SC state, the decompressor moves back to the NC state if static context damage is detected.

如果检测到静态上下文损坏,则解压缩程序将从SC状态移回NC状态。

Allowing decompression:

允许解压缩:

In the SC state, packets carrying sufficient information on the dynamic fields covered by an 8-bit CRC (e.g., IR and IR-DYN) or CO packets covered by a 7-bit CRC can be decompressed; otherwise, the packet MUST NOT be decompressed and MUST NOT be delivered to upper layers.

在SC状态下,可以解压缩携带关于由8位CRC(例如,IR和IR-DYN)覆盖的动态字段的足够信息的分组或由7位CRC覆盖的CO分组;否则,数据包不得解压缩,也不得传送到上层。

Feedback logic:

反馈逻辑:

In the SC state, the decompressor should send a STATIC-NACK if CRC validation of an IR/IR-DYN/IR-CR fails and static context damage is assumed. If any other packet type is received, the decompressor should send a NACK. Both of the above cases are subject to the feedback rate limitation as described in Section 5.3.2.

在SC状态下,如果IR/IR-DYN/IR-CR的CRC验证失败并且假设静态上下文损坏,则解压缩程序应发送静态NACK。如果接收到任何其他数据包类型,解压缩程序应发送NACK。上述两种情况均受到第5.3.2节中所述的反馈率限制。

Once a packet has been validated and decompressed correctly, the decompressor MUST transit to the FC state.

一旦数据包被正确验证和解压缩,解压缩程序必须转换到FC状态。

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

In the Full Context (FC) state, both the static and the dynamic parts of the decompressor context are valid. From the FC state, the decompressor moves back to the SC state if context damage is detected.

在完整上下文(FC)状态下,解压器上下文的静态和动态部分都有效。如果检测到上下文损坏,则解压缩程序将从FC状态移回SC状态。

Allowing decompression:

允许解压缩:

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

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

Feedback logic:

反馈逻辑:

In the FC state, the decompressor should send a NACK if the decompression of any packet type fails and context damage is assumed, subject to the feedback rate limitation as described in Section 5.3.2.

在FC状态下,如果任何数据包类型的解压缩失败,并且假设上下文损坏,则解压缩程序应发送NACK,并遵守第5.3.2节所述的反馈速率限制。

5.3.2. Feedback Logic
5.3.2. 反馈逻辑

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) establishes this channel.

解压器可以发送正反馈(ACKs),以最初建立特定流的反馈通道。正反馈(ACKs)或负反馈(NACKs)建立此通道。

Once the feedback channel is established, the decompressor is REQUIRED to continue sending NACKs or STATIC-NACKs for as long as the context is associated with the same profile, in this case with profile 0x0006, as per the logic defined for each state in Section 5.3.1.

一旦建立反馈通道,根据第5.3.1节中为每个状态定义的逻辑,只要上下文与相同的配置文件(在这种情况下为配置文件0x0006)关联,解压器就需要继续发送NACK或静态NACK。

The decompressor MAY send ACKs upon successful decompression of any packet type. In particular, when a packet carrying a significant context update is correctly decompressed, the decompressor MAY send an ACK.

解压器可以在成功解压任何包类型时发送ack。具体地,当携带重要上下文更新的分组被正确解压缩时,解压缩器可以发送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 to the same event.

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

5.3.3. Context Replication
5.3.3. 上下文复制

ROHC-TCP supports context replication; therefore, the decompressor MUST implement the additional decompressor and feedback logic defined in [RFC4164].

ROHC-TCP支持上下文复制;因此,解压器必须实现[RFC4164]中定义的附加解压器和反馈逻辑。

6. Encodings in ROHC-TCP (Normative)
6. ROHC-TCP中的编码(标准)
6.1. Control Fields in ROHC-TCP
6.1. ROHC-TCP中的控制字段

In ROHC-TCP, a number of control fields are used by the decompressor in its interpretation of the format of the packets received from the compressor.

在ROHC-TCP中,解压器在解释从压缩器接收的数据包格式时使用了许多控制字段。

A control field is a field that is transmitted from the compressor to the decompressor, but is not part of the uncompressed header. Values for control fields can be set up in the context of both the compressor and the decompressor. Once established at the decompressor, the values of these fields should be kept until updated by another packet.

控制字段是从压缩机传输到解压缩器的字段,但不是未压缩标头的一部分。可以在压缩机和解压缩器的上下文中设置控制字段的值。一旦在解压缩程序中建立,这些字段的值应该保留,直到被另一个数据包更新。

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

There is no field in the TCP header that can act as the master sequence number for TCP compression, as explained in [RFC4413], Section 5.6.

如[RFC4413]第5.6节所述,TCP报头中没有字段可作为TCP压缩的主序列号。

To overcome this problem, ROHC-TCP introduces a control field called the Master Sequence Number (MSN) field. The MSN field is created at the compressor, rather than using one of the fields already present in the uncompressed header. The compressor increments the value of the MSN by one for each packet that it sends.

为了克服这个问题,ROHC-TCP引入了一个称为主序列号(MSN)字段的控制字段。MSN字段是在压缩器处创建的,而不是使用未压缩标头中已存在的字段之一。压缩器为其发送的每个数据包将MSN的值增加1。

The MSN field has the following two functions:

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

1. Differentiating between packets when sending feedback data.

1. 发送反馈数据时区分数据包。

2. Inferring the value of incrementing fields such as the IP-ID.

2. 推断递增字段(如IP-ID)的值。

The MSN field is present in every packet sent by the compressor. The MSN is LSB encoded within the CO packets, and the 16-bit MSN is sent in full in IR/IR-DYN packets. The decompressor always sends the MSN as part of the feedback information. The compressor can later use the MSN to infer which packet the decompressor is acknowledging.

MSN字段存在于压缩机发送的每个数据包中。MSN在CO包中进行LSB编码,16位MSN在IR/IR-DYN包中完整发送。解压器总是发送MSN作为反馈信息的一部分。压缩器稍后可以使用MSN来推断解压器正在确认哪个数据包。

When the MSN is initialized, it SHOULD be initialized to a random value. The compressor should only initialize a new MSN for the initial IR or IR-CR packet sent for a CID that corresponds to a context that is not already associated with this profile. In other words, if the compressor reuses the same CID to compress many TCP flows one after the other, the MSN is not reinitialized but rather continues to increment monotonically.

初始化MSN时,应将其初始化为随机值。压缩器应仅为初始IR或IR-CR数据包初始化一个新MSN,该初始IR或IR-CR数据包是为对应于尚未与此配置文件关联的上下文的CID发送的。换句话说,如果压缩器重用相同的CID一个接一个地压缩多个TCP流,则MSN不会重新初始化,而是继续单调递增。

For context replication, the compressor does not use the MSN of the base context when sending the IR-CR packet, unless the replication process overwrites the base context (i.e., Base CID == CID). Instead, the compressor uses the value of the MSN if it already exists in the ROHC-TCP context being associated with the new flow (CID); otherwise, the MSN is initialized to a new value.

对于上下文复制,压缩器在发送IR-CR数据包时不使用基本上下文的MSN,除非复制过程覆盖基本上下文(即,基本CID==CID)。相反,如果MSN的值已经存在于与新流(CID)关联的ROHC-TCP上下文中,则压缩器使用MSN的值;否则,MSN将初始化为新值。

6.1.2. IP-ID Behavior
6.1.2. IP-ID行为

The IP-ID field of the IPv4 header can have different change patterns. Conceptually, a compressor monitors changes in the value of the IP-ID field and selects encoding methods and packet formats that are the closest match to the observed change pattern.

IPv4标头的IP-ID字段可以具有不同的更改模式。从概念上讲,压缩器监视IP-ID字段值的变化,并选择与观察到的变化模式最匹配的编码方法和数据包格式。

ROHC-TCP defines different types of compression techniques for the IP-ID, to provide the flexibility to compress any of the behaviors it may observe for this field: sequential in network byte order (NBO), sequential byte-swapped, random (RND), or constant to a value of zero.

ROHC-TCP为IP-ID定义了不同类型的压缩技术,以提供对该字段可能观察到的任何行为进行压缩的灵活性:网络字节顺序顺序(NBO)、顺序字节交换、随机(RND)或常数为零。

The compressor monitors changes in the value of the IP-ID field for a number of packets, to identify which one of the above listed compression alternatives is the closest match to the observed change pattern. The compressor can then select packet formats and encoding methods based on the identified field behavior.

压缩器监控多个数据包的IP-ID字段值的变化,以确定上面列出的压缩备选方案中哪一个与观察到的变化模式最匹配。然后,压缩器可以根据识别的字段行为选择数据包格式和编码方法。

If more than one level of IP headers is present, ROHC-TCP can assign a sequential behavior (NBO or byte-swapped) only to the IP-ID of the innermost IP header. This is because only this IP-ID can possibly have a sufficiently close correlation with the MSN (see also Section 6.1.1) to compress it as a sequentially changing field. Therefore, a compressor MUST NOT assign either the sequential (NBO) or the sequential byte-swapped behavior to tunneling headers.

如果存在多个级别的IP报头,ROHC-TCP只能将顺序行为(NBO或字节交换)分配给最内层IP报头的IP-ID。这是因为只有该IP-ID可能与MSN有足够密切的相关性(另见第6.1.1节),以将其压缩为连续变化的字段。因此,压缩器不得将顺序(NBO)或顺序字节交换行为分配给隧道头。

The control field for the IP-ID behavior determines which set of packet formats will be used. These control fields are also used to determine the contents of the irregular chain item (see Section 6.2) for each IP header.

IP-ID行为的控制字段确定将使用哪组数据包格式。这些控制字段还用于确定每个IP标头的不规则链项目的内容(见第6.2节)。

6.1.3. Explicit Congestion Notification (ECN)
6.1.3. 显式拥塞通知(ECN)

When ECN [RFC3168] is used once on a flow, the ECN bits could change quite often. ROHC-TCP maintains a control field in the context to indicate whether or not ECN is used. This control field is transmitted in the dynamic chain of the TCP header, and its value can be updated using specific compressed headers carrying a 7-bit CRC.

当ECN[RFC3168]在流上使用一次时,ECN位可能会经常更改。ROHC-TCP在上下文中维护一个控制字段,以指示是否使用ECN。此控制字段在TCP报头的动态链中传输,其值可以使用带有7位CRC的特定压缩报头进行更新。

When this control field indicates that ECN is being used, items of all IP and TCP headers in the irregular chain include bits used for ECN. To preserve octet-alignment, all of the TCP reserved bits are transmitted and, for outer IP headers, the entire Type of Service/ Traffic Class (TOS/TC) field is included in the irregular chain. When there is only one IP header present in the packet (i.e., no IP tunneling is used), this compression behavior allows the compressor to handle changes in the ECN bits by adding a single octet to the compressed header.

当此控制字段指示正在使用ECN时,不规则链中所有IP和TCP头的项包括用于ECN的位。为了保持八位字节对齐,传输所有TCP保留位,对于外部IP报头,整个服务/流量类别(TOS/TC)字段包含在不规则链中。当数据包中仅存在一个IP报头时(即,不使用IP隧道),此压缩行为允许压缩器通过向压缩报头添加单个八位组来处理ECN位中的更改。

The reason for including the ECN bits of all IP headers in the compressed packet when the control field is set is that the profile needs to efficiently compress flows containing IP tunnels using the "full-functionality option" of Section 9.1 of [RFC3168]. For these flows, a change in the ECN bits of an inner IP header is propagated to the outer IP headers. When the "limited-functionality" option is used, the compressor will therefore sometimes send one octet more than necessary per tunnel header, but this has been considered a reasonable trade-off when designing this profile.

设置控制字段时,将所有IP头的ECN位包括在压缩数据包中的原因是,配置文件需要使用[RFC3168]第9.1节的“全功能选项”有效压缩包含IP隧道的流。对于这些流,内部IP报头的ECN位的更改会传播到外部IP报头。当使用“有限功能”选项时,压缩机有时会发送一个八位字节,超过每个隧道头所需的数量,但在设计此剖面时,这被认为是一个合理的权衡。

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

Some packet 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.

某些数据包类型使用一个或多个包含子报头信息的链。链的功能是根据类似的特征(如静态、动态或不规则字段)对字段进行分组。链接是通过从最外层的头中的字段开始,按照在未压缩数据包中的出现顺序将每个头的项附加到链中来完成的。

Chains are defined for all headers compressed by ROHC-TCP, as listed below. Also listed are the names of the encoding methods used to encode each of these protocol headers.

链是为ROHC-TCP压缩的所有头定义的,如下所示。还列出了用于对每个协议头进行编码的编码方法的名称。

o TCP [RFC0793], encoding method: "tcp"

o TCP[RFC0793],编码方法:“TCP”

o IPv4 [RFC0791], encoding method: "ipv4"

o IPv4[RFC0791],编码方法:“IPv4”

o IPv6 [RFC2460], encoding method: "ipv6"

o IPv6[RFC2460],编码方法:“IPv6”

o AH [RFC4302], encoding method: "ah"

o AH[RFC4302],编码方式:“AH”

o GRE [RFC2784][RFC2890], encoding method: "gre"

o GRE[RFC2784][RFC2890],编码方法:“GRE”

o MINE [RFC2004], encoding method: "mine"

o MINE[RFC2004],编码方式:“MINE”

o IPv6 Destination Options header [RFC2460], encoding method: "ip_dest_opt"

o IPv6目标选项标头[RFC2460],编码方法:“ip_dest_opt”

o IPv6 Hop-by-Hop Options header [RFC2460], encoding method: "ip_hop_opt"

o IPv6逐跳选项标头[RFC2460],编码方法:“ip_-Hop_-opt”

o IPv6 Routing header [RFC2460], encoding method: "ip_rout_opt"

o IPv6路由报头[RFC2460],编码方法:“ip_rout_opt”

Static chain:

静态链:

The static chain consists of one item for each header of the chain of protocol headers to be compressed, starting from the outermost IP header and ending with a TCP header. In the formal description of the packet formats, this static chain item for each header is a format whose name is suffixed by "_static". The static chain is only used in IR packets.

静态链由要压缩的协议头链的每个头的一个项组成,从最外层的IP头开始,以TCP头结束。在包格式的正式描述中,每个头的静态链项是一种格式,其名称后缀为“_static”。静态链仅用于IR数据包。

Dynamic chain:

动态链:

The dynamic chain consists of one item for each header of the chain of protocol headers to be compressed, starting from the outermost IP header and ending with a TCP header. The dynamic chain item for the TCP header also contains a compressed list of TCP options (see Section 6.3). In the formal description of the packet formats, the dynamic chain item for each header type is a format whose name is suffixed by "_dynamic". The dynamic chain is used in both IR and IR-DYN packets.

动态链由要压缩的协议头链的每个头的一个项目组成,从最外层的IP头开始,以TCP头结束。TCP标头的动态链项还包含TCP选项的压缩列表(参见第6.3节)。在包格式的正式描述中,每种头类型的动态链项是一种格式,其名称后缀为“_dynamic”。动态链用于IR和IR-DYN数据包。

Replicate chain:

复制链:

The replicate chain consists of one item for each header in the chain of protocol headers to be compressed, starting from the outermost IP header and ending with a TCP header. The replicate chain item for the TCP header also contains a compressed list of TCP options (see Section 6.3). In the formal description of the packet formats, the replicate chain item for each header type is a

复制链由要压缩的协议头链中每个头的一个项目组成,从最外层的IP头开始,以TCP头结束。TCP标头的复制链项目还包含TCP选项的压缩列表(参见第6.3节)。在包格式的形式化描述中,每个头类型的复制链项是

format whose name is suffixed by "_replicate". Header fields that are not present in the replicate chain are replicated from the base context. The replicate chain is only used in the IR-CR packet.

名称后缀为“\u replicate”的格式。复制链中不存在的头字段从基本上下文复制。复制链仅用于IR-CR数据包中。

Irregular chain:

不规则链:

The structure of the irregular chain is analogous to the structure of the static chain. For each compressed packet, the irregular chain is appended at the specified location in the general format of the compressed packets as defined in Section 7.3. This chain also includes the irregular chain items for TCP options as defined in Section 6.3.6, which are placed directly after the irregular chain item of the TCP header, and in the same order as the options appear in the uncompressed packet. In the formal description of the packet formats, the irregular chain item for each header type is a format whose name is suffixed by "_irregular". The irregular chain is used only in CO packets.

不规则链的结构类似于静态链的结构。对于每个压缩包,按照第7.3节中定义的压缩包的一般格式,在指定位置附加不规则链。该链还包括第6.3.6节中定义的TCP选项的不规则链项,这些不规则链项直接放置在TCP报头的不规则链项之后,其顺序与未压缩数据包中出现的选项相同。在包格式的正式描述中,每种头类型的不规则链项是一种格式,其名称后缀为“_unregular”。不规则链仅用于CO数据包。

The format of the irregular chain for the innermost IP header differs from the format of outer IP headers, since this header is part of the compressed base header.

最内层IP头的不规则链的格式不同于外部IP头的格式,因为此头是压缩的基本头的一部分。

6.3. Compressing TCP Options with List Compression
6.3. 使用列表压缩压缩压缩TCP选项

This section describes in detail how list compression is applied to the TCP options. In the definition of the packet formats for ROHC-TCP, the most frequent TCP options have one encoding method each, as listed in the table below.

本节详细介绍如何将列表压缩应用于TCP选项。在ROHC-TCP的数据包格式定义中,最常见的TCP选项各有一种编码方法,如下表所示。

           +-----------------+------------------------+
           |   Option name   |  Encoding method name  |
           +-----------------+------------------------+
           |      NOP        | tcp_opt_nop            |
           |      EOL        | tcp_opt_eol            |
           |      MSS        | tcp_opt_mss            |
           |  WINDOW SCALE   | tcp_opt_wscale         |
           |   TIMESTAMP     | tcp_opt_ts             |
           | SACK-PERMITTED  | tcp_opt_sack_permitted |
           |      SACK       | tcp_opt_sack           |
           | Generic options | tcp_opt_generic        |
           +-----------------+------------------------+
        
           +-----------------+------------------------+
           |   Option name   |  Encoding method name  |
           +-----------------+------------------------+
           |      NOP        | tcp_opt_nop            |
           |      EOL        | tcp_opt_eol            |
           |      MSS        | tcp_opt_mss            |
           |  WINDOW SCALE   | tcp_opt_wscale         |
           |   TIMESTAMP     | tcp_opt_ts             |
           | SACK-PERMITTED  | tcp_opt_sack_permitted |
           |      SACK       | tcp_opt_sack           |
           | Generic options | tcp_opt_generic        |
           +-----------------+------------------------+
        

Each of these encoding methods has an uncompressed format, a format suffixed by "_list_item" and a format suffixed by "_irregular". In some cases, a single encoding method may have multiple "_list_item"

这些编码方法中的每一种都有一种未压缩格式、一种后缀为“\u list\u item”的格式和一种后缀为“\u unregular”的格式。在某些情况下,单个编码方法可能有多个“\u列表\u项”

or "_irregular" formats, in which case bindings inside these formats determine what format is used. This is further described in the following sections.

或“_unregular”格式,在这种情况下,这些格式中的绑定决定使用什么格式。以下各节将对此进行进一步描述。

6.3.1. List Compression
6.3.1. 列表压缩

The TCP options 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:

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

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

To compress this list, ROHC-TCP uses a list compression scheme, which compresses each of these items individually and combines them into a compressed list.

为了压缩这个列表,ROHC-TCP使用一个列表压缩方案,该方案单独压缩这些项中的每一项,并将它们组合成一个压缩列表。

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

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

1) When a context is being initialized, a complete representation of the compressed list of options is transmitted. All options that have any content are present in the compressed list of items sent by the compressor.

1) 初始化上下文时,将传输选项压缩列表的完整表示。压缩程序发送的项目压缩列表中存在所有包含任何内容的选项。

Then, once the context has been initialized:

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

2) When the structure AND the content of the list are unchanged, no information about the list is sent in compressed headers.

2) 当列表的结构和内容不变时,不会在压缩头中发送有关列表的任何信息。

3) When the structure of the list is constant, and when only the content defined within the irregular format for one or more options is changed, no information about the list needs to be sent in compressed base headers; the irregular content is sent as part of the irregular chain, as described in Section 6.3.6.

3) 当列表的结构是固定的,并且仅当一个或多个选项的不规则格式中定义的内容发生更改时,不需要在压缩的基本标题中发送关于列表的信息;不规则内容作为不规则链的一部分发送,如第6.3.6节所述。

4) When the structure of the list changes, a compressed list is sent in the compressed base header, including a representation of its structure and order. Content defined within the irregular format of an option can still be sent as part of the irregular chain (as described in Section 6.3.6), provided that the item content is not part of the compressed list.

4) 当列表的结构改变时,压缩的列表在压缩的基本头中发送,包括其结构和顺序的表示。如果项目内容不是压缩列表的一部分,则在选项的不规则格式中定义的内容仍可作为不规则链的一部分发送(如第6.3.6节所述)。

6.3.2. Table-Based Item Compression
6.3.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 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 successfully verified using the CRC. The decompressor retrieves the item from the table whenever an index without an accompanying item is received.

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

If an index without an accompanying item is received and the decompressor does not have any context for this index, the header MUST be discarded and a NACK SHOULD be sent.

如果接收到没有附带项的索引,并且解压缩程序没有该索引的任何上下文,则必须丢弃标头并发送NACK。

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

Each item present in a compressed list is represented by:

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

o an index into the table of items

o 项目表的索引

o 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 项目(如果设置了存在位)

Decompression of an item will fail if the presence bit is not set and the decompressor has no entry in the context for that item.

如果未设置存在位且解压器在该项的上下文中没有条目,则该项的解压将失败。

A compressed list of TCP options uses the following encoding:

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

        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.

M:压缩列表中的席项数。

XI_1, ..., XI_m: m XI items. Each XI represents one TCP option in the uncompressed packet, in the same order as they appear in the uncompressed packet.

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

The format of an XI item is as follows:

一席项目的格式如下:

                 +---+---+---+---+
         PS = 0: | X |   Index   |
                 +---+---+---+---+
        
                 +---+---+---+---+
         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 and is instead included in the irregular chain.

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.3.4.

索引:项表中的索引。见第6.3.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. The format of the entries in the item list is described in the table in Section 6.3. The compressed format(s) suffixed by "_list_item" in the encoding methods defines the item inside the compressed item list.

项目1,…,项目n:每个项目对应于席席1,XI=1,席,…第6.3节的表格中描述了项目列表中条目的格式。编码方法中后缀为“_list_item”的压缩格式定义了压缩项列表中的项。

6.3.4. Item Table Mappings
6.3.4. 项表映射

The item table for TCP options list compression is limited to 16 different items, since it is unlikely that any packet flow will contain a larger number of unique options.

TCP选项列表压缩的项表限制为16个不同的项,因为任何数据包流都不可能包含更多的唯一选项。

The mapping between the TCP option type and table indexes are listed in the table below:

TCP选项类型和表索引之间的映射如下表所示:

         +-----------------+---------------+
         |   Option name   |  Table index  |
         +-----------------+---------------+
         |      NOP        |       0       |
         |      EOL        |       1       |
         |      MSS        |       2       |
         |  WINDOW SCALE   |       3       |
         |   TIMESTAMP     |       4       |
         | SACK-PERMITTED  |       5       |
         |      SACK       |       6       |
         | Generic options |      7-15     |
         +-----------------+---------------+
        
         +-----------------+---------------+
         |   Option name   |  Table index  |
         +-----------------+---------------+
         |      NOP        |       0       |
         |      EOL        |       1       |
         |      MSS        |       2       |
         |  WINDOW SCALE   |       3       |
         |   TIMESTAMP     |       4       |
         | SACK-PERMITTED  |       5       |
         |      SACK       |       6       |
         | Generic options |      7-15     |
         +-----------------+---------------+
        

Some TCP options are used more frequently than others. To simplify their compression, a part of the item table is reserved for these option types, as shown on the table above. Both the compressor and the decompressor MUST use these mappings between item and indexes to (de)compress TCP options when using list compression.

某些TCP选项的使用频率高于其他选项。为了简化它们的压缩,item表的一部分是为这些选项类型保留的,如上表所示。使用列表压缩时,压缩器和解压缩器都必须使用项和索引之间的这些映射来(反)压缩TCP选项。

It is expected that the option types for which an index is reserved in the item table will only appear once in a list. However, if an option type is detected twice in the same options list and if both options have a different content, the compressor should compress the second occurrence of the option type by mapping it to a generic compressed option. Otherwise, if the options have the exact same content, the compressor can still use the same table index for both.

项目表中为其保留索引的选项类型在列表中仅出现一次。但是,如果在同一选项列表中两次检测到选项类型,并且两个选项的内容不同,则压缩器应通过将选项类型的第二个匹配项映射到通用压缩选项来压缩该选项类型。否则,如果选项的内容完全相同,则压缩器仍然可以对这两个选项使用相同的表索引。

The NOP option

NOP选项

The NOP option can appear more than once in the list. However, since its value is always the same, no context information needs to be transmitted. Multiple NOP options can thus be mapped to the same index. Since the NOP option does not have any content when compressed as a "_list_item", it will never be present in the item list. For consistency, the compressor should still establish an entry in the list by setting the presence bit, as done for the other type of options.

NOP选项可以在列表中出现多次。但是,由于其值始终相同,因此不需要传输上下文信息。因此,可以将多个NOP选项映射到同一索引。由于NOP选项在压缩为“\u列表\u项目”时没有任何内容,因此它永远不会出现在项目列表中。为了保持一致性,压缩器仍应通过设置存在位在列表中建立一个条目,就像对其他类型的选项所做的那样。

List compression always preserves the original order of each item in the decompressed list, whether or not the item is present in the compressed "_list_item" or if multiple items of the same type can be mapped to the same index, as for the NOP option.

列表压缩始终保留解压列表中每个项的原始顺序,无论该项是否存在于压缩的“\u List\u item”中,或者同一类型的多个项是否可以映射到同一索引(如NOP选项)。

The EOL option

下线选项

The size of the compressed format for the EOL option can be larger than one octet, and it is defined so that it includes the option padding. This is because the EOL should terminate the parsing of the options, but it can also be followed by padding octets that all have the value zero.

EOL选项的压缩格式的大小可以大于一个八位字节,并且它的定义使其包含选项填充。这是因为EOL应该终止对选项的解析,但它后面也可以填充所有值为零的八位字节。

The Generic option

通用选项

The Generic option can be used to compress any type of TCP option that does not have a reserved index in the item table.

泛型选项可用于压缩项表中没有保留索引的任何类型的TCP选项。

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

A compressed list for TCP options that is part of the dynamic chain (e.g., in IR or IR-DYN packets) must have all its list items present, i.e., all X-bits in the XI list MUST be set.

作为动态链的一部分的TCP选项的压缩列表(例如,在IR或Ir DYN分组中)必须具有其所有列表项,即,必须设置席列表中的所有X位。

6.3.6. Irregular Chain Items for TCP Options
6.3.6. TCP选项的不规则链项

The "_list_item" represents the option inside the compressed item list, and the "_irregular" format is used for the option fields that are expected to change with each packet. When an item of the specified type is present in the current context, these irregular fields are present in each compressed packet, as part of the irregular chain. Since many of the TCP option types are not expected to change for the duration of a flow, many of the "_irregular" formats are empty.

“_list_item”表示压缩项列表中的选项,“_unregular”格式用于预期随每个数据包更改的选项字段。当指定类型的项出现在当前上下文中时,这些不规则字段作为不规则链的一部分出现在每个压缩包中。由于许多TCP选项类型在流持续期间不会更改,因此许多“\u unregular”格式为空。

The irregular chain for TCP options is structured analogously to the structure of the TCP options in the uncompressed packet. If a compressed list is present in the compressed packet, then the irregular chain for TCP options must not contain irregular items for the list items that are transmitted inside the compressed list (i.e., items in the list that have the X-bit set in its XI). The items that are not present in the compressed list, but are present in the uncompressed list, must have their respective irregular items present in the irregular chain.

TCP选项的不规则链的结构类似于未压缩数据包中TCP选项的结构。如果压缩包中存在压缩列表,则TCP选项的不规则链不得包含压缩列表中传输的列表项的不规则项(即列表中X位设置在其XI中的项)。压缩列表中不存在但未压缩列表中存在的项必须在不规则链中存在各自的不规则项。

6.3.7. Replication of TCP Options
6.3.7. TCP选项的复制

The entire table of TCP options items is always replicated when using the IR-CR packet. In the IR-CR packet, the list of options for the new flow is also transmitted as a compressed list in the IR-CR packet.

使用IR-CR数据包时,始终复制TCP选项项的整个表。在IR-CR分组中,新流的选项列表也作为IR-CR分组中的压缩列表发送。

6.4. Profile-Specific Encoding Methods
6.4. 特定于配置文件的编码方法

This section defines encoding methods that are specific to this profile. These methods are used in the formal definition of the packet formats in Section 8.

本节定义特定于此配置文件的编码方法。这些方法用于第8节中数据包格式的正式定义。

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

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

此编码方法压缩IPv4标头的标头校验和字段。该校验和在[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. When almost all IP header information is compressed away, and when decompression is verified by a CRC computed over the original header for every compressed packet, there is no point in having this additional checksum; instead, it can be recomputed at the decompressor side.

如上所述,报头校验和保护单个跃点不处理损坏的报头。当几乎所有的IP报头信息都被压缩掉,并且当解压通过在每个压缩包的原始报头上计算的CRC进行验证时,没有必要使用这个额外的校验和;相反,它可以在解压缩器端重新计算。

The "inferred_ip_v4_header_checksum" encoding method thus compresses the IPv4 header checksum down to a size of zero bits. Using this encoding method, the decompressor infers the value of this field using the computation above.

因此,“推断的\u ip\u v4\u报头\u校验和”编码方法将IPv4报头校验和压缩为零位大小。使用此编码方法,解压器使用上述计算推断此字段的值。

This encoding method implicitly assumes that the compressor will not process a corrupted header; otherwise, it cannot guarantee that the checksum as recomputed by the decompressor will be bitwise identical to its original value before compression.

此编码方法隐式假设压缩器不会处理损坏的头;否则,它不能保证解压器重新计算的校验和在压缩前按位与其原始值相同。

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

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

此编码方法压缩最小封装头校验和。[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 zero. The IP header and IP payload (after the minimal forwarding header) are not included in this checksum computation.

最小转发报头中所有16位字的补码和的16位补码。为了计算校验和,校验和字段的值为零。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_checksum”编码方法将最小封装报头校验和压缩到零位大小,即,此字段的压缩报头中不传输任何位。使用此编码方法,解压器使用上述计算推断此字段的值。

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

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

6.4.3. inferred_ip_v4_length
6.4.3. 推断的\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 [RFC0791] as follows:

此编码方法压缩IPv4标头的总长度字段。IPv4标头的总长度字段在[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 Total Length field down to a size of zero bits. 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.4.4. inferred_ip_v6_length
6.4.4. 推断的ip长度

This encoding method compresses the Payload Length field of the IPv6 header. This length field is defined in [RFC2460] as follows:

此编码方法压缩IPv6标头的有效负载长度字段。该长度字段在[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. 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报头的有效负载长度字段压缩到零位大小。使用这种编码方法,解压器通过以八位字节为单位计算解压后整个数据包的长度来推断此字段的值。

6.4.5. inferred_offset
6.4.5. 推断的偏移量

This encoding method compresses the data offset field of the TCP header.

此编码方法压缩TCP标头的数据偏移量字段。

The "inferred_offset" encoding method is used on the Data Offset field of the TCP header. This field is defined in [RFC0793] as:

“推断的_偏移量”编码方法用于TCP标头的数据偏移量字段。该字段在[RFC0793]中定义为:

Data Offset: 4 bits

数据偏移量:4位

The number of 32-bit words in the TCP header. This indicates where the data begins. The TCP header (even one including options) is an integral number of 32 bits long.

TCP标头中的32位字数。这表示数据从何处开始。TCP报头(甚至包括选项)是32位长的整数。

The "inferred_offset" encoding method compresses the Data Offset field of the TCP header down to a size of zero bits. Using this encoding method, the decompressor infers the value of this field by first decompressing the TCP options list, and by then setting:

“推断的_偏移”编码方法将TCP头的数据偏移字段压缩到零位大小。使用此编码方法,解压器首先解压TCP选项列表,然后设置:

              data offset = (options length / 4) + 5
        
              data offset = (options length / 4) + 5
        

The equation above uses integer arithmetic.

上面的等式使用整数运算。

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

In CO packets (see Section 7.3), the innermost IP header and the TCP header are combined to create a compressed base header. In some cases, the IP header will have a number of extension headers between itself and the TCP header.

在CO数据包中(参见第7.3节),最里面的IP报头和TCP报头被组合起来创建一个压缩的基本报头。在某些情况下,IP报头在其自身和TCP报头之间会有许多扩展报头。

To remain formally correct, the base header must define some representation of these extension headers, which is what this encoding method is used for. This encoding method skips over all the extension headers and does not encode any of the fields. Changed fields in these headers are encoded in the irregular chain.

为了保持形式上的正确性,基本头必须定义这些扩展头的某种表示,这就是此编码方法的用途。此编码方法跳过所有扩展头,不编码任何字段。这些标题中更改的字段在不规则链中编码。

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

This encoding method, as well as the baseheader_extension_headers encoding method described above, is needed for the specification to remain formally correct. It is used in CO packets (see Section 7.3) to describe tunneling IP headers and their respective extension headers (i.e., all headers located before the innermost IP header).

该编码方法以及上述baseheader_扩展_headers编码方法是规范保持形式正确所必需的。它用于CO数据包(见第7.3节)中,用于描述隧道IP头及其各自的扩展头(即位于最内层IP头之前的所有头)。

This encoding method skips over all the fields in these headers and does not perform any encoding. Changed fields in outer headers are instead handled by the irregular chain.

此编码方法跳过这些头中的所有字段,不执行任何编码。外部标题中更改的字段由不规则链处理。

6.4.8. Scaled Encoding of Fields
6.4.8. 字段的缩放编码

Some header fields will exhibit a change pattern where the field increases by a constant value or by multiples of the same value.

某些标题字段将显示一种更改模式,其中字段增加一个常量值或相同值的倍数。

Examples of fields that may have this behavior are the TCP Sequence Number and the TCP Acknowledgment Number. For such fields, ROHC-TCP provides the means to downscale the field value before applying LSB encoding, which allows the compressor to transmit fewer bits.

可能具有此行为的字段示例有TCP序列号和TCP确认号。对于此类字段,ROHC-TCP提供了在应用LSB编码之前缩小字段值的方法,这允许压缩器传输更少的位。

To be able to use scaled encoding, the field is required to fulfill the following equation:

为了能够使用缩放编码,该字段需要满足以下等式:

        unscaled_value = scaling_factor * scaled_value + residue
        
        unscaled_value = scaling_factor * scaled_value + residue
        

To use the scaled encoding, the compressor must be confident that the decompressor has established values for the "residue" and the "scaling_factor", so that it can correctly decompress the field when only an LSB-encoded "scaled_value" is present in the compressed packet.

为了使用缩放编码,压缩器必须确信解压器已经为“剩余”和“缩放因子”建立了值,以便当压缩包中仅存在LSB编码的“缩放因子”时,压缩器能够正确地解压缩字段。

Once the compressor is confident that the value of the scaling_factor and the value of the residue have been established in the decompressor, the compressor may send compressed packets using the scaled representation of the field. The compressor MUST NOT use scaled encoding with the value of the scaling_factor set to zero.

一旦压缩器确信已在解压缩器中建立缩放因子的值和剩余值,则压缩器可使用字段的缩放表示发送压缩分组。压缩程序不得使用缩放因子值设置为零的缩放编码。

If the compressor detects that the value of the residue has changed, or if the compressor uses a different value for the scaling factor, it MUST NOT use scaled encoding until it is confident that the decompressor has received the new value(s) of these fields.

如果压缩器检测到剩余值已更改,或者如果压缩器使用不同的缩放因子值,则在确信解压缩器已接收到这些字段的新值之前,不得使用缩放编码。

When the unscaled value of the field wraps around, the value of the residue is likely to change, even if the scaling_factor remains constant. In such a case, the compressor must act in the same way as for any other change in the residue.

当字段的未缩放值环绕时,即使缩放因子保持不变,余数的值也可能发生变化。在这种情况下,压缩机的工作方式必须与残渣的任何其他变化相同。

The following subsections describe how the scaled encoding is applied to specific fields in ROHC-TCP, in particular, how the scaling_factor and residue values are established for the different fields.

以下小节描述了缩放编码如何应用于ROHC-TCP中的特定字段,特别是如何为不同字段建立缩放因子和剩余值。

6.4.8.1. Scaled TCP Sequence Number Encoding
6.4.8.1. 缩放TCP序列号编码

For some TCP flows, such as data transfers, the payload size will be constant over periods of time. For such flows, the TCP Sequence Number is bound to increase by multiples of the payload size between packets, which means that this field can be a suitable target for scaled encoding. When using this encoding, the payload size will be used as the scaling factor (i.e., as the value for scaling_factor) of this encoding. This means that the scaling factor does not need to be explicitly transmitted, but is instead inferred from the length of the payload in the compressed packet.

对于某些TCP流,例如数据传输,有效负载大小将在一段时间内保持不变。对于此类流,TCP序列号必然会增加数据包之间有效负载大小的倍数,这意味着该字段可以成为缩放编码的合适目标。使用此编码时,有效负载大小将用作此编码的比例因子(即,作为比例因子的值)。这意味着不需要显式地传输比例因子,而是根据压缩分组中的有效载荷长度来推断。

Establishing scaling_factor:

确定比例因子:

The scaling factor is established by sending unscaled TCP Sequence Number bits, so that the decompressor can infer the scaling_factor from the payload size.

缩放因子是通过发送未缩放的TCP序列号位来建立的,因此解压器可以从有效负载大小推断缩放因子。

Establishing residue:

确定残留物:

The residue is established identically as the scaling_factor, i.e., by sending unscaled TCP Sequence Number bits.

余数与缩放因子相同,即通过发送未缩放的TCP序列号位来确定。

A detailed specification of how the TCP Sequence Number uses the scaled encoding can be found in the definitions of the packet formats, in Section 8.2.

TCP序列号如何使用缩放编码的详细规范可在第8.2节的数据包格式定义中找到。

6.4.8.2. Scaled Acknowledgment Number Encoding
6.4.8.2. 按比例确认号码编码

Similar to the pattern exhibited by the TCP Sequence Number, the expected increase in the TCP Acknowledgment Number is often constant and is therefore suitable for scaled encoding.

与TCP序列号显示的模式类似,TCP确认号的预期增加通常是恒定的,因此适合于缩放编码。

For the TCP Acknowledgment Number, the scaling factor depends on the size of packets flowing in the opposite direction; this information might not be available to the compressor/decompressor pair. For this reason, ROHC-TCP uses an explicitly transmitted scaling factor to compress the TCP Acknowledgment Number.

对于TCP确认号,比例因子取决于反向流动的数据包的大小;此信息可能对压缩机/解压缩器对不可用。因此,ROHC-TCP使用显式传输的比例因子来压缩TCP确认号。

Establishing scaling_factor:

确定比例因子:

The scaling factor is established by explicitly transmitting the value of the scaling factor (called ack_stride in the formal notation in Section 8.2) to the decompressor, using one of the packet types that can carry this information.

通过使用可携带此信息的数据包类型之一,将比例因子的值(在第8.2节的形式表示法中称为ack_stride)显式传输到解压缩器,从而确定比例因子。

Establishing residue:

确定残留物:

The scaling residue is established by sending unscaled TCP Acknowledgment Number bits, so that the decompressor can infer its value from the unscaled value and the scaling factor (ack_stride).

通过发送未缩放的TCP确认号位来建立缩放剩余,以便解压缩程序可以根据未缩放值和缩放因子(ack_)推断其值。

A detailed specification of how the TCP Acknowledgment Number uses the scaled encoding can be found in the definitions of the packet formats, in Section 8.2.

TCP确认号如何使用缩放编码的详细规范可在第8.2节的数据包格式定义中找到。

The compressor MAY use the scaled acknowledgment number encoding; what value it will use as the scaling factor is up to the compressor implementation. In the case where there is a co-located decompressor processing packets of the same TCP flow in the opposite direction, the scaling factor for the sequence number used for that flow can be used by the compressor to determine a suitable scaling factor for the TCP Acknowledgment number for this flow.

压缩器可以使用缩放确认号编码;它将使用什么值作为比例因子取决于压缩机的实现。在存在以相反方向处理相同TCP流的数据包的同一位置解压器的情况下,压缩器可以使用用于该流的序列号的比例因子来确定该流的TCP确认号的合适比例因子。

6.5. Encoding Methods with External Parameters
6.5. 带外部参数的编码方法

A number of encoding methods in Section 8.2 have one or more arguments for which the derivation of the parameter's value is outside the scope of the ROHC-FN specification of the header formats. This section lists the encoding methods together with a definition of each of their parameters.

第8.2节中的许多编码方法有一个或多个参数,其参数值的推导超出了头格式的ROHC-FN规范的范围。本节列出了编码方法及其每个参数的定义。

o ipv6(is_innermost, ttl_irregular_chain_flag, ip_inner_ecn):

o ipv6(是最内层的,ttl不规则链标志,ip内部ecn):

is_innermost: This Boolean flag is set to true when processing the innermost IP header; otherwise, it is set to false.

is_innerst:当处理最内层的IP头时,此布尔标志设置为true;否则,它将设置为false。

ttl_irregular_chain_flag: This parameter must be set to the value that was used for the corresponding "ttl_irregular_chain_flag" parameter of the "co_baseheader" encoding method (as defined below) when extracting the irregular chain for a compressed header; otherwise, it is set to zero and ignored for other types of chains.

ttl_unregular_chain_flag:此参数必须设置为在为压缩头提取不规则链时用于“co_baseheader”编码方法(定义如下)的对应“ttl_unregular_chain_flag”参数的值;否则,它将设置为零,并对其他类型的链忽略。

ip_inner_ecn: This parameter is bound by the encoding method; therefore, it should be undefined when calling this encoding method. This value is then used to bind the corresponding

ip_internal_ecn:此参数受编码方法的约束;因此,在调用此编码方法时,它应该是未定义的。然后使用该值绑定相应的

parameter in the "tcp" encoding method, as its value is needed when processing the irregular chain for TCP. See the definition of the "ip_inner_ecn" parameter for the "tcp" encoding method below.

“tcp”编码方法中的参数,因为在处理tcp的不规则链时需要该参数的值。请参阅下面“tcp”编码方法的“ip_internal_ecn”参数的定义。

o ipv4(is_innermost, ttl_irregular_chain_flag, ip_inner_ecn, ip_id_behavior_value):

o ipv4(是最内部的,ttl\U不规则的\U链\U标志,ip\U内部\U ecn,ip\U id\U行为\U值):

See definition of arguments for "ipv6" above.

请参阅上面“ipv6”参数的定义。

ip_id_behavior_value: 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 8.2.

ip_id_behavior_value:使用名称以前缀ip_id_behavior_开头的常量之一,并按照第8.2节的定义,设置为2位整数值。

o tcp_opt_eol(nbits):

o tcp_opt_eol(nbits):

nbits: This parameter is set to the length of the padding data located after the EOL option type octet to the end of the TCP options in the uncompressed header.

nbits:此参数设置为位于EOL选项类型八位字节之后的填充数据的长度,直到未压缩标头中TCP选项的末尾。

o tcp_opt_sack(ack_value):

o tcp_opt_sack(确认值):

ack_value: Set to the value of the Acknowledgment Number field of the TCP header.

确认值:设置为TCP头的确认号字段的值。

o tcp(payload_size, ack_stride_value, ip_inner_ecn):

o tcp(有效负载大小、确认步长值、ip内部ecn):

payload_size: Set to the length (in octets) of the payload following the TCP header.

payload_size:设置为TCP头后面的有效负载的长度(以八位字节为单位)。

ack_stride_value: This parameter is the scaling factor used when scaling the TCP Acknowledgment Number. Its value is set by the compressor implementation. See Section 6.4.8.2 for recommendations on how to set this value.

ack_stride_值:此参数是缩放TCP确认号时使用的缩放因子。其值由压缩器实现设置。有关如何设置该值的建议,请参见第6.4.8.2节。

ip_inner_ecn: This parameter binds with the value given to the corresponding "ip_inner_ecn" parameter by the "ipv4" or the "ipv6" encoding method when processing the innermost IP header of this packet. See also the definition of the "ip_inner_ecn" parameter to the "ipv6" and "ipv4" encoding method above.

ip_inner_ecn:在处理此数据包最内层的ip报头时,此参数与“ipv4”或“ipv6”编码方法为相应的“ip_inner_ecn”参数指定的值绑定。另请参见上述“ipv6”和“ipv4”编码方法的“ip_internal_ecn”参数定义。

o co_baseheader(payload_size, ack_stride_value, ttl_irregular_chain_flag, ip_id_behavior_value):

o co_baseheader(有效载荷大小、确认步幅值、ttl_不规则链标志、ip_id_行为值):

payload_size: Set to the length (in octets) of the payload following the TCP header.

payload_size:设置为TCP头后面的有效负载的长度(以八位字节为单位)。

ack_stride_value: This parameter is the scaling factor used when scaling the TCP Acknowledgment Number. Its value is set by the compressor implementation. See Section 6.4.8.2 for recommendations on how to set this value.

ack_stride_值:此参数是缩放TCP确认号时使用的缩放因子。其值由压缩器实现设置。有关如何设置该值的建议,请参见第6.4.8.2节。

ttl_irregular_chain_flag: This parameter is set to one if the TTL/Hop Limit of an outer header has changed compared to its reference in the context; otherwise, it is set to zero. The value used for this parameter is also used for the "ttl_irregular_chain_flag" argument for the "ipv4" and "ipv6" encoding methods when processing the irregular chain, as defined above for the "ipv6" and "ipv4" encoding methods.

ttl_unregular_chain_flag:如果外部头的ttl/Hop限制相对于上下文中的引用发生了变化,则此参数设置为1;否则,它将设置为零。处理不规则链时,此参数使用的值还用于“ipv4”和“ipv6”编码方法的“ttl_unregular_chain_flag”参数,如上文为“ipv6”和“ipv4”编码方法定义的。

ip_id_behavior_value: 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 8.2.

ip_id_behavior_value:使用名称以前缀ip_id_behavior_开头的常量之一,并按照第8.2节的定义,设置为2位整数值。

7. Packet Types (Normative)
7. 数据包类型(标准)

ROHC-TCP uses three different packet types: the Initialization and Refresh (IR) packet type, the Context Replication (IR-CR) packet type, and the Compressed (CO) packet type.

ROHC-TCP使用三种不同的数据包类型:初始化和刷新(IR)数据包类型、上下文复制(IR-CR)数据包类型和压缩(CO)数据包类型。

Each packet type defines a number of packet formats: two packet formats are defined for the IR type, one packet format is defined for the IR-CR type, and two sets of eight base header formats are defined for the CO type with one additional format that is common to both sets.

每个数据包类型定义了许多数据包格式:为IR类型定义了两种数据包格式,为IR-CR类型定义了一种数据包格式,为CO类型定义了两组八种基本报头格式,其中一种是两组通用的附加格式。

The profile identifier for ROHC-TCP is 0x0006.

ROHC-TCP的配置文件标识符为0x0006。

7.1. Initialization and Refresh (IR) Packets
7.1. 初始化和刷新(IR)数据包

ROHC-TCP uses the basic structure of the ROHC IR and IR-DYN packets as defined in [RFC5795] (Sections 5.2.2.1 and 5.2.2.2, respectively).

ROHC-TCP使用[RFC5795]中定义的ROHC IR和IR-DYN数据包的基本结构(分别为第5.2.2.1节和第5.2.2.2节)。

Packet type: IR

数据包类型:IR

This packet type communicates the static part and the dynamic part of the context.

此数据包类型用于通信上下文的静态部分和动态部分。

For the ROHC-TCP IR packet, the value of the x bit MUST be set to one. It has the following format, which corresponds to the "Header" and "Payload" fields described in Section 5.2.1 of [RFC5795]:

对于ROHC-TCP IR数据包,x位的值必须设置为1。其格式如下,对应于[RFC5795]第5.2.1节中所述的“标题”和“有效载荷”字段:

        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 = 0x06        | 1 octet
      +---+---+---+---+---+---+---+---+
      |              CRC              | 1 octet
      +---+---+---+---+---+---+---+---+
      |                               |
      /         Static chain          / variable length
      |                               |
       - - - - - - - - - - - - - - - -
      |                               |
      /         Dynamic chain         / variable length
      |                               |
       - - - - - - - - - - - - - - - -
      |                               |
      /            Payload            / 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 = 0x06        | 1 octet
      +---+---+---+---+---+---+---+---+
      |              CRC              | 1 octet
      +---+---+---+---+---+---+---+---+
      |                               |
      /         Static chain          / variable length
      |                               |
       - - - - - - - - - - - - - - - -
      |                               |
      /         Dynamic chain         / variable length
      |                               |
       - - - - - - - - - - - - - - - -
      |                               |
      /            Payload            / variable length
      |                               |
       - - - - - - - - - - - - - - - -
        

CRC: 8-bit CRC, computed according to Section 5.3.1.1 of [RFC5795]. The CRC covers the entire IR header, thus excluding payload, padding, and feedback, if any.

CRC:8位CRC,根据[RFC5795]第5.3.1.1节计算。CRC覆盖整个IR报头,因此不包括有效负载、填充和反馈(如果有)。

Static chain: See Section 6.2.

静态链:见第6.2节。

Dynamic chain: See Section 6.2.

动态链:见第6.2节。

Payload: The payload of the corresponding original packet, if any. The payload consists of all data after the last octet of the TCP header to the end of the uncompressed packet. The presence of a payload is inferred from the packet length.

有效载荷:对应原始数据包的有效载荷(如果有)。有效负载由TCP报头最后一个八位字节之后到未压缩数据包末尾的所有数据组成。根据数据包长度推断有效负载的存在。

Packet type: IR-DYN

数据包类型:IR-DYN

This packet type communicates the dynamic part of the context.

此数据包类型传递上下文的动态部分。

The ROHC-TCP IR-DYN packet has the following format, which corresponds to the "Header" and "Payload" fields described in Section 5.2.1 of [RFC5795]:

ROHC-TCP IR-DYN数据包具有以下格式,对应于[RFC5795]第5.2.1节中描述的“标头”和“有效载荷”字段:

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

CRC: 8-bit CRC, computed according to Section 5.3.1.1 of [RFC5795]. The CRC covers the entire IR-DYN header, thus excluding payload, padding, and feedback, if any.

CRC:8位CRC,根据[RFC5795]第5.3.1.1节计算。CRC覆盖整个IR-DYN报头,因此不包括有效负载、填充和反馈(如果有)。

Dynamic chain: See Section 6.2.

动态链:见第6.2节。

Payload: The payload of the corresponding original packet, if any. The payload consists of all data after the last octet of the TCP header to end of the uncompressed packet. The presence of a payload is inferred from the packet length.

有效载荷:对应原始数据包的有效载荷(如果有)。有效负载由TCP报头最后一个八位字节之后到未压缩数据包末尾的所有数据组成。根据数据包长度推断有效负载的存在。

7.2. Context Replication (IR-CR) Packets
7.2. 上下文复制(IR-CR)数据包

Context replication requires a dedicated IR packet format that uniquely identifies the IR-CR packet for the ROHC-TCP profile. This section defines the profile-specific part of the IR-CR packet [RFC4164].

上下文复制需要专用的IR数据包格式,该格式唯一地标识ROHC-TCP配置文件的IR-CR数据包。本节定义了IR-CR数据包[RFC4164]的配置文件特定部分。

Packet type: IR-CR

数据包类型:IR-CR

This packet type communicates a reference to a base context along with the static and dynamic parts of the replicated context that differs from the base context.

此数据包类型传递对基本上下文的引用以及与基本上下文不同的复制上下文的静态和动态部分。

The ROHC-TCP IR-CR packet follows the general format of the ROHC IR-CR packet, as defined in [RFC4164], Section 3.5.2. With consideration to the extensibility of the IR packet type defined in [RFC5795], the ROHC-TCP profile supports context replication through the profile-specific part of the IR packet. This is achieved using the bit (x) left in the IR header for "Profile specific information". For ROHC-TCP, this bit is defined as a flag indicating whether this packet is an IR packet or an IR-CR packet. For the ROHC-TCP IR-CR packet, the value of the x bit MUST be set to zero.

ROHC-TCP IR-CR数据包遵循[RFC4164]第3.5.2节中定义的ROHC IR-CR数据包的一般格式。考虑到[RFC5795]中定义的IR数据包类型的可扩展性,ROHC-TCP配置文件支持通过IR数据包的配置文件特定部分进行上下文复制。这是通过使用IR标题中“配置文件特定信息”的剩余位(x)实现的。对于ROHC-TCP,该位被定义为指示该数据包是IR数据包还是IR-CR数据包的标志。对于ROHC-TCP IR-CR数据包,x位的值必须设置为零。

The ROHC-TCP IR-CR has the following format, which corresponds to the "Header" and "Payload" fields described in Section 5.2.1 of [RFC5795]:

ROHC-TCP IR-CR具有以下格式,对应于[RFC5795]第5.2.1节中描述的“标题”和“有效载荷”字段:

        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   0 | IR-CR type octet
      +---+---+---+---+---+---+---+---+
      :                               :
      /       0-2 octets of CID       / 1-2 octets if for large CIDs
      :                               :
      +---+---+---+---+---+---+---+---+
      |         Profile = 0x06        | 1 octet
      +---+---+---+---+---+---+---+---+
      |              CRC              | 1 octet
      +---+---+---+---+---+---+---+---+
      | B |             CRC7          | 1 octet
      +---+---+---+---+---+---+---+---+
      :   Reserved    |   Base CID    : 1 octet, for small CID, if B=1
      +---+---+---+---+---+---+---+---+
      :                               :
      /           Base CID            / 1-2 octets, for large CIDs,
      :                               : if B=1
      +---+---+---+---+---+---+---+---+
      |                               |
      /        Replicate chain        / variable length
      |                               |
       - - - - - - - - - - - - - - - -
      |                               |
      /            Payload            / 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   0 | IR-CR type octet
      +---+---+---+---+---+---+---+---+
      :                               :
      /       0-2 octets of CID       / 1-2 octets if for large CIDs
      :                               :
      +---+---+---+---+---+---+---+---+
      |         Profile = 0x06        | 1 octet
      +---+---+---+---+---+---+---+---+
      |              CRC              | 1 octet
      +---+---+---+---+---+---+---+---+
      | B |             CRC7          | 1 octet
      +---+---+---+---+---+---+---+---+
      :   Reserved    |   Base CID    : 1 octet, for small CID, if B=1
      +---+---+---+---+---+---+---+---+
      :                               :
      /           Base CID            / 1-2 octets, for large CIDs,
      :                               : if B=1
      +---+---+---+---+---+---+---+---+
      |                               |
      /        Replicate chain        / variable length
      |                               |
       - - - - - - - - - - - - - - - -
      |                               |
      /            Payload            / variable length
      |                               |
       - - - - - - - - - - - - - - - -
        

B: B = 1 indicates that the Base CID field is present.

B:B=1表示存在基本CID字段。

CRC: This CRC covers the entire IR-CR header, thus excluding payload, padding, and feedback, if any. This 8-bit CRC is calculated according to Section 5.3.1.1 of [RFC5795].

CRC:该CRC覆盖整个IR-CR报头,因此不包括有效负载、填充和反馈(如果有)。根据[RFC5795]第5.3.1.1节计算该8位CRC。

CRC7: The CRC over the original, uncompressed, header. Calculated according to Section 3.5.1.1 of [RFC4164].

CRC7:原始未压缩标头上的CRC。根据[RFC4164]第3.5.1.1节计算。

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

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

Base CID: CID of base context. Encoded according to [RFC4164], Section 3.5.3.

基本CID:基本上下文的CID。根据[RFC4164]第3.5.3节进行编码。

Replicate chain: See Section 6.2.

复制链:见第6.2节。

Payload: The payload of the corresponding original packet, if any. The presence of a payload is inferred from the packet length.

有效载荷:对应原始数据包的有效载荷(如果有)。根据数据包长度推断有效负载的存在。

7.3. Compressed (CO) Packets
7.3. 压缩(CO)数据包

The ROHC-TCP CO packets communicate irregularities in the packet header. All CO packets carry a CRC and can update the context.

ROHC-TCP CO数据包在数据包报头中进行不规则通信。所有CO数据包都带有CRC,可以更新上下文。

The general format for a compressed TCP header is as follows, which corresponds to the "Header" and "Payload" fields described in Section 5.2.1 of [RFC5795]:

压缩TCP报头的一般格式如下所示,对应于[RFC5795]第5.2.1节中描述的“报头”和“有效载荷”字段:

         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 number of octets
       +---+---+---+---+---+---+---+---+
       :        Irregular chain        :
       /   (including irregular chain  /  variable
       :    items for TCP options)     :
        --- --- --- --- --- --- --- ---
       |                               |
       /            Payload            / 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 number of octets
       +---+---+---+---+---+---+---+---+
       :        Irregular chain        :
       /   (including irregular chain  /  variable
       :    items for TCP options)     :
        --- --- --- --- --- --- --- ---
       |                               |
       /            Payload            / variable length
       |                               |
        - - - - - - - - - - - - - - - -
        

Base header: The complete set of base headers is defined in Section 8.

基本标题:第8节定义了完整的基本标题集。

Irregular chain: See Sections 6.2 and 6.3.6.

不规则链:见第6.2节和第6.3.6节。

Payload: The payload of the corresponding original packet, if any. The presence of a payload is inferred from the packet length.

有效载荷:对应原始数据包的有效载荷(如果有)。根据数据包长度推断有效负载的存在。

8. Header Formats (Normative)
8. 标题格式(标准)

This section describes the set of compressed TCP/IP packet formats. The normative description of the packet formats is given using the formal notation for ROHC profiles defined in [RFC4997]. The formal description of the packet formats specifies all of the information needed to compress and decompress a header relative to the context.

本节介绍一组压缩TCP/IP数据包格式。数据包格式的规范性描述使用[RFC4997]中定义的ROHC配置文件的形式符号给出。数据包格式的形式化描述指定了压缩和解压缩相对于上下文的报头所需的所有信息。

In particular, the notation provides a list of all the fields present in the uncompressed and compressed TCP/IP headers, and defines how to map from each uncompressed packet to its compressed equivalent and vice versa.

特别是,该符号提供了未压缩和压缩TCP/IP头中存在的所有字段的列表,并定义了如何从每个未压缩数据包映射到其压缩等效数据包,反之亦然。

8.1. Design Rationale for Compressed Base Headers
8.1. 压缩基头的设计原理

The compressed header formats are defined as two separate sets: one set for the packets where the innermost IP header contains a sequential IP-ID (either network byte order or byte swapped), and one set for the packets without sequential IP-ID (either random, zero, or no IP-ID).

压缩头格式定义为两个独立的集合:一个集合用于最内层IP头包含顺序IP-ID(网络字节顺序或字节交换)的数据包,另一个集合用于不包含顺序IP-ID(随机、零或无IP-ID)的数据包。

These two sets of header formats are referred to as the "sequential" and the "random" set of header formats, respectively.

这两组标题格式分别称为“顺序”和“随机”标题格式集。

In addition, there is one compressed format that is common to both sets of header formats and that can thus be used regardless of the type of IP-ID behavior. This format can transmit rarely changing fields and also send the frequently changing fields coded in variable lengths. It can also change the value of control fields such as IP-ID behavior and ECN behavior.

此外,有一种压缩格式对这两组头格式都是通用的,因此无论IP-ID行为的类型如何,都可以使用这种格式。这种格式可以传输很少变化的字段,也可以发送以可变长度编码的频繁变化的字段。它还可以更改控制字段的值,例如IP-ID行为和ECN行为。

All compressed base headers contain a 3-bit CRC, unless they update control fields such as "ip_id_behavior" or "ecn_used" that affect the interpretation of subsequent headers. Headers that can modify these control fields carry a 7-bit CRC instead.

所有压缩的基本报头都包含3位CRC,除非它们更新影响后续报头解释的控制字段,如“ip_id_behavior”或“ecn_used”。可以修改这些控制字段的报头携带7位CRC。

When discussing LSB-encoded fields below, "p" equals the "offset_param" and "k" equals the "num_lsbs_param" in [RFC4997].

在下面讨论LSB编码字段时,[RFC4997]中的“p”等于“offset_param”,而“k”等于“num_lsbs_param”。

The encoding methods used in the compressed base headers are based on the following design criteria:

压缩基本标头中使用的编码方法基于以下设计标准:

o MSN

o MSN

Since the MSN is a number generated by the compressor, it only needs to be large enough to ensure robust operation and to accommodate a small amount of reordering [RFC4163]. Therefore, each compressed base header has an MSN field that is LSB-encoded with k=4 and p=4 to handle a reordering depth of up to 4 packets. Additional guidance to improve robustness when reordering is possible can be found in [RFC4224].

由于MSN是由压缩机生成的一个数字,它只需要足够大,以确保稳健的运行,并适应少量的重新排序[RFC4163]。因此,每个压缩的基本报头都有一个MSN字段,该字段用k=4和p=4进行LSB编码,以处理多达4个数据包的重新排序深度。[RFC4224]中提供了在可能重新排序时提高稳健性的其他指南。

o TCP Sequence Number

o TCP序列号

ROHC-TCP has the capability to handle bulk data transfers efficiently, for which the sequence number is expected to increase by about 1460 octets (which can be represented by 11 bits). For the compressed base headers to handle retransmissions (i.e., negative delta to the sequence number),

ROHC-TCP具有高效处理批量数据传输的能力,对于批量数据传输,序列号预计将增加约1460个八位字节(可由11位表示)。对于处理重传的压缩基本报头(即序列号的负增量),

the LSB interpretation interval has to handle negative offsets about as large as positive offsets, which means that one more bit is needed.

LSB解释间隔必须处理大约与正偏移量一样大的负偏移量,这意味着需要多一位。

Also, for ROHC-TCP to be robust to losses, two additional bits are added to the LSB encoding of the sequence number. This means that the base headers should contain at least 14 bits of LSB-encoded sequence number when present. According to the logic above, the LSB offset value is set to be as large as the positive offset, i.e., p = 2^(k-1)-1.

此外,为了使ROHC-TCP对丢失具有鲁棒性,在序列号的LSB编码中添加了两个额外的位。这意味着当存在时,基本报头应包含至少14位的LSB编码序列号。根据上述逻辑,LSB偏移值被设置为与正偏移一样大,即p=2^(k-1)-1。

o TCP Acknowledgment Number

o TCP确认号

The design criterion for the acknowledgment number is similar to that of the TCP Sequence Number. However, often only every other data packet is acknowledged, which means that the expected delta value is twice as large as for sequence numbers.

确认号的设计标准与TCP序列号的设计标准相似。然而,通常只确认其他数据包,这意味着预期的增量值是序列号的两倍。

Therefore, at least 15 bits of acknowledgment number should be used in compressed base headers. Since the acknowledgment number is expected to constantly increase, and the only exception to this is packet reordering (either on the ROHC channel [RFC3759] or prior to the compression point), the negative offset for LSB encoding is set to be 1/4 of the total interval, i.e., p = 2^(k-2)-1.

因此,在压缩的基本报头中应使用至少15位的确认号。由于确认号预计会不断增加,唯一的例外是分组重新排序(在ROHC信道[RFC3759]上或在压缩点之前),因此LSB编码的负偏移量被设置为总间隔的1/4,即p=2^(k-2)-1。

o TCP Window

o TCP窗口

The TCP Window field is expected to increase in increments of similar size as the TCP Sequence Number; therefore, the design criterion for the TCP window is to send at least 14 bits when used.

TCP窗口字段预计将以与TCP序列号大小相似的增量增加;因此,TCP窗口的设计标准是在使用时至少发送14位。

o IP-ID

o IP-ID

For the "sequential" set of packet formats, all the compressed base headers contain LSB-encoded IP-ID offset bits, where the offset is the difference between the value of the MSN field and the value of the IP-ID field. The requirement is that at least 3 bits of IP-ID should always be present, but it is preferable to use 4 to 7 bits. When k=3 then p=1, and if k>3 then p=3 since the offset is expected to increase most of the time.

对于“顺序”分组格式集,所有压缩的基本报头都包含LSB编码的IP-ID偏移位,其中偏移量是MSN字段值和IP-ID字段值之间的差值。要求至少有3位IP-ID始终存在,但最好使用4到7位。当k=3时,p=1,如果k>3,则p=3,因为预计偏移量在大部分时间都会增加。

Each set of header formats contains eight different compressed base headers. The reason for having this large number of header formats is that the TCP Sequence Number, TCP Acknowledgment Number, and TCP Window are frequently changing in a non-linear pattern.

每组标题格式包含八个不同的压缩基本标题。有这么多报头格式的原因是TCP序列号、TCP确认号和TCP窗口经常以非线性模式变化。

The design of the header formats is derived from the field behavior analysis found in [RFC4413].

标题格式的设计源自[RFC4413]中的字段行为分析。

All of the compressed base headers transmit LSB-encoded MSN bits, the TCP Push flag, and a CRC, and in addition to this, all the base headers in the sequential packet format set contain LSB-encoded IP-ID bits.

所有压缩的基本报头都传输LSB编码的MSN位、TCP推送标志和CRC,此外,顺序分组格式集中的所有基本报头都包含LSB编码的IP-ID位。

The following header formats exist in both the sequential and random packet format sets:

顺序和随机数据包格式集中都存在以下报头格式:

o Format 1: This header format carries changes to the TCP Sequence Number and is expected to be used on the downstream of a data transfer.

o 格式1:此标头格式携带对TCP序列号的更改,预计将在数据传输的下游使用。

o Format 2: This header format carries the TCP Sequence Number in scaled form and is expected to be useful for the downstream of a data transfer where the payload size is constant for multiple packets.

o 格式2:此报头格式以缩放形式携带TCP序列号,预计对于多个数据包的有效负载大小恒定的数据传输下游非常有用。

o Format 3: This header format carries changes in the TCP Acknowledgment Number and is expected to be useful for the acknowledgment direction of a data transfer.

o 格式3:此报头格式携带TCP确认号的更改,预计对数据传输的确认方向有用。

o Format 4: This header format is similar to format 3, but carries a scaled TCP Acknowledgment Number.

o 格式4:此标头格式类似于格式3,但带有缩放的TCP确认号。

o Format 5: This header format carries both the TCP Sequence Number and the TCP Acknowledgment Number and is expected to be useful for flows that send data in both directions.

o 格式5:此标头格式同时携带TCP序列号和TCP确认号,预计对双向发送数据的流很有用。

o Format 6: This header format is similar to format 5, but carries the TCP Sequence Number in scaled form, when the payload size is static for certain intervals in a data flow.

o 格式6:该报头格式类似于格式5,但当数据流中的有效负载大小在一定时间间隔内是静态的时,它以比例形式携带TCP序列号。

o Format 7: This header format carries changes to both the TCP Acknowledgment Number and the TCP Window and is expected to be useful for the acknowledgment flows of data connections.

o 格式7:此报头格式携带对TCP确认号和TCP窗口的更改,预计对数据连接的确认流有用。

o Format 8: This header format is used to convey changes to some of the more seldom changing fields in the TCP flow, such as ECN behavior, RST/SYN/FIN flags, the TTL/Hop Limit, and the TCP options list. This format carries a 7-bit CRC, since it can change the structure of the contents of the irregular chain for subsequent packets. Note that this can be seen as a reduced form of the common packet format.

o 格式8:此标头格式用于将更改传达给TCP流中一些很少更改的字段,例如ECN行为、RST/SYN/FIN标志、TTL/Hop限制和TCP选项列表。这种格式携带7位CRC,因为它可以改变后续数据包的不规则链内容的结构。注意,这可以看作是通用数据包格式的简化形式。

o Common header format: The common header format can be used for all kinds of IP-ID behavior and should be useful when some of the more rarely changing fields in the IP or TCP header change. Since this header format can update control fields that decide how the decompressor interprets packets, it carries a 7-bit CRC to reduce the probability of context corruption. This header can basically convey changes to any of the dynamic fields in the IP and TCP headers, and it uses a large set of flags to provide information about which fields are present in the header format.

o 公共头格式:公共头格式可用于所有类型的IP-ID行为,并且在IP或TCP头中一些很少更改的字段更改时应该很有用。由于此报头格式可以更新决定解压器如何解释数据包的控制字段,因此它携带7位CRC以降低上下文损坏的可能性。此标头基本上可以将更改传递给IP和TCP标头中的任何动态字段,并且它使用大量标志来提供有关标头格式中存在哪些字段的信息。

8.2. Formal Definition of Header Formats
8.2. 标题格式的形式化定义
// NOTE: The irregular, static, and dynamic chains (see Section 6.2)
// 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.2)
// 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_SEQUENTIAL = 0;
IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED = 1;
IP_ID_BEHAVIOR_RANDOM = 2;
IP_ID_BEHAVIOR_ZERO = 3;
        
IP_ID_BEHAVIOR_SEQUENTIAL = 0;
IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED = 1;
IP_ID_BEHAVIOR_RANDOM = 2;
IP_ID_BEHAVIOR_ZERO = 3;
        
////////////////////////////////////////////
// Global control fields
////////////////////////////////////////////
        
////////////////////////////////////////////
// Global control fields
////////////////////////////////////////////
        
CONTROL {
  ecn_used            [ 1 ];
  msn                 [ 16 ];
  // ip_id fields are for innermost IP header only
  ip_id_offset                               [ 16 ];
  ip_id_behavior_innermost                   [  2 ];
  // ACK-related
  ack_stride                                 [ 32 ];
  ack_number_scaled                          [ 32 ];
  ack_number_residue                         [ 32 ];
  seq_number_scaled                          [ 32 ];
  seq_number_residue                         [ 32 ];
}
        
CONTROL {
  ecn_used            [ 1 ];
  msn                 [ 16 ];
  // ip_id fields are for innermost IP header only
  ip_id_offset                               [ 16 ];
  ip_id_behavior_innermost                   [  2 ];
  // ACK-related
  ack_stride                                 [ 32 ];
  ack_number_scaled                          [ 32 ];
  ack_number_residue                         [ 32 ];
  seq_number_scaled                          [ 32 ];
  seq_number_residue                         [ 32 ];
}
        
///////////////////////////////////////////////
// Encoding methods not specified in FN syntax
///////////////////////////////////////////////
        
///////////////////////////////////////////////
// Encoding methods not specified in FN syntax
///////////////////////////////////////////////
        
list_tcp_options               "defined in Section 6.3.3";
inferred_ip_v4_header_checksum "defined in Section 6.4.1";
inferred_mine_header_checksum  "defined in Section 6.4.2";
inferred_ip_v4_length          "defined in Section 6.4.3";
inferred_ip_v6_length          "defined in Section 6.4.4";
inferred_offset                "defined in Section 6.4.5";
baseheader_extension_headers   "defined in Section 6.4.6";
baseheader_outer_headers       "defined in Section 6.4.7";
        
list_tcp_options               "defined in Section 6.3.3";
inferred_ip_v4_header_checksum "defined in Section 6.4.1";
inferred_mine_header_checksum  "defined in Section 6.4.2";
inferred_ip_v4_length          "defined in Section 6.4.3";
inferred_ip_v6_length          "defined in Section 6.4.4";
inferred_offset                "defined in Section 6.4.5";
baseheader_extension_headers   "defined in Section 6.4.6";
baseheader_outer_headers       "defined in Section 6.4.7";
        
////////////////////////////////////////////
// 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 {
    field =:= irregular(width) [ width ];
    ENFORCE(flag == 1);
  }
        
  COMPRESSED irreg_enc {
    field =:= irregular(width) [ width ];
    ENFORCE(flag == 1);
  }
        
  COMPRESSED static_enc {
    field =:= static [ 0 ];
    ENFORCE(flag == 0);
  }
}
        
  COMPRESSED static_enc {
    field =:= static [ 0 ];
    ENFORCE(flag == 0);
  }
}
        
zero_or_irreg(flag, width)
{
  UNCOMPRESSED {
    field [ width ];
  }
        
zero_or_irreg(flag, width)
{
  UNCOMPRESSED {
    field [ width ];
  }
        
  COMPRESSED non_zero {
    field =:= irregular(width) [ width ];
    ENFORCE(flag == 0);
  }
        
  COMPRESSED non_zero {
    field =:= irregular(width) [ width ];
    ENFORCE(flag == 0);
  }
        
  COMPRESSED zero {
    field =:= uncompressed_value(width, 0) [ 0 ];
    ENFORCE(flag == 1);
        
  COMPRESSED zero {
    field =:= uncompressed_value(width, 0) [ 0 ];
    ENFORCE(flag == 1);
        
  }
}
        
  }
}
        
variable_length_32_enc(flag)
{
  UNCOMPRESSED {
    field [ 32 ];
  }
        
variable_length_32_enc(flag)
{
  UNCOMPRESSED {
    field [ 32 ];
  }
        
  COMPRESSED not_present {
    field =:= static [ 0 ];
    ENFORCE(flag == 0);
  }
        
  COMPRESSED not_present {
    field =:= static [ 0 ];
    ENFORCE(flag == 0);
  }
        
  COMPRESSED lsb_8_bit {
    field =:= lsb(8, 63) [ 8 ];
    ENFORCE(flag == 1);
  }
        
  COMPRESSED lsb_8_bit {
    field =:= lsb(8, 63) [ 8 ];
    ENFORCE(flag == 1);
  }
        
  COMPRESSED lsb_16_bit {
    field =:= lsb(16, 16383) [ 16 ];
    ENFORCE(flag == 2);
  }
        
  COMPRESSED lsb_16_bit {
    field =:= lsb(16, 16383) [ 16 ];
    ENFORCE(flag == 2);
  }
        
  COMPRESSED irreg_32_bit {
    field =:= irregular(32) [ 32 ];
    ENFORCE(flag == 3);
  }
}
        
  COMPRESSED irreg_32_bit {
    field =:= irregular(32) [ 32 ];
    ENFORCE(flag == 3);
  }
}
        
optional32(flag)
{
  UNCOMPRESSED {
    item [ 0, 32 ];
  }
        
optional32(flag)
{
  UNCOMPRESSED {
    item [ 0, 32 ];
  }
        
  COMPRESSED present {
    item =:= irregular(32) [ 32 ];
    ENFORCE(flag == 1);
  }
        
  COMPRESSED present {
    item =:= irregular(32) [ 32 ];
    ENFORCE(flag == 1);
  }
        
  COMPRESSED not_present {
    item =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag == 0);
  }
}
        
  COMPRESSED not_present {
    item =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag == 0);
  }
}
        

lsb_7_or_31

lsb_7_或_31

{
  UNCOMPRESSED {
    item [ 32 ];
  }
        
{
  UNCOMPRESSED {
    item [ 32 ];
  }
        
  COMPRESSED lsb_7 {
    discriminator =:= '0'       [ 1 ];
    item          =:= lsb(7, 8) [ 7 ];
  }
        
  COMPRESSED lsb_7 {
    discriminator =:= '0'       [ 1 ];
    item          =:= lsb(7, 8) [ 7 ];
  }
        
  COMPRESSED lsb_31 {
    discriminator =:= '1'          [ 1 ];
    item          =:= lsb(31, 256) [ 31 ];
  }
}
        
  COMPRESSED lsb_31 {
    discriminator =:= '1'          [ 1 ];
    item          =:= lsb(31, 256) [ 31 ];
  }
}
        
opt_lsb_7_or_31(flag)
{
  UNCOMPRESSED {
    item [ 0, 32 ];
  }
        
opt_lsb_7_or_31(flag)
{
  UNCOMPRESSED {
    item [ 0, 32 ];
  }
        
  COMPRESSED present {
    item =:= lsb_7_or_31 [ 8, 32 ];
    ENFORCE(flag == 1);
  }
        
  COMPRESSED present {
    item =:= lsb_7_or_31 [ 8, 32 ];
    ENFORCE(flag == 1);
  }
        
  COMPRESSED not_present {
    item =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag == 0);
  }
}
        
  COMPRESSED not_present {
    item =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag == 0);
  }
}
        
crc3(data_value, data_length)
{
  UNCOMPRESSED {
  }
        
crc3(data_value, data_length)
{
  UNCOMPRESSED {
  }
        
  COMPRESSED {
    crc_value =:=
      crc(3, 0x06, 0x07, data_value, data_length) [ 3 ];
  }
}
        
  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 ];
  }
}
        
one_bit_choice
{
  UNCOMPRESSED {
    field [ 1 ];
  }
        
one_bit_choice
{
  UNCOMPRESSED {
    field [ 1 ];
  }
        
  COMPRESSED zero {
    field [ 1 ];
    ENFORCE(field.UVALUE == 0);
  }
        
  COMPRESSED zero {
    field [ 1 ];
    ENFORCE(field.UVALUE == 0);
  }
        
  COMPRESSED nonzero {
    field [ 1 ];
    ENFORCE(field.UVALUE == 1);
  }
}
        
  COMPRESSED nonzero {
    field [ 1 ];
    ENFORCE(field.UVALUE == 1);
  }
}
        
// 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 {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
        
ip_dest_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 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_0_replicate {
    discriminator =:= '00000000' [ 8 ];
  }
        
  COMPRESSED dest_opt_dynamic {
    value =:=
      irregular(length.UVALUE * 64 + 48) [ length.UVALUE * 64 + 48 ];
  }
  COMPRESSED dest_opt_0_replicate {
    discriminator =:= '00000000' [ 8 ];
  }
        
  COMPRESSED dest_opt_1_replicate {
    discriminator =:= '10000000'                     [ 8 ];
    length        =:= irregular(8)                   [ 8 ];
    value         =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }
        
  COMPRESSED dest_opt_1_replicate {
    discriminator =:= '10000000'                     [ 8 ];
    length        =:= irregular(8)                   [ 8 ];
    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 {

ip_hop_opt{

  UNCOMPRESSED {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
        
  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_0_replicate {
    discriminator =:= '00000000' [ 8 ];
  }
        
  COMPRESSED hop_opt_0_replicate {
    discriminator =:= '00000000' [ 8 ];
  }
        
  COMPRESSED hop_opt_1_replicate {
    discriminator =:= '10000000'                     [ 8 ];
    length        =:= irregular(8)                   [ 8 ];
    value         =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }
        
  COMPRESSED hop_opt_1_replicate {
    discriminator =:= '10000000'                     [ 8 ];
    length        =:= irregular(8)                   [ 8 ];
    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_0_replicate {
    discriminator =:= '00000000' [ 8 ];
  }
        
  COMPRESSED rout_opt_0_replicate {
    discriminator =:= '00000000' [ 8 ];
  }
        
  COMPRESSED rout_opt_0_replicate {
    discriminator =:= '10000000'                     [ 8 ];
    length        =:= irregular(8)                   [ 8 ];
    value         =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }
  COMPRESSED rout_opt_irregular {
  }
}
        
  COMPRESSED rout_opt_0_replicate {
    discriminator =:= '10000000'                     [ 8 ];
    length        =:= irregular(8)                   [ 8 ];
    value         =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }
  COMPRESSED rout_opt_irregular {
  }
}
        
////////////////////////////////////////////
// GRE Header
////////////////////////////////////////////
        
////////////////////////////////////////////
// GRE Header
////////////////////////////////////////////
        
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 {
    value     =:= irregular(16)             [ 16 ];
    reserved1 =:= uncompressed_value(16, 0) [ 0 ];
    ENFORCE(flag_value == 1);
  }
        
  COMPRESSED cs_present {
    value     =:= irregular(16)             [ 16 ];
    reserved1 =:= uncompressed_value(16, 0) [ 0 ];
    ENFORCE(flag_value == 1);
  }
        

COMPRESSED not_present {

压缩不存在{

    value     =:= compressed_value(0, 0) [ 0 ];
    reserved1 =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag_value == 0);
  }
}
        
    value     =:= compressed_value(0, 0) [ 0 ];
    reserved1 =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag_value == 0);
  }
}
        
gre_proto
{
  UNCOMPRESSED {
    protocol [ 16 ];
  }
        
gre_proto
{
  UNCOMPRESSED {
    protocol [ 16 ];
  }
        
  COMPRESSED ether_v4 {
    discriminator =:= compressed_value(1, 0)         [ 1 ];
    protocol      =:= uncompressed_value(16, 0x0800) [ 0 ];
  }
        
  COMPRESSED ether_v4 {
    discriminator =:= compressed_value(1, 0)         [ 1 ];
    protocol      =:= uncompressed_value(16, 0x0800) [ 0 ];
  }
        
  COMPRESSED ether_v6 {
    discriminator =:= compressed_value(1, 1)         [ 1 ];
    protocol      =:= uncompressed_value(16, 0x86DD) [ 0 ];
  }
}
        
  COMPRESSED ether_v6 {
    discriminator =:= compressed_value(1, 1)         [ 1 ];
    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 {

压缩gre_静态{

    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      =:= optional32(k_flag.UVALUE) [ 0, 32 ];
  }
        
    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      =:= optional32(k_flag.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED gre_dynamic {
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE)             [ 0, 16 ];
    sequence_number  =:= optional32(s_flag.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED gre_dynamic {
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE)             [ 0, 16 ];
    sequence_number  =:= optional32(s_flag.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED gre_0_replicate {
    discriminator    =:= '00000000'    [ 8 ];
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE) [ 0, 16 ];
    sequence_number  =:=
      optional32(s_flag.UVALUE)        [ 0, 8, 32 ];
  }
        
  COMPRESSED gre_0_replicate {
    discriminator    =:= '00000000'    [ 8 ];
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE) [ 0, 16 ];
    sequence_number  =:=
      optional32(s_flag.UVALUE)        [ 0, 8, 32 ];
  }
        
  COMPRESSED gre_1_replicate {
    discriminator    =:= '10000'                   [ 5 ];
    c_flag           =:= irregular(1)              [ 1 ];
    k_flag           =:= irregular(1)              [ 1 ];
    s_flag           =:= irregular(1)              [ 1 ];
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE)             [ 0, 16 ];
    key              =:= optional32(k_flag.UVALUE) [ 0, 32 ];
    sequence_number  =:= optional32(s_flag.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED gre_1_replicate {
    discriminator    =:= '10000'                   [ 5 ];
    c_flag           =:= irregular(1)              [ 1 ];
    k_flag           =:= irregular(1)              [ 1 ];
    s_flag           =:= irregular(1)              [ 1 ];
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE)             [ 0, 16 ];
    key              =:= optional32(k_flag.UVALUE) [ 0, 32 ];
    sequence_number  =:= optional32(s_flag.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED gre_irregular {
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE) [ 0, 16 ];
    sequence_number  =:=
      opt_lsb_7_or_31(s_flag.UVALUE)   [ 0, 8, 32 ];
  }
}
        
  COMPRESSED gre_irregular {
    checksum_and_res =:=
      optional_checksum(c_flag.UVALUE) [ 0, 16 ];
    sequence_number  =:=
      opt_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    =:= optional32(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    =:= optional32(s_bit.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED mine_dynamic {
  }
        
  COMPRESSED mine_dynamic {
  }
        
  COMPRESSED mine_0_replicate {
    discriminator =:= '00000000' [ 8 ];
  }
        
  COMPRESSED mine_0_replicate {
    discriminator =:= '00000000' [ 8 ];
  }
        
  COMPRESSED mine_1_replicate {
    discriminator =:= '10000000'               [ 8 ];
    s_bit         =:= irregular(1)             [ 1 ];
    res_bits      =:= irregular(7)             [ 7 ];
    orig_dest     =:= irregular(32)            [ 32 ];
    orig_src      =:= optional32(s_bit.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED mine_1_replicate {
    discriminator =:= '10000000'               [ 8 ];
    s_bit         =:= irregular(1)             [ 1 ];
    res_bits      =:= irregular(7)             [ 7 ];
    orig_dest     =:= irregular(32)            [ 32 ];
    orig_src      =:= optional32(s_bit.UVALUE) [ 0, 32 ];
  }
        
  COMPRESSED mine_irregular {
  }
}
        
  COMPRESSED mine_irregular {
  }
}
        
/////////////////////////////////////////////
// Authentication Header (AH)
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// Authentication Header (AH)
/////////////////////////////////////////////
        
ah
{
  UNCOMPRESSED {
    next_header     [ 8 ];
    length          [ 8 ];
    res_bits        [ 16 ];
    spi             [ 32 ];
    sequence_number [ 32 ];
    icv             [ length.UVALUE*32-32 ];
  }
        
ah
{
  UNCOMPRESSED {
    next_header     [ 8 ];
    length          [ 8 ];
    res_bits        [ 16 ];
    spi             [ 32 ];
    sequence_number [ 32 ];
    icv             [ length.UVALUE*32-32 ];
  }
        
  DEFAULT {
    next_header     =:= static;
    length          =:= static;
    res_bits        =:= static;
    spi             =:= static;
    sequence_number =:= static;
  }
        
  DEFAULT {
    next_header     =:= static;
    length          =:= static;
    res_bits        =:= 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 {
    res_bits        =:= irregular(16) [ 16 ];
    sequence_number =:= irregular(32) [ 32 ];
    icv       =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        
  COMPRESSED ah_dynamic {
    res_bits        =:= irregular(16) [ 16 ];
    sequence_number =:= irregular(32) [ 32 ];
    icv       =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        
  COMPRESSED ah_0_replicate {
    discriminator   =:= '00000000'    [ 8 ];
    sequence_number =:= irregular(32) [ 32 ];
    icv             =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        
  COMPRESSED ah_0_replicate {
    discriminator   =:= '00000000'    [ 8 ];
    sequence_number =:= irregular(32) [ 32 ];
    icv             =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        
  COMPRESSED ah_1_replicate {
    discriminator   =:= '10000000'    [ 8 ];
    length          =:= irregular(8)  [ 8 ];
    res_bits        =:= irregular(16) [ 16 ];
    spi             =:= irregular(32) [ 32 ];
        
  COMPRESSED ah_1_replicate {
    discriminator   =:= '10000000'    [ 8 ];
    length          =:= irregular(8)  [ 8 ];
    res_bits        =:= irregular(16) [ 16 ];
    spi             =:= irregular(32) [ 32 ];
        
    sequence_number =:= irregular(32) [ 32 ];
    icv             =:=
      irregular(length.UVALUE*32-32)  [ length.UVALUE*32-32 ];
  }
        
    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 {
    flow_label [ 20 ];
  }
        
fl_enc
{
  UNCOMPRESSED {
    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 ];
  }
}
        
// The is_innermost flag is true if this is the innermost IP header
// If extracting the irregular chain for a compressed packet:
//   - ttl_irregular_chain_flag must have the same value as it had when
//     processing co_baseheader.
//   - ip_inner_ecn is bound in this encoding method and the value that
//     it gets bound to should be passed to the tcp encoding method
//   For other formats than the irregular chain, these two are ignored
ipv6(is_innermost, ttl_irregular_chain_flag, ip_inner_ecn)
{
  UNCOMPRESSED {
    version         =:= uncompressed_value(4, 6) [ 4 ];
    dscp                                         [ 6 ];
    ip_ecn_flags                                 [ 2 ];
    flow_label                                   [ 20 ];
        
// The is_innermost flag is true if this is the innermost IP header
// If extracting the irregular chain for a compressed packet:
//   - ttl_irregular_chain_flag must have the same value as it had when
//     processing co_baseheader.
//   - ip_inner_ecn is bound in this encoding method and the value that
//     it gets bound to should be passed to the tcp encoding method
//   For other formats than the irregular chain, these two are ignored
ipv6(is_innermost, ttl_irregular_chain_flag, ip_inner_ecn)
{
  UNCOMPRESSED {
    version         =:= uncompressed_value(4, 6) [ 4 ];
    dscp                                         [ 6 ];
    ip_ecn_flags                                 [ 2 ];
    flow_label                                   [ 20 ];
        
    payload_length                               [ 16 ];
    next_header                                  [ 8 ];
    ttl_hopl                                     [ 8 ];
    src_addr                                     [ 128 ];
    dst_addr                                     [ 128 ];
  }
        
    payload_length                               [ 16 ];
    next_header                                  [ 8 ];
    ttl_hopl                                     [ 8 ];
    src_addr                                     [ 128 ];
    dst_addr                                     [ 128 ];
  }
        
  DEFAULT {
    dscp           =:= static;
    ip_ecn_flags   =:= static;
    flow_label     =:= static;
    payload_length =:= inferred_ip_v6_length;
    next_header    =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    dst_addr       =:= static;
  }
        
  DEFAULT {
    dscp           =:= static;
    ip_ecn_flags   =:= 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 ];
    reserved     =:= '00'           [ 2 ];
    flow_label   =:= fl_enc         [ 5, 21 ];
    next_header  =:= irregular(8)   [ 8 ];
    src_addr     =:= irregular(128) [ 128 ];
    dst_addr     =:= irregular(128) [ 128 ];
  }
        
  COMPRESSED ipv6_static {
    version_flag =:= '1'            [ 1 ];
    reserved     =:= '00'           [ 2 ];
    flow_label   =:= fl_enc         [ 5, 21 ];
    next_header  =:= irregular(8)   [ 8 ];
    src_addr     =:= irregular(128) [ 128 ];
    dst_addr     =:= irregular(128) [ 128 ];
  }
        
  COMPRESSED ipv6_dynamic {
    dscp         =:= irregular(6) [ 6 ];
    ip_ecn_flags =:= irregular(2) [ 2 ];
    ttl_hopl     =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED ipv6_dynamic {
    dscp         =:= irregular(6) [ 6 ];
    ip_ecn_flags =:= irregular(2) [ 2 ];
    ttl_hopl     =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED ipv6_replicate {
    dscp         =:= irregular(6) [ 6 ];
    ip_ecn_flags =:= irregular(2) [ 2 ];
    reserved     =:= '000'        [ 3 ];
    flow_label   =:= fl_enc       [ 5, 21 ];
  }
        
  COMPRESSED ipv6_replicate {
    dscp         =:= irregular(6) [ 6 ];
    ip_ecn_flags =:= irregular(2) [ 2 ];
    reserved     =:= '000'        [ 3 ];
    flow_label   =:= fl_enc       [ 5, 21 ];
  }
        
  COMPRESSED ipv6_outer_without_ttl_irregular {
    dscp         =:= static_or_irreg(ecn_used.UVALUE, 6) [ 0, 6 ];
    ip_ecn_flags =:= static_or_irreg(ecn_used.UVALUE, 2) [ 0, 2 ];
    ENFORCE(ttl_irregular_chain_flag == 0);
    ENFORCE(is_innermost == false);
  }
        
  COMPRESSED ipv6_outer_without_ttl_irregular {
    dscp         =:= static_or_irreg(ecn_used.UVALUE, 6) [ 0, 6 ];
    ip_ecn_flags =:= static_or_irreg(ecn_used.UVALUE, 2) [ 0, 2 ];
    ENFORCE(ttl_irregular_chain_flag == 0);
    ENFORCE(is_innermost == false);
  }
        

COMPRESSED ipv6_outer_with_ttl_irregular {

带ttl的压缩ipv6\u外部\u{

    dscp         =:= static_or_irreg(ecn_used.UVALUE, 6) [ 0, 6 ];
    ip_ecn_flags =:= static_or_irreg(ecn_used.UVALUE, 2) [ 0, 2 ];
    ttl_hopl     =:= irregular(8)                        [ 8 ];
    ENFORCE(ttl_irregular_chain_flag == 1);
    ENFORCE(is_innermost == false);
  }
        
    dscp         =:= static_or_irreg(ecn_used.UVALUE, 6) [ 0, 6 ];
    ip_ecn_flags =:= static_or_irreg(ecn_used.UVALUE, 2) [ 0, 2 ];
    ttl_hopl     =:= irregular(8)                        [ 8 ];
    ENFORCE(ttl_irregular_chain_flag == 1);
    ENFORCE(is_innermost == false);
  }
        
  COMPRESSED ipv6_innermost_irregular {
    ENFORCE(ip_inner_ecn == ip_ecn_flags.UVALUE);
    ENFORCE(is_innermost == true);
  }
}
        
  COMPRESSED ipv6_innermost_irregular {
    ENFORCE(ip_inner_ecn == ip_ecn_flags.UVALUE);
    ENFORCE(is_innermost == true);
  }
}
        
/////////////////////////////////////////////
// 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 {

压缩ip_id_seq{

    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL);
  }
        
    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 {
    ip_id =:= irregular(16) [ 16 ];
    ENFORCE(behavior == IP_ID_BEHAVIOR_RANDOM);
  }
        
  COMPRESSED ip_id_rand {
    ip_id =:= irregular(16) [ 16 ];
    ENFORCE(behavior == IP_ID_BEHAVIOR_RANDOM);
  }
        
  COMPRESSED ip_id_zero {
    ip_id =:= uncompressed_value(16, 0) [ 0 ];
    ENFORCE(behavior == IP_ID_BEHAVIOR_ZERO);
  }
}
        
  COMPRESSED ip_id_zero {
    ip_id =:= uncompressed_value(16, 0) [ 0 ];
    ENFORCE(behavior == IP_ID_BEHAVIOR_ZERO);
  }
}
        
// The is_innermost flag is true if this is the innermost IP header
// If extracting the irregular chain for a compressed packet:
//   - ttl_irregular_chain_flag must have the same value as it had when
//     processing co_baseheader.
//   - ip_inner_ecn is bound in this encoding method and the value that
//     it gets bound to should be passed to the tcp encoding method
//   For other formats than the irregular chain, these two are ignored
ipv4(is_innermost, ttl_irregular_chain_flag, ip_inner_ecn,
     ip_id_behavior_value)
{
  UNCOMPRESSED {
    version        =:= uncompressed_value(4, 4)  [ 4 ];
    hdr_length     =:= uncompressed_value(4, 5)  [ 4 ];
    dscp                                         [ 6 ];
    ip_ecn_flags                                 [ 2 ];
    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 ];
  }
        
// The is_innermost flag is true if this is the innermost IP header
// If extracting the irregular chain for a compressed packet:
//   - ttl_irregular_chain_flag must have the same value as it had when
//     processing co_baseheader.
//   - ip_inner_ecn is bound in this encoding method and the value that
//     it gets bound to should be passed to the tcp encoding method
//   For other formats than the irregular chain, these two are ignored
ipv4(is_innermost, ttl_irregular_chain_flag, ip_inner_ecn,
     ip_id_behavior_value)
{
  UNCOMPRESSED {
    version        =:= uncompressed_value(4, 4)  [ 4 ];
    hdr_length     =:= uncompressed_value(4, 5)  [ 4 ];
    dscp                                         [ 6 ];
    ip_ecn_flags                                 [ 2 ];
    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(reorder_ratio.UVALUE == reorder_ratio_value);
        
  CONTROL {
    ENFORCE(reorder_ratio.UVALUE == reorder_ratio_value);
        
    ENFORCE(innermost_ip.UVALUE == is_innermost);
    ip_id_behavior_outer [ 2 ];
    innermost_ip [ 1 ];
  }
        
    ENFORCE(innermost_ip.UVALUE == is_innermost);
    ip_id_behavior_outer [ 2 ];
    innermost_ip [ 1 ];
  }
        
  DEFAULT {
    dscp           =:= static;
    ip_ecn_flags   =:= static;
    df             =:= static;
    ttl_hopl       =:= static;
    protocol       =:= static;
    src_addr       =:= static;
    dst_addr       =:= static;
    ip_id_behavior_outer =:= static;
  }
        
  DEFAULT {
    dscp           =:= static;
    ip_ecn_flags   =:= 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 ];
    reserved     =:= '0000000'     [ 7 ];
    protocol     =:= irregular(8)  [ 8 ];
    src_addr     =:= irregular(32) [ 32 ];
    dst_addr     =:= irregular(32) [ 32 ];
  }
        
  COMPRESSED ipv4_static {
    version_flag =:= '0'           [ 1 ];
    reserved     =:= '0000000'     [ 7 ];
    protocol     =:= irregular(8)  [ 8 ];
    src_addr     =:= irregular(32) [ 32 ];
    dst_addr     =:= irregular(32) [ 32 ];
  }
        
  COMPRESSED ipv4_innermost_dynamic {
    ENFORCE(is_innermost == 1);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    reserved       =:= '00000'             [ 5 ];
    df             =:= irregular(1)        [ 1 ];
    ip_id_behavior_innermost =:= irregular(2) [ 2 ];
    dscp           =:= irregular(6)        [ 6 ];
    ip_ecn_flags   =:= irregular(2)        [ 2 ];
    ttl_hopl       =:= irregular(8)        [ 8 ];
    ip_id          =:=
      ip_id_enc_dyn(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
  }
        
  COMPRESSED ipv4_innermost_dynamic {
    ENFORCE(is_innermost == 1);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    reserved       =:= '00000'             [ 5 ];
    df             =:= irregular(1)        [ 1 ];
    ip_id_behavior_innermost =:= irregular(2) [ 2 ];
    dscp           =:= irregular(6)        [ 6 ];
    ip_ecn_flags   =:= irregular(2)        [ 2 ];
    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 ];
    dscp           =:= irregular(6)        [ 6 ];
    ip_ecn_flags   =:= irregular(2)        [ 2 ];
    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 ];
    dscp           =:= irregular(6)        [ 6 ];
    ip_ecn_flags   =:= irregular(2)        [ 2 ];
    ttl_hopl       =:= irregular(8)        [ 8 ];
    ip_id          =:=
      ip_id_enc_dyn(ip_id_behavior_outer.UVALUE) [ 0, 16 ];
        

}

}

  COMPRESSED ipv4_innermost_replicate {
    ENFORCE(is_innermost == 1);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    reserved       =:= '0000'              [ 4 ];
    ip_id_behavior_innermost =:= irregular(2) [ 2 ];
    ttl_flag       =:= irregular(1)        [ 1 ];
    df             =:= irregular(1)        [ 1 ];
    dscp           =:= irregular(6)        [ 6 ];
    ip_ecn_flags   =:= irregular(2)        [ 2 ];
    ip_id          =:=
      ip_id_enc_dyn(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
    ttl_hopl     =:=
        static_or_irreg(ttl_flag.UVALUE, 8) [ 0, 8 ];
  }
        
  COMPRESSED ipv4_innermost_replicate {
    ENFORCE(is_innermost == 1);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
    reserved       =:= '0000'              [ 4 ];
    ip_id_behavior_innermost =:= irregular(2) [ 2 ];
    ttl_flag       =:= irregular(1)        [ 1 ];
    df             =:= irregular(1)        [ 1 ];
    dscp           =:= irregular(6)        [ 6 ];
    ip_ecn_flags   =:= irregular(2)        [ 2 ];
    ip_id          =:=
      ip_id_enc_dyn(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
    ttl_hopl     =:=
        static_or_irreg(ttl_flag.UVALUE, 8) [ 0, 8 ];
  }
        
  COMPRESSED ipv4_outer_replicate {
    ENFORCE(is_innermost == 0);
    ENFORCE(ip_id_behavior_outer.UVALUE == ip_id_behavior_value);
    reserved       =:= '0000'              [ 4 ];
    ip_id_behavior_outer =:= irregular(2)  [ 2 ]
    ttl_flag       =:= irregular(1)        [ 1 ];
    df             =:= irregular(1)        [ 1 ];
    dscp           =:= irregular(6)        [ 6 ];
    ip_ecn_flags   =:= irregular(2)        [ 2 ];
    ip_id          =:=
      ip_id_enc_dyn(ip_id_behavior_outer.UVALUE) [ 0, 16 ];
    ttl_hopl     =:=
        static_or_irreg(ttl_flag.UVALUE, 8) [ 0, 8 ];
  }
        
  COMPRESSED ipv4_outer_replicate {
    ENFORCE(is_innermost == 0);
    ENFORCE(ip_id_behavior_outer.UVALUE == ip_id_behavior_value);
    reserved       =:= '0000'              [ 4 ];
    ip_id_behavior_outer =:= irregular(2)  [ 2 ]
    ttl_flag       =:= irregular(1)        [ 1 ];
    df             =:= irregular(1)        [ 1 ];
    dscp           =:= irregular(6)        [ 6 ];
    ip_ecn_flags   =:= irregular(2)        [ 2 ];
    ip_id          =:=
      ip_id_enc_dyn(ip_id_behavior_outer.UVALUE) [ 0, 16 ];
    ttl_hopl     =:=
        static_or_irreg(ttl_flag.UVALUE, 8) [ 0, 8 ];
  }
        
  COMPRESSED ipv4_outer_without_ttl_irregular {
    ENFORCE(is_innermost == 0);
    ip_id        =:=
      ip_id_enc_irreg(ip_id_behavior_outer.UVALUE) [ 0, 16 ];
    dscp         =:= static_or_irreg(ecn_used.UVALUE, 6) [ 0, 6 ];
    ip_ecn_flags =:= static_or_irreg(ecn_used.UVALUE, 2) [ 0, 2 ];
    ENFORCE(ttl_irregular_chain_flag == 0);
  }
        
  COMPRESSED ipv4_outer_without_ttl_irregular {
    ENFORCE(is_innermost == 0);
    ip_id        =:=
      ip_id_enc_irreg(ip_id_behavior_outer.UVALUE) [ 0, 16 ];
    dscp         =:= static_or_irreg(ecn_used.UVALUE, 6) [ 0, 6 ];
    ip_ecn_flags =:= static_or_irreg(ecn_used.UVALUE, 2) [ 0, 2 ];
    ENFORCE(ttl_irregular_chain_flag == 0);
  }
        
  COMPRESSED ipv4_outer_with_ttl_irregular {
    ENFORCE(is_innermost == 0);
    ip_id        =:=
      ip_id_enc_irreg(ip_id_behavior_outer.UVALUE)       [ 0, 16 ];
    dscp         =:= static_or_irreg(ecn_used.UVALUE, 6) [ 0, 6 ];
    ip_ecn_flags =:= static_or_irreg(ecn_used.UVALUE, 2) [ 0, 2 ];
    ttl_hopl     =:= irregular(8)                        [ 8 ];
        
  COMPRESSED ipv4_outer_with_ttl_irregular {
    ENFORCE(is_innermost == 0);
    ip_id        =:=
      ip_id_enc_irreg(ip_id_behavior_outer.UVALUE)       [ 0, 16 ];
    dscp         =:= static_or_irreg(ecn_used.UVALUE, 6) [ 0, 6 ];
    ip_ecn_flags =:= static_or_irreg(ecn_used.UVALUE, 2) [ 0, 2 ];
    ttl_hopl     =:= irregular(8)                        [ 8 ];
        
    ENFORCE(ttl_irregular_chain_flag == 1);
  }
        
    ENFORCE(ttl_irregular_chain_flag == 1);
  }
        
  COMPRESSED ipv4_innermost_irregular {
    ENFORCE(is_innermost == 1);
    ip_id          =:=
      ip_id_enc_irreg(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
    ENFORCE(ip_inner_ecn == ip_ecn_flags.UVALUE);
  }
}
        
  COMPRESSED ipv4_innermost_irregular {
    ENFORCE(is_innermost == 1);
    ip_id          =:=
      ip_id_enc_irreg(ip_id_behavior_innermost.UVALUE) [ 0, 16 ];
    ENFORCE(ip_inner_ecn == ip_ecn_flags.UVALUE);
  }
}
        
/////////////////////////////////////////////
// TCP Options
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// TCP Options
/////////////////////////////////////////////
        
// nbits is bound to the remaining length (in bits) of TCP
// options, including the EOL type byte.
tcp_opt_eol(nbits)
{
  UNCOMPRESSED {
    type     =:= uncompressed_value(8, 0) [ 8 ];
    padding  =:=
      uncompressed_value(nbits-8, 0)      [ nbits-8 ];
  }
        
// nbits is bound to the remaining length (in bits) of TCP
// options, including the EOL type byte.
tcp_opt_eol(nbits)
{
  UNCOMPRESSED {
    type     =:= uncompressed_value(8, 0) [ 8 ];
    padding  =:=
      uncompressed_value(nbits-8, 0)      [ nbits-8 ];
  }
        
  CONTROL {
    pad_len [ 8 ];
  }
        
  CONTROL {
    pad_len [ 8 ];
  }
        
  COMPRESSED eol_list_item {
    pad_len =:= compressed_value(8, nbits-8) [ 8 ];
  }
        
  COMPRESSED eol_list_item {
    pad_len =:= compressed_value(8, nbits-8) [ 8 ];
  }
        
  COMPRESSED eol_irregular {
    pad_len =:= static;
    ENFORCE(nbits-8 == pad_len.UVALUE);
  }
}
        
  COMPRESSED eol_irregular {
    pad_len =:= static;
    ENFORCE(nbits-8 == pad_len.UVALUE);
  }
}
        
tcp_opt_nop
{
  UNCOMPRESSED {
    type =:= uncompressed_value(8, 1) [ 8 ];
  }
        
tcp_opt_nop
{
  UNCOMPRESSED {
    type =:= uncompressed_value(8, 1) [ 8 ];
  }
        
  COMPRESSED nop_list_item {
  }
        
  COMPRESSED nop_list_item {
  }
        
  COMPRESSED nop_irregular {
  }
}
        
  COMPRESSED nop_irregular {
  }
}
        
tcp_opt_mss
{
  UNCOMPRESSED {
    type   =:= uncompressed_value(8, 2) [ 8 ];
    length =:= uncompressed_value(8, 4) [ 8 ];
    mss                                 [ 16 ];
  }
        
tcp_opt_mss
{
  UNCOMPRESSED {
    type   =:= uncompressed_value(8, 2) [ 8 ];
    length =:= uncompressed_value(8, 4) [ 8 ];
    mss                                 [ 16 ];
  }
        
  COMPRESSED mss_list_item {
    mss =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED mss_list_item {
    mss =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED mss_irregular {
    mss    =:= static;
  }
}
        
  COMPRESSED mss_irregular {
    mss    =:= static;
  }
}
        
tcp_opt_wscale
{
  UNCOMPRESSED {
    type   =:= uncompressed_value(8, 3) [ 8 ];
    length =:= uncompressed_value(8, 3) [ 8 ];
    wscale                              [ 8 ];
  }
        
tcp_opt_wscale
{
  UNCOMPRESSED {
    type   =:= uncompressed_value(8, 3) [ 8 ];
    length =:= uncompressed_value(8, 3) [ 8 ];
    wscale                              [ 8 ];
  }
        
  COMPRESSED wscale_list_item {
    wscale =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED wscale_list_item {
    wscale =:= irregular(8) [ 8 ];
  }
        
  COMPRESSED wscale_irregular {
    wscale =:= static;
  }
}
        
  COMPRESSED wscale_irregular {
    wscale =:= static;
  }
}
        
ts_lsb
{
  UNCOMPRESSED {
    tsval [ 32 ];
  }
        
ts_lsb
{
  UNCOMPRESSED {
    tsval [ 32 ];
  }
        
  COMPRESSED tsval_7 {
    discriminator =:= '0'        [ 1 ];
    tsval         =:= lsb(7, -1) [ 7 ];
  }
        
  COMPRESSED tsval_7 {
    discriminator =:= '0'        [ 1 ];
    tsval         =:= lsb(7, -1) [ 7 ];
  }
        
  COMPRESSED tsval_14 {
    discriminator =:= '10'        [ 2 ];
    tsval         =:= lsb(14, -1) [ 14 ];
  }
        
  COMPRESSED tsval_14 {
    discriminator =:= '10'        [ 2 ];
    tsval         =:= lsb(14, -1) [ 14 ];
  }
        
  COMPRESSED tsval_21 {
    discriminator =:= '110'               [ 3 ];
    tsval         =:= lsb(21, 0x00040000) [ 21 ];
  }
        
  COMPRESSED tsval_21 {
    discriminator =:= '110'               [ 3 ];
    tsval         =:= lsb(21, 0x00040000) [ 21 ];
  }
        
  COMPRESSED tsval_29 {
    discriminator =:= '111'               [ 3 ];
    tsval         =:= lsb(29, 0x04000000) [ 29 ];
  }
}
        
  COMPRESSED tsval_29 {
    discriminator =:= '111'               [ 3 ];
    tsval         =:= lsb(29, 0x04000000) [ 29 ];
  }
}
        
tcp_opt_ts
{
  UNCOMPRESSED {
    type   =:= uncompressed_value(8, 8)  [ 8 ];
    length =:= uncompressed_value(8, 10) [ 8 ];
    tsval                                [ 32 ];
    tsecho                               [ 32 ];
  }
  COMPRESSED tsopt_list_item {
    tsval  =:= irregular(32) [ 32 ];
    tsecho =:= irregular(32) [ 32 ];
  }
        
tcp_opt_ts
{
  UNCOMPRESSED {
    type   =:= uncompressed_value(8, 8)  [ 8 ];
    length =:= uncompressed_value(8, 10) [ 8 ];
    tsval                                [ 32 ];
    tsecho                               [ 32 ];
  }
  COMPRESSED tsopt_list_item {
    tsval  =:= irregular(32) [ 32 ];
    tsecho =:= irregular(32) [ 32 ];
  }
        
  COMPRESSED tsopt_irregular {
    tsval  =:= ts_lsb [ 8, 16, 24, 32 ];
    tsecho =:= ts_lsb [ 8, 16, 24, 32 ];
  }
}
sack_pure_lsb(base)
{
  UNCOMPRESSED {
    sack_field [ 32 ];
  }
        
  COMPRESSED tsopt_irregular {
    tsval  =:= ts_lsb [ 8, 16, 24, 32 ];
    tsecho =:= ts_lsb [ 8, 16, 24, 32 ];
  }
}
sack_pure_lsb(base)
{
  UNCOMPRESSED {
    sack_field [ 32 ];
  }
        
  CONTROL {
    ENFORCE(sack_field.CVALUE == (sack_field.UVALUE - base));
  }
        
  CONTROL {
    ENFORCE(sack_field.CVALUE == (sack_field.UVALUE - base));
  }
        
  COMPRESSED lsb_15 {
    ENFORCE(sack_field.CVALUE == sack_field.CVALUE <= 0x7fff);
    discriminator =:= '0'           [ 1 ];
    sack_field                      [ 15 ];
        
  COMPRESSED lsb_15 {
    ENFORCE(sack_field.CVALUE == sack_field.CVALUE <= 0x7fff);
    discriminator =:= '0'           [ 1 ];
    sack_field                      [ 15 ];
        

}

}

  COMPRESSED lsb_22 {
    ENFORCE(sack_field.CVALUE == sack_field.CVALUE <= 0x3fffff);
    discriminator =:= '10'          [ 2 ];
    sack_field                      [ 22 ];
  }
        
  COMPRESSED lsb_22 {
    ENFORCE(sack_field.CVALUE == sack_field.CVALUE <= 0x3fffff);
    discriminator =:= '10'          [ 2 ];
    sack_field                      [ 22 ];
  }
        
  COMPRESSED lsb_29 {
    ENFORCE(sack_field.CVALUE == sack_field.CVALUE <= 0x1fffffff);
    discriminator =:= '110'         [ 3 ];
    sack_field                      [ 29 ];
  }
        
  COMPRESSED lsb_29 {
    ENFORCE(sack_field.CVALUE == sack_field.CVALUE <= 0x1fffffff);
    discriminator =:= '110'         [ 3 ];
    sack_field                      [ 29 ];
  }
        
  COMPRESSED full_offset {
    discriminator =:= '11111111'    [ 8 ];
    sack_field                      [ 32 ];
  }
}
        
  COMPRESSED full_offset {
    discriminator =:= '11111111'    [ 8 ];
    sack_field                      [ 32 ];
  }
}
        
sack_block(reference)
{
  UNCOMPRESSED {
    block_start [ 32 ];
    block_end   [ 32 ];
  }
        
sack_block(reference)
{
  UNCOMPRESSED {
    block_start [ 32 ];
    block_end   [ 32 ];
  }
        
  COMPRESSED {
    block_start =:=
      sack_pure_lsb(reference)          [ 16, 24, 32, 40 ];
    block_end   =:=
      sack_pure_lsb(block_start.UVALUE) [ 16, 24, 32, 40 ];
  }
}
        
  COMPRESSED {
    block_start =:=
      sack_pure_lsb(reference)          [ 16, 24, 32, 40 ];
    block_end   =:=
      sack_pure_lsb(block_start.UVALUE) [ 16, 24, 32, 40 ];
  }
}
        
// The value of the parameter is set to the ack_number value
// of the TCP header
tcp_opt_sack(ack_value)
{
        
// The value of the parameter is set to the ack_number value
// of the TCP header
tcp_opt_sack(ack_value)
{
        
  UNCOMPRESSED {
    type    =:= uncompressed_value(8, 5) [ 8 ];
    length                               [ 8 ];
    block_1                              [ 64 ];
    block_2                              [ 0, 64 ];
    block_3                              [ 0, 64 ];
    block_4                              [ 0, 64 ];
  }
        
  UNCOMPRESSED {
    type    =:= uncompressed_value(8, 5) [ 8 ];
    length                               [ 8 ];
    block_1                              [ 64 ];
    block_2                              [ 0, 64 ];
    block_3                              [ 0, 64 ];
    block_4                              [ 0, 64 ];
  }
        
  DEFAULT {
    length  =:= static;
    block_2 =:= uncompressed_value(0, 0);
    block_3 =:= uncompressed_value(0, 0);
    block_4 =:= uncompressed_value(0, 0);
  }
        
  DEFAULT {
    length  =:= static;
    block_2 =:= uncompressed_value(0, 0);
    block_3 =:= uncompressed_value(0, 0);
    block_4 =:= uncompressed_value(0, 0);
  }
        
  COMPRESSED sack1_list_item {
    discriminator =:= '00000001';
    block_1       =:= sack_block(ack_value);
    ENFORCE(length.UVALUE == 10);
  }
        
  COMPRESSED sack1_list_item {
    discriminator =:= '00000001';
    block_1       =:= sack_block(ack_value);
    ENFORCE(length.UVALUE == 10);
  }
        
  COMPRESSED sack2_list_item {
    discriminator =:= '00000010';
    block_1       =:= sack_block(ack_value);
    block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
    ENFORCE(length.UVALUE == 18);
  }
        
  COMPRESSED sack2_list_item {
    discriminator =:= '00000010';
    block_1       =:= sack_block(ack_value);
    block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
    ENFORCE(length.UVALUE == 18);
  }
        
COMPRESSED sack3_list_item {
   discriminator =:= '00000011';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   block_3       =:= sack_block(block_2.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 26);
 }
        
COMPRESSED sack3_list_item {
   discriminator =:= '00000011';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   block_3       =:= sack_block(block_2.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 26);
 }
        
 COMPRESSED sack4_list_item {
   discriminator =:= '00000100';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   block_3       =:= sack_block(block_2.UVALUE && 0xFFFFFFFF);
   block_4       =:= sack_block(block_3.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 34);
 }
        
 COMPRESSED sack4_list_item {
   discriminator =:= '00000100';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   block_3       =:= sack_block(block_2.UVALUE && 0xFFFFFFFF);
   block_4       =:= sack_block(block_3.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 34);
 }
        
  COMPRESSED sack_unchanged_irregular {
    discriminator =:= '00000000';
    block_1       =:= static;
    block_2       =:= static;
    block_3       =:= static;
    block_4       =:= static;
  }
        
  COMPRESSED sack_unchanged_irregular {
    discriminator =:= '00000000';
    block_1       =:= static;
    block_2       =:= static;
    block_3       =:= static;
    block_4       =:= static;
  }
        
  COMPRESSED sack1_irregular {
    discriminator =:= '00000001';
    block_1       =:= sack_block(ack_value);
        
  COMPRESSED sack1_irregular {
    discriminator =:= '00000001';
    block_1       =:= sack_block(ack_value);
        
    ENFORCE(length.UVALUE == 10);
  }
        
    ENFORCE(length.UVALUE == 10);
  }
        
 COMPRESSED sack2_irregular {
   discriminator =:= '00000010';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 18);
 }
        
 COMPRESSED sack2_irregular {
   discriminator =:= '00000010';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 18);
 }
        
 COMPRESSED sack3_irregular {
   discriminator =:= '00000011';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   block_3       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 26);
 }
        
 COMPRESSED sack3_irregular {
   discriminator =:= '00000011';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   block_3       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 26);
 }
        
 COMPRESSED sack4_irregular {
   discriminator =:= '00000100';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   block_3       =:= sack_block(block_2.UVALUE && 0xFFFFFFFF);
   block_4       =:= sack_block(block_3.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 34);
 }
}
        
 COMPRESSED sack4_irregular {
   discriminator =:= '00000100';
   block_1       =:= sack_block(ack_value);
   block_2       =:= sack_block(block_1.UVALUE && 0xFFFFFFFF);
   block_3       =:= sack_block(block_2.UVALUE && 0xFFFFFFFF);
   block_4       =:= sack_block(block_3.UVALUE && 0xFFFFFFFF);
   ENFORCE(length.UVALUE == 34);
 }
}
        
tcp_opt_sack_permitted
{
  UNCOMPRESSED {
    type   =:= uncompressed_value(8, 4) [ 8 ];
    length =:= uncompressed_value(8, 2) [ 8 ];
  }
        
tcp_opt_sack_permitted
{
  UNCOMPRESSED {
    type   =:= uncompressed_value(8, 4) [ 8 ];
    length =:= uncompressed_value(8, 2) [ 8 ];
  }
        
  COMPRESSED sack_permitted_list_item {
  }
        
  COMPRESSED sack_permitted_list_item {
  }
        
  COMPRESSED sack_permitted_irregular {
  }
}
        
  COMPRESSED sack_permitted_irregular {
  }
}
        
tcp_opt_generic
{
  UNCOMPRESSED {
    type                                    [ 8 ];
    length_msb =:= uncompressed_value(1, 0) [ 1 ];
    length_lsb                              [ 7 ];
        
tcp_opt_generic
{
  UNCOMPRESSED {
    type                                    [ 8 ];
    length_msb =:= uncompressed_value(1, 0) [ 1 ];
    length_lsb                              [ 7 ];
        
    contents                           [ length_lsb.UVALUE*8-16 ];
  }
        
    contents                           [ length_lsb.UVALUE*8-16 ];
  }
        
  CONTROL {
    option_static [ 1 ];
  }
        
  CONTROL {
    option_static [ 1 ];
  }
        
  DEFAULT {
    type       =:= static;
    length_lsb =:= static;
    contents   =:= static;
  }
        
  DEFAULT {
    type       =:= static;
    length_lsb =:= static;
    contents   =:= static;
  }
        
  COMPRESSED generic_list_item {
    type          =:= irregular(8)      [ 8 ];
    option_static =:= one_bit_choice    [ 1 ];
    length_lsb    =:= irregular(7)      [ 7 ];
    contents      =:=
      irregular(length_lsb.UVALUE*8-16) [ length_lsb.UVALUE*8-16 ];
  }
        
  COMPRESSED generic_list_item {
    type          =:= irregular(8)      [ 8 ];
    option_static =:= one_bit_choice    [ 1 ];
    length_lsb    =:= irregular(7)      [ 7 ];
    contents      =:=
      irregular(length_lsb.UVALUE*8-16) [ length_lsb.UVALUE*8-16 ];
  }
        
  // Used when context of option has option_static set to one
  COMPRESSED generic_static_irregular {
    ENFORCE(option_static.UVALUE == 1);
  }
        
  // Used when context of option has option_static set to one
  COMPRESSED generic_static_irregular {
    ENFORCE(option_static.UVALUE == 1);
  }
        
  // An item that can change, but currently is unchanged
  COMPRESSED generic_stable_irregular {
    discriminator =:= '11111111' [ 8 ];
    ENFORCE(option_static.UVALUE == 0);
  }
        
  // An item that can change, but currently is unchanged
  COMPRESSED generic_stable_irregular {
    discriminator =:= '11111111' [ 8 ];
    ENFORCE(option_static.UVALUE == 0);
  }
        
  // An item that is assumed to change constantly.
  // Length is not allowed to change here, since a length change is
  // most likely to cause new NOPs or an EOL length change.
  COMPRESSED generic_full_irregular {
    discriminator =:= '00000000'        [ 8 ];
    contents      =:=
      irregular(length_lsb.UVALUE*8-16) [ length_lsb.UVALUE*8-16 ];
    ENFORCE(option_static.UVALUE == 0);
  }
}
        
  // An item that is assumed to change constantly.
  // Length is not allowed to change here, since a length change is
  // most likely to cause new NOPs or an EOL length change.
  COMPRESSED generic_full_irregular {
    discriminator =:= '00000000'        [ 8 ];
    contents      =:=
      irregular(length_lsb.UVALUE*8-16) [ length_lsb.UVALUE*8-16 ];
    ENFORCE(option_static.UVALUE == 0);
  }
}
        
tcp_list_presence_enc(presence)
{
  UNCOMPRESSED {
    tcp_options;
  }
        
tcp_list_presence_enc(presence)
{
  UNCOMPRESSED {
    tcp_options;
  }
        
  COMPRESSED list_not_present {
    tcp_options =:= static [ 0 ];
    ENFORCE(presence == 0);
  }
        
  COMPRESSED list_not_present {
    tcp_options =:= static [ 0 ];
    ENFORCE(presence == 0);
  }
        
  COMPRESSED list_present {
    tcp_options =:= list_tcp_options [ VARIABLE ];
    ENFORCE(presence == 1);
  }
}
        
  COMPRESSED list_present {
    tcp_options =:= list_tcp_options [ VARIABLE ];
    ENFORCE(presence == 1);
  }
}
        
/////////////////////////////////////////////
// TCP Header
/////////////////////////////////////////////
        
/////////////////////////////////////////////
// TCP Header
/////////////////////////////////////////////
        
port_replicate(flags)
{
  UNCOMPRESSED {
    port [ 16 ];
  }
        
port_replicate(flags)
{
  UNCOMPRESSED {
    port [ 16 ];
  }
        
  COMPRESSED port_static_enc {
    port =:= static [ 0 ];
    ENFORCE(flags == 0b00);
  }
        
  COMPRESSED port_static_enc {
    port =:= static [ 0 ];
    ENFORCE(flags == 0b00);
  }
        
  COMPRESSED port_lsb8 {
    port =:= lsb(8, 64) [ 8 ];
    ENFORCE(flags == 0b01);
  }
        
  COMPRESSED port_lsb8 {
    port =:= lsb(8, 64) [ 8 ];
    ENFORCE(flags == 0b01);
  }
        
  COMPRESSED port_irr_enc {
    port =:= irregular(16) [ 16 ];
    ENFORCE(flags == 0b10);
  }
}
        
  COMPRESSED port_irr_enc {
    port =:= irregular(16) [ 16 ];
    ENFORCE(flags == 0b10);
  }
}
        
tcp_irreg_ip_ecn(ip_inner_ecn)
{
  UNCOMPRESSED {
    ip_ecn_flags [ 2 ];
  }
        
tcp_irreg_ip_ecn(ip_inner_ecn)
{
  UNCOMPRESSED {
    ip_ecn_flags [ 2 ];
  }
        
  COMPRESSED ecn_present {
    // This field does not exist in the uncompressed header
    // and therefore cannot use uncompressed_value.
    ip_ecn_flags =:=
      compressed_value(2, ip_inner_ecn) [ 2 ];
        
  COMPRESSED ecn_present {
    // This field does not exist in the uncompressed header
    // and therefore cannot use uncompressed_value.
    ip_ecn_flags =:=
      compressed_value(2, ip_inner_ecn) [ 2 ];
        
    ENFORCE(ecn_used.UVALUE == 1);
  }
        
    ENFORCE(ecn_used.UVALUE == 1);
  }
        
  COMPRESSED ecn_not_present {
    ip_ecn_flags =:= static [ 0 ];
    ENFORCE(ecn_used.UVALUE == 0);
  }
}
        
  COMPRESSED ecn_not_present {
    ip_ecn_flags =:= static [ 0 ];
    ENFORCE(ecn_used.UVALUE == 0);
  }
}
        
rsf_index_enc
{
  UNCOMPRESSED {
    rsf_flag [ 3 ];
  }
        
rsf_index_enc
{
  UNCOMPRESSED {
    rsf_flag [ 3 ];
  }
        
  COMPRESSED none {
    rsf_idx  =:= '00' [ 2 ];
    rsf_flag =:= uncompressed_value(3, 0x00);
  }
        
  COMPRESSED none {
    rsf_idx  =:= '00' [ 2 ];
    rsf_flag =:= uncompressed_value(3, 0x00);
  }
        
  COMPRESSED rst_only {
    rsf_idx  =:= '01' [ 2 ];
    rsf_flag =:= uncompressed_value(3, 0x04);
  }
        
  COMPRESSED rst_only {
    rsf_idx  =:= '01' [ 2 ];
    rsf_flag =:= uncompressed_value(3, 0x04);
  }
        
  COMPRESSED syn_only {
    rsf_idx  =:= '10' [ 2 ];
    rsf_flag =:= uncompressed_value(3, 0x02);
  }
        
  COMPRESSED syn_only {
    rsf_idx  =:= '10' [ 2 ];
    rsf_flag =:= uncompressed_value(3, 0x02);
  }
        
  COMPRESSED fin_only {
    rsf_idx  =:= '11' [ 2 ];
    rsf_flag =:= uncompressed_value(3, 0x01);
  }
}
        
  COMPRESSED fin_only {
    rsf_idx  =:= '11' [ 2 ];
    rsf_flag =:= uncompressed_value(3, 0x01);
  }
}
        
optional_2bit_padding(used_flag)
{
  UNCOMPRESSED {
  }
        
optional_2bit_padding(used_flag)
{
  UNCOMPRESSED {
  }
        
  COMPRESSED used {
    padding =:= compressed_value(2, 0x0) [ 2 ];
    ENFORCE(used_flag == 1);
  }
        
  COMPRESSED used {
    padding =:= compressed_value(2, 0x0) [ 2 ];
    ENFORCE(used_flag == 1);
  }
        
  COMPRESSED unused {
    padding =:= compressed_value(0, 0x0);
        
  COMPRESSED unused {
    padding =:= compressed_value(0, 0x0);
        
    ENFORCE(used_flag == 0);
  }
}
        
    ENFORCE(used_flag == 0);
  }
}
        
// ack_stride_value is the user-selected stride for scaling the
// TCP ack_number
// ip_inner_ecn is the value bound when processing the innermost
// IP header (ipv4 or ipv6 encoding method)
tcp(payload_size, ack_stride_value, ip_inner_ecn)
{
  UNCOMPRESSED {
    src_port      [ 16 ];
    dst_port      [ 16 ];
    seq_number    [ 32 ];
    ack_number    [ 32 ];
    data_offset   [ 4 ];
    tcp_res_flags [ 4 ];
    tcp_ecn_flags [ 2 ];
    urg_flag      [ 1 ];
    ack_flag      [ 1 ];
    psh_flag      [ 1 ];
    rsf_flags     [ 3 ];
    window        [ 16 ];
    checksum      [ 16 ];
    urg_ptr       [ 16 ];
    options       [ (data_offset.UVALUE-5)*32 ];
  }
        
// ack_stride_value is the user-selected stride for scaling the
// TCP ack_number
// ip_inner_ecn is the value bound when processing the innermost
// IP header (ipv4 or ipv6 encoding method)
tcp(payload_size, ack_stride_value, ip_inner_ecn)
{
  UNCOMPRESSED {
    src_port      [ 16 ];
    dst_port      [ 16 ];
    seq_number    [ 32 ];
    ack_number    [ 32 ];
    data_offset   [ 4 ];
    tcp_res_flags [ 4 ];
    tcp_ecn_flags [ 2 ];
    urg_flag      [ 1 ];
    ack_flag      [ 1 ];
    psh_flag      [ 1 ];
    rsf_flags     [ 3 ];
    window        [ 16 ];
    checksum      [ 16 ];
    urg_ptr       [ 16 ];
    options       [ (data_offset.UVALUE-5)*32 ];
  }
        
  CONTROL {
    dummy_field_s =:= field_scaling(payload_size,
      seq_number_scaled.UVALUE, seq_number.UVALUE,
      seq_number_residue.UVALUE) [ 0 ];
    dummy_field_a =:= field_scaling(ack_stride.UVALUE,
      ack_number_scaled.UVALUE, ack_number.UVALUE,
      ack_number_residue.UVALUE) [ 0 ];
    ENFORCE(ack_stride.UVALUE == ack_stride_value);
  }
        
  CONTROL {
    dummy_field_s =:= field_scaling(payload_size,
      seq_number_scaled.UVALUE, seq_number.UVALUE,
      seq_number_residue.UVALUE) [ 0 ];
    dummy_field_a =:= field_scaling(ack_stride.UVALUE,
      ack_number_scaled.UVALUE, ack_number.UVALUE,
      ack_number_residue.UVALUE) [ 0 ];
    ENFORCE(ack_stride.UVALUE == ack_stride_value);
  }
        
  INITIAL {
    ack_stride     =:= uncompressed_value(16, 0);
  }
        
  INITIAL {
    ack_stride     =:= uncompressed_value(16, 0);
  }
        
  DEFAULT {
    src_port      =:= static;
    dst_port      =:= static;
    seq_number    =:= static;
    ack_number    =:= static;
    data_offset   =:= inferred_offset;
        
  DEFAULT {
    src_port      =:= static;
    dst_port      =:= static;
    seq_number    =:= static;
    ack_number    =:= static;
    data_offset   =:= inferred_offset;
        
    tcp_res_flags =:= static;
    tcp_ecn_flags =:= static;
    urg_flag      =:= static;
    ack_flag      =:= uncompressed_value(1, 1);
    rsf_flags     =:= uncompressed_value(3, 0);
    window        =:= static;
    urg_ptr       =:= static;
    ack_stride    =:= static;
    ack_number_scaled =:= static;
    seq_number_scaled =:= static;
    ack_number_residue =:= static;
    seq_number_residue =:= static;
  }
        
    tcp_res_flags =:= static;
    tcp_ecn_flags =:= static;
    urg_flag      =:= static;
    ack_flag      =:= uncompressed_value(1, 1);
    rsf_flags     =:= uncompressed_value(3, 0);
    window        =:= static;
    urg_ptr       =:= static;
    ack_stride    =:= static;
    ack_number_scaled =:= static;
    seq_number_scaled =:= static;
    ack_number_residue =:= static;
    seq_number_residue =:= static;
  }
        
  COMPRESSED tcp_static {
    src_port =:= irregular(16) [ 16 ];
    dst_port =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED tcp_static {
    src_port =:= irregular(16) [ 16 ];
    dst_port =:= irregular(16) [ 16 ];
  }
        
  COMPRESSED tcp_dynamic {
    ecn_used        =:= one_bit_choice          [ 1 ];
    ack_stride_flag =:= irregular(1)            [ 1 ];
    ack_zero        =:= irregular(1)            [ 1 ];
    urp_zero        =:= irregular(1)            [ 1 ];
    tcp_res_flags   =:= irregular(4)            [ 4 ];
    tcp_ecn_flags   =:= irregular(2)            [ 2 ];
    urg_flag        =:= irregular(1)            [ 1 ];
    ack_flag        =:= irregular(1)            [ 1 ];
    psh_flag        =:= irregular(1)            [ 1 ];
    rsf_flags       =:= irregular(3)            [ 3 ];
    msn             =:= irregular(16)           [ 16 ];
    seq_number      =:= irregular(32)           [ 32 ];
    ack_number      =:=
      zero_or_irreg(ack_zero.CVALUE, 32)        [ 0, 32 ];
    window          =:= irregular(16)           [ 16 ];
    checksum        =:= irregular(16)           [ 16 ];
    urg_ptr         =:=
      zero_or_irreg(urp_zero.CVALUE, 16)        [ 0, 16 ];
    ack_stride      =:=
      static_or_irreg(ack_stride_flag.CVALUE, 16) [ 0, 16 ];
    options         =:= list_tcp_options        [ VARIABLE ];
  }
        
  COMPRESSED tcp_dynamic {
    ecn_used        =:= one_bit_choice          [ 1 ];
    ack_stride_flag =:= irregular(1)            [ 1 ];
    ack_zero        =:= irregular(1)            [ 1 ];
    urp_zero        =:= irregular(1)            [ 1 ];
    tcp_res_flags   =:= irregular(4)            [ 4 ];
    tcp_ecn_flags   =:= irregular(2)            [ 2 ];
    urg_flag        =:= irregular(1)            [ 1 ];
    ack_flag        =:= irregular(1)            [ 1 ];
    psh_flag        =:= irregular(1)            [ 1 ];
    rsf_flags       =:= irregular(3)            [ 3 ];
    msn             =:= irregular(16)           [ 16 ];
    seq_number      =:= irregular(32)           [ 32 ];
    ack_number      =:=
      zero_or_irreg(ack_zero.CVALUE, 32)        [ 0, 32 ];
    window          =:= irregular(16)           [ 16 ];
    checksum        =:= irregular(16)           [ 16 ];
    urg_ptr         =:=
      zero_or_irreg(urp_zero.CVALUE, 16)        [ 0, 16 ];
    ack_stride      =:=
      static_or_irreg(ack_stride_flag.CVALUE, 16) [ 0, 16 ];
    options         =:= list_tcp_options        [ VARIABLE ];
  }
        
  COMPRESSED tcp_replicate {
    reserved          =:= '0'                      [ 1 ];
    window_presence   =:= irregular(1)             [ 1 ];
    list_present      =:= irregular(1)             [ 1 ];
    src_port_presence =:= irregular(2)             [ 2 ];
        
  COMPRESSED tcp_replicate {
    reserved          =:= '0'                      [ 1 ];
    window_presence   =:= irregular(1)             [ 1 ];
    list_present      =:= irregular(1)             [ 1 ];
    src_port_presence =:= irregular(2)             [ 2 ];
        
    dst_port_presence =:= irregular(2)             [ 2 ];
    ack_stride_flag   =:= irregular(1)             [ 1 ];
    ack_presence      =:= irregular(1)             [ 1 ];
    urp_presence      =:= irregular(1)             [ 1 ];
    urg_flag          =:= irregular(1)             [ 1 ];
    ack_flag          =:= irregular(1)             [ 1 ];
    psh_flag          =:= irregular(1)             [ 1 ];
    rsf_flags         =:= rsf_index_enc            [ 2 ];
    ecn_used          =:= one_bit_choice           [ 1 ];
    msn               =:= irregular(16)            [ 16 ];
    seq_number        =:= irregular(32)            [ 32 ];
    src_port          =:=
      port_replicate(src_port_presence)      [ 0, 8, 16 ];
    dst_port          =:=
      port_replicate(dst_port_presence)      [ 0, 8, 16 ];
    window            =:=
      static_or_irreg(window_presence, 16)   [ 0, 16 ];
    urg_point         =:=
      static_or_irreg(urp_presence, 16)    [ 0, 16 ];
    ack_number        =:=
      static_or_irreg(ack_presence, 32)    [ 0, 32 ];
    ecn_padding       =:=
      optional_2bit_padding(ecn_used.CVALUE)     [ 0, 2 ];
    tcp_res_flags =:=
      static_or_irreg(ecn_used.CVALUE, 4)        [ 0, 4 ];
    tcp_ecn_flags     =:=
      static_or_irreg(ecn_used.CVALUE, 2)        [ 0, 2 ];
    checksum          =:= irregular(16)            [ 16 ];
    ack_stride        =:=
      static_or_irreg(ack_stride_flag.CVALUE, 16)  [ 0, 16 ];
    options           =:=
      tcp_list_presence_enc(list_present.CVALUE) [ VARIABLE ];
  }
        
    dst_port_presence =:= irregular(2)             [ 2 ];
    ack_stride_flag   =:= irregular(1)             [ 1 ];
    ack_presence      =:= irregular(1)             [ 1 ];
    urp_presence      =:= irregular(1)             [ 1 ];
    urg_flag          =:= irregular(1)             [ 1 ];
    ack_flag          =:= irregular(1)             [ 1 ];
    psh_flag          =:= irregular(1)             [ 1 ];
    rsf_flags         =:= rsf_index_enc            [ 2 ];
    ecn_used          =:= one_bit_choice           [ 1 ];
    msn               =:= irregular(16)            [ 16 ];
    seq_number        =:= irregular(32)            [ 32 ];
    src_port          =:=
      port_replicate(src_port_presence)      [ 0, 8, 16 ];
    dst_port          =:=
      port_replicate(dst_port_presence)      [ 0, 8, 16 ];
    window            =:=
      static_or_irreg(window_presence, 16)   [ 0, 16 ];
    urg_point         =:=
      static_or_irreg(urp_presence, 16)    [ 0, 16 ];
    ack_number        =:=
      static_or_irreg(ack_presence, 32)    [ 0, 32 ];
    ecn_padding       =:=
      optional_2bit_padding(ecn_used.CVALUE)     [ 0, 2 ];
    tcp_res_flags =:=
      static_or_irreg(ecn_used.CVALUE, 4)        [ 0, 4 ];
    tcp_ecn_flags     =:=
      static_or_irreg(ecn_used.CVALUE, 2)        [ 0, 2 ];
    checksum          =:= irregular(16)            [ 16 ];
    ack_stride        =:=
      static_or_irreg(ack_stride_flag.CVALUE, 16)  [ 0, 16 ];
    options           =:=
      tcp_list_presence_enc(list_present.CVALUE) [ VARIABLE ];
  }
        
  COMPRESSED tcp_irregular {
    ip_ecn_flags  =:= tcp_irreg_ip_ecn(ip_inner_ecn)  [ 0, 2 ];
    tcp_res_flags =:=
      static_or_irreg(ecn_used.CVALUE, 4)            [ 0, 4 ];
    tcp_ecn_flags =:=
      static_or_irreg(ecn_used.CVALUE, 2)             [ 0, 2 ];
    checksum      =:= irregular(16)                   [ 16 ];
  }
}
        
  COMPRESSED tcp_irregular {
    ip_ecn_flags  =:= tcp_irreg_ip_ecn(ip_inner_ecn)  [ 0, 2 ];
    tcp_res_flags =:=
      static_or_irreg(ecn_used.CVALUE, 4)            [ 0, 4 ];
    tcp_ecn_flags =:=
      static_or_irreg(ecn_used.CVALUE, 2)             [ 0, 2 ];
    checksum      =:= irregular(16)                   [ 16 ];
  }
}
        
///////////////////////////////////////////////////
// Encoding methods used in compressed base headers
///////////////////////////////////////////////////
        
///////////////////////////////////////////////////
// Encoding methods used in compressed base headers
///////////////////////////////////////////////////
        
dscp_enc(flag)
{
  UNCOMPRESSED {
    dscp [ 6 ];
  }
        
dscp_enc(flag)
{
  UNCOMPRESSED {
    dscp [ 6 ];
  }
        
  COMPRESSED static_enc {
    dscp =:= static [ 0 ];
    ENFORCE(flag == 0);
  }
        
  COMPRESSED static_enc {
    dscp =:= static [ 0 ];
    ENFORCE(flag == 0);
  }
        
  COMPRESSED irreg {
    dscp    =:= irregular(6)           [ 6 ];
    padding =:= compressed_value(2, 0) [ 2 ];
    ENFORCE(flag == 1);
  }
}
        
  COMPRESSED irreg {
    dscp    =:= irregular(6)           [ 6 ];
    padding =:= compressed_value(2, 0) [ 2 ];
    ENFORCE(flag == 1);
  }
}
        
ip_id_lsb(behavior, k, p)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
ip_id_lsb(behavior, k, p)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
  }
        
  CONTROL {
    ip_id_nbo    [ 16 ];
  }
        
  CONTROL {
    ip_id_nbo    [ 16 ];
  }
        
  COMPRESSED nbo {
    ip_id_offset =:= lsb(k, p) [ k ];
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL);
    ENFORCE(ip_id_offset.UVALUE == ip_id.UVALUE - msn.UVALUE);
  }
        
  COMPRESSED nbo {
    ip_id_offset =:= lsb(k, p) [ k ];
    ENFORCE(behavior == IP_ID_BEHAVIOR_SEQUENTIAL);
    ENFORCE(ip_id_offset.UVALUE == ip_id.UVALUE - msn.UVALUE);
  }
        
  COMPRESSED non_nbo {
    ip_id_offset =:= lsb(k, p) [ k ];
    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);
  }
}
        
  COMPRESSED non_nbo {
    ip_id_offset =:= lsb(k, p) [ k ];
    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);
  }
}
        
optional_ip_id_lsb(behavior, indicator)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
        
optional_ip_id_lsb(behavior, indicator)
{
  UNCOMPRESSED {
    ip_id [ 16 ];
        

}

}

  COMPRESSED short {
    ip_id =:= ip_id_lsb(behavior, 8, 3) [ 8 ];
    ENFORCE((behavior == IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    ENFORCE(indicator == 0);
  }
        
  COMPRESSED short {
    ip_id =:= ip_id_lsb(behavior, 8, 3) [ 8 ];
    ENFORCE((behavior == IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (behavior == IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
    ENFORCE(indicator == 0);
  }
        
  COMPRESSED long {
    ip_id =:= irregular(16)  [ 16 ];
    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);
  }
        
  COMPRESSED long {
    ip_id =:= irregular(16)  [ 16 ];
    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);
  }
        
  COMPRESSED not_present {
    ENFORCE((behavior == IP_ID_BEHAVIOR_RANDOM) ||
            (behavior == IP_ID_BEHAVIOR_ZERO));
  }
}
dont_fragment(version)
{
  UNCOMPRESSED {
    df [ 1 ];
  }
        
  COMPRESSED not_present {
    ENFORCE((behavior == IP_ID_BEHAVIOR_RANDOM) ||
            (behavior == IP_ID_BEHAVIOR_ZERO));
  }
}
dont_fragment(version)
{
  UNCOMPRESSED {
    df [ 1 ];
  }
        
  COMPRESSED v4 {
    df =:= irregular(1) [ 1 ];
    ENFORCE(version == 4);
  }
        
  COMPRESSED v4 {
    df =:= irregular(1) [ 1 ];
    ENFORCE(version == 4);
  }
        
  COMPRESSED v6 {
    df =:= compressed_value(1, 0) [ 1 ];
    ENFORCE(version == 6);
  }
}
        
  COMPRESSED v6 {
    df =:= compressed_value(1, 0) [ 1 ];
    ENFORCE(version == 6);
  }
}
        
//////////////////////////////////
// Actual start of compressed packet formats
// Important note:
//   The base header is the compressed representation
//   of the innermost IP header AND the TCP header.
//////////////////////////////////
        
//////////////////////////////////
// Actual start of compressed packet formats
// Important note:
//   The base header is the compressed representation
//   of the innermost IP header AND the TCP header.
//////////////////////////////////
        
// ttl_irregular_chain_flag is set by the user if the TTL/Hop Limit
// of an outer header has changed.  The same value must be passed as
        
// ttl_irregular_chain_flag is set by the user if the TTL/Hop Limit
// of an outer header has changed.  The same value must be passed as
        
// an argument to the ipv4/ipv6 encoding methods when extracting
// the irregular chain items.
co_baseheader(payload_size, ack_stride_value,
              ttl_irregular_chain_flag, ip_id_behavior_value)
{
  UNCOMPRESSED v4 {
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    version        =:= uncompressed_value(4, 4)        [ 4 ];
    header_length  =:= uncompressed_value(4, 5)        [ 4 ];
    dscp                                               [ 6 ];
    ip_ecn_flags                                       [ 2 ];
    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 ];
    checksum                                           [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dest_port                                          [ 16 ];
    seq_number                                         [ 32 ];
    ack_number                                         [ 32 ];
    data_offset                                        [ 4 ];
    tcp_res_flags                                      [ 4 ];
    tcp_ecn_flags                                      [ 2 ];
    urg_flag                                           [ 1 ];
    ack_flag                                           [ 1 ];
    psh_flag                                           [ 1 ];
    rsf_flags                                          [ 3 ];
    window                                             [ 16 ];
    tcp_checksum                                       [ 16 ];
    urg_ptr                                            [ 16 ];
    options                           [ (data_offset.UVALUE-5)*32 ];
  }
        
// an argument to the ipv4/ipv6 encoding methods when extracting
// the irregular chain items.
co_baseheader(payload_size, ack_stride_value,
              ttl_irregular_chain_flag, ip_id_behavior_value)
{
  UNCOMPRESSED v4 {
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    version        =:= uncompressed_value(4, 4)        [ 4 ];
    header_length  =:= uncompressed_value(4, 5)        [ 4 ];
    dscp                                               [ 6 ];
    ip_ecn_flags                                       [ 2 ];
    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 ];
    checksum                                           [ 16 ];
    src_addr                                           [ 32 ];
    dest_addr                                          [ 32 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dest_port                                          [ 16 ];
    seq_number                                         [ 32 ];
    ack_number                                         [ 32 ];
    data_offset                                        [ 4 ];
    tcp_res_flags                                      [ 4 ];
    tcp_ecn_flags                                      [ 2 ];
    urg_flag                                           [ 1 ];
    ack_flag                                           [ 1 ];
    psh_flag                                           [ 1 ];
    rsf_flags                                          [ 3 ];
    window                                             [ 16 ];
    tcp_checksum                                       [ 16 ];
    urg_ptr                                            [ 16 ];
    options                           [ (data_offset.UVALUE-5)*32 ];
  }
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    version =:= uncompressed_value(4, 6)               [ 4 ];
    dscp                                               [ 6 ];
    ip_ecn_flags                                       [ 2 ];
    flow_label                                         [ 20 ];
    payload_length                                     [ 16 ];
        
  UNCOMPRESSED v6 {
    ENFORCE(ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_RANDOM);
    outer_headers  =:= baseheader_outer_headers        [ VARIABLE ];
    version =:= uncompressed_value(4, 6)               [ 4 ];
    dscp                                               [ 6 ];
    ip_ecn_flags                                       [ 2 ];
    flow_label                                         [ 20 ];
    payload_length                                     [ 16 ];
        
    next_header                                        [ 8 ];
    ttl_hopl                                           [ 8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dest_port                                          [ 16 ];
    seq_number                                         [ 32 ];
    ack_number                                         [ 32 ];
    data_offset                                        [ 4 ];
    tcp_res_flags                                      [ 4 ];
    tcp_ecn_flags                                      [ 2 ];
    urg_flag                                           [ 1 ];
    ack_flag                                           [ 1 ];
    psh_flag                                           [ 1 ];
    rsf_flags                                          [ 3 ];
    window                                             [ 16 ];
    tcp_checksum                                       [ 16 ];
    urg_ptr                                            [ 16 ];
    options                           [ (data_offset.UVALUE-5)*32 ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
    next_header                                        [ 8 ];
    ttl_hopl                                           [ 8 ];
    src_addr                                           [ 128 ];
    dest_addr                                          [ 128 ];
    extension_headers =:= baseheader_extension_headers [ VARIABLE ];
    src_port                                           [ 16 ];
    dest_port                                          [ 16 ];
    seq_number                                         [ 32 ];
    ack_number                                         [ 32 ];
    data_offset                                        [ 4 ];
    tcp_res_flags                                      [ 4 ];
    tcp_ecn_flags                                      [ 2 ];
    urg_flag                                           [ 1 ];
    ack_flag                                           [ 1 ];
    psh_flag                                           [ 1 ];
    rsf_flags                                          [ 3 ];
    window                                             [ 16 ];
    tcp_checksum                                       [ 16 ];
    urg_ptr                                            [ 16 ];
    options                           [ (data_offset.UVALUE-5)*32 ];
    df    =:= uncompressed_value(0,0)                  [   0 ];
    ip_id =:= uncompressed_value(0,0)                  [   0 ];
  }
        
  CONTROL {
    dummy_field_s =:= field_scaling(payload_size,
      seq_number_scaled.UVALUE, seq_number.UVALUE,
      seq_number_residue.UVALUE) [ 0 ];
    dummy_field_a =:= field_scaling(ack_stride.UVALUE,
      ack_number_scaled.UVALUE, ack_number.UVALUE,
      ack_number_residue.UVALUE) [ 0 ];
    ENFORCE(ack_stride.UVALUE == ack_stride_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
  }
        
  CONTROL {
    dummy_field_s =:= field_scaling(payload_size,
      seq_number_scaled.UVALUE, seq_number.UVALUE,
      seq_number_residue.UVALUE) [ 0 ];
    dummy_field_a =:= field_scaling(ack_stride.UVALUE,
      ack_number_scaled.UVALUE, ack_number.UVALUE,
      ack_number_residue.UVALUE) [ 0 ];
    ENFORCE(ack_stride.UVALUE == ack_stride_value);
    ENFORCE(ip_id_behavior_innermost.UVALUE == ip_id_behavior_value);
  }
        
  INITIAL {
    ack_stride     =:= uncompressed_value(16, 0);
  }
        
  INITIAL {
    ack_stride     =:= uncompressed_value(16, 0);
  }
        
  DEFAULT {
    tcp_ecn_flags  =:= static;
    data_offset    =:= inferred_offset;
    tcp_res_flags  =:= static;
    rsf_flags      =:= uncompressed_value(3, 0);
    dest_port      =:= static;
    dscp           =:= static;
    src_port       =:= static;
    urg_flag       =:= uncompressed_value(1, 0);
        
  DEFAULT {
    tcp_ecn_flags  =:= static;
    data_offset    =:= inferred_offset;
    tcp_res_flags  =:= static;
    rsf_flags      =:= uncompressed_value(3, 0);
    dest_port      =:= static;
    dscp           =:= static;
    src_port       =:= static;
    urg_flag       =:= uncompressed_value(1, 0);
        
    window         =:= static;
    dest_addr      =:= static;
    version        =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    df             =:= static;
    ack_number     =:= static;
    urg_ptr        =:= static;
    seq_number     =:= static;
    ack_flag       =:= uncompressed_value(1, 1);
    // The default for "options" is case 2) and 3) from
    // the list in Section 6.3.1 (i.e., nothing present in the
    // baseheader itself).
    payload_length =:= inferred_ip_v6_length;
    checksum       =:= inferred_ip_v4_header_checksum;
    length         =:= inferred_ip_v4_length;
    flow_label     =:= static;
    next_header    =:= static;
    ip_ecn_flags   =:= static;
    // The tcp_checksum has no default,
    // it is considered a part of tcp_irregular
    ip_id_behavior_innermost =:= static;
    ecn_used       =:= static;
    ack_stride    =:= static;
    ack_number_scaled =:= static;
    seq_number_scaled =:= static;
    ack_number_residue =:= static;
    seq_number_residue =:= static;
        
    window         =:= static;
    dest_addr      =:= static;
    version        =:= static;
    ttl_hopl       =:= static;
    src_addr       =:= static;
    df             =:= static;
    ack_number     =:= static;
    urg_ptr        =:= static;
    seq_number     =:= static;
    ack_flag       =:= uncompressed_value(1, 1);
    // The default for "options" is case 2) and 3) from
    // the list in Section 6.3.1 (i.e., nothing present in the
    // baseheader itself).
    payload_length =:= inferred_ip_v6_length;
    checksum       =:= inferred_ip_v4_header_checksum;
    length         =:= inferred_ip_v4_length;
    flow_label     =:= static;
    next_header    =:= static;
    ip_ecn_flags   =:= static;
    // The tcp_checksum has no default,
    // it is considered a part of tcp_irregular
    ip_id_behavior_innermost =:= static;
    ecn_used       =:= static;
    ack_stride    =:= static;
    ack_number_scaled =:= static;
    seq_number_scaled =:= static;
    ack_number_residue =:= static;
    seq_number_residue =:= static;
        
    // Default is to have no TTL in irregular chain
    // Can only be nonzero if co_common is used
    ENFORCE(ttl_irregular_chain_flag == 0);
  }
        
    // Default is to have no TTL in irregular chain
    // Can only be nonzero if co_common is used
    ENFORCE(ttl_irregular_chain_flag == 0);
  }
        
  ////////////////////////////////////////////
  // Common compressed packet format
  ////////////////////////////////////////////
        
  ////////////////////////////////////////////
  // Common compressed packet format
  ////////////////////////////////////////////
        
  COMPRESSED co_common {
    discriminator        =:= '1111101'                [ 7 ];
    ttl_hopl_outer_flag  =:=
        compressed_value(1, ttl_irregular_chain_flag) [ 1 ];
    ack_flag             =:= irregular(1)             [ 1 ];
    psh_flag             =:= irregular(1)             [ 1 ];
    rsf_flags            =:= rsf_index_enc            [ 2 ];
    msn                  =:= lsb(4, 4)                [ 4 ];
    seq_indicator        =:= irregular(2)             [ 2 ];
    ack_indicator        =:= irregular(2)             [ 2 ];
        
  COMPRESSED co_common {
    discriminator        =:= '1111101'                [ 7 ];
    ttl_hopl_outer_flag  =:=
        compressed_value(1, ttl_irregular_chain_flag) [ 1 ];
    ack_flag             =:= irregular(1)             [ 1 ];
    psh_flag             =:= irregular(1)             [ 1 ];
    rsf_flags            =:= rsf_index_enc            [ 2 ];
    msn                  =:= lsb(4, 4)                [ 4 ];
    seq_indicator        =:= irregular(2)             [ 2 ];
    ack_indicator        =:= irregular(2)             [ 2 ];
        
    ack_stride_indicator =:= irregular(1)             [ 1 ];
    window_indicator     =:= irregular(1)             [ 1 ];
    ip_id_indicator      =:= irregular(1)             [ 1 ];
    urg_ptr_present      =:= irregular(1)             [ 1 ];
    reserved             =:= compressed_value(1, 0)   [ 1 ];
    ecn_used             =:= one_bit_choice           [ 1 ];
    dscp_present         =:= irregular(1)             [ 1 ];
    ttl_hopl_present     =:= irregular(1)             [ 1 ];
    list_present         =:= irregular(1)             [ 1 ];
    ip_id_behavior_innermost       =:= irregular(2)             [ 2 ];
    urg_flag             =:= irregular(1)             [ 1 ];
    df                   =:= dont_fragment(version.UVALUE)   [ 1 ];
    header_crc           =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    seq_number           =:=
      variable_length_32_enc(seq_indicator.CVALUE) [ 0, 8, 16, 32 ];
    ack_number           =:=
      variable_length_32_enc(ack_indicator.CVALUE) [ 0, 8, 16, 32 ];
    ack_stride           =:=
      static_or_irreg(ack_stride_indicator.CVALUE, 16)  [ 0, 16 ];
    window               =:=
      static_or_irreg(window_indicator.CVALUE, 16)      [ 0, 16 ];
    ip_id                =:=
      optional_ip_id_lsb(ip_id_behavior_innermost.UVALUE,
                         ip_id_indicator.CVALUE)      [ 0, 8, 16 ];
    urg_ptr              =:=
      static_or_irreg(urg_ptr_present.CVALUE, 16)     [ 0, 16 ];
    dscp                 =:=
      dscp_enc(dscp_present.CVALUE)                   [ 0, 8 ];
    ttl_hopl             =:=
      static_or_irreg(ttl_hopl_present.CVALUE, 8)     [ 0, 8 ];
    options              =:=
      tcp_list_presence_enc(list_present.CVALUE)      [ VARIABLE ];
  }
        
    ack_stride_indicator =:= irregular(1)             [ 1 ];
    window_indicator     =:= irregular(1)             [ 1 ];
    ip_id_indicator      =:= irregular(1)             [ 1 ];
    urg_ptr_present      =:= irregular(1)             [ 1 ];
    reserved             =:= compressed_value(1, 0)   [ 1 ];
    ecn_used             =:= one_bit_choice           [ 1 ];
    dscp_present         =:= irregular(1)             [ 1 ];
    ttl_hopl_present     =:= irregular(1)             [ 1 ];
    list_present         =:= irregular(1)             [ 1 ];
    ip_id_behavior_innermost       =:= irregular(2)             [ 2 ];
    urg_flag             =:= irregular(1)             [ 1 ];
    df                   =:= dont_fragment(version.UVALUE)   [ 1 ];
    header_crc           =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    seq_number           =:=
      variable_length_32_enc(seq_indicator.CVALUE) [ 0, 8, 16, 32 ];
    ack_number           =:=
      variable_length_32_enc(ack_indicator.CVALUE) [ 0, 8, 16, 32 ];
    ack_stride           =:=
      static_or_irreg(ack_stride_indicator.CVALUE, 16)  [ 0, 16 ];
    window               =:=
      static_or_irreg(window_indicator.CVALUE, 16)      [ 0, 16 ];
    ip_id                =:=
      optional_ip_id_lsb(ip_id_behavior_innermost.UVALUE,
                         ip_id_indicator.CVALUE)      [ 0, 8, 16 ];
    urg_ptr              =:=
      static_or_irreg(urg_ptr_present.CVALUE, 16)     [ 0, 16 ];
    dscp                 =:=
      dscp_enc(dscp_present.CVALUE)                   [ 0, 8 ];
    ttl_hopl             =:=
      static_or_irreg(ttl_hopl_present.CVALUE, 8)     [ 0, 8 ];
    options              =:=
      tcp_list_presence_enc(list_present.CVALUE)      [ VARIABLE ];
  }
        
  // Send LSBs of sequence number
  COMPRESSED rnd_1 {
    discriminator =:= '101110'                        [ 6 ];
    seq_number    =:= lsb(18, 65535)                  [ 18 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send LSBs of sequence number
  COMPRESSED rnd_1 {
    discriminator =:= '101110'                        [ 6 ];
    seq_number    =:= lsb(18, 65535)                  [ 18 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        

// Send scaled sequence number LSBs COMPRESSED rnd_2 {

//发送缩放序列号LSBs压缩rnd_2{

    discriminator      =:= '1100'                          [ 4 ];
    seq_number_scaled  =:= lsb(4, 7)                       [ 4 ];
    msn                =:= lsb(4, 4)                       [ 4 ];
    psh_flag           =:= irregular(1)                    [ 1 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE(payload_size != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
    discriminator      =:= '1100'                          [ 4 ];
    seq_number_scaled  =:= lsb(4, 7)                       [ 4 ];
    msn                =:= lsb(4, 4)                       [ 4 ];
    psh_flag           =:= irregular(1)                    [ 1 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE(payload_size != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send acknowledgment number LSBs
  COMPRESSED rnd_3 {
    discriminator =:= '0'                             [ 1 ];
    ack_number    =:= lsb(15, 8191)                   [ 15 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send acknowledgment number LSBs
  COMPRESSED rnd_3 {
    discriminator =:= '0'                             [ 1 ];
    ack_number    =:= lsb(15, 8191)                   [ 15 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send acknowledgment number scaled
  COMPRESSED rnd_4 {
    discriminator      =:= '1101'                          [ 4 ];
    ack_number_scaled  =:= lsb(4, 3)                       [ 4 ];
    msn                =:= lsb(4, 4)                       [ 4 ];
    psh_flag           =:= irregular(1)                    [ 1 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE(ack_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send acknowledgment number scaled
  COMPRESSED rnd_4 {
    discriminator      =:= '1101'                          [ 4 ];
    ack_number_scaled  =:= lsb(4, 3)                       [ 4 ];
    msn                =:= lsb(4, 4)                       [ 4 ];
    psh_flag           =:= irregular(1)                    [ 1 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE(ack_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send ACK and sequence number
  COMPRESSED rnd_5 {
    discriminator =:= '100'                           [ 3 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    seq_number    =:= lsb(14, 8191)                   [ 14 ];
    ack_number    =:= lsb(15, 8191)                   [ 15 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send ACK and sequence number
  COMPRESSED rnd_5 {
    discriminator =:= '100'                           [ 3 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    seq_number    =:= lsb(14, 8191)                   [ 14 ];
    ack_number    =:= lsb(15, 8191)                   [ 15 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send both ACK and scaled sequence number LSBs
  COMPRESSED rnd_6 {
    discriminator      =:= '1010'                          [ 4 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    psh_flag           =:= irregular(1)                    [ 1 ];
    ack_number         =:= lsb(16, 16383)                  [ 16 ];
    msn                =:= lsb(4, 4)                       [ 4 ];
    seq_number_scaled  =:= lsb(4, 7)                       [ 4 ];
    ENFORCE(payload_size != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send both ACK and scaled sequence number LSBs
  COMPRESSED rnd_6 {
    discriminator      =:= '1010'                          [ 4 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    psh_flag           =:= irregular(1)                    [ 1 ];
    ack_number         =:= lsb(16, 16383)                  [ 16 ];
    msn                =:= lsb(4, 4)                       [ 4 ];
    seq_number_scaled  =:= lsb(4, 7)                       [ 4 ];
    ENFORCE(payload_size != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send ACK and window
  COMPRESSED rnd_7 {
    discriminator =:= '101111'                        [ 6 ];
    ack_number    =:= lsb(18, 65535)                  [ 18 ];
    window        =:= irregular(16)                   [ 16 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send ACK and window
  COMPRESSED rnd_7 {
    discriminator =:= '101111'                        [ 6 ];
    ack_number    =:= lsb(18, 65535)                  [ 18 ];
    window        =:= irregular(16)                   [ 16 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // An extended packet type for seldom-changing fields
  // Can send LSBs of TTL, RSF flags, change ECN behavior, and
  // options list
  COMPRESSED rnd_8 {
    discriminator =:= '10110'                         [ 5 ];
    rsf_flags     =:= rsf_index_enc                   [ 2 ];
    list_present  =:= irregular(1)                    [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    ttl_hopl      =:= lsb(3, 3)                       [ 3 ];
    ecn_used      =:= one_bit_choice                  [ 1 ];
    seq_number    =:= lsb(16, 65535)                  [ 16 ];
    ack_number    =:= lsb(16, 16383)                  [ 16 ];
    options       =:=
      tcp_list_presence_enc(list_present.CVALUE)      [ VARIABLE ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // An extended packet type for seldom-changing fields
  // Can send LSBs of TTL, RSF flags, change ECN behavior, and
  // options list
  COMPRESSED rnd_8 {
    discriminator =:= '10110'                         [ 5 ];
    rsf_flags     =:= rsf_index_enc                   [ 2 ];
    list_present  =:= irregular(1)                    [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH) [ 7 ];
    msn           =:= lsb(4, 4)                       [ 4 ];
    psh_flag      =:= irregular(1)                    [ 1 ];
    ttl_hopl      =:= lsb(3, 3)                       [ 3 ];
    ecn_used      =:= one_bit_choice                  [ 1 ];
    seq_number    =:= lsb(16, 65535)                  [ 16 ];
    ack_number    =:= lsb(16, 16383)                  [ 16 ];
    options       =:=
      tcp_list_presence_enc(list_present.CVALUE)      [ VARIABLE ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_RANDOM) ||
            (ip_id_behavior_innermost.UVALUE == IP_ID_BEHAVIOR_ZERO));
  }
        
  // Send LSBs of sequence number
  COMPRESSED seq_1 {
    discriminator =:= '1010'                                 [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4, 3) [ 4 ];
    seq_number    =:= lsb(16, 32767)                         [ 16 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)        [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send LSBs of sequence number
  COMPRESSED seq_1 {
    discriminator =:= '1010'                                 [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4, 3) [ 4 ];
    seq_number    =:= lsb(16, 32767)                         [ 16 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)        [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send scaled sequence number LSBs
  COMPRESSED seq_2 {
    discriminator      =:= '11010'                         [ 5 ];
    ip_id              =:=
      ip_id_lsb(ip_id_behavior_innermost.UVALUE, 7, 3)     [ 7 ];
    seq_number_scaled  =:= lsb(4, 7)                       [ 4 ];
    msn                =:= lsb(4, 4)                       [ 4 ];
    psh_flag           =:= irregular(1)                    [ 1 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE(payload_size != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send scaled sequence number LSBs
  COMPRESSED seq_2 {
    discriminator      =:= '11010'                         [ 5 ];
    ip_id              =:=
      ip_id_lsb(ip_id_behavior_innermost.UVALUE, 7, 3)     [ 7 ];
    seq_number_scaled  =:= lsb(4, 7)                       [ 4 ];
    msn                =:= lsb(4, 4)                       [ 4 ];
    psh_flag           =:= irregular(1)                    [ 1 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE(payload_size != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send acknowledgment number LSBs
  COMPRESSED seq_3 {
    discriminator =:= '1001'                                 [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4, 3) [ 4 ];
    ack_number    =:= lsb(16, 16383)                         [ 16 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)        [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send acknowledgment number LSBs
  COMPRESSED seq_3 {
    discriminator =:= '1001'                                 [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4, 3) [ 4 ];
    ack_number    =:= lsb(16, 16383)                         [ 16 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)        [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send scaled acknowledgment number scaled
  COMPRESSED seq_4 {
    discriminator     =:= '0'                             [ 1 ];
    ack_number_scaled =:= lsb(4, 3)                       [ 4 ];
        
  // Send scaled acknowledgment number scaled
  COMPRESSED seq_4 {
    discriminator     =:= '0'                             [ 1 ];
    ack_number_scaled =:= lsb(4, 3)                       [ 4 ];
        
    // Due to having very few ip_id bits, no negative offset
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 3, 1) [ 3 ];
    msn               =:= lsb(4, 4)                       [ 4 ];
    psh_flag          =:= irregular(1)                    [ 1 ];
    header_crc        =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE(ack_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
    // Due to having very few ip_id bits, no negative offset
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 3, 1) [ 3 ];
    msn               =:= lsb(4, 4)                       [ 4 ];
    psh_flag          =:= irregular(1)                    [ 1 ];
    header_crc        =:= crc3(THIS.UVALUE, THIS.ULENGTH) [ 3 ];
    ENFORCE(ack_stride.UVALUE != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send ACK and sequence number
  COMPRESSED seq_5 {
    discriminator =:= '1000'                                 [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4, 3) [ 4 ];
    ack_number    =:= lsb(16, 16383)                         [ 16 ];
    seq_number    =:= lsb(16, 32767)                         [ 16 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)        [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send ACK and sequence number
  COMPRESSED seq_5 {
    discriminator =:= '1000'                                 [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4, 3) [ 4 ];
    ack_number    =:= lsb(16, 16383)                         [ 16 ];
    seq_number    =:= lsb(16, 32767)                         [ 16 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)        [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send both ACK and scaled sequence number LSBs
  COMPRESSED seq_6 {
    discriminator      =:= '11011'                          [ 5 ];
    seq_number_scaled  =:= lsb(4, 7)                        [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 7, 3) [ 7 ];
    ack_number         =:= lsb(16, 16383)                   [ 16 ];
    msn                =:= lsb(4, 4)                        [ 4 ];
    psh_flag           =:= irregular(1)                     [ 1 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH)  [ 3 ];
    ENFORCE(payload_size != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send both ACK and scaled sequence number LSBs
  COMPRESSED seq_6 {
    discriminator      =:= '11011'                          [ 5 ];
    seq_number_scaled  =:= lsb(4, 7)                        [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 7, 3) [ 7 ];
    ack_number         =:= lsb(16, 16383)                   [ 16 ];
    msn                =:= lsb(4, 4)                        [ 4 ];
    psh_flag           =:= irregular(1)                     [ 1 ];
    header_crc         =:= crc3(THIS.UVALUE, THIS.ULENGTH)  [ 3 ];
    ENFORCE(payload_size != 0);
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // Send ACK and window
  COMPRESSED seq_7 {
    discriminator =:= '1100'                                 [ 4 ];
    window        =:= lsb(15, 16383)                         [ 15 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5, 3) [ 5 ];
        
  // Send ACK and window
  COMPRESSED seq_7 {
    discriminator =:= '1100'                                 [ 4 ];
    window        =:= lsb(15, 16383)                         [ 15 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 5, 3) [ 5 ];
        
    ack_number    =:= lsb(16, 32767)                         [ 16 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)        [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
    ack_number    =:= lsb(16, 32767)                         [ 16 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc3(THIS.UVALUE, THIS.ULENGTH)        [ 3 ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
        
  // An extended packet type for seldom-changing fields
  // Can send LSBs of TTL, RSF flags, change ECN behavior, and
  // options list
  COMPRESSED seq_8 {
    discriminator =:= '1011'                                 [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4, 3) [ 4 ];
    list_present  =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)        [ 7 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    ttl_hopl      =:= lsb(3, 3)                              [ 3 ];
    ecn_used      =:= one_bit_choice                         [ 1 ];
    ack_number    =:= lsb(15, 8191)                          [ 15 ];
    rsf_flags     =:= rsf_index_enc                          [ 2 ];
    seq_number    =:= lsb(14, 8191)                          [ 14 ];
    options       =:=
      tcp_list_presence_enc(list_present.CVALUE)       [ VARIABLE ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
}
        
  // An extended packet type for seldom-changing fields
  // Can send LSBs of TTL, RSF flags, change ECN behavior, and
  // options list
  COMPRESSED seq_8 {
    discriminator =:= '1011'                                 [ 4 ];
    ip_id =:= ip_id_lsb(ip_id_behavior_innermost.UVALUE, 4, 3) [ 4 ];
    list_present  =:= irregular(1)                           [ 1 ];
    header_crc    =:= crc7(THIS.UVALUE, THIS.ULENGTH)        [ 7 ];
    msn           =:= lsb(4, 4)                              [ 4 ];
    psh_flag      =:= irregular(1)                           [ 1 ];
    ttl_hopl      =:= lsb(3, 3)                              [ 3 ];
    ecn_used      =:= one_bit_choice                         [ 1 ];
    ack_number    =:= lsb(15, 8191)                          [ 15 ];
    rsf_flags     =:= rsf_index_enc                          [ 2 ];
    seq_number    =:= lsb(14, 8191)                          [ 14 ];
    options       =:=
      tcp_list_presence_enc(list_present.CVALUE)       [ VARIABLE ];
    ENFORCE((ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL) ||
            (ip_id_behavior_innermost.UVALUE ==
             IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED));
  }
}
        
8.3. Feedback Formats and Options
8.3. 反馈格式和选项
8.3.1. Feedback Formats
8.3.1. 反馈格式

This section describes the feedback formats for the ROHC-TCP profile, following the general ROHC feedback format described in Section 5.2.4 of [RFC5795].

本节介绍ROHC-TCP配置文件的反馈格式,遵循[RFC5795]第5.2.4节中描述的一般ROHC反馈格式。

All feedback formats carry a field labeled MSN. The MSN field contains LSBs of the MSN control field described in Section 6.1.1. The sequence number to use is the MSN corresponding to the last header that was successfully CRC-8 validated or CRC verified.

所有反馈格式都带有一个标记为MSN的字段。MSN字段包含第6.1.1节所述MSN控制字段的LSB。要使用的序列号是与成功进行CRC-8验证或CRC验证的最后一个标头相对应的MSN。

FEEDBACK-1

反馈-1

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

MSN: The LSB-encoded master sequence number.

MSN:LSB编码的主序列号。

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|          MSN          |
      +---+---+---+---+---+---+---+---+
      |              MSN              |
      +---+---+---+---+---+---+---+---+
      |              CRC              |
      +---+---+---+---+---+---+---+---+
      /       Feedback options        /
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |Acktype|          MSN          |
      +---+---+---+---+---+---+---+---+
      |              MSN              |
      +---+---+---+---+---+---+---+---+
      |              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已保留(不得用于可解析性)

MSN: The LSB-encoded master sequence number.

MSN:LSB编码的主序列号。

CRC: 8-bit CRC computed over the entire feedback element (as defined in Section 5.3.1.1 of [RFC5795]). For the purpose of computing the CRC, the CRC field is zero. The CRC is calculated using the polynomial defined in [RFC5795].

CRC:在整个反馈元件上计算的8位CRC(定义见[RFC5795]第5.3.1.1节)。为了计算CRC,CRC字段为零。使用[RFC5795]中定义的多项式计算CRC。

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

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

A FEEDBACK-2 of type NACK or STATIC-NACK is always implicitly an acknowledgment for a successfully decompressed packet, which packet corresponds to the MSN of the feedback element, unless the MSN-NOT-VALID option (Section 8.3.2.2) appears in the feedback element.

NACK或STATIC-NACK类型的反馈-2始终隐式表示对成功解压缩数据包的确认,该数据包对应于反馈元素的MSN,除非反馈元素中出现MSN-NOT-VALID选项(第8.3.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 by 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进行比较来验证信息。如果两者不相同,则必须丢弃反馈元素。

8.3.2. Feedback Options
8.3.2. 反馈选项

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

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

        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |   Opt Type    |    Opt Len    |
      +---+---+---+---+---+---+---+---+
      /          option data          /  Opt Length (octets)
      +---+---+---+---+---+---+---+---+
        
        0   1   2   3   4   5   6   7
      +---+---+---+---+---+---+---+---+
      |   Opt Type    |    Opt Len    |
      +---+---+---+---+---+---+---+---+
      /          option data          /  Opt Length (octets)
      +---+---+---+---+---+---+---+---+
        

Each ROHC-TCP feedback option can appear at most once within a FEEDBACK-2.

每个ROHC-TCP反馈选项在反馈-2中最多只能出现一次。

8.3.2.1. The REJECT Option
8.3.2.1. 拒绝选项

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

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

      +---+---+---+---+---+---+---+---+
      |  Opt Type = 2 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        
      +---+---+---+---+---+---+---+---+
      |  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格式中不得出现多次;否则,压缩机必须丢弃整个反馈元件。

8.3.2.2. The MSN-NOT-VALID Option
8.3.2.2. MSN-NOT-VALID选项

The MSN-NOT-VALID option indicates that the MSN of the feedback is not valid.

MSN-NOT-VALID选项表示反馈的MSN无效。

      +---+---+---+---+---+---+---+---+
      |  Opt Type = 3 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        
      +---+---+---+---+---+---+---+---+
      |  Opt Type = 3 |  Opt Len = 0  |
      +---+---+---+---+---+---+---+---+
        

A compressor MUST ignore the MSN of the feedback element when this option is present. Consequently, a NACK or a STATIC-NACK feedback type sent with the MSN-NOT-VALID option is equivalent to a STATIC-NACK with respect to the semantics of the feedback message.

当存在此选项时,压缩机必须忽略反馈元件的MSN。因此,就反馈消息的语义而言,随MSN-NOT-VALID选项发送的NACK或STATIC-NACK反馈类型等同于STATIC-NACK。

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

MSN-NOT-VALID选项不得以FEEDWARD-2格式出现多次,且不得与MSN选项出现在同一反馈元素中;否则,压缩机必须丢弃整个反馈元件。

8.3.2.3. The MSN Option
8.3.2.3. MSN选项

The MSN option provides 2 additional bits of MSN.

MSN选项提供2个附加的MSN位。

      +---+---+---+---+---+---+---+---+
      |  Opt Type = 4 |  Opt Len = 1  |
      +---+---+---+---+---+---+---+---+
      |  MSN  |        Reserved       |
      +---+---+---+---+---+---+---+---+
        
      +---+---+---+---+---+---+---+---+
      |  Opt Type = 4 |  Opt Len = 1  |
      +---+---+---+---+---+---+---+---+
      |  MSN  |        Reserved       |
      +---+---+---+---+---+---+---+---+
        

These 2 bits are the least significant bits of the MSN and are thus concatenated with the 14 bits already present in the FEEDBACK-2 format.

这2位是MSN的最低有效位,因此与反馈-2格式中已经存在的14位相连。

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

MSN选项不得以FEEDBACK-2格式出现多次,且不得与MSN-NOT-VALID选项出现在同一反馈元素中;否则,压缩机必须丢弃整个反馈元件。

8.3.2.4. The CONTEXT_MEMORY Feedback Option
8.3.2.4. 上下文记忆反馈选项

The CONTEXT_MEMORY option means 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.

当接收到CONTEXT_MEMORY选项时,压缩器应采取措施以减少解压缩器内存资源的方式压缩数据包流,或停止压缩数据包流。

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

在反馈-2格式中,上下文记忆选项不得出现多次;否则,压缩机必须丢弃整个反馈元件。

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

If an option type unknown to the compressor is encountered, the compressor MUST continue parsing the rest of the FEEDBACK element, which is possible since the length of the option is explicit, but MUST otherwise ignore the unknown option.

如果遇到压缩器未知的选项类型,压缩器必须继续解析反馈元素的其余部分,这是可能的,因为选项的长度是显式的,但必须忽略未知选项。

9. Changes from RFC 4996
9. RFC 4996的变更

This RFC revises RFC 4996. It is mostly backwards-compatible with RFC 4996, except for two cases that did not interoperate as described below.

本RFC修订了RFC 4996。它主要与RFC 4996向后兼容,除了下面描述的两种情况没有互操作。

9.1. Functional Changes
9.1. 功能变化

o The SACK option compression in [RFC4996] assumed that multiple SACK blocks within the same option would be in sorted order so that the block starts were LSB-encoded from the end of the previous block. This meant that SACK blocks that are not in sorted order could be impossible to compress in some cases. Therefore, the SACK compression in the formal notation has changed and therefore also the bits-on-the-wire.

o [RFC4996]中的SACK选项压缩假定同一选项中的多个SACK块将按排序顺序排列,以便块开始从上一个块的末尾开始进行LSB编码。这意味着在某些情况下,不按排序的SACK块可能无法压缩。因此,形式表示法中的SACK压缩发生了变化,因此线路上的位也发生了变化。

o The ESP NULL header compression has been deprecated due to interoperability problems with needing to know information from the trailer. The ESP NULL compression was already removed from ROHCv2 [RFC5225] for the same reason and it was considered better to remove it from this profile rather than try to fix the interoperability issue.

o 由于互操作性问题,需要从尾部了解信息,因此不推荐使用ESP空标头压缩。出于同样的原因,已经从ROHCv2[RFC5225]中删除了ESP NULL压缩,并且认为最好将其从该配置文件中删除,而不是尝试修复互操作性问题。

9.2. Non-functional Changes
9.2. 非功能性变化

o The way sequential IP-ID compression was described in the FN code was incorrect and the code used for ROHCv2 [RFC5225] has been imported into this specification (e.g., offset is made into a global control field). This does not change the bits-on-the-wire. The only change is how this encoding is described in the formal notation, not how the compression occurs.

o FN代码中描述的顺序IP-ID压缩方式不正确,用于ROHCv2[RFC5225]的代码已导入本规范(例如,偏移量被输入全局控制字段)。这不会改变导线上的位。唯一的变化是在形式表示法中如何描述这种编码,而不是如何进行压缩。

o Default encoding for the 'df' and 'ip_id' fields have been added for IPv6 with 0-bit uncompressed format to clarify that these never appear in IPv6.

o 已使用0位未压缩格式为IPv6添加了“df”和“ip_id”字段的默认编码,以澄清这些字段从未出现在IPv6中。

o The scaled encoding of the Acknowledgment Number and Sequence Number were incorrectly described in the FN code in [RFC4996] and have been updated in the same style as in ROHCv2 [RFC5225]. This does not change the bits-on-the-wire, only the way the compression is described in the FN code.

o [RFC4996]中的FN代码错误地描述了确认号和序列号的缩放编码,并以与ROHCv2[RFC5225]中相同的样式进行了更新。这不会改变导线上的位,只会改变FN代码中描述的压缩方式。

o The external arguments to ipv4 and co_baseheader have been updated. This is again only a change for FN correctness and does not affect interoperability.

o ipv4和co_baseheader的外部参数已更新。这同样只是对FN正确性的更改,并不影响互操作性。

o Errata for [RFC4996] related to minor errors in the FN and textual errors have also been corrected.

o [RFC4996]的勘误表与FN中的小错误和文本错误有关,也已更正。

10. Security Considerations
10. 安全考虑

A malfunctioning or malicious header compressor could cause the header decompressor to reconstitute packets that do not match the original packets but still have valid IP and TCP headers, and possibly also valid TCP checksums. Such corruption may be detected with end-to-end authentication and integrity mechanisms that will not be affected by the compression. Moreover, this header compression scheme uses an internal checksum for verification of reconstructed headers. This reduces the probability of producing decompressed headers not matching the original ones without this being noticed.

出现故障或恶意的报头压缩程序可能会导致报头解压缩程序重新生成与原始数据包不匹配但仍具有有效IP和TCP报头的数据包,并且可能还具有有效的TCP校验和。这种损坏可以通过不受压缩影响的端到端身份验证和完整性机制来检测。此外,此报头压缩方案使用内部校验和来验证重建的报头。这降低了在没有注意到这一点的情况下生成与原始头不匹配的解压缩头的可能性。

Denial-of-service attacks are possible if an intruder can introduce (for example) bogus IR, CO, 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、CO或反馈数据包,从而导致压缩效率降低,则可能发生拒绝服务攻击。然而,能够以这种方式在链路层注入任意数据包的入侵者会引发额外的安全问题,使与使用报头压缩相关的安全问题相形见绌。

11. IANA Considerations
11. IANA考虑

The reference for the ROHC profile identifier 0x0006 has been updated to reference this document instead of RFC 4996.

ROHC配置文件标识符0x0006的参考已更新为参考本文件而非RFC 4996。

A ROHC profile identifier has been reserved by IANA for the profile defined in this document. Profiles 0x0000-0x0005 have previously been reserved; this profile is 0x0006. As for previous ROHC profiles, profile numbers 0xnn06 have been reserved for future updates of this profile.

IANA已为本文档中定义的配置文件保留ROHC配置文件标识符。配置文件0x0000-0x0005之前已保留;此配置文件为0x0006。对于以前的ROHC配置文件,已保留配置文件编号0xnn06,以便将来更新此配置文件。

Profile Usage Document identifier

配置文件使用文档标识符

0x0006 ROHC TCP [RFC6846] 0xnn06 Reserved

0x0006 ROHC TCP[RFC6846]0xnn06保留

12. Acknowledgments
12. 致谢

The authors would like to thank Qian Zhang, Hong Bin Liao, Richard Price, and Fredrik Lindstroem for their work with early versions of this specification. Thanks also to Robert Finking and Carsten Bormann for valuable input and to Carl Knutsson and Gilbert Strom for suggestions and review of the updates made in this document.

作者要感谢张倩、廖洪斌、Richard Price和Fredrik Lindstroem为本规范早期版本所做的工作。还感谢Robert Finking和Carsten Bormann的宝贵意见,以及Carl Knutsson和Gilbert Strom对本文件中更新内容的建议和审查。

Additional thanks: this document was reviewed during working group last-call by committed reviewers Joe Touch and Ted Faber, as well as by Sally Floyd, who provided a review at the request of the Transport Area Directors.

额外感谢:本文件在工作组最后一次电话会议期间由负责审查的Joe Touch和Ted Faber以及Sally Floyd进行了审查,Sally Floyd应交通区域主管的要求进行了审查。

13. References
13. 工具书类
13.1. Normative References
13.1. 规范性引用文件

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

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

[RFC0793] Postel, J., "Transmission Control Protocol", STD 7, RFC 793, September 1981.

[RFC0793]Postel,J.,“传输控制协议”,标准7,RFC 793,1981年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月。

[RFC4164] Pelletier, G., "RObust Header Compression (ROHC): Context Replication for ROHC Profiles", RFC 4164, August 2005.

[RFC4164]Pelletier,G.“鲁棒头压缩(ROHC):ROHC配置文件的上下文复制”,RFC4164,2005年8月。

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

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

[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月。

[RFC5795] Sandlund, K., Pelletier, G., and L-E. Jonsson, "The RObust Header Compression (ROHC) Framework", RFC 5795, March 2010.

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

13.2. Informative References
13.2. 资料性引用

[RFC1144] Jacobson, V., "Compressing TCP/IP headers for low-speed serial links", RFC 1144, February 1990.

[RFC1144]Jacobson,V.,“压缩低速串行链路的TCP/IP报头”,RFC1144,1990年2月。

[RFC1323] Jacobson, V., Braden, B., and D. Borman, "TCP Extensions for High Performance", RFC 1323, May 1992.

[RFC1323]Jacobson,V.,Braden,B.,和D.Borman,“高性能TCP扩展”,RFC 1323,1992年5月。

[RFC2018] Mathis, M., Mahdavi, J., Floyd, S., and A. Romanow, "TCP Selective Acknowledgment Options", RFC 2018, October 1996.

[RFC2018]Mathis,M.,Mahdavi,J.,Floyd,S.,和A.Romanow,“TCP选择性确认选项”,RFC 2018,1996年10月。

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

[RFC2507]Degermark,M.,Nordgren,B.和S.Pink,“IP头压缩”,RFC 2507,1999年2月。

[RFC2883] Floyd, S., Mahdavi, J., Mathis, M., and M. Podolsky, "An Extension to the Selective Acknowledgement (SACK) Option for TCP", RFC 2883, July 2000.

[RFC2883]Floyd,S.,Mahdavi,J.,Mathis,M.,和M.Podolsky,“TCP选择性确认(SACK)选项的扩展”,RFC 28832000年7月。

[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月。

[RFC3168] Ramakrishnan, K., Floyd, S., and D. Black, "The Addition of Explicit Congestion Notification (ECN) to IP", RFC 3168, September 2001.

[RFC3168]Ramakrishnan,K.,Floyd,S.,和D.Black,“向IP添加显式拥塞通知(ECN)”,RFC 3168,2001年9月。

[RFC3759] Jonsson, L-E., "RObust Header Compression (ROHC): Terminology and Channel Mapping Examples", RFC 3759, April 2004.

[RFC3759]Jonsson,L-E,“鲁棒头压缩(ROHC):术语和信道映射示例”,RFC 3759,2004年4月。

[RFC4163] Jonsson, L-E., "RObust Header Compression (ROHC): Requirements on TCP/IP Header Compression", RFC 4163, August 2005.

[RFC4163]Jonsson,L-E,“鲁棒头压缩(ROHC):TCP/IP头压缩要求”,RFC 41632005年8月。

[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月。

[RFC4413] West, M. and S. McCann, "TCP/IP Field Behavior", RFC 4413, March 2006.

[RFC4413]West,M.和S.McCann,“TCP/IP现场行为”,RFC4413,2006年3月。

[RFC4996] Pelletier, G., Sandlund, K., Jonsson, L-E., and M. West, "RObust Header Compression (ROHC): A Profile for TCP/IP (ROHC-TCP)", RFC 4996, July 2007.

[RFC4996]Pelletier,G.,Sandlund,K.,Jonsson,L-E.,和M.West,“鲁棒头压缩(ROHC):TCP/IP配置文件(ROHC-TCP)”,RFC 49962007年7月。

[RFC5225] Pelletier, G. and K. Sandlund, "RObust Header Compression Version 2 (ROHCv2): Profiles for RTP, UDP, IP, ESP and UDP-Lite", RFC 5225, April 2008.

[RFC5225]Pelletier,G.和K.Sandlund,“鲁棒头压缩版本2(ROHCv2):RTP、UDP、IP、ESP和UDP Lite的配置文件”,RFC 52252008年4月。

[RFC5681] Allman, M., Paxson, V., and E. Blanton, "TCP Congestion Control", RFC 5681, September 2009.

[RFC5681]Allman,M.,Paxson,V.和E.Blanton,“TCP拥塞控制”,RFC 56812009年9月。

Authors' Addresses

作者地址

Ghyslain Pelletier InterDigital Communications 1000, Sherbrooke Street West, 10th floor Montreal, Quebec H3A 3G4 Canada

Ghyslain Pelletier InterDigital Communications 1000,Sherbrooke Street West,加拿大魁北克省蒙特利尔市10楼H3A 3G4

   Phone: +46 (0) 70 609 27 73
   EMail: ghyslain.pelletier@interdigital.com
        
   Phone: +46 (0) 70 609 27 73
   EMail: ghyslain.pelletier@interdigital.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
        

Lars-Erik Jonsson Optand 737 Ostersund SE-831 92 Sweden

Lars Erik Jonsson Optand 737 Ostersund SE-831 92瑞典

   Phone: +46 70 365 20 58
   EMail: lars-erik@lejonsson.com
        
   Phone: +46 70 365 20 58
   EMail: lars-erik@lejonsson.com
        

Mark A West Siemens/Roke Manor Roke Manor Research Ltd. Romsey, Hampshire SO51 0ZN UK

Mark A West Siemens/Roke Manor Roke Manor Research Ltd.英国汉普郡罗姆西SO51 0ZN

   Phone: +44 1794 833311
   EMail: mark.a.west@roke.co.uk
   URI:   http://www.roke.co.uk
        
   Phone: +44 1794 833311
   EMail: mark.a.west@roke.co.uk
   URI:   http://www.roke.co.uk