From: Mohsin Kazmi Date: Mon, 17 Mar 2025 13:37:18 +0000 (+0000) Subject: interface: add support for proper checksum handling X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F25%2F42425%2F8;p=vpp.git interface: add support for proper checksum handling Type: improvement Signed-off-by: Mohsin Kazmi Change-Id: I035acc97abb1ce63ce09019b790ee81c803d5d90 --- diff --git a/src/vnet/interface_output.c b/src/vnet/interface_output.c index 8f023a84bfa..7991f6c90d5 100644 --- a/src/vnet/interface_output.c +++ b/src/vnet/interface_output.c @@ -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))