[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[rohc] Request for comments on ROHC-TCP packet formats
Hi all!
After some offline discussions between the ROHC-TCP authors, we have once again
decided to revise the compressed base headers according to the following design
criteria:
- Push bit is always sent
- 3-bit CRC always present unless fields that affect future packet format
interpretation are present (such as ecn_used and ip_id_behavior), if so, a 7-bit
CRC is used.
- MSN: 4 bits with p=4 to allow for reordering and losses.
- Sequence number: at least 14 bits of LSB when present. The reason for 14, is
that we expect a delta_sn of about 1500 bytes, and adding room for
retransmissions (negative offset) and for robustness this gives us 14 bits. For
offset, the interval has been split in half to allow for retransmissions
p=2^(k-1) - 1.
When scaled, 4 bits are used with p=3.
- Ack number: At least 15 bits of LSB when present. Similar analysis to that
above, but since only every two packets are normally acked, we need one extra
bit. Since Ack numbers increasing apart from when we have prelink reordering, we
have set p=2^(k-2) - 1 (25% space negative offset). When scaled, 4 bits are used
with p=3
- Window: Changes in window are expected to be similar to the changes in
sequence number and therefore 14 bits of LSBs should be used, but it is
preferrable to send all the 16 bits. p=2^(k -1) - 1.
- IP-ID (when sequential): 4 bits are preferrable, but 3 can be allowed and if
there are "free bits", use up to 8 bits. For 4 or more bits, use p=3, if k<3 use
p=1.
- Discriminator: The length of the discriminator for each packet format is
decided upon based on the number of bits available to achieve byte alignemnt
after all fields in the header have fulfilled their design criteria. Also, the
packet formats deemed to be most important have often received the shortest
discriminators to limit header size, but in some cases this was not possible.
The set of packet formats attached to this mail (co_rnd_<x> and co_seq_<x> plus
co_common) have been made to meet these requirements, so comments on both the
formats themselves and also on the requirements above are appreciated.
With the ROHC-TCP "development" now going on for a number of years, we would
very much like to get this done and we feel that these packet formats are
something that is nearing "last-callable". Therefore, now is a good time to
comment on them since changes later on will be a lot harder to do.
If you do not like to read ROHC-FN to understand the packet formats, the
attached text document also contains regular box notation ascii-pictures of the
compressed base headers. The rest of the packet formats (chains & list
compression) are still only expressed in ROHC-FN.
/Kristofer Sandlund, Effnet AB
% Packet formats for TCP-ROHC
%
% $Id: tcp-pf.txt,v 1.28 2005/01/12 13:44:30 ks Exp $
%
% TODO
% - Does ack and seq scaling have a zero-division issue since they appear in
% the default_methods section?
% - ack scaling could be applied to a larger number of packet formats
% Maybe let _10 and/or _8 use one bit to indicate of ack is scaled or not
% andin that case use 8 bits less?
% - REVIEW OF PACKET FORMAT CONTENT!
% List of encoding methods that are expected to be predefined
% by the FN:
%
irregular (length) === "predefined by FN";
static === "predefined by FN";
compressed_value (length, value) === "predefined by FN";
lsb (lsbs, offset) === "predefined by FN";
crc (b, p, i, d, l) === "predefined by FN";
uncompressed_value (length, value) === "predefined by FN";
% Encoding methods not specified in FN syntax:
inferred_mine_header_checksum === "insert reference here";
inferred_ip_v6_length === "insert reference here";
inferred_ip_v4_header_checksum === "insert reference here";
inferred_ip_v4_length === "insert reference here";
inferred_offset === "insert reference here";
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Global control fields
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The control fields here reside in the context and are persistent between
% packets. Some of these (such as the sequence number scaling/residue are
% never transmitted explicitly, but are inferred from other values.
control_fields = ecn_used, %[ 1 ]
msn, %[ 16 ]
ip_inner_ecn, %[ 2 ]
seq_number_scaled, %[ 32 ]
seq_number_residue, %[ 32 ]
ack_stride, %[ 16 ]
ack_number_scaled, %[ 16 ]
ack_number_residue; %[ 16 ]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% General structures
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
static_or_irreg32(flag) ===
{
uncompressed_format = field; %[ 32 ]
format_irreg_enc = field, %[ 32 ]
{
let (flag == 1);
field ::= irregular(32);
};
format_static_enc = field, %[ 0 ]
{
let (flag == 0);
field ::= static;
};
};
static_or_irreg16(flag) ===
{
uncompressed_format = field; %[ 16 ]
format_irreg_enc = field, %[ 16 ]
{
let (flag == 1);
field ::= irregular(16);
};
format_static_enc = field, %[ 0 ]
{
let (flag == 0);
field ::= static;
};
};
static_or_irreg8(flag) ===
{
uncompressed_format = field; %[ 8 ]
format_irreg_enc = field, %[ 8 ]
{
let (flag == 1);
field ::= irregular(8);
};
format_static_enc = field, %[ 0 ]
{
let (flag == 0);
field ::= static;
};
};
variable_length_32_enc(flag) ===
{
uncompressed_format = field; %[ 32 ]
format_not_present = field, %[ 0 ]
{
let(flag == 0);
field ::= static;
};
format_8_bit = field, %[ 8 ]
{
let(flag == 1);
field ::= lsb(8, 63);
};
format_16_bit = field, %[ 16 ]
{
let(flag == 2);
field ::= lsb(16, 16383);
};
format_32_bit = field, %[ 32 ]
{
let(flag == 3);
field ::= irregular(32);
};
};
variable_length_16_enc(flag) ===
{
uncompressed_format = field; %[ 16 ]
format_not_present = field, %[ 0 ]
{
let(flag == 0);
field ::= static;
};
format_8_bit = field, %[ 8 ]
{
let(flag == 1);
field ::= lsb(8, 63);
};
format_16_bit = field, %[ 16 ]
{
let(flag == 2);
field ::= irregular(16);
};
};
optional32 (flag) ===
{
uncompressed_format = item; % 0 or 32 bits
format_present = item, %[ 32 ]
{
let (flag == 1);
item ::= irregular (32);
};
format_not_present = item, %[ 0 ]
{
let (flag == 0);
item ::= compressed_value (0, 0);
};
};
lsb_7_or_31 ===
{
uncompressed_format = item; % 7 or 31 bits
format_lsb_7 = discriminator, %[ 1 ]
item, %[ 7 ]
{
discriminator ::= '0';
item ::= lsb (7, 8);
};
format_lsb_31 = discriminator, %[ 1 ]
item, %[ 31 ]
{
discriminator ::= '1';
item ::= lsb (31, 256);
};
};
opt_lsb_7_or_31 (flag) ===
{
uncompressed_format = item; % 32 bits
format_present = item, % 8 or 32 bits
{
let (flag == 1);
item ::= lsb_7_or_31;
};
format_not_present = item, %[ 0 ]
{
let (flag == 0);
item ::= compressed_value (0, 0);
};
};
crc3 (data_value, data_length) ===
{
uncompressed_format = ;
compressed_format = crc_value, %[ 3 ]
{
crc_value ::= crc(3, 0x06, 0x07, data_value, data_length);
};
};
crc7 (data_value, data_length) ===
{
uncompressed_format = ;
compressed_format = crc_value, %[ 7 ]
{
crc_value ::= crc(7, 0x79, 0x7f, data_value, data_length);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% IPv6 Destination options header
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ip_dest_opt ===
{
uncompressed_format = next_header, %[ 8 ]
length, %[ 8 ]
value; % n bits
default_methods =
{
next_header ::= static;
length ::= static;
value ::= static;
};
format_dest_opt_static = next_header, %[ 8 ]
length, %[ 8 ]
{
next_header ::= irregular(8);
length ::= irregular(8);
};
format_dest_opt_dynamic = value, % n bits
{
value ::= irregular(length:uncomp_value * 64 + 48);
};
format_dest_opt_replicate_0 = discriminator, %[ 8 ]
{
discriminator ::= '00000000';
};
format_dest_opt_replicate_1 = discriminator, %[ 8 ]
length, %[ 8 ]
value, % n bits
{
discriminator ::= '10000000';
length ::= irregular(8);
value ::= irregular(length:uncomp_value * 64 + 48);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% IPv6 Hop-by-Hop options header
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ip_hop_opt ===
{
uncompressed_format = next_header, %[ 8 ]
length, %[ 8 ]
value; % n bits
default_methods =
{
next_header ::= static;
length ::= static;
value ::= static;
};
format_hop_opt_static = next_header, %[ 8 ]
length, %[ 8 ]
{
next_header ::= irregular(8);
length ::= irregular(8);
};
format_hop_opt_dynamic = value, % n bits
{
value ::= irregular(length:uncomp_value * 64 + 48);
};
format_hop_opt_replicate_0 = discriminator, %[ 8 ]
{
discriminator ::= '00000000';
};
format_hop_opt_replicate_1 = discriminator, %[ 8 ]
length, %[ 8 ]
value, % n bits
{
discriminator ::= '10000000';
length ::= irregular(8);
value ::= irregular(length:uncomp_value * 64 + 48);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% IPv6 Routing header
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ip_rout_opt ===
{
uncompressed_format = next_header, %[ 8 ]
length, %[ 8 ]
value; % n bits
default_methods =
{
next_header ::= static;
length ::= static;
value ::= static;
};
format_rout_opt_static = next_header, %[ 8 ]
length, %[ 8 ]
value, % n bits
{
next_header ::= irregular(8);
length ::= irregular(8);
value ::= irregular(length:uncomp_value * 64 + 48);
};
format_rout_opt_dynamic =
{
};
format_rout_opt_replicate_0 = discriminator, %[ 8 ]
{
discriminator ::= '00000000';
};
format_rout_opt_replicate_1 = discriminator, %[ 8 ]
length, %[ 8 ]
value, % n bits
{
discriminator ::= '10000000';
length ::= irregular(8);
value ::= irregular(length:uncomp_value * 64 + 48);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% GRE Header
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
optional_checksum (flag_value) ===
{
uncompressed_format = value, % 0 or 16 bits
reserved1; % 0 or 16 bits
format_cs_present = value, %[ 16 ]
reserved1, %[ 0 ]
{
let (flag_value == 1);
value ::= irregular (16);
reserved1 ::= uncompressed_value (16, 0);
};
format_not_present = value, %[ 0 ]
reserved1, %[ 0 ]
{
let (flag_value == 0);
value ::= compressed_value (0, 0);
reserved1 ::= compressed_value (0, 0);
};
};
gre_proto ===
{
uncompressed_format = protocol; %[ 16 ]
default_methods =
{
};
format_ether_v4 = discriminator, %[ 1 ]
{
discriminator ::= compressed_value (1, 0);
protocol ::= uncompressed_value (16, 0x0800);
};
format_ether_v6 = discriminator, %[ 1 ]
{
discriminator ::= compressed_value (1, 1);
protocol ::= uncompressed_value (16, 0x86DD);
};
};
gre ===
{
uncompressed_format = c_flag, %[ 1 ]
r_flag, %[ 1 ]
k_flag, %[ 1 ]
s_flag, %[ 1 ]
reserved0, %[ 9 ]
version, %[ 3 ]
protocol, %[ 16 ]
checksum_and_res, % 0 or 32 bits
key, % 0 or 32 bits
sequence_number; % 0 or 32 bits
default_methods =
{
c_flag ::= static;
r_flag ::= static;
k_flag ::= static;
s_flag ::= static;
reserved0 ::= uncompressed_value (9, 0);
version ::= static;
protocol ::= static;
key ::= static;
checksum_and_res ::= optional_checksum (c_flag);
};
format_gre_static = protocol, %[ 1 ]
c_flag, %[ 1 ]
r_flag, %[ 1 ]
k_flag, %[ 1 ]
s_flag, %[ 1 ]
version, %[ 3 ]
key, % 0 or 32 bits
{
protocol ::= gre_proto;
c_flag ::= irregular (1);
r_flag ::= irregular (1);
k_flag ::= irregular (1);
s_flag ::= irregular (1);
version ::= irregular (3);
key ::= optional32 (k_flag);
sequence_number ::= static;
};
format_gre_dynamic = checksum_and_res,% 0 or 16 bits
sequence_number, % 0 or 32 bits
{
sequence_number ::= optional32 (s_flag);
};
format_gre_replicate_0 = discriminator, %[ 8 ]
checksum_and_res,% 0 or 16 bits
sequence_number, % 0, 8 or 32 bits
{
discriminator ::= '00000000';
sequence_number ::= opt_lsb_7_or_31 (s_flag);
};
format_gre_replicate_1 =
discriminator, %[ 8 ]
c_flag, %[ 1 ]
r_flag, %[ 1 ]
k_flag, %[ 1 ]
s_flag, %[ 1 ]
reserved, %[ 1 ]
version, %[ 3 ]
checksum_and_res,% 0 or 16 bits
key, % 0 or 32 bits
sequence_number, % 0 or 32 bits
{
discriminator ::= '10000000';
c_flag ::= irregular (1);
r_flag ::= irregular (1);
k_flag ::= irregular (1);
s_flag ::= irregular (1);
reserved ::= '0';
version ::= irregular (3);
key ::= optional32 (k_flag);
sequence_number ::= optional32 (s_flag);
};
format_gre_irregular = checksum_and_res,% 0 or 16 bits
sequence_number, % 0, 8 or 32 bits
{
sequence_number ::= opt_lsb_7_or_31 (s_flag);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MINE header
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
mine ===
{
uncompressed_format = next_header, %[ 8 ]
s_bit, %[ 1 ]
res_bits, %[ 7 ]
checksum, %[ 16 ]
orig_dest, %[ 32 ]
orig_src; % 0 or 32 bits
default_methods =
{
next_header ::= static;
s_bit ::= static;
res_bits ::= static;
checksum ::= inferred_mine_header_checksum;
orig_dest ::= static;
orig_src ::= static;
};
format_mine_static = next_header,%[ 8 ]
s_bit, %[ 1 ],
res_bits, %[ 7 ],
orig_dest, %[ 32 ]
orig_src, % 0 or 32 bits
{
next_header ::= irregular (8);
s_bit ::= irregular (1);
res_bits ::= irregular (7);
% include reserved - no benefit in removing them
orig_dest ::= irregular (32);
orig_src ::= optional32 (s_bit);
};
format_mine_dynamic =
{
};
format_mine_replicate_0 = discriminator, %[ 8 ]
checksum, %[ 0 ]
{
discriminator ::= '00000000';
};
format_mine_replicate_1 = discriminator, %[ 8 ]
s_bit, %[ 1 ]
res_bits, %[ 7 ]
orig_dest, %[ 32 ]
orig_src, % 0 or 32 bits
{
discriminator ::= '10000000';
s_bit ::= irregular (1);
res_bits ::= irregular (7);
orig_dest ::= irregular (32);
orig_src ::= optional32 (s_bit);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Authentication Header (AH)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ah ===
{
uncompressed_format = next_header, %[ 8 ]
length, %[ 8 ]
res_bits, %[ 16 ]
spi, %[ 32 ]
sequence_number, %[ 32 ]
auth_data; % n bits
default_methods =
{
next_header ::= static;
length ::= static;
res_bits ::= static;
spi ::= static;
sequence_number ::= static;
auth_data ::= irregular (length:uncomp_value * 32 - 32);
};
format_ah_static = next_header, %[ 8 ]
length, %[ 8 ]
spi, %[ 32 ]
{
next_header ::= irregular(8);
length ::= irregular (8);
spi ::= irregular (32);
};
format_ah_dynamic = res_bits, %[ 16 ]
sequence_number, %[ 32 ]
auth_data, % n bits
{
res_bits ::= irregular (16);
sequence_number ::= irregular (32);
};
format_ah_replicate_0 = discriminator, %[ 8 ]
sequence_number, % 8 or 32 bits
auth_data, % n bits
{
discriminator ::= '00000000';
sequence_number ::= lsb_7_or_31;
};
format_ah_replicate_1 = discriminator, %[ 8 ]
length, %[ 8 ]
res_bits, %[ 16 ]
spi, %[ 32 ]
sequence_number, %[ 32 ]
auth_data, % n bits
{
discriminator ::= '10000000';
length ::= irregular (8);
res_bits ::= irregular (16);
spi ::= irregular (32);
sequence_number ::= irregular (32);
};
format_ah_irregular = sequence_number, % 8 or 32 bits
auth_data, % n bits
{
sequence_number ::= lsb_7_or_31;
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% ESP header (NULL encrypted)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
esp_null ===
{
uncompressed_format = spi, %[ 32 ]
sequence_number, %[ 32 ]
next_header; %[ 8 ]
default_methods =
{
spi ::= static;
% Next header will always be present in the trailer part,
% but sometimes it will ALSO be present in the header
% (static chain only).
nh_field ::= static; % Control field
next_header ::= static;
sequence_number ::= static;
};
format_esp_static = nh_field, %[ 8 ]
spi, %[ 32 ]
{
% identify next header assume next 96 bits skipped
% to get to end of packet (i.e. this is anchored from the end
% of the packet, not the start)
nh_field ::= compressed_value(8, next_header);
next_header ::= irregular (8); % At packet end!
spi ::= irregular (32);
};
format_esp_dynamic = sequence_number, %[ 32 ]
{
sequence_number ::= irregular (32);
};
format_esp_replicate_0 = discriminator, %[ 8 ]
sequence_number, % 8 or 32 bits
{
discriminator ::= '00000000';
sequence_number ::= lsb_7_or_31;
};
format_esp_replicate_1 = discriminator, %[ 8 ]
spi, %[ 32 ]
sequence_number, %[ 32 ]
{
discriminator ::= '10000000';
spi ::= irregular (32);
sequence_number ::= irregular (32);
};
format_esp_irregular = sequence_number, % 8 or 32 bits
{
sequence_number ::= lsb_7_or_31;
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Structures common for IPv4 and IPv6
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
irreg_tos_tc ===
{
uncompressed_format = tos_tc; %[ 6 ]
format_tos_tc_present = tos_tc , %[ 6 ]
{
let(ecn_used:uncomp_value == 1);
tos_tc ::= irregular (6);
};
format_tos_tc_not_present = tos_tc , %[ 0 ]
{
let(ecn_used:uncomp_value == 0);
tos_tc ::= static;
};
};
ip_irreg_ecn ===
{
uncompressed_format = ip_ecn_flags; %[ 2 ]
format_tc_present = ip_ecn_flags, %[ 2 ]
{
let(ecn_used:uncomp_value == 1);
ip_ecn_flags ::= irregular (2);
};
format_tc_not_present = ip_ecn_flags, %[ 0 ]
{
let(ecn_used:uncomp_value == 0);
ip_ecn_flags ::= static;
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% IPv6 Header
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
fl_enc ===
{
uncompressed_format = flow_label;
format_fl_zero = discriminator, %[ 1 ]
flow_label, %[ 0 ]
reserved, %[ 4 ]
{
discriminator ::= '0';
flow_label ::= uncompressed_value (20, 0);
reserved ::= '0000';
};
format_fl_non_zero = discriminator, %[ 1 ]
flow_label, %[ 20 ]
{
discriminator ::= '1';
flow_label ::= irregular (20);
};
};
% The argument flag should only be used if this flag was set when processing
% a compressed base header, if not, the flag should be zero.
ipv6 (ttl_irregular_chain_flag) ===
{
uncompressed_format = version, %[ 4 ]
tos_tc, %[ 6 ]
ip_ecn_flags, %[ 2 ]
flow_label, %[ 20 ]
payload_length, %[ 16 ]
next_header, %[ 8 ]
ttl_hopl, %[ 8 ]
src_addr, %[ 128 ]
dst_addr; %[ 128 ]
default_methods =
{
version ::= uncompressed_value (4, 6);
tos_tc ::= 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;
};
format_ipv6_static = version_flag, %[ 1 ]
reserved, %[ 2 ]
flow_label, % 5 or 21 bits
next_header, %[ 8 ]
src_addr, %[ 128 ]
dst_addr, %[ 128 ]
{
version_flag ::= '1';
reserved ::= '00';
flow_label ::= fl_enc;
next_header ::= irregular (8);
src_addr ::= irregular(128);
dst_addr ::= irregular(128);
};
format_ipv6_dynamic = tos_tc, %[ 6 ]
ip_ecn_flags, %[ 2 ]
ttl_hopl, %[ 8 ]
{
tos_tc ::= irregular (6);
ip_ecn_flags ::= irregular (2);
ttl_hopl ::= irregular (8);
};
format_ipv6_replicate = tos_tc, %[ 6 ]
ip_ecn_flags, %[ 2 ]
{
tos_tc ::= irregular (6);
ip_ecn_flags ::= irregular (2);
};
format_ipv6_outer_irregular_without_ttl
= tos_tc, % 0 or 6 bits
ip_ecn_flags, % 0 or 2 bits
{
% for 'outer' headers only, irregular chain is required
tos_tc ::= irreg_tos_tc;
ip_ecn_flags ::= ip_irreg_ecn;
let(ttl_irregular_chain_flag == 0);
};
format_ipv6_outer_irregular_with_ttl
= tos_tc, % 0 or 6 bits
ip_ecn_flags, % 0 or 2 bits
ttl_hopl, %[ 8 ]
{
% for 'outer' headers only, irregular chain is required
tos_tc ::= irreg_tos_tc;
ip_ecn_flags ::= ip_irreg_ecn;
let(ttl_irregular_chain_flag == 1);
ttl_hopl ::= irregular(8);
};
% Note that the ECN bits are stored in the global control field
% so that they can be output in TCP irregular chain.
format_ipv6_innermost_irregular =
{
let(ip_inner_ecn:uncomp_value ==
ip_ecn_flags:uncomp_value);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% IPv4 Header
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ip_id_enc_dyn (behavior) ===
{
uncompressed_format = ip_id; %[ 16 ]
format_ip_id_seq = ip_id, %[ 16 ]
{
let ((behavior == 0) || (behavior == 1) || (behavior == 2));
% In dynamic chain, but random, seq, and seq-swapped are 16 bits
ip_id ::= irregular(16);
};
format_ip_id_zero = ip_id, %[ 0 ]
{
let (behavior == 3);
% Zero IPID
ip_id ::= uncompressed_value (16, 0);
};
};
ip_id_enc_irreg (behavior) ===
{
uncompressed_format = ip_id; %[ 16 ]
format_ip_id_seq = ip_id, %[ 0 ]
{
let (behavior == 0); % sequential
ip_id ::= static; % Nothing to send in irregular chain
};
format_ip_id_seq_swapped = ip_id, %[ 0 ]
{
let (behavior == 1); % sequential-swapped
ip_id ::= static; % Nothing to send in irregular chain
};
format_ip_id_rand = ip_id, %[ 16 ]
{
let (behavior == 2); % random
ip_id ::= irregular (16);
};
format_ip_id_zero = ip_id, %[ 0 ]
{
let (behavior == 3); % zero
ip_id ::= uncompressed_value (16, 0);
};
};
ip_id_behavior_enc ===
{
uncompressed_format = ip_id_behavior; %[ 2 ]
format_sequential = ip_id_behavior, %[ 2 ]
{
ip_id_behavior ::= '00';
};
format_sequential_swapped = ip_id_behavior, %[ 2 ]
{
ip_id_behavior ::= '01';
};
format_random = ip_id_behavior, %[ 2 ]
{
ip_id_behavior ::= '10';
};
format_zero = ip_id_behavior, %[ 2 ]
{
ip_id_behavior ::= '11';
};
};
% The argument flag should only be used if this flag was set when processing
% a compressed base header, if not, the flag should be zero.
ipv4 (ttl_irregular_chain_flag) ===
{
uncompressed_format = version, %[ 4 ]
hdr_length, %[ 4 ]
protocol, %[ 8 ]
tos_tc, %[ 6 ]
ip_ecn_flags,%[ 2 ]
ttl_hopl, %[ 8 ]
df, %[ 1 ]
mf, %[ 1 ]
rf, %[ 1 ]
frag_offset, %[ 13 ]
ip_id, %[ 16 ]
src_addr, %[ 32 ]
dst_addr, %[ 32 ]
checksum, %[ 16 ]
length; %[ 16 ]
control_fields = ip_id_behavior; %[ 2 ]
default_methods =
{
version ::= static;
hdr_length ::= uncompressed_value (4, 5);
protocol ::= static;
tos_tc ::= static;
ip_ecn_flags ::= static;
ttl_hopl ::= static;
df ::= static;
mf ::= uncompressed_value (1, 0);
rf ::= static;
frag_offset ::= uncompressed_value (13, 0);
ip_id ::= uncompressed_value (16, 0);
ip_id_behavior ::= static;
src_addr ::= static;
dst_addr ::= static;
checksum ::= inferred_ip_v4_header_checksum;
length ::= inferred_ip_v4_length;
};
format_ipv4_static = version_flag, %[ 1 ]
reserved, %[ 7 ]
protocol, %[ 8 ]
src_addr, %[ 32 ]
dst_addr, %[ 32 ]
{
version_flag ::= '0';
reserved ::= '0000000';
protocol ::= irregular (8);
src_addr ::= irregular(32);
dst_addr ::= irregular(32);
};
format_ipv4_dynamic = reserved, %[ 5 ]
df, %[ 1 ]
ip_id_behavior, %[ 2 ]
tos_tc, %[ 6 ]
ip_ecn_flags, %[ 2 ]
ttl_hopl, %[ 8 ]
ip_id, % 0/16 bits
{
reserved ::= '00000';
%
% compressor chooses behavior of IP-ID
% 00 = sequential
% 01 = sequential byteswapped
% 10 = random
% 11 = zero
%
ip_id_behavior ::= ip_id_behavior_enc;
df ::= irregular (1);
tos_tc ::= irregular (6);
ip_ecn_flags ::= irregular (2);
ttl_hopl ::= irregular (8);
ip_id ::= ip_id_enc_dyn (ip_id_behavior);
};
format_ipv4_replicate_0 = discriminator, %[ 8 ]
ip_id, % 0 or 16 bits
tos_tc, %[ 6 ]
ip_ecn_flags, %[ 2 ]
{
discriminator ::= '00000000';
ip_id_behavior ::= static;
ip_id ::= ip_id_enc_irreg (ip_id_behavior);
tos_tc ::= irregular (6);
ip_ecn_flags ::= irregular (2);
};
format_ipv4_replicate_1 = discriminator, %[ 5 ]
df, %[ 1 ]
ip_id_behavior, %[ 2 ]
tos_tc, %[ 6 ]
ip_ecn_flags, %[ 2 ]
ttl_hopl, %[ 8 ]
ip_id, % 0/16 bits
{
discriminator ::= '10000';
df ::= irregular (1);
tos_tc ::= irregular (6);
ip_ecn_flags ::= irregular (2);
ttl_hopl ::= irregular (8);
%
% compressor chooses behavior of IP-ID
% 00 = sequential
% 01 = sequential byteswapped
% 10 = random
% 11 = zero
%
ip_id_behavior ::= ip_id_behavior_enc;
ip_id ::= ip_id_enc_dyn (ip_id_behavior);
};
format_ipv4_outer_irregular_without_ttl =
ip_id, % 0 or 16 bits
tos_tc, % 0 or 6 bits
ip_ecn_flags, % 0 or 2 bits
{
ip_id_behavior ::= static;
ip_id ::= ip_id_enc_irreg (ip_id_behavior);
tos_tc ::= irreg_tos_tc;
ip_ecn_flags ::= ip_irreg_ecn;
let(ttl_irregular_chain_flag == 0);
};
format_ipv4_outer_irregular_with_ttl =
ip_id, % 0 or 16 bits
tos_tc, % 0 or 6 bits
ip_ecn_flags, % 0 or 2 bits
ttl_hopl, %[ 8 ]
{
ip_id_behavior ::= static;
ip_id ::= ip_id_enc_irreg (ip_id_behavior);
tos_tc ::= irreg_tos_tc;
ip_ecn_flags ::= ip_irreg_ecn;
let(ttl_irregular_chain_flag == 1);
ttl_hopl ::= irregular(8);
};
% Note that the ECN bits are stored in the global control field
% so that they can be output in TCP irregular chain.
format_ipv4_innermost_irregular = ip_id, % 0 or 16 bits
{
ip_id_behavior ::= static;
ip_id ::= ip_id_enc_irreg (ip_id_behavior);
let(ip_inner_ecn:uncomp_value ==
ip_ecn_flags:uncomp_value);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% TCP Options
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% EOL marks the end of the option list and, based on
% the description in RFC 793 and the BSB TCP code,
% nothing after this should be processed...
% So, ignore everything after the EOL option
% (according to 793 it must be 0)
%
% The length of the padding needs to be transmitted with the compressed list
% since the length of the list can be unknown to the decompressor.
%
tcp_opt_eol(nbits) === {
uncompressed_format = type, %[ 8 ]
padding; % (nbits - 8) bits
default_methods =
{
type ::= uncompressed_value (8, 0);
pad_len ::= static;
padding ::= uncompressed_value (nbits - 8, 0);
};
format_eol_list_item = pad_len, % 8 bits
padding, %[ 0 ]
{
pad_len ::= compressed_value(8, nbits - 8);
};
format_eol_irregular =
{
let(nbits - 8 == pad_len:uncomp_value);
};
};
tcp_opt_nop ===
{
uncompressed_format = type; %[ 8 ]
default_methods =
{
type ::= uncompressed_value (8, 1);
};
format_nop_list_item =
{
};
format_nop_irregular =
{
};
};
tcp_opt_mss ===
{
uncompressed_format = type, %[ 8 ]
length, %[ 8 ]
mss; %[ 16 ]
default_methods =
{
type ::= uncompressed_value (8, 2);
length ::= uncompressed_value (8, 4);
mss ::= static;
};
format_mss_list_item = mss, %[ 16 ]
{
mss ::= irregular (16);
};
format_mss_irregular =
{
};
};
tcp_opt_wscale ===
{
uncompressed_format = type, %[ 8 ]
length, %[ 8 ]
wscale; %[ 8 ]
default_methods =
{
type ::= uncompressed_value (8, 3);
length ::= uncompressed_value (8, 3);
wscale ::= static;
};
format_wscale_list_item = wscale, %[ 8 ]
{
wscale ::= irregular (8);
};
format_wscale_irregular =
{
};
};
ts_lsb ===
{
uncompressed_format = tsval;
format_tsval_15 = discriminator, %[ 1 ]
tsval, %[ 15 ]
{
discriminator ::= '0';
tsval ::= lsb (15, -1);
};
format_tsval_22 = discriminator, %[ 2 ]
tsval, %[ 22 ]
{
discriminator ::= '10';
tsval ::= lsb (22, -1);
};
format_tsval_30 = discriminator, %[ 2 ]
tsval, %[ 30 ]
{
discriminator ::= '11';
% Large negative LSB offset, so that the 30-bit format
% can handle possible prelink reordering
tsval ::= lsb (30, 0x08000000);
};
};
tcp_opt_tsopt ===
{
uncompressed_format = type, %[ 8 ]
length, %[ 8 ]
tsval, %[ 32 ]
tsecho; %[ 32 ]
default_methods =
{
type ::= uncompressed_value (8, 8);
length ::= uncompressed_value (8, 10);
};
format_tsopt_list_item = tsval, %[ 32 ]
tsecho, %[ 32 ]
{
tsval ::= irregular (32);
tsecho ::= irregular (32);
};
format_tsopt_irregular = tsval, % 16, 24 or 32 bits
tsecho, % 16, 24 or 32 bits
{
tsval ::= ts_lsb;
tsecho ::= ts_lsb;
};
};
sack_var_length_enc (base) ===
{
uncompressed_format = sack_field; %[ 32 ]
default_methods =
{
let (sack_offset:uncomp_value ==
sack_field:uncomp_value - base);
let (sack_offset:uncomp_length == 32);
};
format_lsb_15 = discriminator, %[ 1 ]
sack_offset, %[ 15 ]
{
discriminator ::= '0';
sack_offset ::= lsb (15, -1);
};
format_lsb_22 = discriminator, %[ 2 ]
sack_offset, %[ 22 ]
{
discriminator ::= '10';
sack_offset ::= lsb (22, -1);
};
format_lsb_30 = discriminator, %[ 2 ]
sack_offset, %[ 30 ]
{
discriminator ::= '11';
sack_offset ::= lsb (30, -1);
};
};
tcp_opt_sack_block (prev_block_end) ===
{
uncompressed_format = block_start, %[ 32 ]
block_end; %[ 32 ]
format_0 = block_start, % 16, 24 or 32 bits
block_end, % 16, 24 or 32 bits
{
block_start ::= sack_var_length_enc (prev_block_end);
block_end ::= sack_var_length_enc (block_start);
};
};
tcp_opt_sack(ack_value) ===
{
% The ACK value from the TCP header is needed as input parameter.
uncompressed_format = type, %[ 8 ]
length, %[ 8 ]
block_1, %[ 64 ]
block_2, % 0 or 64 bits
block_3, % 0 or 64 bits
block_4; % 0 or 64 bits
default_methods =
{
length ::= static;
type ::= uncompressed_value (8, 5);
block_2 ::= uncompressed_value (0, 0);
block_3 ::= uncompressed_value (0, 0);
block_4 ::= uncompressed_value (0, 0);
};
format_sack1_list_item = discriminator,
block_1,
{
let(length:uncomp_value == 10);
discriminator ::= '00000001';
block_1 ::= tcp_opt_sack_block (ack_value);
};
format_sack2_list_item = discriminator,
block_1,
block_2,
{
let(length:uncomp_value == 18);
discriminator ::= '00000010';
block_1 ::= tcp_opt_sack_block (ack_value);
block_2 ::= tcp_opt_sack_block (block_1_end:uncomp_value);
};
format_sack3_list_item = discriminator,
block_1,
block_2,
block_3,
{
let(length:uncomp_value == 26);
discriminator ::= '00000011';
block_1 ::= tcp_opt_sack_block (ack_value);
block_2 ::= tcp_opt_sack_block (block_1_end:uncomp_value);
block_3 ::= tcp_opt_sack_block (block_2_end:uncomp_value);
};
format_sack4_list_item = discriminator,
block_1,
block_2,
block_3,
block_4,
{
let(length:uncomp_value == 34);
discriminator ::= '00000100';
block_1 ::= tcp_opt_sack_block (ack_value);
block_2 ::= tcp_opt_sack_block (block_1_end:uncomp_value);
block_3 ::= tcp_opt_sack_block (block_2_end:uncomp_value);
block_4 ::= tcp_opt_sack_block (block_3_end:uncomp_value);
};
format_sack_unchanged_irregular = discriminator,
block_1,
block_2,
block_3,
block_4,
{
discriminator ::= '00000000';
block_1 ::= static;
block_2 ::= static;
block_3 ::= static;
block_4 ::= static;
};
format_sack1_irregular = discriminator,
block_1,
{
let(length:uncomp_value == 10);
discriminator ::= '00000001';
block_1 ::= tcp_opt_sack_block (ack_value);
};
format_sack2_irregular = discriminator,
block_1,
block_2,
{
let(length:uncomp_value == 18);
discriminator ::= '00000010';
block_1 ::= tcp_opt_sack_block (ack_value);
block_2 ::= tcp_opt_sack_block (block_1_end:uncomp_value);
};
format_sack3_irregular = discriminator,
block_1,
block_2,
block_3,
{
let(length:uncomp_value == 26);
discriminator ::= '00000011';
block_1 ::= tcp_opt_sack_block (ack_value);
block_2 ::= tcp_opt_sack_block (block_1_end:uncomp_value);
block_3 ::= tcp_opt_sack_block (block_2_end:uncomp_value);
};
format_sack4_irregular = discriminator,
block_1,
block_2,
block_3,
block_4,
{
let(length:uncomp_value == 34);
discriminator ::= '00000100';
block_1 ::= tcp_opt_sack_block (ack_value);
block_2 ::= tcp_opt_sack_block (block_1_end:uncomp_value);
block_3 ::= tcp_opt_sack_block (block_2_end:uncomp_value);
block_4 ::= tcp_opt_sack_block (block_3_end:uncomp_value);
};
};
tcp_opt_sack_permitted ===
{
uncompressed_format = type, %[ 8 ]
length; %[ 8 ]
default_methods =
{
type ::= uncompressed_value (8, 4);
length ::= uncompressed_value (8, 2);
};
format_sack_permitted_list_item =
{
};
format_sack_permitted_irregular =
{
};
};
tcp_opt_generic ===
{
uncompressed_format = type, %[ 8 ]
length_msb, %[ 1 ]
length_lsb, %[ 7 ]
contents; % n bits
control_fields = option_static; %[ 1 ]
default_methods =
{
type ::= static;
%
% lengths are always < 128
% (i.e. the msb is always 0)
%
length_msb ::= uncompressed_value (1, 0);
length_lsb ::= static;
contents ::= static;
};
format_generic_list_item = type, %[ 8 ]
option_static, %[ 1 ]
length_lsb, %[ 7 ]
contents, % n bits
{
type ::= irregular (8);
option_static ::= irregular (1);
length_lsb ::= irregular (7);
contents ::= irregular (length_len:uncomp_value * 8 - 16);
};
% Used when context of option has option_static set to one
format_generic_irregular_static =
{
let(option_static:uncomp_value == 1);
};
% An item that can change, but currently is unchanged
format_generic_irregular_stable = discriminator, %[ 8 ]
{
let(option_static:uncomp_value == 0);
discriminator ::= '11111111';
};
% An item that can change, and has changed compared to context.
% Length is not allowed to change here, since a length change is
% most likely to cause new NOPs or an EOL length change.
format_generic_irregular_full = discriminator, %[ 8 ]
contents, % n bits
{
let(option_static:uncomp_value == 0);
discriminator ::= '00000000';
contents ::= irregular (length_lsb:uncomp_value * 8 - 16);
};
};
list_tcp_options(nbits) === {
uncompressed_format = item, tail;
default_methods = {
let(nbits >= item:uncomp_length);
tail ::= list_tcp_options(nbits - item:uncomp_length);
};
compressed_format_list_end = {
let(nbits == 0);
item ::= irregular(0);
tail ::= irregular(0);
};
compressed_format_eol = item, tail {
let(nbits == item:uncomp_length); % redundant
item ::= tcp_opt_eol(nbits);
tail ::= irregular(0);
};
compressed_format_nop = item, tail {
item ::= tcp_opt_nop;
};
compressed_format_mss = item, tail {
item ::= tcp_opt_mss;
};
compressed_format_wscale = item, tail {
item ::= tcp_opt_wscale;
};
compressed_format_tsopt = item, tail {
item ::= tcp_opt_tsopt;
};
compressed_format_sack = item, tail {
item ::= tcp_opt_sack;
};
compressed_format_permitted = item, tail {
item ::= tcp_opt_sack_permitted;
};
compressed_format_generic = item, tail {
item ::= tcp_opt_generic;
};
};
tcp_list_presence_enc(list_length, presence) ===
{
uncompressed_format = tcp_options;
format_list_not_present = tcp_options, %[ 0 ]
{
let (presence == 0);
tcp_options ::= static;
};
format_list_present = tcp_options, % 8 + n*8 bits
{
let (presence == 1);
tcp_options ::= list_tcp_options(list_length);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% TCP Header
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
port_replicate(flags) ===
{
uncompressed_format = port; %[ 16 ]
format_port_static_enc = port, %[ 0 ]
{
let(flags == 00);
port ::= static;
};
format_port_lsb8 = port, %[ 8 ]
{
let(flags == 01);
port ::= lsb (8, 64);
};
format_port_irr_enc = port, %[ 16 ]
{
let(flags == 10);
port ::= irregular (16);
};
};
zero_or_irr16_enc(flag) ===
{
uncompressed_format = field; %[ 16 ]
format_non_zero = field, %[ 16 ]
{
let(flag == 0);
field ::= irregular (16);
};
format_zero = field, %[ 0 ]
{
let(flag == 1);
field ::= uncompressed_value (16, 0);
};
};
ack_enc_dyn(flag) ===
{
uncompressed_format = ack_number; %[ 32 ]
format_ack_non_zero = ack_number, %[ 32 ]
{
let(flag == 0);
ack_number ::= irregular (32);
};
format_ack_zero = ack_number, %[ 0 ]
{
let(flag == 1);
ack_number ::= uncompressed_value (32, 0);
};
};
tcp_ecn_flags_enc ===
{
uncompressed_format = tcp_ecn_flags; %[ 2 ]
format_irreg = tcp_ecn_flags, %[ 2 ]
{
let(ecn_used:uncomp_value == 1);
tcp_ecn_flags ::= irregular(2);
};
format_unused =
{
let(ecn_used:uncomp_value == 0);
tcp_ecn_flags ::= static;
};
};
tcp_res_flags_enc ===
{
uncompressed_format = tcp_res_flags; %[ 4 ]
format_irreg = tcp_res_flags, %[ 4 ]
{
let(ecn_used:uncomp_value == 1);
tcp_res_flags ::= irregular(4);
};
format_unused =
{
let(ecn_used:uncomp_value == 0);
tcp_res_flags ::= uncompressed_value(4, 0);
};
};
tcp_irreg_ip_ecn ===
{
uncompressed_format = ip_ecn_flags; %[ 2 ]
format_tc_present = ip_ecn_flags, %[ 2 ]
{
let(ecn_used:uncomp_value == 1);
ip_ecn_flags ::= compressed_value(2, ip_inner_ecn:uncomp_value);
};
format_tc_not_present = ip_ecn_flags, %[ 0 ]
{
let(ecn_used:uncomp_value == 0);
ip_inner_ecn ::= static; % Global control field
ip_ecn_flags ::= compressed_value(0,0); % Nothing transmit
};
};
rsf_index_enc ===
{
uncompressed_format = rsf_flag; %[ 3 ]
format_none = rsf_idx, %[ 2 ]
{
rsf_idx ::= '00';
rsf_flag ::= uncompressed_value (3, 0x00);
};
format_rst_only = rsf_idx, %[ 2 ]
{
rsf_idx ::= '01';
rsf_flag ::= uncompressed_value (3, 0x01);
};
format_syn_only = rsf_idx, %[ 2 ]
{
rsf_idx ::= '10';
rsf_flag ::= uncompressed_value (3, 0x02);
};
format_fin_only = rsf_idx, %[ 2 ]
{
rsf_idx ::= '11';
rsf_flag ::= uncompressed_value (3, 0x04);
};
};
optional_2bit_padding(used_flag) ===
{
uncompressed_format = padding; % 0 or 2 bits
format_used = padding, %[ 2 ]
{
let(used_flag == 1);
padding ::= compressed_value (2, 0x0);
};
format_unused = padding,
{
let(used_flag == 0);
padding ::= compressed_value (0, 0x0);
};
};
tcp ===
{
uncompressed_format = src_port, %[ 16 ]
dst_port, %[ 16 ]
rsf_flags, %[ 3 ]
psh_flag, %[ 1 ]
urg_flag, %[ 1 ]
ack_flag, %[ 1 ]
data_offset, %[ 4 ]
tcp_res_flags,%[ 4 ]
tcp_ecn_flags,%[ 2 ]
urg_ptr, %[ 16 ]
window, %[ 16 ]
checksum, %[ 16 ]
seq_number, %[ 32 ]
ack_number, %[ 32 ]
options; % n bits
default_methods =
{
src_port ::= static;
dst_port ::= static;
seq_number ::= static;
ack_number ::= static;
rsf_flags ::= static;
psh_flag ::= irregular (1);
urg_flag ::= static;
ack_flag ::= uncompressed_value (1, 1);
urg_ptr ::= static;
window ::= static;
checksum ::= irregular (16);
tcp_ecn_flags ::= static;
tcp_res_flags ::= static;
};
format_tcp_static = src_port, %[ 16 ]
dst_port, %[ 16 ]
{
src_port ::= irregular(16);
dst_port ::= irregular(16);
};
format_tcp_dynamic = ecn_used, %[ 1 ]
ack_stride_zero, %[ 1 ]
ack_zero, %[ 1 ]
urp_zero, %[ 1 ]
tcp_res_flags, %[ 4 ]
tcp_ecn_flags, %[ 2 ]
urg_flag, %[ 1 ]
ack_flag, %[ 1 ]
psh_flag, %[ 1 ]
rsf_flags, %[ 3 ]
msn, %[ 16 ]
seq_number, %[ 32 ]
ack_number, % 0 or 32 bits
window, %[ 16 ]
checksum, %[ 16 ]
urg_ptr, % 0 or 16 bits
ack_stride, % 0 or 16 bits
options, % n bits
{
ecn_used ::= irregular (1);
ack_stride_zero ::= irregular (1);
ack_zero ::= irregular (1);
urp_zero ::= irregular (1);
ack_flag ::= irregular (1);
urg_flag ::= irregular (1);
psh_flag ::= irregular (1);
tcp_ecn_flags ::= irregular (2);
padding ::= '0';
rsf_flags ::= irregular (3);
tcp_res_flags ::= irregular (4);
msn ::= irregular (16);
seq_number ::= irregular (32);
window ::= irregular (16);
checksum ::= irregular (16);
urg_ptr ::= zero_or_irr16_enc(urp_zero);
ack_number ::= ack_enc_dyn(ack_zero);
ack_stride ::= zero_or_irr16_enc(ack_stride_zero);
options ::= list_tcp_options(list_length);
};
format_tcp_replicate = reserved, %[ 3 ]
list_present, %[ 1 ]
src_port_presence, %[ 2 ]
dst_port_presence, %[ 2 ]
ack_number, %[ 1 ]
urp_presence, %[ 1 ]
urg_flag, %[ 1 ]
ack_flag, %[ 1 ]
psh_flag, %[ 1 ]
rsf_flags, %[ 2 ]
ecn_used, %[ 1 ]
msn, %[ 16 ]
seq_number, %[ 32 ]
src_port, % 0, 8 or 16 bits
dst_port, % 0, 8 or 16 bits
urg_point, % 0 or 16 bits
ack_number, % 0 or 32 bits
ecn_padding, % 0 or 2 bits
tcp_res_flags, % 0 or 4 bits
tcp_ecn_flags, % 0 or 2 bits
options_list, % n bits
{
reserved ::= '000';
options_replicate ::= irregular (1);
msn ::= irregular (16);
urg_flag ::= irregular (1);
ack_flag ::= irregular (1);
psh_flag ::= irregular (1);
rsf_flags ::= rsf_index_enc;
ecn_used ::= irregular (1);
src_port ::= port_replicate(src_port_presence);
dst_port ::= port_replicate(dst_port_presence);
seq_number ::= irregular(32);
ack_number ::= static_or_irreg32(ack_presence);
window ::= static_or_irreg16(window_presence);
urg_point ::= static_or_irreg16(urp_presence);
ecn_padding ::= optional_2bit_padding(ecn_used);
tcp_res_flags ::= tcp_res_flags_enc;
tcp_ecn_flags ::= tcp_ecn_flags_enc;
options_list ::= tcp_list_presence_enc
((data_offset:uncomp_value + 20) / 4,
list_present);
};
% ECN from innermost IP header is taken from global control field.
format_tcp_irregular = ip_ecn_flags, % 0 or 2 bits
tcp_res_flags, % 0 or 4 bits
tcp_ecn_flags, % 0 or 2 bits
checksum, %[ 16 ]
{
ip_ecn_flags ::= tcp_irreg_ip_ecn;
tcp_ecn_flags ::= tcp_ecn_flags_enc;
tcp_res_flags ::= tcp_res_flags_enc;
checksum ::= irregular (16);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Structures used in compressed base headers
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
tos_tc_enc(flag) ===
{
uncompressed_format = tos_tc; %[ 6 ]
format_static = tos_tc, %[ 0 ]
{
let (flag == 0);
tos_tc ::= static;
};
format_irreg = tos_tc, %[ 6 ]
padding,
{
let (flag == 1);
tos_tc ::= irregular(6);
padding ::= compressed_value (2, 0);
};
};
ip_id_lsb (behavior, k, p) ===
{
uncompressed_format = ip_id; %[ 16 ]
default_methods =
{
let (ip_id:uncomp_length == 16);
};
format_nbo = ip_id_offset, % k bits
{
let (behavior == 0);
let (ip_id_offset:uncomp_value ==
ip_id:uncomp_value - msn:uncomp_value);
let (ip_id_offset:uncomp_length == 16);
ip_id_offset ::= lsb (k, p);
};
format_non_nbo = ip_id_offset, % k bits
{
let (behavior == 1);
let (ip_id_nbo:uncomp_value ==
(ip_id:uncomp_value / 256) + (ip_id:uncomp_value & 255) * 256);
let (ip_id_nbo:uncomp_length == 16);
let (ip_id_offset:uncomp_value ==
ip_id_nbo:uncomp_value - msn:uncomp_value);
let (ip_id_offset:uncomp_length == 16);
ip_id_offset ::= lsb (k, p);
};
};
dont_fragment(version) ===
{
uncompressed_format = df; %[ 1 ]
compressed_format_v4 = df, %[ 1 ]
{
let (version == 4);
df ::= irregular(1);
};
compressed_format_v6 = df,
{
let (version == 6);
df ::= compressed_value(1,0);
};
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 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 an "output argument" that should be passed to the
% processing of the irregular chain for outer IP headers.
co_baseheader(payload_size, ttl_irregular_chain_flag) ===
{
uncompressed_format_v4 = version,
header_length,
tos_tc,
ip_ecn_flags,
length,
ip_id,
df,
mf,
rf,
frag_offset,
ttl_hopl,
next_header,
checksum,
src_addr,
dest_addr,
src_port,
dest_port,
seq_number,
ack_number,
data_offset,
tcp_res_flags,
tcp_ecn_flags,
urg_flag,
ack_flag,
psh_flag,
rsf_flags,
tcp_checksum,
urg_ptr,
window,
tcp_options,
{
let (version:uncomp_value == 4);
};
uncompressed_format_v6 = version,
tos_tc,
ip_ecn_flags,
flow_label,
payload_length,
next_header,
ttl_hopl,
src_addr,
dest_addr,
src_port,
dest_port,
seq_number,
ack_number,
data_offset,
tcp_res_flags,
tcp_ecn_flags,
urg_flag,
ack_flag,
psh_flag,
rsf_flags,
tcp_checksum,
urg_ptr,
window,
tcp_options,
{
let (version:uncomp_value == 6);
};
control_fields = ip_id_behavior; % 2 bits
default_methods =
{
version ::= static;
tos_tc ::= static;
ip_ecn_flags ::= static;
ttl_hopl ::= static;
next_header ::= static;
src_addr ::= static;
dest_addr ::= static;
flow_label ::= static;
header_length ::= uncompressed_value (4,5);
length ::= inferred_ip_v4_length;
ip_id ::= irregular(16);
rf ::= static;
df ::= static;
mf ::= static;
frag_offset ::= static;
checksum ::= inferred_ip_checksum;
src_port ::= static;
dest_port ::= static;
seq_number ::= static;
ack_number ::= static;
data_offset ::= inferred_offset;
tcp_ecn ::= static;
psh_flag ::= irregular (1);
urg_flag ::= uncompressed_value (1, 0);
ack_flag ::= uncompressed_value (1, 1);
window ::= static;
tcp_checksum ::= irregular(16);
urg_ptr ::= static;
rsf_flags ::= uncompressed_value (3, 0);
let (version:uncomp_length == 4);
let (seq_number_scaled:uncomp_value ==
seq_number:uncomp_value / payload_size);
let (seq_number_residue:uncomp_value ==
mod(seq_number:uncomp_value, payload_size));
let (ack_number:uncomp_value ==
(ack_stride:uncomp_value * ack_number_scaled:uncomp_value) +
ack_number_residue:uncomp_value);
let (ack_number_residue:uncomp_value ==
mod(ack_number:uncomp_value, ack_stride:uncomp_value));
};
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Common compressed packet format
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
format_co_common = discriminator, %[ 7 ]
ttl_hopl_outer_flag, %[ 1 ]
ack_flag, %[ 1 ]
psh_flag, %[ 1 ]
rsf_flags, %[ 2 ]
msn, %[ 4 ]
seq_indicator, %[ 2 ]
ack_indicator, %[ 2 ]
ack_stride_indicator,%[ 1 ]
window_indicator, %[ 1 ]
ip_id_indicator, %[ 2 ]
urg_ptr_present, %[ 1 ]
ecn_used, %[ 1 ]
tos_tc_present, %[ 1 ]
ttl_hopl_present, %[ 1 ]
list_present, %[ 1 ]
ip_id_behavior, %[ 2 ]
urg_flag, %[ 1 ]
df, %[ 1 ]
header_crc, %[ 7 ]
seq_number, % 0, 8, 16, 32 bits
ack_number, % 0, 8, 16, 32 bits
ack_stride, % 0 or 16 bits
window, % 0 or 16 bits
ip_id, % 0, 8, 16 bits
urg_ptr, % 0 or 16 bits
tos_tc, % 0 or 8 bits
ttl_hopl, % 0 or 8 bits
options_list, % n bits
{
discriminator ::= '1111101';
ttl_hopl_outer_flag::= irregular(1);
% Need to bind argument so that user can pass it on to the
% structure for IPv4/IPv6 irregular chain.
let(ttl_irregular_chain_flag:uncomp_value == ttl_hopl_outer_flag);
tos_tc_present ::= irregular(1);
ttl_hopl_present ::= irregular(1);
ack_flag ::= irregular(1);
psh_flag ::= irregular(1);
msn ::= lsb (4, 3);
df ::= dont_fragment(version:uncomp_value);
header_crc ::= crc7(this:uncomp_value,
this:uncomp_length);
urg_flag ::= irregular(1);
urg_ptr_present ::= irregular(1);
ecn_used ::= irregular(1);
list_present ::= irregular(1);
ip_id_behavior ::= ip_id_behavior_enc;
rsf_flags ::= rsf_index_enc;
window_indicator ::= irregular(1);
ip_id_indicator ::= irregular(2);
seq_indicator ::= irregular(2);
ack_indicator ::= irregular(2);
ack_stride_indicator ::= irregular(1);
seq_number ::= variable_length_32_enc(seq_indicator);
ack_number ::= variable_length_32_enc(ack_indicator);
ack_stride ::= static_or_irreg16(ack_stride_indicator);
window ::= static_or_irreg16(window_indicator);
ip_id ::= variable_length_16_enc(ip_id_indicator);
urg_ptr ::= static_or_irreg16(urg_ptr_present);
ttl_hops ::= static_or_irreg8(ttl_hopl_present);
tos_tc ::= tos_tc_enc(tos_tc_present);
options_list ::= tcp_list_presence_enc
((data_offset:uncomp_value + 20) / 4,
list_present);
};
% 0 1 2 3 4 5 6 7
% +---+---+---+---+---+---+---+---+
% | 1 1 1 1 1 0 1 |tho| tho controls irregular chain TTL/Hoplimit
% +===+===+===+===+===+===+===+===+
% |ACK|PSH| RSF | MSN |
% +---+---+---+---+---+---+---+---+
% | sn | a_sn |ast|win| ip_id |
% +---+---+---+---+---+---+---+---+
% |urg|ecn|tos|ttl|lst|IPIDbeh|URG|
% +---+---+---+---+---+---+---+---+
% |DF | CRC |
% +---+---+---+---+---+---+---+---+
% / SN / 0, 8, 16, 32 bits, indicated by sn
% --- --- --- --- --- --- --- ---
% / ACK_SN / 0, 8, 16, 32 bits, indicated by a_sn
% --- --- --- --- --- --- --- ---
% / ACK_STRIDE / 0 or 16 bits, indicated by ast
% --- --- --- --- --- --- --- ---
% / WINDOW / 0 or 16 bits, indicated by win
% --- --- --- --- --- --- --- ---
% / IP-ID / 0, 8, 16 bits, indicated by ip_id
% --- --- --- --- --- --- --- ---
% / URG-PTR / 16 bits, if urg=1
% --- --- --- --- --- --- --- ---
% /IP-ECN |TCP-ECN| TCP_RES / 8 bits, if ecn=1
% --- --- --- --- --- --- --- ---
% / TOS / 8 bits, if tos=1
% --- --- --- --- --- --- --- ---
% / TTL / 8 bits, if ttl=1
% --- --- --- --- --- --- --- ---
% / options_list / n*8 bits, if lst=1
% --- --- --- --- --- --- --- ---
% NON-SEQUENTIAL PACKET FORMATS
% +------+--------+-----+-----+-----+---------+---------+
% |Name |Disc |MSN |SN |ACK |Window |Comment |
% +------+--------+-----+-----+-----+---------+---------+
% |_1 |10111110|4 |16 |0 | | |
% +------+--------+-----+-----+-----+---------+---------+
% |_2 |1100 |4 |*4 |0 | | |
% +------+--------+-----+-----+-----+---------+---------+
% |_3 |0 |4 |0 |15 | | |
% +------+--------+-----+-----+-----+---------+---------+
% |_4 |1101 |4 |0 |4* | | |
% +------+--------+-----+-----+-----+---------+---------+
% |_5 |100 |4 |14 |15 | | |
% +------+--------+-----+-----+-----+---------+---------+
% |_6 |10110 |4 |*4 |15 | | |
% +------+--------+-----+-----+-----+---------+---------+
% |_7 |1010 |4 |14 |0 |14 | |
% +------+--------+-----+-----+-----+---------+---------+
% |_8 |10111111|4 |0 |16 |16 | |
% +------+--------+-----+-----+-----+---------+---------+
% |_9 |101110 |4 |*4 |0 |14 | |
% +------+--------+-----+-----+-----+---------+---------+
% |_10 |1011110 |4 |14 |16 | |and more |
% +------+--------+-----+-----+-----+---------+---------+
% Send LSBs of sequence number
format_rnd_1 = discriminator, %[ 8 ]
seq_number, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '10111110';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
seq_number ::= lsb(16, 32767);
};
% 0 1 2 3 4 5 6 7
% +---+---+---+---+---+---+---+---+
% | 1 0 1 1 1 1 1 0 |
% +===+===+===+===+===+===+===+===+
% | SN... |
% +---+---+---+---+---+---+---+---+
% | ...SN |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send scaled sequence number LSBs
format_rnd_2 = discriminator, %[ 4 ]
seq_number_scaled, %[ 4 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '1100';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
seq_number_scaled ::= lsb(4, 7);
seq_number_residue ::= static;
};
% 0 1 2 3 4 5 6 7
% +---+---+---+---+---+---+---+---+
% | 1 1 0 0 | SN_SCALED |
% +===+===+===+===+===+===+===+===+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send acknowledgement number LSBs
format_rnd_3 = discriminator, %[ 1 ]
ack_number, %[ 15 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '0';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number ::= lsb(15, 8191);
};
% 0 1 2 3 4 5 6 7
% +---+---+---+---+---+---+---+---+
% | 0 | ACK_SN... |
% +===+===+===+===+===+===+===+===+
% | ...ACK_SN |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send acknowledgement number scaled
format_rnd_4 = discriminator, %[ 4 ]
ack_number_scaled, %[ 4 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '1101';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number_scaled ::= lsb(4, 3);
ack_number_residue ::= static;
};
% 0 1 2 3 4 5 6 7
% +---+---+---+---+---+---+---+---+
% | 1 1 0 1 | ACK_SN_SCALED |
% +===+===+===+===+===+===+===+===+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send ACK and sequence number
format_rnd_5 = discriminator, %[ 3 ]
psh_flag, %[ 1 ]
msn, %[ 4 ]
header_crc, %[ 3 ]
seq_number, %[ 14 ]
ack_number, %[ 15 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '100';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number ::= lsb(15, 8191);
seq_number ::= lsb(14, 8191);
};
% 0 1 2 3 4 5 6 7
% +---+---+---+---+---+---+---+---+
% | 1 0 0 |PSH| MSN |
% +===+===+===+===+===+===+===+===+
% | MSN | CRC |A..|
% +---+---+---+---+---+---+---+---+
% | ...ACK_SN... |
% +---+---+---+---+---+---+---+---+
% |..A| SN... |
% +---+---+---+---+---+---+---+---+
% | ...SN |
% +---+---+---+---+---+---+---+---+
% Send both ACK and scaled sequence number LSBs
format_rnd_6 = discriminator, %[ 5 ]
header_crc, %[ 3 ]
psh_flag, %[ 1 ]
ack_number, %[ 15 ]
msn, %[ 4 ]
seq_number_scaled, %[ 4 ],
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '10110';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number ::= lsb(15, 8191);
seq_number_scaled ::= lsb(4, 7);
seq_number_residue ::= static;
};
% +---+---+---+---+---+---+---+---+
% | 1 0 1 1 0 | CRC |
% +===+===+===+===+===+===+===+===+
% |PSH| ACK_SN... |
% +---+---+---+---+---+---+---+---+
% | ...ACK_SN... |
% +---+---+---+---+---+---+---+---+
% | MSN | SN_SCALED |
% +---+---+---+---+---+---+---+---+
% Send sequence number and window
format_rnd_7 = discriminator, %[ 4 ]
seq_number, %[ 14 ]
window, %[ 14 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '1010';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
seq_number ::= lsb(14, 8191);
window ::= lsb(14, 8191);
};
% +---+---+---+---+---+---+---+---+
% | 1 0 1 0 | SN... |
% +===+===+===+===+===+===+===+===+
% | SN...
% +---+---+---+---+---+---+---+---+
% | ...SN | WINDOW... |
% +---+---+---+---+---+---+---+---+
% | WINDOW |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send ACK and window
format_rnd_8 = discriminator, %[ 8 ]
ack_number, %[ 16 ]
window, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '10111111';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number ::= lsb(16, 16383);
window ::= irregular(16);
};
% +---+---+---+---+---+---+---+---+
% | 1 0 1 1 1 1 1 1 |
% +===+===+===+===+===+===+===+===+
% | |
% + ACK_SN +
% | |
% +---+---+---+---+---+---+---+---+
% | |
% + WINDOW +
% | |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send scaled sequence number and window.
format_rnd_9 = discriminator, %[ 6 ]
seq_number_scaled, %[ 4 ]
window, %[ 14 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '101110';
msn ::= lsb(4, 4);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
window ::= lsb(14, 8191);
seq_number_scaled ::= lsb(4, 3);
seq_number_residue ::= static;
};
% +---+---+---+---+---+---+---+---+
% | 1 0 1 1 1 0 |SN_SC..|
% +===+===+===+===+===+===+===+===+
% |..SN_SC| WINDOW... |
% +---+---+---+---+---+---+---+---+
% | ...WINDOW |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% A packet halfway between co_common and compressed packets
% Can send LSBs of TTL, RSF flags, change ECN behavior and options list
format_rnd_10 = discriminator, %[ 7 ]
ecn_used, %[ 1 ]
list_present, %[ 1 ]
header_crc, %[ 7 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
ttl_hopl, %[ 3 ]
rsf_flags, %[ 2 ]
seq_number, %[ 14 ]
ack_number, %[ 16 ]
options_list, % 0 or X bits
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '1011110';
msn ::= lsb(4, 4);
header_crc ::= crc7 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
list_present ::= irregular(1);
options_list ::= tcp_list_presence_enc
((data_offset:uncomp_value + 20) / 4,
list_present);
rsf_flags ::= rsf_index_enc;
ecn_used ::= irregular(1);
ttl_hopl ::= lsb(3, 3);
seq_number ::= lsb(14, 8191);
ack_number ::= lsb(16, 16383);
};
% +---+---+---+---+---+---+---+---+
% | 1 0 1 1 1 1 1 |ECN|
% +===+===+===+===+===+===+===+===+
% |lst| CRC |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| TTL |
% +---+---+---+---+---+---+---+---+
% | RSF | SN... |
% +---+---+---+---+---+---+---+---+
% | ..SN |
% +---+---+---+---+---+---+---+---+
% | |
% + ACK_SN +
% | |
% +---+---+---+---+---+---+---+---+
% / options_list / n*8 bits, if lst=1
% --- --- --- --- --- --- --- ---
% SEQUENTIAL PACKET FORMATS
% +------+------+-----+-----+-----+-----+-----+---------+
% |Name |Disc |MSN |ID |SN |ACK |Win |Comment |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_1 |1010 |4 |4 |16 |0 | | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_2 |11001 |4 |7 |*4 |0 | | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_3 |1001 |4 |4 |0 |16 | | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_4 |0 |4 |3 |0 |*4 | | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_5 |1000 |4 |4 |16 |16 | | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_6 |110110|4 |6 |*4 |16 | | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_7 |11010 |4 |5 |14 |0 |16 | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_8 |11000 |4 |5 |0 |16 |14 | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_9 |110111|4 |6 |*4 |0 |16 | |
% +------+------+-----+-----+-----+-----+-----+---------+
% |_10 |1011 |4 |4 |14 |15 | |and more |
% +------+------+-----+-----+-----+-----+-----+---------+
% Send LSBs of sequence number
format_seq_1 = discriminator, %[ 4 ]
ip_id, %[ 4 ]
seq_number, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '1010';
msn ::= lsb(4, 4);
ip_id ::= ip_id_lsb (ip_id_behavior, 4, 3);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
seq_number ::= lsb(16, 32767);
};
% +---+---+---+---+---+---+---+---+
% | 1 0 1 0 | IP-ID |
% +===+===+===+===+===+===+===+===+
% | |
% + SN +
% | |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send scaled sequence number LSBs
format_seq_2 = discriminator, %[ 5 ]
ip_id, %[ 7 ]
seq_number_scaled, %[ 4 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '11001';
msn ::= lsb(4, 4);
ip_id ::= ip_id_lsb (ip_id_behavior, 7, 3);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
seq_number_scaled ::= lsb(4, 7);
seq_number_residue ::= static;
};
% +---+---+---+---+---+---+---+---+
% | 1 1 0 0 1 | IP-ID... |
% +===+===+===+===+===+===+===+===+
% | ...IP-ID | SN_SCALED |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send acknowledgement number LSBs
format_seq_3 = discriminator, %[ 4 ]
ip_id, %[ 4 ]
ack_number, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '1001';
msn ::= lsb(4, 4);
ip_id ::= ip_id_lsb (ip_id_behavior, 4, 3);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number ::= lsb(16, 16383);
};
% +---+---+---+---+---+---+---+---+
% | 1 0 0 1 | IP-ID |
% +===+===+===+===+===+===+===+===+
% | |
% + ACK_SN +
% | |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send scaled acknowledgement number scaled
format_seq_4 = discriminator, %[ 1 ]
ack_number_scaled,%[ 4 ]
ip_id, %[ 3 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '0';
msn ::= lsb(4, 4);
% Note that due to having very few ip_id bits, no reordering offset
ip_id ::= ip_id_lsb (ip_id_behavior, 3, 1);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number_scaled ::= lsb(4, 3);
ack_number_residue ::= static;
};
% +---+---+---+---+---+---+---+---+
% | 0 | ACK_SN_SCALED | IP-ID |
% +===+===+===+===+===+===+===+===+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send ACK and sequence number
format_seq_5 = discriminator, %[ 4 ]
ip_id, %[ 4 ]
ack_number, %[ 16 ]
seq_number, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '1000';
msn ::= lsb(4, 4);
ip_id ::= ip_id_lsb (ip_id_behavior, 4, 3);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number ::= lsb(16, 16383);
seq_number ::= lsb(16, 32767);
};
% +---+---+---+---+---+---+---+---+
% | 1 0 0 0 | IP-ID |
% +===+===+===+===+===+===+===+===+
% | |
% + ACK_SN +
% | |
% +---+---+---+---+---+---+---+---+
% | |
% + SN +
% | |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send both ACK and scaled sequence number LSBs
format_seq_6 = discriminator, %[ 6 ]
seq_number_scaled, %[ 4 ]
ip_id, %[ 6 ]
ack_number, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '110110';
seq_number_scaled ::= lsb(4, 7);
seq_number_residue ::= static;
ip_id ::= ip_id_lsb (ip_id_behavior, 6, 3);
ack_number ::= lsb(16, 16383);
msn ::= lsb(4, 4);
psh_flag ::= irregular (1);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
};
% +---+---+---+---+---+---+---+---+
% | 1 1 0 1 0 0 |SN_SC..|
% +===+===+===+===+===+===+===+===+
% |..SN_SC| IP-ID |
% +---+---+---+---+---+---+---+---+
% | |
% + ACK_SN +
% | |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send sequence number and window
format_seq_7 = discriminator, %[ 5 ]
seq_number, %[ 14 ]
ip_id, %[ 5 ]
window, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '11010';
msn ::= lsb(4, 4);
ip_id ::= ip_id_lsb (ip_id_behavior, 5, 3);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
seq_number ::= lsb(14, 8191);
window ::= irregular(16);
};
% +---+---+---+---+---+---+---+---+
% | 1 1 0 1 0 | SN.. |
% +===+===+===+===+===+===+===+===+
% | ..SN.. |
% +---+---+---+---+---+---+---+---+
% | ..SN | IP-ID |
% +---+---+---+---+---+---+---+---+
% | |
% + WINDOW +
% | |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send ACK and window
format_seq_8 = discriminator, %[ 5 ]
window, %[ 14 ]
ip_id, %[ 5 ]
ack_number, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '110';
msn ::= lsb(4, 4);
ip_id ::= ip_id_lsb (ip_id_behavior, 5, 3);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
ack_number ::= lsb(16, 32767);
window ::= irregular(16);
};
% +---+---+---+---+---+---+---+---+
% | 1 1 0 0 0 | WINDOW.. |
% +===+===+===+===+===+===+===+===+
% | ..WINDOW.. |
% +---+---+---+---+---+---+---+---+
% | ..WINDOW | IP-ID |
% +---+---+---+---+---+---+---+---+
% | |
% + ACK +
% | |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% Send scaled sequence number and window.
format_seq_9 = discriminator, %[ 6 ]
ip_id, %[ 6 ]
seq_number_scaled, %[ 4 ]
window, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '00101';
msn ::= lsb(4, 4);
ip_id ::= ip_id_lsb (ip_id_behavior, 3, 3);
header_crc ::= crc3 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
window ::= lsb(11, 1023);
seq_number_scaled ::= lsb(5, 31);
seq_number_residue ::= static;
};
% +---+---+---+---+---+---+---+---+
% | 1 1 0 1 1 1 |IP-ID..|
% +===+===+===+===+===+===+===+===+
% | ..IP-ID | SN_SCALED |
% +---+---+---+---+---+---+---+---+
% | |
% + WINDOW +
% | |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| CRC |
% +---+---+---+---+---+---+---+---+
% A packet halfway between co_common and compressed packets
% Can send LSBs of TTL, RSF flags, change ECN behavior and options list
format_seq_10 = discriminator, %[ 4 ]
ip_id, %[ 4 ]
list_present, %[ 1 ]
header_crc, %[ 7 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
ttl_hopl, %[ 3 ]
ecn_used, %[ 1 ]
ack_number, %[ 15 ]
rsf_flags, %[ 2 ]
seq_number, %[ 14 ]
options_list, % Nx8 bits
{
let ((ip_id_behavior:uncomp_value == 2) ||
(ip_id_behavior:uncomp_value == 3));
discriminator ::= '1011';
msn ::= lsb(4, 4);
ip_id ::= ip_id_lsb (ip_id_behavior, 4, 3);
header_crc ::= crc7 (this:uncomp_value,
this:uncomp_length);
psh_flag ::= irregular (1);
list_present ::= irregular(1);
options_list ::= tcp_list_presence_enc
((data_offset:uncomp_value + 20) / 4,
list_present);
rsf_flags ::= rsf_index_enc;
ecn_used ::= irregular(1);
ttl_hopl ::= lsb(3, 3);
seq_number ::= lsb(14, 8191);
ack_number ::= lsb(15, 8191);
};
% +---+---+---+---+---+---+---+---+
% | 1 0 1 1 | IP-ID |
% +===+===+===+===+===+===+===+===+
% |lst| CRC |
% +---+---+---+---+---+---+---+---+
% | MSN |PSH| TTL |
% +---+---+---+---+---+---+---+---+
% |ECN| ACK_SN... |
% +---+---+---+---+---+---+---+---+
% | ..ACK_SN |
% +---+---+---+---+---+---+---+---+
% | RSF | SN.. |
% +---+---+---+---+---+---+---+---+
% | ..SN |
% +---+---+---+---+---+---+---+---+
% / options_list / n*8 bits, if lst=1
% --- --- --- --- --- --- --- ---
};
_______________________________________________
Rohc mailing list
Rohc at ietf.org
https://www1.ietf.org/mailman/listinfo/rohc