From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 2134145E37; Thu, 5 Dec 2024 10:20:10 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id ABDA9402C4; Thu, 5 Dec 2024 10:20:09 +0100 (CET) Received: from m16.mail.163.com (m16.mail.163.com [117.135.210.4]) by mails.dpdk.org (Postfix) with ESMTP id CD1EF40B99 for ; Wed, 4 Dec 2024 11:06:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com; s=s110527; h=From:Subject:Date:Message-ID:MIME-Version; bh=FR7e6 yV3QqXGckwp6fLy9SMia3JkfyjtmGUH4M8gnh4=; b=KPkd/S+bdj89fPw9gm7l0 IITFSk6THowuvM8MWckzJBcLSv/iYKKrQ5K7ARBKxXXW7rPVXW1qZNVmopSUUt9V 0OYLIc5FPuWwbGnIgZNvfBkiFx/BBAIkIOxja1uvLGe4AFt/pgf6yJ4iYK44G5tF ecGkN5s918MS+ERy47NVQI= Received: from localhost.localdomain (unknown [183.156.80.93]) by gzsmtp3 (Coremail) with SMTP id PigvCgAn3A2OKVBnF4_cEQ--.33546S2; Wed, 04 Dec 2024 18:06:08 +0800 (CST) From: Caiqiang Liao <18859237562@163.com> To: maxime.coquelin@redhat.com, chenbox@nvidia.com Cc: dev@dpdk.org, Caiqiang Liao <18859237562@163.com> Subject: [PATCH] lib/gso: gso Adds the processing of IPV6 tcp packets Date: Wed, 4 Dec 2024 18:05:51 +0800 Message-ID: <20241204100551.2914-1-18859237562@163.com> X-Mailer: git-send-email 2.43.0.windows.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID: PigvCgAn3A2OKVBnF4_cEQ--.33546S2 X-Coremail-Antispam: 1Uf129KBjvAXoW3urW5Wr1rWryUKw4Utw1rtFb_yoW8JFy7to W0q3ykuw1Igr1rur1vkry2qF97ZwsYga18Cr4FqF4jyrn0gr4DCwn3G3yfXF45Jr40gF1q va4xKa4fXa17Wrn7n29KB7ZKAUJUUUU8529EdanIXcx71UUUUU7v73VFW2AGmfu7bjvjm3 AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxUbwZ2UUUUU X-Originating-IP: [183.156.80.93] X-CM-SenderInfo: rprymkyzstlkiws6il2tof0z/xtbB0hCrtWdQIbf0cwAAs6 X-Mailman-Approved-At: Thu, 05 Dec 2024 10:20:09 +0100 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The rte_gso_segment function increases the processing of IPV6 tcp packets Signed-off-by: Caiqiang Liao <18859237562@163.com> --- lib/gso/gso_common.h | 38 +++++++++++++++++++ lib/gso/gso_tcp6.c | 60 +++++++++++++++++++++++++++++ lib/gso/gso_tcp6.h | 41 ++++++++++++++++++++ lib/gso/gso_tunnel_tcp6.c | 80 +++++++++++++++++++++++++++++++++++++++ lib/gso/gso_tunnel_tcp6.h | 44 +++++++++++++++++++++ lib/gso/meson.build | 2 + lib/gso/rte_gso.c | 18 +++++++++ 7 files changed, 283 insertions(+) create mode 100644 lib/gso/gso_tcp6.c create mode 100644 lib/gso/gso_tcp6.h create mode 100644 lib/gso/gso_tunnel_tcp6.c create mode 100644 lib/gso/gso_tunnel_tcp6.h diff --git a/lib/gso/gso_common.h b/lib/gso/gso_common.h index d1c1b73091..52f3d4f6ca 100644 --- a/lib/gso/gso_common.h +++ b/lib/gso/gso_common.h @@ -38,6 +38,20 @@ #define IS_IPV4_UDP(flag) (((flag) & (RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_IPV4)) == \ (RTE_MBUF_F_TX_UDP_SEG | RTE_MBUF_F_TX_IPV4)) +#define IS_IPV6_TCP(flag) (((flag) & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_IPV6)) == \ + (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_IPV6)) + +#define IS_IPV4_VXLAN_TCP6(flag) (((flag) & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_IPV6 | \ + RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_TUNNEL_MASK)) == \ + (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_IPV6 | RTE_MBUF_F_TX_OUTER_IPV4 | \ + RTE_MBUF_F_TX_TUNNEL_VXLAN)) + +#define IS_IPV4_GRE_TCP6(flag) (((flag) & (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_IPV6 | \ + RTE_MBUF_F_TX_OUTER_IPV4 | RTE_MBUF_F_TX_TUNNEL_MASK)) == \ + (RTE_MBUF_F_TX_TCP_SEG | RTE_MBUF_F_TX_IPV6 | RTE_MBUF_F_TX_OUTER_IPV4 | \ + RTE_MBUF_F_TX_TUNNEL_GRE)) + + /** * Internal function which updates the UDP header of a packet, following * segmentation. This is required to update the header's datagram length field. @@ -110,6 +124,30 @@ update_ipv4_header(struct rte_mbuf *pkt, uint16_t l3_offset, uint16_t id) ipv4_hdr->packet_id = rte_cpu_to_be_16(id); } +/** + * Internal function which updates the IPv6 header of a packet, following + * segmentation. This is required to update the header's 'total_length' field, + * to reflect the reduced length of the now-segmented packet. Furthermore, the + * header's 'packet_id' field must be updated to reflect the new ID of the + * now-segmented packet. + * + * @param pkt + * The packet containing the IPv6 header. + * @param l3_offset + * The offset of the IPv6 header from the start of the packet. + * @param id + * The new ID of the packet. + */ +static inline void +update_ipv6_header(struct rte_mbuf *pkt, uint16_t l3_offset) +{ + struct rte_ipv6_hdr *ipv6_hdr; + + ipv6_hdr = (struct rte_ipv6_hdr *)(rte_pktmbuf_mtod(pkt, char *) + l3_offset); + ipv6_hdr->payload_len = htons(pkt->pkt_len - l3_offset - sizeof(struct rte_ipv6_hdr)); +} + + /** * Internal function which divides the input packet into small segments. * Each of the newly-created segments is organized as a two-segment MBUF, diff --git a/lib/gso/gso_tcp6.c b/lib/gso/gso_tcp6.c new file mode 100644 index 0000000000..a77d26663e --- /dev/null +++ b/lib/gso/gso_tcp6.c @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017 Intel Corporation + */ + +#include "gso_common.h" +#include "gso_tcp6.h" + +static void +update_ipv6_tcp_headers(struct rte_mbuf *pkt, struct rte_mbuf **segs, + uint16_t nb_segs) +{ + struct rte_ipv6_hdr *ipv6_hdr; + struct rte_tcp_hdr *tcp_hdr; + uint32_t sent_seq; + uint16_t tail_idx, i; + uint16_t l3_offset = pkt->l2_len; + uint16_t l4_offset = l3_offset + pkt->l3_len; + + ipv6_hdr = (struct rte_ipv6_hdr *)(rte_pktmbuf_mtod(pkt, char*) + + l3_offset); + tcp_hdr = (struct rte_tcp_hdr *)((char *)ipv6_hdr + pkt->l3_len); + sent_seq = ntohl(tcp_hdr->sent_seq); + tail_idx = nb_segs - 1; + + for (i = 0; i < nb_segs; i++) { + update_ipv6_header(segs[i], l3_offset); + update_tcp_header(segs[i], l4_offset, sent_seq, i < tail_idx); + sent_seq += (segs[i]->pkt_len - segs[i]->data_len); + } +} + +int +gso_tcp6_segment(struct rte_mbuf *pkt, uint16_t gso_size, + struct rte_mempool *direct_pool, + struct rte_mempool *indirect_pool, + struct rte_mbuf **pkts_out, + uint16_t nb_pkts_out) +{ + uint16_t pyld_unit_size, hdr_offset; + int ret = 1; + + hdr_offset = pkt->l2_len; + hdr_offset += pkt->l3_len + pkt->l4_len; + + /* Don't process the packet without data */ + if (hdr_offset >= pkt->pkt_len) { + return 0; + } + pyld_unit_size = gso_size - hdr_offset; + + /* Segment the payload */ + ret = gso_do_segment(pkt, hdr_offset, pyld_unit_size, direct_pool, + indirect_pool, pkts_out, nb_pkts_out); + if (ret <= 1) + return ret; + + update_ipv6_tcp_headers(pkt, pkts_out, ret); + + return ret; +} diff --git a/lib/gso/gso_tcp6.h b/lib/gso/gso_tcp6.h new file mode 100644 index 0000000000..8fa5c8bedb --- /dev/null +++ b/lib/gso/gso_tcp6.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017 Intel Corporation + */ + +#ifndef _GSO_TCP6_H_ +#define _GSO_TCP6_H_ + +#include + +/** + * Segment an IPv6/TCP packet. This function doesn't check if the input + * packet has correct checksums, and doesn't update checksums for output + * GSO segments. Furthermore, it doesn't process IP fragment packets. + * + * @param pkt + * The packet mbuf to segment. + * @param gso_size + * The max length of a GSO segment, measured in bytes. + * @param direct_pool + * MBUF pool used for allocating direct buffers for output segments. + * @param indirect_pool + * MBUF pool used for allocating indirect buffers for output segments. + * @param pkts_out + * Pointer array used to store the MBUF addresses of output GSO + * segments, when the function succeeds. If the memory space in + * pkts_out is insufficient, it fails and returns -EINVAL. + * @param nb_pkts_out + * The max number of items that 'pkts_out' can keep. + * + * @return + * - The number of GSO segments filled in pkts_out on success. + * - Return -ENOMEM if run out of memory in MBUF pools. + * - Return -EINVAL for invalid parameters. + */ +int gso_tcp6_segment(struct rte_mbuf *pkt, uint16_t gso_size, + struct rte_mempool *direct_pool, + struct rte_mempool *indirect_pool, + struct rte_mbuf **pkts_out, + uint16_t nb_pkts_out); + +#endif diff --git a/lib/gso/gso_tunnel_tcp6.c b/lib/gso/gso_tunnel_tcp6.c new file mode 100644 index 0000000000..ad6ec2f7c3 --- /dev/null +++ b/lib/gso/gso_tunnel_tcp6.c @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017 Intel Corporation + */ + +#include "gso_common.h" +#include "gso_tunnel_tcp6.h" + +static void +update_tunnel_ipv6_tcp_headers(struct rte_mbuf *pkt, struct rte_mbuf **segs, + uint16_t nb_segs) +{ + struct rte_ipv4_hdr *out_ipv4_hdr; + struct rte_ipv6_hdr *ipv6_hdr; + struct rte_tcp_hdr *tcp_hdr; + uint32_t sent_seq; + uint16_t outer_id, tail_idx, i; + uint16_t outer_ipv4_offset, inner_ipv6_offset; + uint16_t udp_gre_offset, tcp_offset; + uint8_t update_udp_hdr; + + outer_ipv4_offset = pkt->outer_l2_len; + udp_gre_offset = outer_ipv4_offset + pkt->outer_l3_len; + inner_ipv6_offset = udp_gre_offset + pkt->l2_len; + tcp_offset = inner_ipv6_offset + pkt->l3_len; + + /* Outer IPv4 header. */ + out_ipv4_hdr = (struct rte_ipv4_hdr *)(rte_pktmbuf_mtod(pkt, char *) + + outer_ipv4_offset); + outer_id = ntohs(out_ipv4_hdr->packet_id); + + /* Inner IPv6 header. */ + ipv6_hdr = (struct rte_ipv6_hdr *)(rte_pktmbuf_mtod(pkt, char *) + + inner_ipv6_offset); + + tcp_hdr = (struct rte_tcp_hdr *)((char *)ipv6_hdr + pkt->l3_len); + sent_seq = ntohl(tcp_hdr->sent_seq); + tail_idx = nb_segs - 1; + + /* Only update UDP header for VxLAN packets. */ + update_udp_hdr = (pkt->ol_flags & RTE_MBUF_F_TX_TUNNEL_VXLAN) ? 1 : 0; + + for (i = 0; i < nb_segs; i++) { + update_ipv4_header(segs[i], outer_ipv4_offset, outer_id); + if (update_udp_hdr) + update_udp_header(segs[i], udp_gre_offset); + update_ipv6_header(segs[i], inner_ipv6_offset); + update_tcp_header(segs[i], tcp_offset, sent_seq, i < tail_idx); + outer_id++; + sent_seq += (segs[i]->pkt_len - segs[i]->data_len); + } +} + +int +gso_tunnel_tcp6_segment(struct rte_mbuf *pkt, + uint16_t gso_size, + struct rte_mempool *direct_pool, + struct rte_mempool *indirect_pool, + struct rte_mbuf **pkts_out, + uint16_t nb_pkts_out) +{ + uint16_t pyld_unit_size, hdr_offset; + int ret = 1; + + hdr_offset = pkt->outer_l2_len + pkt->outer_l3_len + pkt->l2_len; + hdr_offset += pkt->l3_len + pkt->l4_len; + + /* Don't process the packet without data */ + if (hdr_offset >= pkt->pkt_len) { + return 0; + } + pyld_unit_size = gso_size - hdr_offset; + + /* Segment the payload */ + ret = gso_do_segment(pkt, hdr_offset, pyld_unit_size, direct_pool, + indirect_pool, pkts_out, nb_pkts_out); + if (ret <= 1) + return ret; + update_tunnel_ipv6_tcp_headers(pkt, pkts_out, ret); + return ret; +} diff --git a/lib/gso/gso_tunnel_tcp6.h b/lib/gso/gso_tunnel_tcp6.h new file mode 100644 index 0000000000..d2e0e051cb --- /dev/null +++ b/lib/gso/gso_tunnel_tcp6.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2017 Intel Corporation + */ + +#ifndef _GSO_TUNNEL_TCP6_H_ +#define _GSO_TUNNEL_TCP6_H_ + +#include + +/** + * Segment a tunneling packet with inner TCP/IPv6 headers. This function + * doesn't check if the input packet has correct checksums, and doesn't + * update checksums for output GSO segments. Furthermore, it doesn't + * process IP fragment packets. + * + * @param pkt + * The packet mbuf to segment. + * @param gso_size + * The max length of a GSO segment, measured in bytes. + * @param direct_pool + * MBUF pool used for allocating direct buffers for output segments. + * @param indirect_pool + * MBUF pool used for allocating indirect buffers for output segments. + * @param pkts_out + * Pointer array used to store the MBUF addresses of output GSO + * segments, when it succeeds. If the memory space in pkts_out is + * insufficient, it fails and returns -EINVAL. + * @param nb_pkts_out + * The max number of items that 'pkts_out' can keep. + * + * @return + * - The number of GSO segments filled in pkts_out on success. + * - Return -ENOMEM if run out of memory in MBUF pools. + * - Return -EINVAL for invalid parameters. + */ +int +gso_tunnel_tcp6_segment(struct rte_mbuf *pkt, + uint16_t gso_size, + struct rte_mempool *direct_pool, + struct rte_mempool *indirect_pool, + struct rte_mbuf **pkts_out, + uint16_t nb_pkts_out); +#endif + diff --git a/lib/gso/meson.build b/lib/gso/meson.build index 622411df8f..fb9980adb0 100644 --- a/lib/gso/meson.build +++ b/lib/gso/meson.build @@ -5,8 +5,10 @@ sources = files( 'gso_common.c', 'gso_tcp4.c', 'gso_udp4.c', + 'gso_tcp6.c', 'gso_tunnel_tcp4.c', 'gso_tunnel_udp4.c', + 'gso_tunnel_tcp6.c', 'rte_gso.c', ) headers = files('rte_gso.h') diff --git a/lib/gso/rte_gso.c b/lib/gso/rte_gso.c index e29c7d884a..ceb57b4c62 100644 --- a/lib/gso/rte_gso.c +++ b/lib/gso/rte_gso.c @@ -10,7 +10,9 @@ #include "rte_gso.h" #include "gso_common.h" #include "gso_tcp4.h" +#include "gso_tcp6.h" #include "gso_tunnel_tcp4.h" +#include "gso_tunnel_tcp6.h" #include "gso_tunnel_udp4.h" #include "gso_udp4.h" @@ -68,6 +70,14 @@ rte_gso_segment(struct rte_mbuf *pkt, ret = gso_tunnel_udp4_segment(pkt, gso_size, direct_pool, indirect_pool, pkts_out, nb_pkts_out); + } else if ((IS_IPV4_VXLAN_TCP6(pkt->ol_flags) && + (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO)) || + ((IS_IPV4_GRE_TCP6(pkt->ol_flags) && + (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO)))) { + pkt->ol_flags &= (~RTE_MBUF_F_TX_TCP_SEG); + ret = gso_tunnel_tcp6_segment(pkt, gso_size, + direct_pool, indirect_pool, + pkts_out, nb_pkts_out); } else if (IS_IPV4_TCP(pkt->ol_flags) && (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_TCP_TSO)) { pkt->ol_flags &= (~RTE_MBUF_F_TX_TCP_SEG); @@ -79,6 +89,14 @@ rte_gso_segment(struct rte_mbuf *pkt, pkt->ol_flags &= (~RTE_MBUF_F_TX_UDP_SEG); ret = gso_udp4_segment(pkt, gso_size, direct_pool, indirect_pool, pkts_out, nb_pkts_out); + } else if ((IS_IPV6_TCP(pkt->ol_flags) && + (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO)) || + ((IS_IPV4_GRE_TCP4(pkt->ol_flags) && + (gso_ctx->gso_types & RTE_ETH_TX_OFFLOAD_GRE_TNL_TSO)))) { + pkt->ol_flags &= (~RTE_MBUF_F_TX_TCP_SEG); + ret = gso_tcp6_segment(pkt, gso_size, + direct_pool, indirect_pool, + pkts_out, nb_pkts_out); } else { ret = -ENOTSUP; /* only UDP or TCP allowed */ } -- 2.43.0.windows.1