← Back to team overview

rohc team mailing list archive

IP-ID handling in the ROHC TCP profile (Was: Re: rohc-lib 1.7.0 - problem with new return values (rohc_status_t) and lost tcp packets)

 

Hi Sean,
 
> > Any progress on the IP-ID patch?
> > 
> > I now have time to spend testing if you would like.
> 
> I didn't have time to look at it again. I'll retrieve the patch this
> weekend and send it to you so you can test it in its current state.

I re-worked the IP-ID patch to make it work again with the main branch.
It builds fine on x86 and all non-regression tests run fine too.

Tell me if it improves the situation for you.

Regards,
Didier
=== modified file 'src/comp/c_tcp.c'
--- src/comp/c_tcp.c	2014-06-23 21:17:33 +0000
+++ src/comp/c_tcp.c	2014-07-20 09:48:03 +0000
@@ -137,11 +137,12 @@ struct tcp_tmp_variables
 	size_t nr_opt_ts_reply_bits_0x40000;
 
 	uint16_t ip_id;
+	uint16_t ip_id_offset;
 	bool ip_id_behavior_changed;
-	bool ip_id_hi9_changed; /* TODO: replace by the number of required bits */
-	bool ip_id_hi11_changed; /* TODO: replace by the number of required bits */
-	bool ip_id_hi12_changed; /* TODO: replace by the number of required bits */
-	bool ip_id_hi13_changed; /* TODO: replace by the number of required bits */
+	/** The minimal number of bits required to encode the IP-ID with p = 1 */
+	size_t nr_ipid_bits_1;
+	/** The minimal number of bits required to encode the IP-ID with p = 3 */
+	size_t nr_ipid_bits_3;
 
 	uint8_t ttl_hopl;
 	int ttl_irregular_chain_flag;
@@ -411,6 +412,8 @@ struct sc_tcp_context
 	///        compression of packet
 	struct tcp_tmp_variables tmp;
 
+	struct c_wlsb *ipid_wlsb;
+
 	uint8_t ip_context[1];
 };
 
@@ -984,6 +987,16 @@ static bool c_tcp_create(struct rohc_com
 
 	memcpy(&(tcp_context->old_tcphdr), tcp, sizeof(tcphdr_t));
 
+	/* IP-ID offset */
+	tcp_context->ipid_wlsb =
+		c_create_wlsb(16, comp->wlsb_window_width, ROHC_LSB_SHIFT_VAR);
+	if(tcp_context->ipid_wlsb == NULL)
+	{
+		rohc_error(context->compressor, ROHC_TRACE_COMP, context->profile->id,
+		           "failed to create W-LSB context for IP-ID offset");
+		goto free_context;
+	}
+
 	/* TCP sequence number */
 	tcp_context->seq_num = rohc_ntoh32(tcp->seq_num);
 	tcp_context->seq_wlsb =
@@ -992,7 +1005,7 @@ static bool c_tcp_create(struct rohc_com
 	{
 		rohc_error(context->compressor, ROHC_TRACE_COMP, context->profile->id,
 		           "failed to create W-LSB context for TCP sequence number");
-		goto free_context;
+		goto free_wlsb_ipid;
 	}
 	tcp_context->seq_scaled_wlsb = c_create_wlsb(32, 4, 7);
 	if(tcp_context->seq_scaled_wlsb == NULL)
@@ -1095,6 +1108,8 @@ free_wlsb_seq_scaled:
 	c_destroy_wlsb(tcp_context->seq_scaled_wlsb);
 free_wlsb_seq:
 	c_destroy_wlsb(tcp_context->seq_wlsb);
+free_wlsb_ipid:
+	c_destroy_wlsb(tcp_context->ipid_wlsb);
 free_context:
 	c_generic_destroy(context);
 error:
@@ -1124,6 +1139,7 @@ static void c_tcp_destroy(struct rohc_co
 	c_destroy_wlsb(tcp_context->ack_wlsb);
 	c_destroy_wlsb(tcp_context->seq_scaled_wlsb);
 	c_destroy_wlsb(tcp_context->seq_wlsb);
+	c_destroy_wlsb(tcp_context->ipid_wlsb);
 	c_generic_destroy(context);
 }
 
@@ -4649,9 +4665,10 @@ static int co_baseheader(struct rohc_com
 	{
 		// =:= irregular(1) [ 1 ];
 		ret = c_optional_ip_id_lsb(context, ip_context.v4->ip_id_behavior,
-		                           ip_context.v4->last_ip_id,
+		                           tcp_context->tmp.nr_ipid_bits_3,
 		                           tcp_context->tmp.ip_id,
-		                           g_context->sn, mptr.uint8, &indicator);
+		                           tcp_context->tmp.ip_id_offset,
+		                           mptr.uint8, &indicator);
 		if(ret < 0)
 		{
 			rohc_comp_warn(context, "failed to encode optional_ip_id_lsb(ip_id)");
@@ -5286,7 +5303,6 @@ static size_t c_tcp_build_seq_1(struct r
 {
 	struct c_generic_context *g_context;
 	uint32_t seq_num;
-	uint16_t ip_id;
 
 	assert(context != NULL);
 	assert(context->specific != NULL);
@@ -5300,9 +5316,7 @@ static size_t c_tcp_build_seq_1(struct r
 	rohc_comp_debug(context, "code seq_1 packet");
 
 	seq1->discriminator = 0x0a; /* '1010' */
-	ip_id = rohc_ntoh16(ip.ipv4->ip_id);
-	seq1->ip_id = c_ip_id_lsb(context, ip_context.v4->ip_id_behavior, 4, 3,
-	                          ip_context.v4->last_ip_id, ip_id, g_context->sn);
+	seq1->ip_id = tcp_context->tmp.ip_id_offset & 0x0f;
 	seq_num = rohc_ntoh32(tcp->seq_num) & 0xffff;
 	seq1->seq_num = rohc_hton16(seq_num);
 	seq1->msn = g_context->sn & 0xf;
@@ -5337,8 +5351,6 @@ static size_t c_tcp_build_seq_2(struct r
                                 seq_2_t *const seq2)
 {
 	struct c_generic_context *g_context;
-	uint16_t ip_id;
-	uint8_t ip_id_lsb;
 
 	assert(context != NULL);
 	assert(context->specific != NULL);
@@ -5352,11 +5364,8 @@ static size_t c_tcp_build_seq_2(struct r
 	rohc_comp_debug(context, "code seq_2 packet");
 
 	seq2->discriminator = 0x1a; /* '11010' */
-	ip_id = rohc_ntoh16(ip.ipv4->ip_id);
-	ip_id_lsb = c_ip_id_lsb(context, ip_context.v4->ip_id_behavior, 7, 3,
-	                        ip_context.v4->last_ip_id, ip_id, g_context->sn);
-	seq2->ip_id1 = (ip_id_lsb >> 4) & 0x7;
-	seq2->ip_id2 = ip_id_lsb & 0x0f;
+	seq2->ip_id1 = (tcp_context->tmp.ip_id_offset >> 4) & 0x7;
+	seq2->ip_id2 = tcp_context->tmp.ip_id_offset & 0x0f;
 	seq2->seq_num_scaled = tcp_context->seq_num_scaled & 0xf;
 	seq2->msn = g_context->sn & 0xf;
 	seq2->psh_flag = tcp->psh_flag;
@@ -5390,7 +5399,6 @@ static size_t c_tcp_build_seq_3(struct r
                                 seq_3_t *const seq3)
 {
 	struct c_generic_context *g_context;
-	uint16_t ip_id;
 
 	assert(context != NULL);
 	assert(context->specific != NULL);
@@ -5404,9 +5412,7 @@ static size_t c_tcp_build_seq_3(struct r
 	rohc_comp_debug(context, "code seq_3 packet");
 
 	seq3->discriminator = 0x09; /* '1001' */
-	ip_id = rohc_ntoh16(ip.ipv4->ip_id);
-	seq3->ip_id = c_ip_id_lsb(context, ip_context.v4->ip_id_behavior, 4, 3,
-	                          ip_context.v4->last_ip_id, ip_id, g_context->sn);
+	seq3->ip_id = tcp_context->tmp.ip_id_offset & 0xf;
 	seq3->ack_num = rohc_hton16(rohc_ntoh32(tcp->ack_num) & 0xffff);
 	seq3->msn = g_context->sn & 0xf;
 	seq3->psh_flag = tcp->psh_flag;
@@ -5441,7 +5447,6 @@ static size_t c_tcp_build_seq_4(struct r
                                 seq_4_t *const seq4)
 {
 	struct c_generic_context *g_context;
-	uint16_t ip_id;
 
 	assert(context != NULL);
 	assert(context->specific != NULL);
@@ -5457,9 +5462,7 @@ static size_t c_tcp_build_seq_4(struct r
 
 	seq4->discriminator = 0x00; /* '0' */
 	seq4->ack_num_scaled = tcp_context->ack_num_scaled & 0xf;
-	ip_id = rohc_ntoh16(ip.ipv4->ip_id);
-	seq4->ip_id = c_ip_id_lsb(context, ip_context.v4->ip_id_behavior, 3, 1,
-	                          ip_context.v4->last_ip_id, ip_id, g_context->sn);
+	seq4->ip_id = tcp_context->tmp.ip_id_offset & 0x7;
 	seq4->msn = g_context->sn & 0xf;
 	seq4->psh_flag = tcp->psh_flag;
 	seq4->header_crc = 0; /* for CRC computation */
@@ -5494,7 +5497,6 @@ static size_t c_tcp_build_seq_5(struct r
 {
 	struct c_generic_context *g_context;
 	uint32_t seq_num;
-	uint16_t ip_id;
 
 	assert(context != NULL);
 	assert(context->specific != NULL);
@@ -5508,9 +5510,7 @@ static size_t c_tcp_build_seq_5(struct r
 	rohc_comp_debug(context, "code seq_5 packet");
 
 	seq5->discriminator = 0x08; /* '1000' */
-	ip_id = rohc_ntoh16(ip.ipv4->ip_id);
-	seq5->ip_id = c_ip_id_lsb(context, ip_context.v4->ip_id_behavior, 4, 3,
-	                          ip_context.v4->last_ip_id, ip_id, g_context->sn);
+	seq5->ip_id = tcp_context->tmp.ip_id_offset & 0xf;
 	seq5->ack_num = rohc_hton16(rohc_ntoh32(tcp->ack_num) & 0xffff);
 	seq_num = rohc_ntoh32(tcp->seq_num) & 0xffff;
 	seq5->seq_num = rohc_hton16(seq_num);
@@ -5546,7 +5546,6 @@ static size_t c_tcp_build_seq_6(struct r
 {
 	struct c_generic_context *g_context;
 	uint8_t seq_num_scaled;
-	uint16_t ip_id;
 
 	assert(context != NULL);
 	assert(context->specific != NULL);
@@ -5567,9 +5566,7 @@ static size_t c_tcp_build_seq_6(struct r
 	seq6->seq_num_scaled2 = seq_num_scaled & 0x01;
 
 	/* IP-ID */
-	ip_id = rohc_ntoh16(ip.ipv4->ip_id);
-	seq6->ip_id = c_ip_id_lsb(context, ip_context.v4->ip_id_behavior, 7, 3,
-	                          ip_context.v4->last_ip_id, ip_id, g_context->sn);
+	seq6->ip_id = tcp_context->tmp.ip_id_offset & 0x7f;
 	seq6->ack_num = rohc_hton16(rohc_ntoh32(tcp->ack_num) & 0xffff);
 	seq6->msn = g_context->sn & 0xf;
 	seq6->psh_flag = tcp->psh_flag;
@@ -5604,7 +5601,6 @@ static size_t c_tcp_build_seq_7(struct r
 {
 	struct c_generic_context *g_context;
 	uint16_t window;
-	uint16_t ip_id;
 
 	assert(context != NULL);
 	assert(context->specific != NULL);
@@ -5627,9 +5623,7 @@ static size_t c_tcp_build_seq_7(struct r
 	seq7->window3 = window & 0x07;
 
 	/* IP-ID */
-	ip_id = rohc_ntoh16(ip.ipv4->ip_id);
-	seq7->ip_id = c_ip_id_lsb(context, ip_context.v4->ip_id_behavior, 5, 3,
-	                          ip_context.v4->last_ip_id, ip_id, g_context->sn);
+	seq7->ip_id = tcp_context->tmp.ip_id_offset & 0x1f;
 	seq7->ack_num = rohc_hton16(rohc_ntoh32(tcp->ack_num) & 0xffff);
 	seq7->msn = g_context->sn & 0xf;
 	seq7->psh_flag = tcp->psh_flag;
@@ -5668,7 +5662,6 @@ static bool c_tcp_build_seq_8(struct roh
 	size_t comp_opts_len;
 	uint16_t ack_num;
 	uint16_t seq_num;
-	uint16_t ip_id;
 	bool is_ok;
 
 	assert(context != NULL);
@@ -5686,10 +5679,7 @@ static bool c_tcp_build_seq_8(struct roh
 	seq8->discriminator = 0x0b; /* '1011' */
 
 	/* IP-ID */
-	ip_id = rohc_ntoh16(ip.ipv4->ip_id);
-	seq8->ip_id = c_ip_id_lsb(context, ip_context.v4->ip_id_behavior, 4, 3,
-	                          ip_context.v4->last_ip_id, ip_id, g_context->sn);
-
+	seq8->ip_id = tcp_context->tmp.ip_id_offset & 0xf;
 	seq8->list_present = 0; /* options are set later */
 	seq8->header_crc = 0; /* for CRC computation */
 	seq8->msn = g_context->sn & 0xf;
@@ -5986,36 +5976,6 @@ static bool tcp_encode_uncomp_fields(str
 			(inner_ip_ctxt.v4->last_ip_id_behavior != inner_ip_ctxt.v4->ip_id_behavior);
 		tcp_field_descr_change(context, "IP-ID behavior",
 		                       tcp_context->tmp.ip_id_behavior_changed);
-		if(inner_ip_ctxt.vx->ip_id_behavior == IP_ID_BEHAVIOR_SEQ)
-		{
-			tcp_context->tmp.ip_id_hi9_changed =
-				((inner_ip_ctxt.v4->last_ip_id & 0xFF80) != (tcp_context->tmp.ip_id & 0xFF80));
-			tcp_context->tmp.ip_id_hi11_changed =
-				((inner_ip_ctxt.v4->last_ip_id & 0xFFE0) != (tcp_context->tmp.ip_id & 0xFFE0));
-			tcp_context->tmp.ip_id_hi12_changed =
-				((inner_ip_ctxt.v4->last_ip_id & 0xFFF0) != (tcp_context->tmp.ip_id & 0xFFF0));
-			tcp_context->tmp.ip_id_hi13_changed =
-				((inner_ip_ctxt.v4->last_ip_id & 0xFFF8) != (tcp_context->tmp.ip_id & 0xFFF8));
-		}
-		else if(inner_ip_ctxt.vx->ip_id_behavior == IP_ID_BEHAVIOR_SEQ_SWAP)
-		{
-			tcp_context->tmp.ip_id_hi9_changed =
-				((inner_ip_ctxt.v4->last_ip_id & 0x80FF) != (tcp_context->tmp.ip_id & 0x80FF));
-			tcp_context->tmp.ip_id_hi11_changed =
-				((inner_ip_ctxt.v4->last_ip_id & 0xE0FF) != (tcp_context->tmp.ip_id & 0xE0FF));
-			tcp_context->tmp.ip_id_hi12_changed =
-				((inner_ip_ctxt.v4->last_ip_id & 0xF0FF) != (tcp_context->tmp.ip_id & 0xF0FF));
-			tcp_context->tmp.ip_id_hi13_changed =
-				((inner_ip_ctxt.v4->last_ip_id & 0xF8FF) != (tcp_context->tmp.ip_id & 0xF8FF));
-		}
-		else
-		{
-			tcp_context->tmp.ip_id_hi9_changed = false; /* TODO: true/false ? */
-			tcp_context->tmp.ip_id_hi11_changed = false; /* TODO: true/false ? */
-			tcp_context->tmp.ip_id_hi12_changed = false; /* TODO: true/false ? */
-			tcp_context->tmp.ip_id_hi13_changed = false; /* TODO: true/false ? */
-		}
-
 		tcp_context->tmp.ip_df_changed =
 			(inner_ip_hdr.ipv4->df != inner_ip_ctxt.v4->df);
 		tcp_field_descr_change(context, "DF", tcp_context->tmp.ip_df_changed);
@@ -6024,16 +5984,78 @@ static bool tcp_encode_uncomp_fields(str
 			(inner_ip_hdr.ipv4->dscp != inner_ip_ctxt.v4->dscp);
 		tcp_field_descr_change(context, "DSCP", tcp_context->tmp.dscp_changed);
 
+		/* how many bits are required to encode the new IP-ID? */
+		if(context->state == ROHC_COMP_STATE_IR)
+		{
+			/* send all bits in IR state */
+			tcp_context->tmp.nr_ipid_bits_1 = 16;
+			tcp_context->tmp.nr_ipid_bits_3 = 16;
+			rohc_comp_debug(context, "IR state: force using 16 bits to encode "
+			                "new IP-ID");
+		}
+		else if(inner_ip_ctxt.v4->ip_id_behavior != IP_ID_BEHAVIOR_SEQ &&
+		        inner_ip_ctxt.v4->ip_id_behavior != IP_ID_BEHAVIOR_SEQ_SWAP)
+		{
+			/* send all bits if behavior is not sequential */
+			tcp_context->tmp.nr_ipid_bits_1 = 16;
+			tcp_context->tmp.nr_ipid_bits_3 = 16;
+			rohc_comp_debug(context, "IP-ID behavior changed: force using 16 "
+			                "bits to encode new IP-ID");
+		}
+		else
+		{
+			/* send only required bits in FO or SO states and if behavior is
+			 * sequential */
+
+			if(inner_ip_ctxt.v4->ip_id_behavior == IP_ID_BEHAVIOR_SEQ)
+			{
+				tcp_context->tmp.ip_id_offset =
+					tcp_context->tmp.ip_id - g_context->sn;
+			}
+			else
+			{
+				const uint16_t ip_id_nbo = swab16(tcp_context->tmp.ip_id);
+				tcp_context->tmp.ip_id_offset = ip_id_nbo - g_context->sn;
+			}
+
+			if(!wlsb_get_kp_32bits(tcp_context->ipid_wlsb,
+			                       tcp_context->tmp.ip_id_offset, 1,
+			                       &tcp_context->tmp.nr_ipid_bits_1))
+			{
+				rohc_warning(context->compressor, ROHC_TRACE_COMP,
+				             context->profile->id, "failed to find the minimal "
+				             "number of bits required for IP-ID offset 0x%04x "
+				             "and p = 1", tcp_context->tmp.ip_id_offset);
+				goto error;
+			}
+			rohc_comp_debug(context, "%zd bits are required to encode new "
+			                "IP-ID offset 0x%04x with p = 1",
+			                tcp_context->tmp.nr_ipid_bits_1,
+			                tcp_context->tmp.ip_id_offset);
+			if(!wlsb_get_kp_32bits(tcp_context->ipid_wlsb,
+			                       tcp_context->tmp.ip_id_offset, 3,
+			                       &tcp_context->tmp.nr_ipid_bits_3))
+			{
+				rohc_warning(context->compressor, ROHC_TRACE_COMP,
+			             context->profile->id, "failed to find the minimal "
+			             "number of bits required for IP-ID offset 0x%04x and "
+			             "p = 3", tcp_context->tmp.ip_id_offset);
+				goto error;
+			}
+			rohc_comp_debug(context, "%zd bits are required to encode new IP-ID "
+			                "offset 0x%04x with p = 3",
+			                tcp_context->tmp.nr_ipid_bits_3,
+			                tcp_context->tmp.ip_id_offset);
+		}
+		c_add_wlsb(tcp_context->ipid_wlsb, g_context->sn,
+		           tcp_context->tmp.ip_id_offset);
+
 		tcp = (tcphdr_t *) (inner_ip_hdr.ipv4 + 1);
 	}
 	else
 	{
 		tcp_context->tmp.ip_id = 0;
 		tcp_context->tmp.ip_id_behavior_changed = false;
-		tcp_context->tmp.ip_id_hi9_changed = false;
-		tcp_context->tmp.ip_id_hi11_changed = false;
-		tcp_context->tmp.ip_id_hi12_changed = false;
-		tcp_context->tmp.ip_id_hi13_changed = false;
 		tcp_context->tmp.ip_df_changed = false;
 
 		tcp_context->tmp.dscp_changed =
@@ -6044,11 +6066,6 @@ static bool tcp_encode_uncomp_fields(str
 
 		tcp = (tcphdr_t *) (inner_ip_hdr.ipv6 + 1);
 	}
-	rohc_comp_debug(context, "IP-ID: high 9 = %u, high 11 = %u, high 12 = %u, "
-	                "high 13 = %u", tcp_context->tmp.ip_id_hi9_changed,
-	                tcp_context->tmp.ip_id_hi11_changed,
-	                tcp_context->tmp.ip_id_hi12_changed,
-	                tcp_context->tmp.ip_id_hi13_changed);
 
 	seq_num_hbo = rohc_ntoh32(tcp->seq_num);
 	ack_num_hbo = rohc_ntoh32(tcp->ack_num);
@@ -6573,7 +6590,7 @@ static rohc_packet_t tcp_decide_SO_packe
 			 *  - at most 4 LSBs of IP-ID must be transmitted
 			 * otherwise use co_common packet */
 			if(!tcp_context->tmp.tcp_window_changed &&
-			   !tcp_context->tmp.ip_id_hi12_changed && /* TODO: WLSB */
+			   tcp_context->tmp.nr_ipid_bits_3 <= 4 &&
 			   true /* TODO: list changed */ &&
 			   true /* TODO: no more than 4 bits of SN */ &&
 			   true /* TODO: no more than 3 bits of TTL */ &&
@@ -6594,7 +6611,7 @@ static rohc_packet_t tcp_decide_SO_packe
 		{
 			/* seq_7 or co_common */
 			if(/* TODO: no more than 15 bits of TCP window */
-			   !tcp_context->tmp.ip_id_hi11_changed && /* TODO: WLSB */
+			   tcp_context->tmp.nr_ipid_bits_3 <= 5 &&
 			   tcp_context->tmp.nr_ack_bits_32767 <= 16 &&
 			   true /* TODO: no more than 4 bits of SN */ &&
 			   tcp_context->tmp.tcp_rsf_flag_changed)
@@ -6613,7 +6630,7 @@ static rohc_packet_t tcp_decide_SO_packe
 		        (tcp->ack_flag != 0 && !tcp_context->tmp.tcp_ack_num_changed))
 		{
 			/* seq_1, seq_2 or co_common */
-			if(!tcp_context->tmp.ip_id_hi11_changed && /* TODO: WLSB */
+			if(tcp_context->tmp.nr_ipid_bits_3 <= 4 &&
 			   tcp_context->tmp.nr_seq_bits_32767 <= 16 &&
 			   true /* TODO: no more than 4 bits of SN */)
 			{
@@ -6621,7 +6638,7 @@ static rohc_packet_t tcp_decide_SO_packe
 				TRACE_GOTO_CHOICE;
 				packet_type = ROHC_PACKET_TCP_SEQ_1;
 			}
-			else if(!tcp_context->tmp.ip_id_hi9_changed && /* TODO: WLSB */
+			else if(tcp_context->tmp.nr_ipid_bits_3 <= 7 &&
 			        tcp_context->seq_num_scaling_nr >= ROHC_INIT_TS_STRIDE_MIN &&
 			        tcp_context->tmp.nr_seq_scaled_bits <= 4 &&
 			        true /* TODO: no more than 4 bits of SN */)
@@ -6642,14 +6659,14 @@ static rohc_packet_t tcp_decide_SO_packe
 		        tcp_context->tmp.nr_seq_bits_8191 == 0)
 		{
 			/* seq_3, seq_4, or co_common */
-			if(!tcp_context->tmp.ip_id_hi12_changed && /* TODO: WLSB */
+			if(tcp_context->tmp.nr_ipid_bits_3 <= 4 &&
 			   tcp_context->tmp.nr_ack_bits_16383 <= 16 &&
 			   true /* TODO: no more than 4 bits of SN */)
 			{
 				TRACE_GOTO_CHOICE;
 				packet_type = ROHC_PACKET_TCP_SEQ_3;
 			}
-			else if(!tcp_context->tmp.ip_id_hi13_changed && /* TODO: WLSB */
+			else if(tcp_context->tmp.nr_ipid_bits_1 <= 3 &&
 			        tcp_context->ack_stride != 0 &&
 			        tcp_context->tmp.nr_ack_scaled_bits <= 4 &&
 			        true /* TODO: no more than 4 bits of SN */)
@@ -6667,7 +6684,7 @@ static rohc_packet_t tcp_decide_SO_packe
 		{
 			/* sequence and acknowledgment numbers changed:
 			 * seq_5, seq_6, seq_8 or co_common */
-			if(!tcp_context->tmp.ip_id_hi12_changed && /* TODO: WLSB */
+			if(tcp_context->tmp.nr_ipid_bits_3 <= 4 &&
 			   tcp_context->tmp.nr_ack_bits_16383 <= 16 &&
 			   tcp_context->tmp.nr_seq_bits_32767 <= 16 &&
 			   true /* TODO: no more than 4 bits of SN */)
@@ -6675,7 +6692,7 @@ static rohc_packet_t tcp_decide_SO_packe
 				TRACE_GOTO_CHOICE;
 				packet_type = ROHC_PACKET_TCP_SEQ_5;
 			}
-			else if(!tcp_context->tmp.ip_id_hi9_changed && /* TODO: WLSB */
+			else if(tcp_context->tmp.nr_ipid_bits_3 <= 7 &&
 			        tcp_context->seq_num_scaling_nr >= ROHC_INIT_TS_STRIDE_MIN &&
 			        tcp_context->tmp.nr_seq_scaled_bits <= 4 &&
 			        tcp_context->tmp.nr_ack_bits_16383 <= 16 &&
@@ -6685,7 +6702,7 @@ static rohc_packet_t tcp_decide_SO_packe
 				assert(tcp_context->tmp.payload_len > 0);
 				packet_type = ROHC_PACKET_TCP_SEQ_6;
 			}
-			else if(!tcp_context->tmp.ip_id_hi12_changed && /* TODO: WLSB */
+			else if(tcp_context->tmp.nr_ipid_bits_3 <= 4 &&
 			        true /* TODO: list changed */ &&
 			        true /* TODO: no more than 4 bits of SN */ &&
 			        true /* TODO: no more than 3 bits of TTL */ &&

=== modified file 'src/comp/schemes/rfc4996.c'
--- src/comp/schemes/rfc4996.c	2014-06-21 10:59:41 +0000
+++ src/comp/schemes/rfc4996.c	2014-07-20 09:13:07 +0000
@@ -453,72 +453,6 @@ unsigned int rsf_index_enc(const struct
 
 
 /**
- * @brief Compress the lower bits of IP-ID
- *
- * See RFC4996 page 75
- *
- * @param context          The compressor context
- * @param behavior         The IP-ID behavior
- * @param k                The num_lsbs_param parameter for c_lsb()
- * @param p                The offset parameter for c_lsb()
- * @param context_ip_id    The context value of IP-ID
- * @param ip_id            The IP-ID value to compress
- * @param msn              The Master Sequence Number
- * @return                 The lsb of offset between IP-ID and MSN
- */
-uint16_t c_ip_id_lsb(const struct rohc_comp_ctxt *const context,
-                     const int behavior,
-                     const unsigned int k,
-                     const unsigned int p,
-                     const uint16_t context_ip_id,
-                     const uint16_t ip_id,
-                     const uint16_t msn)
-{
-	uint16_t ip_id_offset;
-	uint16_t ip_id_nbo;
-	uint16_t swapped_context_ip_id;
-
-	assert(context != NULL);
-	assert(behavior == IP_ID_BEHAVIOR_SEQ ||
-	       behavior == IP_ID_BEHAVIOR_SEQ_SWAP );
-
-	rohc_comp_debug(context, "behavior = %d, context_ip_id = 0x%04x, "
-	                "ip_id = 0x%04x, msn = 0x%04x", behavior,
-	                context_ip_id, ip_id, msn);
-
-	switch(behavior)
-	{
-		case IP_ID_BEHAVIOR_SEQ:
-			ip_id_offset = ip_id - msn;
-			rohc_comp_debug(context, "ip_id_offset = 0x%04x - 0x%04x = 0x%04x",
-			                ip_id, msn, ip_id_offset);
-			ip_id_offset = c_lsb(context, k, p, context_ip_id - msn,
-			                     ip_id_offset);
-			rohc_comp_debug(context, "ip_id_offset = 0x%04x", ip_id_offset);
-			break;
-		case IP_ID_BEHAVIOR_SEQ_SWAP:
-			ip_id_nbo = swab16(ip_id);
-			rohc_comp_debug(context, "ip_id_nbo = 0x%04x", ip_id_nbo);
-			ip_id_offset = ip_id_nbo - msn;
-			rohc_comp_debug(context, "ip_id_offset = 0x%04x", ip_id_offset);
-			swapped_context_ip_id = swab16(context_ip_id);
-			ip_id_offset = c_lsb(context, k, p, swapped_context_ip_id - msn,
-			                     ip_id_offset);
-			rohc_comp_debug(context, "ip_id_offset = 0x%04x", ip_id_offset);
-			break;
-		default:
-			/* should not happen */
-#if defined(NDEBUG) || defined(__KERNEL__) || defined(ENABLE_DEAD_CODE)
-			ip_id_offset = 0;
-#endif
-			assert(0);
-			break;
-	}
-	return ip_id_offset;
-}
-
-
-/**
  * @brief Compress or not the IP-ID
  *
  * See RFC4996 page 76
@@ -535,9 +469,9 @@ uint16_t c_ip_id_lsb(const struct rohc_c
  */
 int c_optional_ip_id_lsb(const struct rohc_comp_ctxt *const context,
                          const int behavior,
-                         const uint16_t context_ip_id,
+                         const size_t nr_ipid_bits_3,
                          const uint16_t ip_id,
-                         const uint16_t msn,
+                         const uint16_t ip_id_offset,
                          uint8_t *const rohc_data,
                          int *const indicator)
 {
@@ -545,17 +479,18 @@ int c_optional_ip_id_lsb(const struct ro
 
 	assert(context != NULL);
 
-	rohc_comp_debug(context, "behavior = 0x%04x, context_ip_id = 0x%04x, "
-	                "ip_id = 0x%04x, msn = 0x%04x", behavior, context_ip_id,
-	                ip_id, msn);
+	rohc_comp_debug(context, "optional_ip_id_lsb: behavior = %d, "
+	                "nr_ipid_bits_3 = %zu, ip_id = 0x%04x, "
+	                "ip_id_offset = 0x%04x\n", behavior, nr_ipid_bits_3,
+	                ip_id, ip_id_offset);
 
 	switch(behavior)
 	{
 		case IP_ID_BEHAVIOR_SEQ:
-			if((context_ip_id & 0xff00) == (ip_id & 0xff00))
+			if(nr_ipid_bits_3 <= 8)
 			{
-				rohc_data[0] = c_ip_id_lsb(context, behavior, 8, 3,
-				                           context_ip_id, ip_id, msn);
+				/* short */
+				rohc_data[0] = ip_id_offset & 0xff;
 				*indicator = 0;
 				length++;
 				rohc_comp_debug(context, "write ip_id = 0x%02x", rohc_data[0]);
@@ -570,10 +505,10 @@ int c_optional_ip_id_lsb(const struct ro
 			}
 			break;
 		case IP_ID_BEHAVIOR_SEQ_SWAP:
-			if((context_ip_id & 0x00ff) == (ip_id & 0x00ff))
+			if(nr_ipid_bits_3 <= 8)
 			{
-				rohc_data[0] = c_ip_id_lsb(context, behavior, 8, 3,
-				                           context_ip_id, ip_id, msn);
+				/* short */
+				rohc_data[0] = ip_id_offset & 0xff;
 				*indicator = 0;
 				length++;
 				rohc_comp_debug(context, "write ip_id = 0x%02x", rohc_data[0]);
@@ -597,7 +532,7 @@ int c_optional_ip_id_lsb(const struct ro
 			assert(0); /* should never happen */
 			*indicator = 0;
 			length = 0;
-			break;
+			return -1;
 	}
 
 	return length;

=== modified file 'src/comp/schemes/rfc4996.h'
--- src/comp/schemes/rfc4996.h	2014-06-27 15:21:48 +0000
+++ src/comp/schemes/rfc4996.h	2014-07-20 09:03:11 +0000
@@ -158,22 +158,13 @@ void c_field_scaling(uint32_t *const sca
 // RFC4996 page 71
 unsigned int rsf_index_enc(const struct rohc_comp_ctxt *const context,
                            unsigned int rsf_flags);
-// RFC4996 page 75
-uint16_t c_ip_id_lsb(const struct rohc_comp_ctxt *const context,
-                     const int behavior,
-                     const unsigned int k,
-                     const unsigned int p,
-                     const uint16_t context_ip_id,
-                     const uint16_t ip_id,
-                     const uint16_t msn)
-	__attribute__((warn_unused_result, nonnull(1)));
 
 /* optional_ip_id_lsb encoding method */
 int c_optional_ip_id_lsb(const struct rohc_comp_ctxt *const context,
                          const int behavior,
-                         const uint16_t context_ip_id,
+                         const size_t nr_ipid_bits_3,
                          const uint16_t ip_id,
-                         const uint16_t msn,
+                         const uint16_t ip_id_offset,
                          uint8_t *const rohc_data,
                          int *const indicator)
 	__attribute__((warn_unused_result, nonnull(1, 6, 7)));

=== modified file 'src/decomp/d_tcp.c'
--- src/decomp/d_tcp.c	2014-06-27 15:21:48 +0000
+++ src/decomp/d_tcp.c	2014-07-20 10:26:35 +0000
@@ -274,6 +274,8 @@ struct d_tcp_context
 
 	tcphdr_t old_tcphdr;
 
+	struct rohc_lsb_decode *ipid_lsb_ctxt;
+
 	uint8_t ip_context[MAX_IP_CONTEXT_SIZE];
 };
 
@@ -429,6 +431,16 @@ static void * d_tcp_create(const struct
 	memset(tcp_context, 0, sizeof(struct d_tcp_context));
 	g_context->specific = tcp_context;
 
+	/* create the LSB decoding context for the IP-ID offset */
+	tcp_context->ipid_lsb_ctxt = rohc_lsb_new(ROHC_LSB_SHIFT_VAR, 16);
+	if(tcp_context->ipid_lsb_ctxt == NULL)
+	{
+		rohc_error(context->decompressor, ROHC_TRACE_DECOMP, context->profile->id,
+		           "failed to create the LSB decoding context for the IP-ID "
+		           "offset");
+		goto free_tcp_context;
+	}
+
 	/* create the LSB decoding context for the sequence number */
 	tcp_context->seq_lsb_ctxt = rohc_lsb_new(ROHC_LSB_SHIFT_VAR, 32);
 	if(tcp_context->seq_lsb_ctxt == NULL)
@@ -436,7 +448,7 @@ static void * d_tcp_create(const struct
 		rohc_error(context->decompressor, ROHC_TRACE_DECOMP, context->profile->id,
 		           "failed to create the LSB decoding context for the sequence "
 		           "number");
-		goto free_tcp_context;
+		goto free_lsb_ipid;
 	}
 
 	/* create the LSB decoding context for the scaled sequence number */
@@ -540,6 +552,8 @@ free_lsb_scaled_seq:
 	rohc_lsb_free(tcp_context->seq_scaled_lsb_ctxt);
 free_lsb_seq:
 	rohc_lsb_free(tcp_context->seq_lsb_ctxt);
+free_lsb_ipid:
+	rohc_lsb_free(tcp_context->ipid_lsb_ctxt);
 free_tcp_context:
 	zfree(tcp_context);
 destroy_context:
@@ -587,6 +601,8 @@ static void d_tcp_destroy(void *const co
 	rohc_lsb_free(tcp_context->seq_scaled_lsb_ctxt);
 	/* destroy the LSB decoding context for the sequence number */
 	rohc_lsb_free(tcp_context->seq_lsb_ctxt);
+	/* destroy the LSB decoding context for the IP-ID offset */
+	rohc_lsb_free(tcp_context->ipid_lsb_ctxt);
 
 #if 0 /* TODO: sn_lsb_ctxt is not initialized, either remove it or use it fully */
 	/* destroy the LSB decoding context for SN */
@@ -839,6 +855,7 @@ static int d_tcp_decode_ir(struct rohc_d
 	struct d_tcp_context *tcp_context = g_context->specific;
 	ip_context_ptr_t ip_context;
 	base_header_ip_t base_header;
+	base_header_ip_t inner_ip_hdr;
 	tcphdr_t *tcp;
 	unsigned int payload_size;
 	const uint8_t *remain_data;
@@ -902,6 +919,7 @@ static int d_tcp_decode_ir(struct rohc_d
 
 		protocol = ip_context.vx->next_header;
 		ip_context.uint8 += ip_context.vx->context_length;
+		inner_ip_hdr.uint8 = base_header.uint8;
 		if(base_header.ipvx->version == IPV4)
 		{
 			base_header.ipv4->length = 0; /* force init to 0 */
@@ -984,6 +1002,7 @@ static int d_tcp_decode_ir(struct rohc_d
 
 		protocol = ip_context.vx->next_header;
 		ip_context.uint8 += ip_context.vx->context_length;
+		inner_ip_hdr.uint8 = base_header.uint8;
 		if(base_header.ipvx->version == IPV4)
 		{
 			++base_header.ipv4;
@@ -1093,6 +1112,7 @@ static int d_tcp_decode_ir(struct rohc_d
 			rohc_decomp_debug(context, "IP checksum = 0x%04x on %zu bytes",
 			                  rohc_ntoh16(base_header.ipv4->checksum),
 			                  base_header.ipv4->header_length * sizeof(uint32_t));
+			inner_ip_hdr.uint8 = base_header.uint8;
 			++base_header.ipv4;
 			++ip_context.v4;
 			uncomp_len -= sizeof(base_header_ip_v4_t);
@@ -1104,6 +1124,7 @@ static int d_tcp_decode_ir(struct rohc_d
 			base_header.ipv6->payload_length = rohc_hton16(uncomp_len);
 			rohc_decomp_debug(context, "IPv6 payload length = %d",
 			                  rohc_ntoh16(base_header.ipv6->payload_length));
+			inner_ip_hdr.uint8 = base_header.uint8;
 			++base_header.ipv6;
 			++ip_context.v6;
 			while(rohc_is_ipv6_opt(protocol))
@@ -1127,6 +1148,13 @@ static int d_tcp_decode_ir(struct rohc_d
 	rohc_lsb_set_ref(tcp_context->seq_lsb_ctxt, rohc_ntoh32(tcp->seq_num), false);
 	rohc_decomp_debug(context, "sequence number 0x%08x is the new reference",
 	                  rohc_ntoh32(tcp->seq_num));
+	if(inner_ip_hdr.ipvx->version == IPV4)
+	{
+		rohc_lsb_set_ref(tcp_context->ipid_lsb_ctxt,
+		                 rohc_ntoh16(inner_ip_hdr.ipv4->ip_id) - tcp_context->msn, false);
+		rohc_decomp_debug(context, "IP-ID offset 0x%04x is the new reference",
+		                  rohc_ntoh16(inner_ip_hdr.ipv4->ip_id) - tcp_context->msn);
+	}
 	if(payload_size != 0)
 	{
 		rohc_lsb_set_ref(tcp_context->seq_scaled_lsb_ctxt,
@@ -1171,6 +1199,7 @@ static int d_tcp_decode_irdyn(struct roh
 	struct d_tcp_context *tcp_context = g_context->specific;
 	ip_context_ptr_t ip_context;
 	base_header_ip_t base_header;
+	base_header_ip_t inner_ip_hdr;
 	tcphdr_t *tcp;
 	unsigned int payload_size;
 	const uint8_t *remain_data;
@@ -1232,6 +1261,7 @@ static int d_tcp_decode_irdyn(struct roh
 
 		protocol = ip_context.vx->next_header;
 		ip_context.uint8 += ip_context.vx->context_length;
+		inner_ip_hdr.uint8 = base_header.uint8;
 		if(base_header.ipvx->version == IPV4)
 		{
 			base_header.ipv4->length = 0; /* force init to 0 */
@@ -1328,6 +1358,7 @@ static int d_tcp_decode_irdyn(struct roh
 			rohc_decomp_debug(context, "IP checksum = 0x%04x for %d",
 			                  rohc_ntoh16(base_header.ipv4->checksum),
 			                  base_header.ipv4->header_length);
+			inner_ip_hdr.uint8 = base_header.uint8;
 			++base_header.ipv4;
 			++ip_context.v4;
 			uncomp_len -= sizeof(base_header_ip_v4_t);
@@ -1339,6 +1370,7 @@ static int d_tcp_decode_irdyn(struct roh
 			base_header.ipv6->payload_length = rohc_hton16(uncomp_len);
 			rohc_decomp_debug(context, "payload_length = %d",
 			                  rohc_ntoh16(base_header.ipv6->payload_length));
+			inner_ip_hdr.uint8 = base_header.uint8;
 			++base_header.ipv6;
 			++ip_context.v6;
 			while(rohc_is_ipv6_opt(protocol))
@@ -1366,6 +1398,13 @@ static int d_tcp_decode_irdyn(struct roh
 	rohc_lsb_set_ref(tcp_context->seq_lsb_ctxt, rohc_ntoh32(tcp->seq_num), false);
 	rohc_decomp_debug(context, "sequence number 0x%08x is the new reference",
 	                  rohc_ntoh32(tcp->seq_num));
+	if(inner_ip_hdr.ipvx->version == IPV4)
+	{
+		rohc_lsb_set_ref(tcp_context->ipid_lsb_ctxt,
+		                 rohc_ntoh16(inner_ip_hdr.ipv4->ip_id) - tcp_context->msn, false);
+		rohc_decomp_debug(context, "IP-ID offset 0x%04x is the new reference",
+		                  rohc_ntoh16(inner_ip_hdr.ipv4->ip_id) - tcp_context->msn);
+	}
 	if(payload_size != 0)
 	{
 		rohc_lsb_set_ref(tcp_context->seq_scaled_lsb_ctxt,
@@ -4429,6 +4468,7 @@ static int d_tcp_decode_CO(struct rohc_d
 	struct d_tcp_context *tcp_context;
 	ip_context_ptr_t ip_inner_context;
 	ip_context_ptr_t ip_context;
+	base_header_ip_t inner_ip_hdr;
 	uint16_t tcp_options_size = 0;
 	uint32_t seq_num_scaled_bits = 0;
 	size_t seq_num_scaled_nr = 0;
@@ -4440,6 +4480,7 @@ static int d_tcp_decode_CO(struct rohc_d
 	int size;
 	int ttl_irregular_chain_flag = 0;
 	int ip_inner_ecn;
+	uint16_t ip_id_offset;
 	uint16_t ip_id;
 	int ret;
 
@@ -5025,6 +5066,7 @@ static int d_tcp_decode_CO(struct rohc_d
 #endif
 			base_header.ipv4->ttl_hopl = ip_context.v4->ttl_hopl;
 			protocol = ip_context.v4->protocol;
+			inner_ip_hdr.uint8 = base_header.uint8;
 			++base_header.ipv4;
 			++ip_context.v4;
 		}
@@ -5035,6 +5077,7 @@ static int d_tcp_decode_CO(struct rohc_d
 			base_header.ipv6->dscp2 = ip_context.v6->dscp & 0x03;
 			base_header.ipv6->ttl_hopl = ip_context.v6->ttl_hopl;
 			protocol = ip_context.v6->next_header;
+			inner_ip_hdr.uint8 = base_header.uint8;
 			++base_header.ipv6;
 			++ip_context.v6;
 		}
@@ -5135,17 +5178,20 @@ static int d_tcp_decode_CO(struct rohc_d
 		/* IP-ID behavior */
 		ip_inner_context.v4->ip_id_behavior = co_common->ip_id_behavior;
 		ret = d_optional_ip_id_lsb(context, rohc_opts_data,
+		                           tcp_context->ipid_lsb_ctxt,
 		                           co_common->ip_id_behavior,
 		                           co_common->ip_id_indicator,
-		                           ip_inner_context.v4->last_ip_id,
-		                           &ip_id, msn);
+		                           msn, &ip_id_offset, &ip_id);
 		if(ret < 0)
 		{
 			rohc_decomp_warn(context, "optional_ip_id_lsb(ip_id) failed");
 			goto error;
 		}
-		rohc_decomp_debug(context, "IP-ID = 0x%04x (%d bytes in packet)",
-		                  ip_id, ret);
+		if(co_common->ip_id_behavior != IP_ID_BEHAVIOR_RAND)
+		{
+			rohc_decomp_debug(context, "IP-ID = 0x%04x (%d bytes in packet)",
+			                  ip_id, ret);
+		}
 		rohc_opts_data += ret;
 
 		/* URG pointer */
@@ -5241,6 +5287,7 @@ static int d_tcp_decode_CO(struct rohc_d
 		uint32_t ack_num_p;
 		uint32_t ack_num_scaled;
 		uint8_t ttl_hopl;
+		bool decode_ok;
 
 		tcp->seq_num = tcp_context->old_tcphdr.seq_num;
 		tcp->ack_num = tcp_context->old_tcphdr.ack_num;
@@ -5452,9 +5499,15 @@ static int d_tcp_decode_CO(struct rohc_d
 
 				rohc_decomp_debug(context, "decode seq_1 packet");
 
-				ip_id = d_ip_id_lsb(context, ip_inner_context.v4->ip_id_behavior,
-				                    4, 3, ip_inner_context.v4->last_ip_id,
-				                    seq_1->ip_id, msn);
+				decode_ok = d_ip_id_lsb(context, tcp_context->ipid_lsb_ctxt,
+				                        ip_inner_context.v4->ip_id_behavior, msn,
+				                        seq_1->ip_id, 4, 3, &ip_id_offset, &ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
 
 				/* decode sequence number from packet bits and context */
 				encoded_seq_num = rohc_ntoh16(seq_1->seq_num);
@@ -5476,9 +5529,15 @@ static int d_tcp_decode_CO(struct rohc_d
 				rohc_decomp_debug(context, "decode seq_2 packet");
 
 				ip_id_lsb = (seq_2->ip_id1 << 4) | seq_2->ip_id2;
-				ip_id = d_ip_id_lsb(context, ip_inner_context.v4->ip_id_behavior,
-				                    7, 3, ip_inner_context.v4->last_ip_id,
-				                    ip_id_lsb, msn);
+				decode_ok = d_ip_id_lsb(context, tcp_context->ipid_lsb_ctxt,
+				                        ip_inner_context.v4->ip_id_behavior, msn,
+				                        ip_id_lsb, 7, 3, &ip_id_offset, &ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
 				seq_num_scaled_bits = seq_2->seq_num_scaled;
 				seq_num_scaled_nr = 4;
 				rohc_decomp_debug(context, "seq_2: %zu bits of scaled sequence "
@@ -5493,9 +5552,15 @@ static int d_tcp_decode_CO(struct rohc_d
 
 				rohc_decomp_debug(context, "decode seq_3 packet");
 
-				ip_id = d_ip_id_lsb(context, ip_inner_context.v4->ip_id_behavior,
-				                    4, 3, ip_inner_context.v4->last_ip_id,
-				                    seq_3->ip_id, msn);
+				decode_ok = d_ip_id_lsb(context, tcp_context->ipid_lsb_ctxt,
+				                        ip_inner_context.v4->ip_id_behavior, msn,
+				                        seq_3->ip_id, 4, 3, &ip_id_offset, &ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
 
 				/* retrieve ACK number bits */
 				ack_num_bits = rohc_ntoh16(seq_3->ack_num);
@@ -5529,9 +5594,17 @@ static int d_tcp_decode_CO(struct rohc_d
 				                  "0x%x", ack_num_scaled,
 				                  tcp_context->ack_num_residue,
 				                  rohc_ntoh32(tcp->ack_num));
-				ip_id = d_ip_id_lsb(context, ip_inner_context.v4->ip_id_behavior,
-				                    3, 1, ip_inner_context.v4->last_ip_id,
-				                    seq_4->ip_id, msn);
+
+				decode_ok = d_ip_id_lsb(context, tcp_context->ipid_lsb_ctxt,
+				                        ip_inner_context.v4->ip_id_behavior, msn,
+				                        seq_4->ip_id, 3, 1, &ip_id_offset, &ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
+
 				tcp->psh_flag = seq_4->psh_flag;
 				break;
 			}
@@ -5542,9 +5615,16 @@ static int d_tcp_decode_CO(struct rohc_d
 				uint32_t decoded_seq_num;
 
 				rohc_decomp_debug(context, "decode seq_5 packet");
-				ip_id = d_ip_id_lsb(context, ip_inner_context.v4->ip_id_behavior,
-				                    4, 3, ip_inner_context.v4->last_ip_id,
-				                    seq_5->ip_id, msn);
+
+				decode_ok = d_ip_id_lsb(context, tcp_context->ipid_lsb_ctxt,
+				                        ip_inner_context.v4->ip_id_behavior, msn,
+				                        seq_5->ip_id, 4, 3, &ip_id_offset, &ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
 
 				/* retrieve ACK number bits */
 				ack_num_bits = rohc_ntoh16(seq_5->ack_num);
@@ -5575,9 +5655,16 @@ static int d_tcp_decode_CO(struct rohc_d
 				rohc_decomp_debug(context, "seq_6: %zu bits of scaled sequence "
 				                  "number 0x%x", seq_num_scaled_nr,
 				                  seq_num_scaled_bits);
-				ip_id = d_ip_id_lsb(context, ip_inner_context.v4->ip_id_behavior,
-				                    7, 3, ip_inner_context.v4->last_ip_id,
-				                    seq_6->ip_id, msn);
+
+				decode_ok = d_ip_id_lsb(context, tcp_context->ipid_lsb_ctxt,
+				                        ip_inner_context.v4->ip_id_behavior, msn,
+				                        seq_6->ip_id, 7, 3, &ip_id_offset, &ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
 
 				/* retrieve ACK number bits */
 				ack_num_bits = rohc_ntoh16(seq_6->ack_num);
@@ -5597,9 +5684,16 @@ static int d_tcp_decode_CO(struct rohc_d
 				window = (seq_7->window1 << 11) | (seq_7->window2 << 3) |
 				         seq_7->window3;
 				tcp->window = rohc_hton16( d_lsb(context, 15,16383,rohc_ntoh16(tcp_context->old_tcphdr.window),window) );
-				ip_id = d_ip_id_lsb(context, ip_inner_context.v4->ip_id_behavior,
-				                    5, 3, ip_inner_context.v4->last_ip_id,
-				                    seq_7->ip_id, msn);
+
+				decode_ok = d_ip_id_lsb(context, tcp_context->ipid_lsb_ctxt,
+				                        ip_inner_context.v4->ip_id_behavior, msn,
+				                        seq_7->ip_id, 5, 3, &ip_id_offset, &ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
 
 				/* retrieve ACK number bits */
 				ack_num_bits = rohc_ntoh16(seq_7->ack_num);
@@ -5616,9 +5710,17 @@ static int d_tcp_decode_CO(struct rohc_d
 				uint16_t enc_seq_num;
 
 				rohc_decomp_debug(context, "decode seq_8 packet");
-				ip_id = d_ip_id_lsb(context, ip_inner_context.v4->ip_id_behavior,
-				                    4, 3, ip_inner_context.v4->last_ip_id,
-				                    seq_8->ip_id, msn);
+
+				decode_ok = d_ip_id_lsb(context, tcp_context->ipid_lsb_ctxt,
+				                        ip_inner_context.v4->ip_id_behavior, msn,
+				                        seq_8->ip_id, 4, 3, &ip_id_offset, &ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
+
 				tcp->psh_flag = seq_8->psh_flag;
 				ttl_hopl = d_lsb(context, 3, 3, ip_inner_context.vx->ttl_hopl,
 				                 seq_8->ttl_hopl);
@@ -5761,6 +5863,8 @@ static int d_tcp_decode_CO(struct rohc_d
 				}
 				base_header_inner.ipv4->ip_id = rohc_hton16(ip_id);
 				ip_inner_context.v4->last_ip_id = ip_id;
+				rohc_decomp_debug(context, "new last IP-ID = 0x%04x",
+				                  ip_inner_context.v4->last_ip_id);
 				break;
 			}
 			case IP_ID_BEHAVIOR_SEQ_SWAP:
@@ -5780,6 +5884,8 @@ static int d_tcp_decode_CO(struct rohc_d
 
 				base_header_inner.ipv4->ip_id = rohc_hton16(swapped_ip_id);
 				ip_inner_context.v4->last_ip_id = swapped_ip_id;
+				rohc_decomp_debug(context, "new last IP-ID = 0x%04x",
+				                  ip_inner_context.v4->last_ip_id);
 				break;
 			}
 			case IP_ID_BEHAVIOR_RAND:
@@ -5964,6 +6070,12 @@ static int d_tcp_decode_CO(struct rohc_d
 	rohc_lsb_set_ref(tcp_context->seq_lsb_ctxt, rohc_ntoh32(tcp->seq_num), false);
 	rohc_decomp_debug(context, "sequence number 0x%08x is the new reference",
 	                  rohc_ntoh32(tcp->seq_num));
+	if(inner_ip_hdr.ipvx->version == IPV4)
+	{
+		rohc_lsb_set_ref(tcp_context->ipid_lsb_ctxt, ip_id - msn, false);
+		rohc_decomp_debug(context, "IP-ID offset 0x%04x is the new reference",
+		                  ip_id - msn);
+	}
 	if(payload_len != 0)
 	{
 		rohc_lsb_set_ref(tcp_context->seq_scaled_lsb_ctxt,

=== modified file 'src/decomp/schemes/rfc4996.c'
--- src/decomp/schemes/rfc4996.c	2014-06-21 10:59:41 +0000
+++ src/decomp/schemes/rfc4996.c	2014-07-20 10:05:43 +0000
@@ -42,21 +42,6 @@
 #include <assert.h>
 
 
-/* TODO: to be removed once c_lsb and d_c_lsb are removed */
-/**
- * @brief Table of the mask for lsb()
- */
-static unsigned int lsb_masks[] =
-{
-	0x00000,
-	0x00001, 0x00003, 0x00007, 0x0000F,
-	0x0001F, 0x0003F, 0x0007F, 0x000FF,
-	0x001FF, 0x003FF, 0x007FF, 0x00FFF,
-	0x01FFF, 0x03FFF, 0x07FFF, 0x0FFFF,
-	0x1FFFF, 0x3FFFF, 0x7FFFF, 0xFFFFF
-};
-
-
 /**
  * @brief Table of the mask for lsb()
  */
@@ -350,106 +335,71 @@ unsigned int rsf_index_dec( unsigned int
 
 
 /**
- * @brief Compress the lower bits of the given value.
- *
- * See RFC4997 page 27
- *
- * @param context          The compressor context
- * @param num_lsbs_param   The number of bits
- * @param offset_param     The offset
- * @param context_value    The value of the context
- * @param original_value   The value to compress
- * @return                 The compressed value with num_lsbs_param bits
- *
- * @todo TODO: duplicated code from rfc4996_encoding.c
- */
-static uint32_t d_c_lsb(const struct rohc_decomp_ctxt *const context,
-                        int num_lsbs_param,
-                        unsigned int offset_param,
-                        unsigned int context_value,
-                        unsigned int original_value)
-{
-	unsigned int lower_bound;
-	unsigned int upper_bound;
-	unsigned int value;
-
-	assert(context != NULL);
-
-	rohc_decomp_debug(context, "num_lsb = %d, offset_param = %d, "
-	                  "context_value = 0x%x, original_value = 0x%x",
-	                  num_lsbs_param, offset_param, context_value,
-	                  original_value);
-
-	assert( num_lsbs_param > 0 && num_lsbs_param <= 18 );
-
-	lower_bound = context_value - offset_param;
-	upper_bound = context_value + lsb_masks[num_lsbs_param] - offset_param;
-
-	value = original_value & lsb_masks[num_lsbs_param];
-
-	rohc_decomp_debug(context, "0x%x < value (0x%x) < 0x%x => return 0x%x",
-	                  lower_bound, original_value, upper_bound, value);
-
-	return value;
-}
-
-
-/**
  * @brief Decompress the lower bits of IP-ID
  *
  * See RFC4996 page 75
  *
  * @param context        The decompression context
+ * @param lsb            The LSB decompression context
  * @param behavior       The IP-ID behavior
  * @param k              The num_lsbs_param parameter for d_lsb()
  * @param p              The offset parameter for d_lsb()
  * @param context_ip_id  The context IP-ID value
  * @param value          The value to decompress
  * @param msn            The Master Sequence Number
- * @return               The IP-ID
  */
-uint16_t d_ip_id_lsb(const struct rohc_decomp_ctxt *const context,
-                     const int behavior,
-                     const unsigned int k,
-                     const unsigned int p,
-                     const uint16_t context_ip_id,
-                     const uint16_t value,
-                     const uint16_t msn)
+bool d_ip_id_lsb(const struct rohc_decomp_ctxt *const context,
+                 const struct rohc_lsb_decode *const lsb,
+                 const int behavior,
+                 const uint32_t msn,
+                 const uint16_t ip_id_bits,
+                 const uint16_t ip_id_bits_nr,
+                 const rohc_lsb_shift_t p,
+                 uint16_t *const ip_id_offset,
+                 uint16_t *const ip_id)
 {
-	uint16_t ip_id_offset;
-	uint16_t ip_id;
+	uint32_t ip_id_offset32;
+	bool decode_ok;
 
-	assert(context != NULL);
+	assert(behavior == IP_ID_BEHAVIOR_SEQ ||
+	       behavior == IP_ID_BEHAVIOR_SEQ_SWAP);
 
-	rohc_decomp_debug(context, "behavior = %d, k = %d, p = %d, "
-	                  "context_ip_id = 0x%04x, value = 0x%04x, msn = 0x%04x",
-	                  behavior, k, p, context_ip_id, value, msn);
+	rohc_decomp_debug(context, "ip_id_lsb: behavior = %d, MSN = 0x%02x, "
+	                  "%zu-bits 0x%x, p = %d", behavior, msn, ip_id_bits_nr,
+	                  ip_id_bits, p);
+
+	/* decode the IP-ID offset with LSB */
+	decode_ok = rohc_lsb_decode(lsb, ROHC_LSB_REF_0, 0, ip_id_bits,
+	                            ip_id_bits_nr, p, &ip_id_offset32);
+	if(!decode_ok)
+	{
+		rohc_warning(context->decompressor, ROHC_TRACE_DECOMP, context->profile->id,
+		             "failed to decode %zu IP-ID offset bits 0x%x with "
+		             "p = %u", ip_id_bits_nr, ip_id_bits, p);
+		goto error;
+	}
+	assert((ip_id_offset32 & 0xffff) == ip_id_offset32);
+	*ip_id_offset = (uint16_t) ip_id_offset32;
+	rohc_decomp_debug(context, "decoded IP-ID offset = 0x%04x (%zu bits "
+	                  "0x%x with p = %d)", *ip_id_offset, ip_id_bits_nr,
+	                  ip_id_bits, p);
 
-	switch(behavior)
+	/* compute the IP-ID from the IP-ID offset */
+	if(behavior == IP_ID_BEHAVIOR_SEQ)
 	{
-		case IP_ID_BEHAVIOR_SEQ:
-			ip_id = context_ip_id + 1;
-			ip_id_offset = ip_id - msn;
-			ip_id_offset = d_c_lsb(context, k, p, context_ip_id - msn,
-			                       ip_id_offset);
-			rohc_decomp_debug(context, "new ip_id = 0x%04x, ip_id_offset = "
-			                  "0x%04x, value = 0x%04x", ip_id, ip_id_offset,
-			                  value);
-			assert(ip_id_offset == value); /* TODO: should not assert */
-			return ip_id;
-		case IP_ID_BEHAVIOR_SEQ_SWAP:
-			ip_id = swab16(context_ip_id);
-			ip_id++;
-			ip_id_offset = ip_id - msn;
-			ip_id_offset = d_c_lsb(context, k, p, ip_id - 1 - msn, ip_id_offset);
-			rohc_decomp_debug(context, "new ip_id = 0x%04x, ip_id_offset = "
-			                  "0x%04x, value = 0x%04x", ip_id, ip_id_offset,
-			                  value);
-			assert(ip_id_offset == value); /* TODO: should not assert */
-			return ip_id;
+		*ip_id = (*ip_id_offset) + msn;
+	}
+	else /* IP_ID_BEHAVIOR_SEQ_SWAP */
+	{
+		/* compute the IP-ID from the IP-ID offset */
+		*ip_id = swab16((*ip_id_offset) + msn);
 	}
+	rohc_decomp_debug(context, "decoded IP-ID = 0x%04x", *ip_id);
 
-	return 0;
+	return true;
+
+error:
+	return false;
 }
 
 
@@ -470,30 +420,38 @@ uint16_t d_ip_id_lsb(const struct rohc_d
  */
 int d_optional_ip_id_lsb(const struct rohc_decomp_ctxt *const context,
                          const uint8_t *const rohc_data,
+                         const struct rohc_lsb_decode *const lsb,
                          const int behavior,
                          const int indicator,
-                         const uint16_t context_ip_id,
-                         uint16_t *const ip_id,
-                         const uint16_t msn)
+                         const uint16_t msn,
+                         uint16_t *const ip_id_offset,
+                         uint16_t *const ip_id)
 {
 	size_t length = 0;
 
 	assert(context != NULL);
 
-	rohc_decomp_debug(context, "behavior = %d, indicator = %d, "
-	                  "context_ip_id = 0x%04x, msn = 0x%04x", behavior,
-	                  indicator, context_ip_id, msn);
+	rohc_decomp_debug(context, "optional_ip_id_lsb: behavior = %d, "
+	                  "indicator = %d, MSN = 0x%04x", behavior, indicator,
+	                  msn);
 
 	switch(behavior)
 	{
 		case IP_ID_BEHAVIOR_SEQ:
 			if(indicator == 0)
 			{
-				*ip_id = (context_ip_id & 0xff00) |
-				         d_ip_id_lsb(context, behavior, 8, 3, context_ip_id,
-				                     rohc_data[0], msn);
-				rohc_decomp_debug(context, "read ip_id = 0x%04x -> 0x%04x",
-				                  rohc_data[0], *ip_id);
+				const uint16_t ip_id_lsb = rohc_data[0] & 0xff;
+				const bool decode_ok =
+					d_ip_id_lsb(context, lsb, behavior, msn, ip_id_lsb, 8, 3,
+					            ip_id_offset, ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
+				rohc_decomp_debug(context, "decoded IP-ID from 8-bit LSB encoded "
+				                  "0x%02x = 0x%04x", rohc_data[0], *ip_id);
 				length++;
 			}
 			else
@@ -501,19 +459,25 @@ int d_optional_ip_id_lsb(const struct ro
 				memcpy(ip_id, rohc_data, sizeof(uint16_t));
 				length += sizeof(uint16_t);
 				*ip_id = rohc_ntoh16(*ip_id);
-				rohc_decomp_debug(context, "read ip_id = 0x%04x", *ip_id);
+				*ip_id_offset = (*ip_id) - msn;
+				rohc_decomp_debug(context, "irregular IP-ID = 0x%04x", *ip_id);
 			}
 			break;
 		case IP_ID_BEHAVIOR_SEQ_SWAP:
-		{
-			const uint16_t swapped_context_ip_id = swab16(context_ip_id);
 			if(indicator == 0)
 			{
-				*ip_id = (swapped_context_ip_id & 0xff00) |
-				          d_ip_id_lsb(context, behavior, 8, 3, context_ip_id,
-				                      rohc_data[0], msn);
-				rohc_decomp_debug(context, "read ip_id = 0x%04x -> 0x%04x",
-				                  rohc_data[0], *ip_id);
+				const uint16_t ip_id_lsb = rohc_data[0] & 0xff;
+				const bool decode_ok =
+					d_ip_id_lsb(context, lsb, behavior, msn, ip_id_lsb, 8, 3,
+					            ip_id_offset, ip_id);
+				if(!decode_ok)
+				{
+					rohc_decomp_warn(context, "failed to decode the W-LSB-encoded "
+					                 "IP-ID offset");
+					goto error;
+				}
+				rohc_decomp_debug(context, "decoded IP-ID from 8-bit LSB encoded "
+				                  "0x%02x = 0x%04x", rohc_data[0], *ip_id);
 				length++;
 			}
 			else
@@ -521,10 +485,10 @@ int d_optional_ip_id_lsb(const struct ro
 				memcpy(ip_id, rohc_data, sizeof(uint16_t));
 				length += sizeof(uint16_t);
 				*ip_id = rohc_ntoh16(*ip_id);
-				rohc_decomp_debug(context, "read ip_id = 0x%04x", *ip_id);
+				*ip_id_offset = (*ip_id) - msn;
+				rohc_decomp_debug(context, "irregular IP-ID = 0x%04x", *ip_id);
 			}
 			break;
-		}
 		case IP_ID_BEHAVIOR_RAND:
 			break;
 		case IP_ID_BEHAVIOR_ZERO:
@@ -535,6 +499,9 @@ int d_optional_ip_id_lsb(const struct ro
 	}
 
 	return length;
+
+error:
+	return -1;
 }
 
 

=== modified file 'src/decomp/schemes/rfc4996.h'
--- src/decomp/schemes/rfc4996.h	2014-06-27 15:21:48 +0000
+++ src/decomp/schemes/rfc4996.h	2014-07-20 10:02:57 +0000
@@ -83,24 +83,27 @@ uint32_t d_field_scaling(const uint32_t
 unsigned int rsf_index_dec( unsigned int rsf_index );
 
 // RFC4996 page 75
-uint16_t d_ip_id_lsb(const struct rohc_decomp_ctxt *const context,
-                     const int behavior,
-                     const unsigned int k,
-                     const unsigned int p,
-                     const uint16_t context_ip_id,
-                     const uint16_t value,
-                     const uint16_t msn)
-	__attribute__((warn_unused_result, nonnull(1)));
+bool d_ip_id_lsb(const struct rohc_decomp_ctxt *const context,
+                 const struct rohc_lsb_decode *const lsb,
+                 const int behavior,
+                 const uint32_t msn,
+                 const uint16_t ip_id_bits,
+                 const uint16_t ip_id_bits_nr,
+                 const rohc_lsb_shift_t p,
+                 uint16_t *const ip_id_offset,
+                 uint16_t *const ip_id)
+	__attribute__((warn_unused_result, nonnull(1, 2, 8, 9)));
 
 // RFC4996 page 76
 int d_optional_ip_id_lsb(const struct rohc_decomp_ctxt *const context,
                          const uint8_t *const rohc_data,
+                         const struct rohc_lsb_decode *const lsb,
                          const int behavior,
                          const int indicator,
-                         const uint16_t context_ip_id,
-                         uint16_t *const ip_id,
-                         const uint16_t msn)
-	__attribute__((warn_unused_result, nonnull(1, 2, 6)));
+                         const uint16_t msn,
+                         uint16_t *const ip_id_offset,
+                         uint16_t *const ip_id)
+	__attribute__((warn_unused_result, nonnull(1, 2, 3, 7, 8)));
 
 int dscp_decode(const uint8_t *const rohc_data,
                 const uint8_t context_value,

Attachment: signature.asc
Description: PGP signature


References