tech-invite   World Map     

IETF     RFCs     Groups     SIP     ABNFs    |    3GPP     Specs     Gloss.     Arch.     IMS     UICC    |    Misc.    |    search     info

RFC 6846

 
 
 

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

Part 3 of 5, p. 38 to 57
Prev RFC Part       Next RFC Part

 


prevText      Top      Up      ToC       Page 38 
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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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      Up      ToC       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 RFC Part