[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[rohc] FN let statements and TCP packet formats (was: Updated FN Draft - Appendix A)
> You say that sometimes you do not know whether it will be only an
> "if", but I have not seen an example of when this is really needed.
> I'm still waiting for a realistic example of when one would have
> to have that. Just because the current definition of let allows that
> does not mean it is really needed.
OK, so let's go for proof by contradiction. I'll go through the current
tcp-profile and replace each occurrence of "let" with either an assignment,
or an if statement. Then if the meaning is changed from that in the current
profile, somebody needs to shout up and say why it's wrong. Otherwise I
agree with you that "if" and assignment are clearer: whilst it goes against
the grain for me personally, is probably the better solution.
To be as clear as possible, I've used "when" for the non-binding conditional
case, and ordinary assignment syntax (i.e. single equals sign) for
assignment. Here goes:
static_or_irreg32(flag) ===
{
uc_format = field; %[ 32 ]
co_format_irreg_enc = field, %[ 32 ]
{
when (flag == 1);
field ::= irregular(32);
};
co_format_static_enc = field, %[ 0 ]
{
when (flag == 0);
field ::= static;
};
};
Similarly for static_or_irreg16(flag), static_or_irreg8(flag).
variable_length_32_enc(flag) ===
{
uc_format = field; %[ 32 ]
co_format_not_present = field, %[ 0 ]
{
when(flag == 0);
field ::= static;
};
co_format_8_bit = field, %[ 8 ]
{
when(flag == 1);
field ::= lsb(8, 63);
};
co_format_16_bit = field, %[ 16 ]
{
when(flag == 2);
field ::= lsb(16, 16383);
};
co_format_32_bit = field, %[ 32 ]
{
when(flag == 3);
field ::= irregular(32);
};
};
Similarly for variable_length_16_enc(flag).
optional32(flag) ===
{
uc_format = item; % 0 or 32 bits
co_format_present = item, %[ 32 ]
{
when(flag == 1);
item ::= irregular (32);
};
co_format_not_present = item, %[ 0 ]
{
when(flag == 0);
item ::= compressed_value (0, 0);
};
};
opt_lsb_7_or_31 (flag) ===
{
uc_format = item; % 32 bits
co_format_present = item, % 8 or 32 bits
{
when (flag == 1);
item ::= lsb_7_or_31;
};
co_format_not_present = item, %[ 0 ]
{
when (flag == 0);
item ::= compressed_value (0, 0);
};
};
optional_checksum (flag_value) ===
{
uc_format = value, % 0 or 16 bits
reserved1; % 0 or 16 bits
co_format_cs_present = value, %[ 16 ]
reserved1, %[ 0 ]
{
when(flag_value == 1);
value ::= irregular (16);
reserved1 ::= uncompressed_value (16, 0);
};
co_format_not_present = value, %[ 0 ]
reserved1, %[ 0 ]
{
when(flag_value == 0);
value ::= compressed_value (0, 0);
reserved1 ::= compressed_value (0, 0);
};
};
irreg_tos_tc ===
{
uc_format = tos_tc; %[ 6 ]
co_format_tos_tc_present = tos_tc, %[ 6 ]
{
when(ecn_used:uncomp_value == 1);
tos_tc ::= irregular (6);
};
co_format_tos_tc_not_present = tos_tc, %[ 0 ]
{
when(ecn_used:uncomp_value == 0);
tos_tc ::= static;
};
};
Similarly for ip_irreg_ecn.
co_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;
when(ttl_irregular_chain_flag == 0);
};
co_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;
when(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.
co_format_ipv6_innermost_irregular =
{
ip_inner_ecn:uncomp_value = ip_ecn_flags:uncomp_value;
};
ip_id_enc_dyn (behavior) ===
{
uc_format = ip_id; %[ 16 ]
co_format_ip_id_seq = ip_id, %[ 16 ]
{
when((behavior == 0) || (behavior == 1) || (behavior == 2));
% In dynamic chain, but random, seq, and seq-swapped are 16
bits
ip_id ::= irregular(16);
};
co_format_ip_id_zero = ip_id, %[ 0 ]
{
when(behavior == 3);
% Zero IPID
ip_id ::= uncompressed_value (16, 0);
};
};
ip_id_enc_irreg (behavior) ===
{
uc_format = ip_id; %[ 16 ]
co_format_ip_id_seq = ip_id, %[ 0 ]
{
when(behavior == 0); % sequential
ip_id ::= static; % Nothing to send in irregular chain
};
co_format_ip_id_seq_swapped = ip_id, %[ 0 ]
{
when(behavior == 1); % sequential-swapped
ip_id ::= static; % Nothing to send in irregular chain
};
co_format_ip_id_rand = ip_id, %[ 16 ]
{
when(behavior == 2); % random
ip_id ::= irregular (16);
};
co_format_ip_id_zero = ip_id, %[ 0 ]
{
when(behavior == 3); % zero
ip_id ::= uncompressed_value (16, 0);
};
};
ip_id_behavior_enc ===
{
uc_format = ip_id_behavior; %[ 2 ]
default_methods =
{
ip_id_behavior ::= irregular(2);
};
co_format_sequential = ip_id_behavior, %[ 2 ]
{
ip_id_behavior:uncomp_value = 0b00;
};
co_format_sequential_swapped = ip_id_behavior, %[ 2 ]
{
ip_id_behavior:uncomp_value = 0b01;
};
co_format_random = ip_id_behavior, %[ 2 ]
{
ip_id_behavior:uncomp_value = 0b10;
};
co_format_zero = ip_id_behavior, %[ 2 ]
{
ip_id_behavior:uncomp_value = 0b11;
};
};
As an aside, I think this format has a bug in it (see separate post).
co_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:uncomp_value);
tos_tc ::= irreg_tos_tc;
ip_ecn_flags ::= ip_irreg_ecn;
when(ttl_irregular_chain_flag == 0);
};
co_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:uncomp_value);
tos_tc ::= irreg_tos_tc;
ip_ecn_flags ::= ip_irreg_ecn;
when(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.
co_format_ipv4_innermost_irregular = ip_id, % 0 or 16 bits
{
ip_id_behavior ::= static;
ip_id ::= ip_id_enc_irreg
(ip_id_behavior:uncomp_value);
ip_inner_ecn:uncomp_value = ip_ecn_flags:uncomp_value;
};
tcp_opt_eol(nbits) ===
{
uc_format = type, %[ 8 ]
padding; % (nbits - 8) bits
default_methods =
{
type ::= uncompressed_value(8, 0);
pad_len ::= static;
padding ::= uncompressed_value (nbits - 8, 0);
};
co_format_eol_list_item = pad_len, % 8 bits
padding, %[ 0 ]
{
pad_len ::= compressed_value(8, nbits - 8);
};
co_format_eol_irregular =
{
pad_len:uncomp_value = nbits - 8;
};
};
Again I think this has a bug in it in that the default static encoding will
never be used.
sack_var_length_enc (base) ===
{
uc_format = sack_field; %[ 32 ]
default_methods =
{
sack_offset:uncomp_value = sack_field:uncomp_value - base;
sack_offset:uncomp_length = 32;
sack_field:uncomp_length = 32;
};
co_format_lsb_15 = discriminator, %[ 1 ]
sack_offset, %[ 15 ]
{
discriminator ::= '0';
sack_offset ::= lsb (15, -1);
};
co_format_lsb_22 = discriminator, %[ 2 ]
sack_offset, %[ 22 ]
{
discriminator ::= '10';
sack_offset ::= lsb (22, -1);
};
co_format_lsb_30 = discriminator, %[ 2 ]
sack_offset, %[ 30 ]
{
discriminator ::= '11';
sack_offset ::= lsb (30, -1);
};
};
co_format_sack1_list_item = discriminator,
block_1,
{
when(length:uncomp_value == 10);
discriminator ::= '00000001';
block_1 ::= tcp_opt_sack_block (ack_value);
};
Similarly for other sack list items
tcp_opt_generic ===
{
uc_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;
option_static:uncomp_length = 1;
};
co_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
co_format_generic_irregular_static =
{
option_static:uncomp_value = 1;
};
% An item that can change, but currently is unchanged
co_format_generic_irregular_stable = discriminator, %[ 8 ]
{
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.
co_format_generic_irregular_full = discriminator, %[ 8 ]
contents, % n bits
{
option_static:uncomp_value = 0;
discriminator ::= '00000000';
contents ::= irregular (length_lsb:uncomp_value * 8 -
16);
};
};
list_tcp_options(nbits, ack_value) === {
uc_format = item, tail;
default_methods = {
when(nbits >= item:uncomp_length);
tail ::= list_tcp_options(nbits - item:uncomp_length, ack_value);
};
co_format_list_end = {
when(nbits == 0);
item ::= irregular(0);
tail ::= irregular(0);
};
co_format_eol = item, tail {
when(nbits == item:uncomp_length); % redundant
item ::= tcp_opt_eol(nbits);
tail ::= irregular(0);
};
:
:
Again, I think the "when" in default_methods here should be moved to the
uc_format encodings list.
tcp_list_presence_enc(list_length, presence, ack_value) ===
{
uc_format = tcp_options;
co_format_list_not_present = tcp_options, %[ 0 ]
{
when(presence == 0);
tcp_options ::= static;
};
co_format_list_present = tcp_options, % 8 + n*8 bits
{
when(presence == 1);
tcp_options ::= list_tcp_options(list_length, ack_value);
};
};
port_replicate(flags) ===
{
uc_format = port; %[ 16 ]
co_format_port_static_enc = port, %[ 0 ]
{
when(flags == 0b00);
port ::= static;
};
co_format_port_lsb8 = port, %[ 8 ]
{
when(flags == 0b01);
port ::= lsb (8, 64);
};
co_format_port_irr_enc = port, %[ 16 ]
{
when(flags == 0b10);
port ::= irregular (16);
};
};
zero_or_irr16_enc(flag) ===
{
uc_format = field; %[ 16 ]
co_format_non_zero = field, %[ 16 ]
{
when(flag == 0);
field ::= irregular (16);
};
co_format_zero = field, %[ 0 ]
{
when(flag == 1);
field ::= uncompressed_value (16, 0);
};
};
ack_enc_dyn(flag) ===
{
uc_format = ack_number; %[ 32 ]
co_format_ack_non_zero = ack_number, %[ 32 ]
{
when(flag == 0);
ack_number ::= irregular (32);
};
co_format_ack_zero = ack_number, %[ 0 ]
{
when(flag == 1);
ack_number ::= uncompressed_value (32, 0);
};
};
tcp_ecn_flags_enc ===
{
uc_format = tcp_ecn_flags; %[ 2 ]
co_format_irreg = tcp_ecn_flags, %[ 2 ]
{
when(ecn_used:uncomp_value == 1);
tcp_ecn_flags ::= irregular(2);
};
co_format_unused =
{
when(ecn_used:uncomp_value == 0);
tcp_ecn_flags ::= static;
};
};
tcp_res_flags_enc ===
{
uc_format = tcp_res_flags; %[ 4 ]
co_format_irreg = tcp_res_flags, %[ 4 ]
{
when(ecn_used:uncomp_value == 1);
tcp_res_flags ::= irregular(4);
};
co_format_unused =
{
when(ecn_used:uncomp_value == 0);
tcp_res_flags ::= uncompressed_value(4, 0);
};
};
tcp_irreg_ip_ecn ===
{
uc_format = ip_ecn_flags; %[ 2 ]
co_format_tc_present = ip_ecn_flags, %[ 2 ]
{
when(ecn_used:uncomp_value == 1);
ip_ecn_flags ::= compressed_value(2, ip_inner_ecn:uncomp_value);
};
co_format_tc_not_present = ip_ecn_flags, %[ 0 ]
{
when(ecn_used:uncomp_value == 0);
ip_inner_ecn ::= static; % Global control field
ip_ecn_flags ::= compressed_value(0,0); % Nothing transmit
};
};
optional_2bit_padding(used_flag) ===
{
uc_format = ;
co_format_used = padding, %[ 2 ]
{
when(used_flag == 1);
padding ::= compressed_value (2, 0x0);
};
co_format_unused = padding,
{
when(used_flag == 0);
padding ::= compressed_value (0, 0x0);
};
};
tos_tc_enc(flag) ===
{
uc_format = tos_tc; %[ 6 ]
co_format_static = tos_tc, %[ 0 ]
{
when(flag == 0);
tos_tc ::= static;
};
co_format_irreg = tos_tc, %[ 6 ]
padding, %[ 2 ]
{
when(flag == 1);
tos_tc ::= irregular(6);
padding ::= compressed_value (2, 0);
};
};
ip_id_lsb (behavior, k, p) ===
{
uc_format = ip_id; %[ 16 ]
default_methods =
{
ip_id:uncomp_length == 16;
};
co_format_nbo = ip_id_offset, % k bits
{
when(behavior == 0);
ip_id_offset:uncomp_value = ip_id:uncomp_value
- msn:uncomp_value;
ip_id_offset:uncomp_length = 16;
ip_id_offset ::= lsb (k, p);
};
co_format_non_nbo = ip_id_offset, % k bits
{
when(behavior == 1);
ip_id_nbo:uncomp_value = (ip_id:uncomp_value / 256)
+ (ip_id:uncomp_value & 255) * 256;
ip_id_nbo:uncomp_length = 16;
ip_id_offset:uncomp_value = ip_id_nbo:uncomp_value
- msn:uncomp_value;
ip_id_offset:uncomp_length = 16;
ip_id_offset ::= lsb (k, p);
};
};
Note there is an error here - the ip_id_offset is not specified as a control
field and yet it has an uncompressed side, which needs declaring. The above
example however is a great illustration of the benefit of L-E's idea - it
makes the profile considerably easier to read (IMHO).
dont_fragment(version) ===
{
uc_format = df; %[ 1 ]
co_format_v4 = df, %[ 1 ]
{
when(version == 4);
df ::= irregular(1);
};
co_format_v6 = df,
{
when(version == 6);
df ::= compressed_value(1,0);
};
};
co_baseheader(payload_size, ttl_irregular_chain_flag) ===
{
uc_format_v4 = version, %[ 4 ]
header_length, %[ 4 ]
:
options_list, % n bits
{
when(version:uncomp_value == 4);
};
uc_format_v6 = version, %[ 4 ]
tos_tc, %[ 6 ]
:
options_list, % n bits
{
when(version:uncomp_value == 6);
};
control_fields = ip_id_behavior; % 2 bits
default_methods =
{
version ::= static;
tos_tc ::= static;
:
:
version:uncomp_length = 4;
seq_number_scaled:uncomp_value =
seq_number:uncomp_value / payload_size;
seq_number_residue:uncomp_value =
mod(seq_number:uncomp_value, payload_size);
ack_number:uncomp_value =
(ack_stride:uncomp_value * ack_number_scaled:uncomp_value) +
ack_number_residue:uncomp_value;
ack_number_residue:uncomp_value =
mod(ack_number:uncomp_value, ack_stride:uncomp_value);
};
co_format_co_common = discriminator, %[ 7 ]
ttl_hopl_outer_flag, %[ 1 ]
:
:
{
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.
ttl_irregular_chain_flag = ttl_hopl_outer_flag:uncomp_value;
:
:
};
% Send LSBs of sequence number
co_format_rnd_1 = discriminator, %[ 8 ]
seq_number, %[ 16 ]
msn, %[ 4 ]
psh_flag, %[ 1 ]
header_crc, %[ 3 ]
{
when((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);
};
similarly for all other co_formats
_______________________________________________
Rohc mailing list
Rohc at ietf.org
https://www1.ietf.org/mailman/listinfo/rohc