pg: icmp4 & tcp4 ip length issue

length in ip4 header could be 0, when the length edit is fixed
this happens if length is not specified or size is specified as, f.g., 100-100
As a result, tcp and icmp would get a negative value for checksum calculation

Change-Id: I55fa1f5e95717ea4149cb3b8c9b73caf88ae7f98
Signed-off-by: Kingwel Xie <kingwel.xie@ericsson.com>
diff --git a/src/vnet/ip/icmp4.c b/src/vnet/ip/icmp4.c
index 3626e96..a598ca9 100644
--- a/src/vnet/ip/icmp4.c
+++ b/src/vnet/ip/icmp4.c
@@ -653,7 +653,13 @@
       ASSERT (p0->current_data == 0);
       ip0 = (void *) (p0->data + ip_offset);
       icmp0 = (void *) (p0->data + icmp_offset);
-      len0 = clib_net_to_host_u16 (ip0->length) - ip4_header_bytes (ip0);
+
+      /* if IP length has been specified, then calculate the length based on buffer */
+      if (ip0->length == 0)
+	len0 = vlib_buffer_length_in_chain (vm, p0) - icmp_offset;
+      else
+	len0 = clib_net_to_host_u16 (ip0->length) - icmp_offset;
+
       icmp0->checksum =
 	~ip_csum_fold (ip_incremental_checksum (0, icmp0, len0));
     }
diff --git a/src/vnet/tcp/tcp_pg.c b/src/vnet/tcp/tcp_pg.c
index 3be4592..45eaed9 100644
--- a/src/vnet/tcp/tcp_pg.c
+++ b/src/vnet/tcp/tcp_pg.c
@@ -77,7 +77,11 @@
       ASSERT (p0->current_data == 0);
       ip0 = (void *) (p0->data + ip_offset);
       tcp0 = (void *) (p0->data + tcp_offset);
-      tcp_len0 = clib_net_to_host_u16 (ip0->length) - sizeof (ip0[0]);
+      /* if IP length has been specified, then calculate the length based on buffer */
+      if (ip0->length == 0)
+	tcp_len0 = vlib_buffer_length_in_chain (vm, p0) - tcp_offset;
+      else
+	tcp_len0 = clib_net_to_host_u16 (ip0->length) - tcp_offset;
 
       /* Initialize checksum with header. */
       if (BITS (sum0) == 32)