interface: add support for proper checksum handling 25/42425/8
authorMohsin Kazmi <[email protected]>
Mon, 17 Mar 2025 13:37:18 +0000 (13:37 +0000)
committerBenoit Ganne <[email protected]>
Mon, 16 Jun 2025 09:17:57 +0000 (09:17 +0000)
Type: improvement

Signed-off-by: Mohsin Kazmi <[email protected]>
Change-Id: I035acc97abb1ce63ce09019b790ee81c803d5d90

src/vnet/interface_output.c

index 8f023a8..7991f6c 100644 (file)
@@ -167,10 +167,32 @@ vnet_interface_output_trace (vlib_main_t * vm,
 }
 
 static_always_inline void
-vnet_interface_output_handle_offload (vlib_main_t *vm, vlib_buffer_t *b)
+vnet_interface_output_handle_offload (vlib_main_t *vm, vlib_buffer_t *b,
+                                     vnet_hw_if_caps_t caps)
 {
+  u8 oflags;
   if (b->flags & VNET_BUFFER_F_GSO)
     return;
+  oflags = vnet_buffer (b)->oflags;
+
+  if ((caps & VNET_HW_IF_CAP_TX_CKSUM) == VNET_HW_IF_CAP_TX_CKSUM)
+    {
+      if (((oflags & VNET_BUFFER_OFFLOAD_F_TNL_IPIP) !=
+          VNET_BUFFER_OFFLOAD_F_TNL_IPIP) &&
+         ((oflags & VNET_BUFFER_OFFLOAD_F_TNL_VXLAN) !=
+          VNET_BUFFER_OFFLOAD_F_TNL_VXLAN))
+       return;
+
+      if (((oflags & VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM) !=
+          VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM) &&
+         ((oflags & VNET_BUFFER_OFFLOAD_F_OUTER_UDP_CKSUM) !=
+          VNET_BUFFER_OFFLOAD_F_OUTER_UDP_CKSUM))
+       {
+         if ((caps & VNET_HW_IF_CAP_TX_FIXED_OFFSET) !=
+             VNET_HW_IF_CAP_TX_FIXED_OFFSET)
+           return;
+       }
+    }
   vnet_calc_checksums_inline (vm, b, b->flags & VNET_BUFFER_F_IS_IP4,
                              b->flags & VNET_BUFFER_F_IS_IP6);
   vnet_calc_outer_checksums_inline (vm, b);
@@ -180,8 +202,8 @@ static_always_inline uword
 vnet_interface_output_node_inline (vlib_main_t *vm, u32 sw_if_index,
                                   vlib_combined_counter_main_t *ccm,
                                   vlib_buffer_t **b, void **p,
-                                  u32 config_index, u8 arc, u32 n_left,
-                                  int processing_level)
+                                  vnet_hw_if_caps_t caps, u32 config_index,
+                                  u8 arc, u32 n_left, int processing_level)
 {
   u32 n_bytes = 0;
   u32 n_bytes0, n_bytes1, n_bytes2, n_bytes3;
@@ -257,10 +279,10 @@ vnet_interface_output_node_inline (vlib_main_t *vm, u32 sw_if_index,
 
       if (processing_level >= 1 && (or_flags & VNET_BUFFER_F_OFFLOAD))
        {
-         vnet_interface_output_handle_offload (vm, b[0]);
-         vnet_interface_output_handle_offload (vm, b[1]);
-         vnet_interface_output_handle_offload (vm, b[2]);
-         vnet_interface_output_handle_offload (vm, b[3]);
+         vnet_interface_output_handle_offload (vm, b[0], caps);
+         vnet_interface_output_handle_offload (vm, b[1], caps);
+         vnet_interface_output_handle_offload (vm, b[2], caps);
+         vnet_interface_output_handle_offload (vm, b[3], caps);
        }
 
       n_left -= 4;
@@ -295,8 +317,8 @@ vnet_interface_output_node_inline (vlib_main_t *vm, u32 sw_if_index,
            vlib_increment_combined_counter (ccm, ti, tx_swif0, 1, n_bytes0);
        }
 
-      if (processing_level >= 1)
-       vnet_interface_output_handle_offload (vm, b[0]);
+      if ((processing_level >= 1) && (b[0]->flags & VNET_BUFFER_F_OFFLOAD))
+       vnet_interface_output_handle_offload (vm, b[0], caps);
 
       n_left -= 1;
       b += 1;
@@ -639,27 +661,31 @@ VLIB_NODE_FN (vnet_interface_output_node)
 
   ccm = im->combined_sw_if_counters + VNET_INTERFACE_COUNTER_TX;
 
-  /* if not all three flags IP4_,TCP_,UDP_CKSUM set, do compute them
-   * here before sending to the interface */
-  if ((hi->caps & VNET_HW_IF_CAP_TX_CKSUM) != VNET_HW_IF_CAP_TX_CKSUM)
+  /* if not all three flags IP4_,TCP_,UDP_, IP4_OUTER_, UDP_OUTER_CKSUM set, do
+   * compute them here before sending to the interface */
+  if ((hi->caps & VNET_HW_IF_CAP_TX_CKSUM_MASK) !=
+      VNET_HW_IF_CAP_TX_CKSUM_MASK)
     do_tx_offloads = 1;
 
   // basic processing
   if (do_tx_offloads == 0 && arc_or_subif == 0 && is_parr == 0)
     n_bytes = vnet_interface_output_node_inline (
-      vm, sw_if_index, ccm, bufs, NULL, config_index, arc, n_buffers, 0);
+      vm, sw_if_index, ccm, bufs, NULL, 0, config_index, arc, n_buffers, 0);
   // basic processing + tx offloads
   else if (do_tx_offloads == 1 && arc_or_subif == 0 && is_parr == 0)
-    n_bytes = vnet_interface_output_node_inline (
-      vm, sw_if_index, ccm, bufs, NULL, config_index, arc, n_buffers, 1);
+    n_bytes = vnet_interface_output_node_inline (vm, sw_if_index, ccm, bufs,
+                                                NULL, hi->caps, config_index,
+                                                arc, n_buffers, 1);
   // basic processing + tx offloads + vlans + arcs
   else if (do_tx_offloads == 1 && arc_or_subif == 1 && is_parr == 0)
-    n_bytes = vnet_interface_output_node_inline (
-      vm, sw_if_index, ccm, bufs, NULL, config_index, arc, n_buffers, 2);
+    n_bytes = vnet_interface_output_node_inline (vm, sw_if_index, ccm, bufs,
+                                                NULL, hi->caps, config_index,
+                                                arc, n_buffers, 2);
   // basic processing + tx offloads + vlans + arcs + multi-txqs
   else
-    n_bytes = vnet_interface_output_node_inline (
-      vm, sw_if_index, ccm, bufs, p, config_index, arc, n_buffers, 3);
+    n_bytes = vnet_interface_output_node_inline (vm, sw_if_index, ccm, bufs, p,
+                                                hi->caps, config_index, arc,
+                                                n_buffers, 3);
 
   from = vlib_frame_vector_args (frame);
   if (PREDICT_TRUE (next_index == VNET_INTERFACE_OUTPUT_NEXT_TX))