vxlan: fix the inner packet checksum calculation 95/27395/3
authorMohsin Kazmi <sykazmi@cisco.com>
Tue, 2 Jun 2020 13:21:03 +0000 (15:21 +0200)
committerMohsin Kazmi <sykazmi@cisco.com>
Tue, 9 Jun 2020 13:18:03 +0000 (15:18 +0200)
Type: fix

Change-Id: I1da4ace9f3e548af4b5b3373d695e4214c5df2ff
Signed-off-by: Mohsin Kazmi <sykazmi@cisco.com>
src/vnet/vxlan-gbp/encap.c
src/vnet/vxlan/encap.c

index a606b89..4514fda 100644 (file)
@@ -17,6 +17,7 @@
 #include <vnet/vnet.h>
 #include <vnet/ip/ip.h>
 #include <vnet/ethernet/ethernet.h>
+#include <vnet/interface_output.h>
 #include <vnet/vxlan-gbp/vxlan_gbp.h>
 #include <vnet/qos/qos_types.h>
 #include <vnet/adj/rewrite.h>
@@ -102,8 +103,17 @@ vxlan_gbp_encap_inline (vlib_main_t * vm,
     sizeof (ip4_vxlan_gbp_header_t) : sizeof (ip6_vxlan_gbp_header_t);
   u16 const l3_len = is_ip4 ? sizeof (ip4_header_t) : sizeof (ip6_header_t);
   u32 const csum_flags = is_ip4 ? VNET_BUFFER_F_OFFLOAD_IP_CKSUM |
-    VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM :
-    VNET_BUFFER_F_IS_IP6 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM;
+    VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
+    VNET_BUFFER_F_L3_HDR_OFFSET_VALID | VNET_BUFFER_F_L4_HDR_OFFSET_VALID :
+    VNET_BUFFER_F_IS_IP6 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
+    VNET_BUFFER_F_L3_HDR_OFFSET_VALID | VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
+  u32 const inner_packet_csum_offload_flags =
+    VNET_BUFFER_F_OFFLOAD_IP_CKSUM | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
+    VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
+  u32 const inner_packet_removed_flags =
+    VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_IS_IP6 |
+    VNET_BUFFER_F_L2_HDR_OFFSET_VALID | VNET_BUFFER_F_L3_HDR_OFFSET_VALID |
+    VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
 
   while (n_left_from > 0)
     {
@@ -136,6 +146,30 @@ vxlan_gbp_encap_inline (vlib_main_t * vm,
          n_left_to_next -= 2;
          n_left_from -= 2;
 
+         u32 or_flags = b[0]->flags | b[1]->flags;
+         if (csum_offload && (or_flags & inner_packet_csum_offload_flags))
+           {
+             /* Only calculate the non-GSO packet csum offload */
+             if ((b[0]->flags & VNET_BUFFER_F_GSO) == 0)
+               {
+                 vnet_calc_checksums_inline (vm, b[0],
+                                             b[0]->flags &
+                                             VNET_BUFFER_F_IS_IP4,
+                                             b[0]->flags &
+                                             VNET_BUFFER_F_IS_IP6);
+                 b[0]->flags &= ~inner_packet_removed_flags;
+               }
+             if ((b[1]->flags & VNET_BUFFER_F_GSO) == 0)
+               {
+                 vnet_calc_checksums_inline (vm, b[1],
+                                             b[1]->flags &
+                                             VNET_BUFFER_F_IS_IP4,
+                                             b[1]->flags &
+                                             VNET_BUFFER_F_IS_IP6);
+                 b[1]->flags &= ~inner_packet_removed_flags;
+               }
+           }
+
          u32 flow_hash0 = vnet_l2_compute_flow_hash (b[0]);
          u32 flow_hash1 = vnet_l2_compute_flow_hash (b[1]);
 
@@ -353,6 +387,20 @@ vxlan_gbp_encap_inline (vlib_main_t * vm,
          n_left_from -= 1;
          n_left_to_next -= 1;
 
+         if (csum_offload && (b[0]->flags & inner_packet_csum_offload_flags))
+           {
+             /* Only calculate the non-GSO packet csum offload */
+             if ((b[0]->flags & VNET_BUFFER_F_GSO) == 0)
+               {
+                 vnet_calc_checksums_inline (vm, b[0],
+                                             b[0]->flags &
+                                             VNET_BUFFER_F_IS_IP4,
+                                             b[0]->flags &
+                                             VNET_BUFFER_F_IS_IP6);
+                 b[0]->flags &= ~inner_packet_removed_flags;
+               }
+           }
+
          u32 flow_hash0 = vnet_l2_compute_flow_hash (b[0]);
 
          /* Get next node index and adj index from tunnel next_dpo */
index 2bc221a..787758a 100644 (file)
@@ -18,6 +18,7 @@
 #include <vnet/vnet.h>
 #include <vnet/ip/ip.h>
 #include <vnet/ethernet/ethernet.h>
+#include <vnet/interface_output.h>
 #include <vnet/vxlan/vxlan.h>
 #include <vnet/qos/qos_types.h>
 #include <vnet/adj/rewrite.h>
@@ -98,8 +99,18 @@ vxlan_encap_inline (vlib_main_t * vm,
     sizeof (ip4_vxlan_header_t) : sizeof (ip6_vxlan_header_t);
   u16 const l3_len = is_ip4 ? sizeof (ip4_header_t) : sizeof (ip6_header_t);
   u32 const csum_flags = is_ip4 ? VNET_BUFFER_F_OFFLOAD_IP_CKSUM |
-    VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM :
-    VNET_BUFFER_F_IS_IP6 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM;
+    VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
+    VNET_BUFFER_F_L3_HDR_OFFSET_VALID | VNET_BUFFER_F_L4_HDR_OFFSET_VALID :
+    VNET_BUFFER_F_IS_IP6 | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
+    VNET_BUFFER_F_L3_HDR_OFFSET_VALID | VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
+  u32 const inner_packet_csum_offload_flags =
+    VNET_BUFFER_F_OFFLOAD_IP_CKSUM | VNET_BUFFER_F_OFFLOAD_UDP_CKSUM |
+    VNET_BUFFER_F_OFFLOAD_TCP_CKSUM;
+  u32 const inner_packet_removed_flags =
+    VNET_BUFFER_F_IS_IP4 | VNET_BUFFER_F_IS_IP6 |
+    VNET_BUFFER_F_L2_HDR_OFFSET_VALID | VNET_BUFFER_F_L3_HDR_OFFSET_VALID |
+    VNET_BUFFER_F_L4_HDR_OFFSET_VALID;
+
   vlib_get_buffers (vm, from, bufs, n_left_from);
 
   while (n_left_from > 0)
@@ -132,6 +143,30 @@ vxlan_encap_inline (vlib_main_t * vm,
          vlib_buffer_t *b1 = b[1];
          b += 2;
 
+         u32 or_flags = b0->flags | b1->flags;
+         if (csum_offload && (or_flags & inner_packet_csum_offload_flags))
+           {
+             /* Only calculate the non-GSO packet csum offload */
+             if ((b0->flags & VNET_BUFFER_F_GSO) == 0)
+               {
+                 vnet_calc_checksums_inline (vm, b0,
+                                             b0->flags &
+                                             VNET_BUFFER_F_IS_IP4,
+                                             b0->flags &
+                                             VNET_BUFFER_F_IS_IP6);
+                 b0->flags &= ~inner_packet_removed_flags;
+               }
+             if ((b1->flags & VNET_BUFFER_F_GSO) == 0)
+               {
+                 vnet_calc_checksums_inline (vm, b1,
+                                             b1->flags &
+                                             VNET_BUFFER_F_IS_IP4,
+                                             b1->flags &
+                                             VNET_BUFFER_F_IS_IP6);
+                 b1->flags &= ~inner_packet_removed_flags;
+               }
+           }
+
          u32 flow_hash0 = vnet_l2_compute_flow_hash (b0);
          u32 flow_hash1 = vnet_l2_compute_flow_hash (b1);
 
@@ -342,6 +377,20 @@ vxlan_encap_inline (vlib_main_t * vm,
          vlib_buffer_t *b0 = b[0];
          b += 1;
 
+         if (csum_offload && (b0->flags & inner_packet_csum_offload_flags))
+           {
+             /* Only calculate the non-GSO packet csum offload */
+             if ((b0->flags & VNET_BUFFER_F_GSO) == 0)
+               {
+                 vnet_calc_checksums_inline (vm, b0,
+                                             b0->flags &
+                                             VNET_BUFFER_F_IS_IP4,
+                                             b0->flags &
+                                             VNET_BUFFER_F_IS_IP6);
+                 b0->flags &= ~inner_packet_removed_flags;
+               }
+           }
+
          u32 flow_hash0 = vnet_l2_compute_flow_hash (b0);
 
          /* Get next node index and adj index from tunnel next_dpo */