Tech-invite3GPPspaceIETFspace
959493929190898887868584838281807978777675747372717069686766656463626160595857565554535251504948474645444342414039383736353433323130292827262524232221201918171615141312111009080706050403020100
in Index   Prev   Next

RFC 6846

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

Pages: 96
Proposed Standard
Errata
Obsoletes:  4996
Part 3 of 5 – Pages 38 to 57
First   Prev   Next

Top   ToC   RFC6846 - Page 38   prevText

7. Packet Types (Normative)

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. 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. The profile identifier for ROHC-TCP is 0x0006.

7.1. Initialization and Refresh (IR) Packets

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). Packet type: 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]:
Top   ToC   RFC6846 - Page 39
        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.

      Static chain: See Section 6.2.

      Dynamic chain: See Section 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.

   Packet type: 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]:
Top   ToC   RFC6846 - Page 40
        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.

      Dynamic chain: See Section 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.

7.2. Context Replication (IR-CR) Packets

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]. Packet type: 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.
Top   ToC   RFC6846 - Page 41
   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.

   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]:

        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
      |                               |
       - - - - - - - - - - - - - - - -
Top   ToC   RFC6846 - Page 42
      B: B = 1 indicates that the Base CID field is present.

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

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

      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.

      Replicate chain: See Section 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

The ROHC-TCP CO packets communicate irregularities in the packet header. All CO packets carry a CRC and can update the context. 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]:
Top   ToC   RFC6846 - Page 43
         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.

      Irregular chain: See Sections 6.2 and 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)

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. 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.
Top   ToC   RFC6846 - Page 44

8.1. Design Rationale for Compressed Base Headers

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). 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. 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. When discussing LSB-encoded fields below, "p" equals the "offset_param" and "k" equals the "num_lsbs_param" in [RFC4997]. The encoding methods used in the compressed base headers are based on the following design criteria: 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]. o TCP Sequence Number 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),
Top   ToC   RFC6846 - Page 45
         the LSB interpretation interval has to handle negative offsets
         about as large as positive offsets, which means that one more
         bit is needed.

         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.

   o  TCP Acknowledgment Number

         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.

         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.

   o  TCP Window

         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.

   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.

   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.
Top   ToC   RFC6846 - Page 46
   The design of the header formats is derived from the field behavior
   analysis found in [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.

   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  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  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  Format 4: This header format is similar to format 3, but carries a
      scaled TCP Acknowledgment Number.

   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  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  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  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.
Top   ToC   RFC6846 - Page 47
   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.

8.2. Formal Definition of Header Formats

// 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 //////////////////////////////////////////// IP_ID_BEHAVIOR_SEQUENTIAL = 0; IP_ID_BEHAVIOR_SEQUENTIAL_SWAPPED = 1; IP_ID_BEHAVIOR_RANDOM = 2; IP_ID_BEHAVIOR_ZERO = 3; //////////////////////////////////////////// // 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 ]; }
Top   ToC   RFC6846 - Page 48
///////////////////////////////////////////////
// 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";

////////////////////////////////////////////
// General encoding methods
////////////////////////////////////////////

static_or_irreg(flag, width)
{
  UNCOMPRESSED {
    field [ width ];
  }

  COMPRESSED irreg_enc {
    field =:= irregular(width) [ width ];
    ENFORCE(flag == 1);
  }

  COMPRESSED static_enc {
    field =:= static [ 0 ];
    ENFORCE(flag == 0);
  }
}

zero_or_irreg(flag, width)
{
  UNCOMPRESSED {
    field [ width ];
  }

  COMPRESSED non_zero {
    field =:= irregular(width) [ width ];
    ENFORCE(flag == 0);
  }

  COMPRESSED zero {
    field =:= uncompressed_value(width, 0) [ 0 ];
    ENFORCE(flag == 1);
Top   ToC   RFC6846 - Page 49
  }
}

variable_length_32_enc(flag)
{
  UNCOMPRESSED {
    field [ 32 ];
  }

  COMPRESSED not_present {
    field =:= static [ 0 ];
    ENFORCE(flag == 0);
  }

  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 irreg_32_bit {
    field =:= irregular(32) [ 32 ];
    ENFORCE(flag == 3);
  }
}

optional32(flag)
{
  UNCOMPRESSED {
    item [ 0, 32 ];
  }

  COMPRESSED present {
    item =:= irregular(32) [ 32 ];
    ENFORCE(flag == 1);
  }

  COMPRESSED not_present {
    item =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag == 0);
  }
}

lsb_7_or_31
Top   ToC   RFC6846 - Page 50
{
  UNCOMPRESSED {
    item [ 32 ];
  }

  COMPRESSED lsb_7 {
    discriminator =:= '0'       [ 1 ];
    item          =:= lsb(7, 8) [ 7 ];
  }

  COMPRESSED lsb_31 {
    discriminator =:= '1'          [ 1 ];
    item          =:= lsb(31, 256) [ 31 ];
  }
}

opt_lsb_7_or_31(flag)
{
  UNCOMPRESSED {
    item [ 0, 32 ];
  }

  COMPRESSED present {
    item =:= lsb_7_or_31 [ 8, 32 ];
    ENFORCE(flag == 1);
  }

  COMPRESSED not_present {
    item =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag == 0);
  }
}

crc3(data_value, data_length)
{
  UNCOMPRESSED {
  }

  COMPRESSED {
    crc_value =:=
      crc(3, 0x06, 0x07, data_value, data_length) [ 3 ];
  }
}

crc7(data_value, data_length)
{
  UNCOMPRESSED {
  }
Top   ToC   RFC6846 - Page 51
  COMPRESSED {
    crc_value =:=
      crc(7, 0x79, 0x7f, data_value, data_length) [ 7 ];
  }
}

one_bit_choice
{
  UNCOMPRESSED {
    field [ 1 ];
  }

  COMPRESSED zero {
    field [ 1 ];
    ENFORCE(field.UVALUE == 0);
  }

  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
  }

  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);
  }
}
Top   ToC   RFC6846 - Page 52
////////////////////////////////////////////
// IPv6 Destination options header
////////////////////////////////////////////

ip_dest_opt
{
  UNCOMPRESSED {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }

  DEFAULT {
    length      =:= static;
    next_header =:= static;
    value       =:= static;
  }

  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_1_replicate {
    discriminator =:= '10000000'                     [ 8 ];
    length        =:= irregular(8)                   [ 8 ];
    value         =:=
      irregular(length.UVALUE*64+48) [ length.UVALUE * 64 + 48 ];
  }

  COMPRESSED dest_opt_irregular {
  }
}

////////////////////////////////////////////
// IPv6 Hop-by-Hop options header
////////////////////////////////////////////

ip_hop_opt
{
Top   ToC   RFC6846 - Page 53
  UNCOMPRESSED {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }

  DEFAULT {
    length      =:= static;
    next_header =:= static;
    value       =:= static;
  }

  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_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_irregular {
  }
}

////////////////////////////////////////////
// IPv6 Routing header
////////////////////////////////////////////

ip_rout_opt
{
  UNCOMPRESSED {
    next_header [ 8 ];
    length      [ 8 ];
    value       [ length.UVALUE * 64 + 48 ];
  }
Top   ToC   RFC6846 - Page 54
  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_dynamic {
  }

  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 {
  }
}

////////////////////////////////////////////
// GRE Header
////////////////////////////////////////////

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 not_present {
Top   ToC   RFC6846 - Page 55
    value     =:= compressed_value(0, 0) [ 0 ];
    reserved1 =:= compressed_value(0, 0) [ 0 ];
    ENFORCE(flag_value == 0);
  }
}

gre_proto
{
  UNCOMPRESSED {
    protocol [ 16 ];
  }

  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 ];
  }
}

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;
  }

  COMPRESSED gre_static {
Top   ToC   RFC6846 - Page 56
    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_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_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
/////////////////////////////////////////////
Top   ToC   RFC6846 - Page 57
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;
  }

  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_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_irregular {
  }
}


(next page on part 4)

Next Section