From ead3da8afd539440bb11100fc5ddc5cccdc0a808 Mon Sep 17 00:00:00 2001 From: Mohsin Kazmi Date: Mon, 28 Apr 2025 17:17:24 +0000 Subject: [PATCH] gso: add support for ipip tso for phyiscal interfaces Type: improvement This patch also improves software GSO handling for tunnel interfaces. Signed-off-by: Mohsin Kazmi Change-Id: I210bf74a65feef0bb39b5925bf8632ef4d627eb5 --- src/plugins/dpdk/device/common.c | 5 ++-- src/plugins/dpdk/device/device.c | 18 ++++++++++++++- src/vnet/gso/node.c | 49 ++++++++++++++++++++++++---------------- src/vnet/interface.h | 2 +- 4 files changed, 51 insertions(+), 23 deletions(-) diff --git a/src/plugins/dpdk/device/common.c b/src/plugins/dpdk/device/common.c index 0049ee84455..f496226c891 100644 --- a/src/plugins/dpdk/device/common.c +++ b/src/plugins/dpdk/device/common.c @@ -41,7 +41,8 @@ static struct { RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM, VNET_HW_IF_CAP_TX_IP4_OUTER_CKSUM }, { RTE_ETH_TX_OFFLOAD_OUTER_UDP_CKSUM, VNET_HW_IF_CAP_TX_UDP_OUTER_CKSUM }, { RTE_ETH_TX_OFFLOAD_TCP_TSO, VNET_HW_IF_CAP_TCP_GSO }, - { RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO, VNET_HW_IF_CAP_VXLAN_TNL_GSO } + { RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO, VNET_HW_IF_CAP_VXLAN_TNL_GSO }, + { RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO, VNET_HW_IF_CAP_IPIP_TNL_GSO } }; void @@ -119,7 +120,7 @@ dpdk_device_setup (dpdk_device_t * xd) /* per-device offload config */ if (xd->conf.enable_tso) txo |= RTE_ETH_TX_OFFLOAD_TCP_CKSUM | RTE_ETH_TX_OFFLOAD_TCP_TSO | - RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO; + RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO | RTE_ETH_TX_OFFLOAD_IPIP_TNL_TSO; if (xd->conf.disable_rx_scatter) rxo &= ~RTE_ETH_RX_OFFLOAD_SCATTER; diff --git a/src/plugins/dpdk/device/device.c b/src/plugins/dpdk/device/device.c index 5fd936d1743..ffa1d7a7bff 100644 --- a/src/plugins/dpdk/device/device.c +++ b/src/plugins/dpdk/device/device.c @@ -199,7 +199,7 @@ dpdk_buffer_tx_offload (dpdk_device_t * xd, vlib_buffer_t * b, int is_ip4 = b->flags & VNET_BUFFER_F_IS_IP4; u32 tso = b->flags & VNET_BUFFER_F_GSO, max_pkt_len; u32 ip_cksum, tcp_cksum, udp_cksum, outer_hdr_len = 0; - u32 outer_ip_cksum, vxlan_tunnel; + u32 outer_ip_cksum, vxlan_tunnel, ipip_tunnel; u64 ol_flags; vnet_buffer_oflags_t oflags = 0; @@ -213,6 +213,7 @@ dpdk_buffer_tx_offload (dpdk_device_t * xd, vlib_buffer_t * b, udp_cksum = oflags & VNET_BUFFER_OFFLOAD_F_UDP_CKSUM; outer_ip_cksum = oflags & VNET_BUFFER_OFFLOAD_F_OUTER_IP_CKSUM; vxlan_tunnel = oflags & VNET_BUFFER_OFFLOAD_F_TNL_VXLAN; + ipip_tunnel = oflags & VNET_BUFFER_OFFLOAD_F_TNL_IPIP; ol_flags = is_ip4 ? RTE_MBUF_F_TX_IPV4 : RTE_MBUF_F_TX_IPV6; ol_flags |= ip_cksum ? RTE_MBUF_F_TX_IP_CKSUM : 0; @@ -235,6 +236,21 @@ dpdk_buffer_tx_offload (dpdk_device_t * xd, vlib_buffer_t * b, vnet_buffer2 (b)->outer_l3_hdr_offset; outer_hdr_len = mb->outer_l2_len + mb->outer_l3_len; } + else if (ipip_tunnel) + { + ol_flags |= outer_ip_cksum ? + RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_OUTER_IP_CKSUM : + RTE_MBUF_F_TX_OUTER_IPV6; + ol_flags |= RTE_MBUF_F_TX_TUNNEL_IPIP; + mb->l2_len = 0; + mb->l3_len = + vnet_buffer (b)->l4_hdr_offset - vnet_buffer (b)->l3_hdr_offset; + mb->outer_l2_len = + vnet_buffer2 (b)->outer_l3_hdr_offset - b->current_data; + mb->outer_l3_len = + vnet_buffer (b)->l3_hdr_offset - vnet_buffer2 (b)->outer_l3_hdr_offset; + outer_hdr_len = mb->outer_l2_len + mb->outer_l3_len; + } else { mb->l2_len = vnet_buffer (b)->l3_hdr_offset - b->current_data; diff --git a/src/vnet/gso/node.c b/src/vnet/gso/node.c index 1fabe44d2ab..20c2e20cf92 100644 --- a/src/vnet/gso/node.c +++ b/src/vnet/gso/node.c @@ -486,12 +486,10 @@ drop_one_buffer_and_count (vlib_main_t * vm, vnet_main_t * vnm, } static_always_inline uword -vnet_gso_node_inline (vlib_main_t * vm, - vlib_node_runtime_t * node, - vlib_frame_t * frame, - vnet_main_t * vnm, - vnet_hw_interface_t * hi, - int is_l2, int is_ip4, int is_ip6, int do_segmentation) +vnet_gso_node_inline (vlib_main_t *vm, vlib_node_runtime_t *node, + vlib_frame_t *frame, vnet_main_t *vnm, + vnet_hw_interface_t *hi, u32 supported_caps, int is_l2, + int is_ip4, int is_ip6, int do_segmentation) { u32 *to_next; u32 next_index = node->cached_next_index; @@ -544,29 +542,25 @@ vnet_gso_node_inline (vlib_main_t * vm, if (PREDICT_FALSE (hi->sw_if_index != swif0)) { hi0 = vnet_get_sup_hw_interface (vnm, swif0); - if ((hi0->caps & VNET_HW_IF_CAP_TCP_GSO) == 0 && - (b[0]->flags & VNET_BUFFER_F_GSO)) + if ((hi0->caps & supported_caps) != supported_caps) break; } if (PREDICT_FALSE (hi->sw_if_index != swif1)) { hi1 = vnet_get_sup_hw_interface (vnm, swif1); - if (!(hi1->caps & VNET_HW_IF_CAP_TCP_GSO) && - (b[1]->flags & VNET_BUFFER_F_GSO)) + if ((hi1->caps & supported_caps) != supported_caps) break; } if (PREDICT_FALSE (hi->sw_if_index != swif2)) { hi2 = vnet_get_sup_hw_interface (vnm, swif2); - if ((hi2->caps & VNET_HW_IF_CAP_TCP_GSO) == 0 && - (b[2]->flags & VNET_BUFFER_F_GSO)) + if ((hi2->caps & supported_caps) != supported_caps) break; } if (PREDICT_FALSE (hi->sw_if_index != swif3)) { hi3 = vnet_get_sup_hw_interface (vnm, swif3); - if (!(hi3->caps & VNET_HW_IF_CAP_TCP_GSO) && - (b[3]->flags & VNET_BUFFER_F_GSO)) + if ((hi3->caps & supported_caps) != supported_caps) break; } @@ -635,18 +629,31 @@ vnet_gso_node_inline (vlib_main_t * vm, vnet_hw_interface_t *hi0; u32 next0 = 0; u32 do_segmentation0 = 0; + u32 caps = hi->caps; swif0 = vnet_buffer (b[0])->sw_if_index[VLIB_TX]; if (PREDICT_FALSE (hi->sw_if_index != swif0)) { hi0 = vnet_get_sup_hw_interface (vnm, swif0); - if ((hi0->caps & VNET_HW_IF_CAP_TCP_GSO) == 0 && - (b[0]->flags & VNET_BUFFER_F_GSO)) + caps = hi0->caps; + if ((hi0->caps & supported_caps) != supported_caps) do_segmentation0 = 1; } else do_segmentation0 = do_segmentation; + if (do_segmentation0) + { + u8 oflags = vnet_buffer (b[0])->oflags; + if ((caps & VNET_HW_IF_CAP_TCP_GSO) == VNET_HW_IF_CAP_TCP_GSO) + { + if (((oflags & VNET_BUFFER_OFFLOAD_F_TNL_VXLAN) != + VNET_BUFFER_OFFLOAD_F_TNL_VXLAN) && + ((oflags & VNET_BUFFER_OFFLOAD_F_TNL_IPIP) != + VNET_BUFFER_OFFLOAD_F_TNL_IPIP)) + do_segmentation0 = 0; + } + } /* speculatively enqueue b0 to the current next frame */ to_next[0] = bi0 = from[0]; to_next += 1; @@ -764,15 +771,19 @@ vnet_gso_inline (vlib_main_t * vm, { u32 *from = vlib_frame_vector_args (frame); vlib_buffer_t *b = vlib_get_buffer (vm, from[0]); + u32 supported_caps = + (VNET_HW_IF_CAP_TCP_GSO | VNET_HW_IF_CAP_VXLAN_TNL_GSO | + VNET_HW_IF_CAP_IPIP_TNL_GSO); + hi = vnet_get_sup_hw_interface (vnm, vnet_buffer (b)->sw_if_index[VLIB_TX]); - if (hi->caps & (VNET_HW_IF_CAP_TCP_GSO | VNET_HW_IF_CAP_VXLAN_TNL_GSO)) - return vnet_gso_node_inline (vm, node, frame, vnm, hi, + if ((hi->caps & supported_caps) == supported_caps) + return vnet_gso_node_inline (vm, node, frame, vnm, hi, supported_caps, is_l2, is_ip4, is_ip6, /* do_segmentation */ 0); else - return vnet_gso_node_inline (vm, node, frame, vnm, hi, + return vnet_gso_node_inline (vm, node, frame, vnm, hi, supported_caps, is_l2, is_ip4, is_ip6, /* do_segmentation */ 1); } diff --git a/src/vnet/interface.h b/src/vnet/interface.h index 8c5c5b177be..c6d01859058 100644 --- a/src/vnet/interface.h +++ b/src/vnet/interface.h @@ -571,7 +571,7 @@ typedef enum vnet_hw_interface_flags_t_ typedef enum vnet_hw_if_caps_t_ { - VNET_HW_INTERFACE_CAP_NONE, + VNET_HW_IF_CAP_NONE, #define _(bit, sfx, str) VNET_HW_IF_CAP_##sfx = (1 << (bit)), foreach_vnet_hw_if_caps #undef _ -- 2.16.6