diff --git a/0100-net-add-tunnel-packet-type-parsing.patch b/0100-net-add-tunnel-packet-type-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..f58ef82e8acf4910a9d238bdf805593c0563b597 --- /dev/null +++ b/0100-net-add-tunnel-packet-type-parsing.patch @@ -0,0 +1,193 @@ +From ab320703aaf1d586c8dd1eaa5d8bffeb11d27f02 Mon Sep 17 00:00:00 2001 +From: Jie Hai +Date: Fri, 14 Feb 2025 09:56:37 +0800 +Subject: [PATCH] net: add tunnel packet type parsing + +[ upstream commit 64ed7f854cf445829b525df7b27ed00a9bcc9b16 ] + +Add packet types parse for vxlan/vxlan-gpe/gtp/geneve packets. + +Signed-off-by: Jie Hai +--- + lib/net/rte_net.c | 110 ++++++++++++++++++++++++++++++++++++++++++---- + 1 file changed, 102 insertions(+), 8 deletions(-) + +diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c +index d680acc..0c32e78 100644 +--- a/lib/net/rte_net.c ++++ b/lib/net/rte_net.c +@@ -14,6 +14,9 @@ + #include + #include + #include ++#include ++#include ++#include + #include + #include + +@@ -126,7 +129,7 @@ ptype_inner_l4(uint8_t proto) + + /* get the tunnel packet type if any, update proto and off. */ + static uint32_t +-ptype_tunnel(uint16_t *proto, const struct rte_mbuf *m, ++ptype_tunnel_without_udp(uint16_t *proto, const struct rte_mbuf *m, + uint32_t *off) + { + switch (*proto) { +@@ -172,6 +175,92 @@ ptype_tunnel(uint16_t *proto, const struct rte_mbuf *m, + } + } + ++/* get the tunnel packet type with UDP port if any, update proto and off. */ ++static uint32_t ++ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m, ++ uint32_t *off, struct rte_net_hdr_lens *hdr_lens) ++{ ++ const struct rte_udp_hdr *uh; ++ struct rte_udp_hdr uh_copy; ++ uint16_t port_no; ++ ++ uh = rte_pktmbuf_read(m, *off, sizeof(*uh), &uh_copy); ++ if (unlikely(uh == NULL)) ++ return 0; ++ ++ *off += sizeof(*uh); ++ if (rte_be_to_cpu_16(uh->src_port) == RTE_GTPC_UDP_PORT) ++ port_no = rte_be_to_cpu_16(uh->src_port); ++ else ++ port_no = rte_be_to_cpu_16(uh->dst_port); ++ switch (port_no) { ++ case RTE_VXLAN_DEFAULT_PORT: { ++ *off += sizeof(struct rte_vxlan_hdr); ++ hdr_lens->inner_l2_len = RTE_ETHER_VXLAN_HLEN; ++ *proto = RTE_VXLAN_GPE_TYPE_ETH; /* just for eth header parse. */ ++ return RTE_PTYPE_TUNNEL_VXLAN; ++ } ++ case RTE_VXLAN_GPE_DEFAULT_PORT: { ++ const struct rte_vxlan_gpe_hdr *vgh; ++ struct rte_vxlan_gpe_hdr vgh_copy; ++ vgh = rte_pktmbuf_read(m, *off, sizeof(*vgh), &vgh_copy); ++ if (unlikely(vgh == NULL)) ++ return 0; ++ *off += sizeof(struct rte_vxlan_gpe_hdr); ++ hdr_lens->inner_l2_len = RTE_ETHER_VXLAN_GPE_HLEN; ++ *proto = vgh->proto; ++ ++ return RTE_PTYPE_TUNNEL_VXLAN_GPE; ++ } ++ case RTE_GTPC_UDP_PORT: ++ case RTE_GTPU_UDP_PORT: { ++ const struct rte_gtp_hdr *gh; ++ struct rte_gtp_hdr gh_copy; ++ uint8_t gtp_len; ++ uint8_t ip_ver; ++ gh = rte_pktmbuf_read(m, *off, sizeof(*gh), &gh_copy); ++ if (unlikely(gh == NULL)) ++ return 0; ++ gtp_len = sizeof(*gh); ++ if (gh->e || gh->s || gh->pn) ++ gtp_len += sizeof(struct rte_gtp_hdr_ext_word); ++ /* ++ * Check message type. If message type is 0xff, it is ++ * a GTP data packet. If not, it is a GTP control packet ++ */ ++ if (gh->msg_type == 0xff) { ++ ip_ver = *(const uint8_t *)((const char *)gh + gtp_len); ++ *proto = (ip_ver) & 0xf0; ++ } else { ++ *proto = 0; ++ } ++ *off += gtp_len; ++ hdr_lens->inner_l2_len = gtp_len + sizeof(struct rte_udp_hdr); ++ if (port_no == RTE_GTPC_UDP_PORT) ++ return RTE_PTYPE_TUNNEL_GTPC; ++ else if (port_no == RTE_GTPU_UDP_PORT) ++ return RTE_PTYPE_TUNNEL_GTPU; ++ return 0; ++ } ++ case RTE_GENEVE_DEFAULT_PORT: { ++ const struct rte_geneve_hdr *gnh; ++ struct rte_geneve_hdr gnh_copy; ++ uint16_t geneve_len; ++ gnh = rte_pktmbuf_read(m, *off, sizeof(*gnh), &gnh_copy); ++ if (unlikely(gnh == NULL)) ++ return 0; ++ geneve_len = sizeof(*gnh) + gnh->opt_len * 4; ++ *off = geneve_len; ++ *proto = gnh->proto; ++ if (gnh->proto == 0) ++ *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); ++ return RTE_PTYPE_TUNNEL_GENEVE; ++ } ++ default: ++ return 0; ++ } ++} ++ + /* parse ipv6 extended headers, update offset and return next proto */ + int + rte_net_skip_ip6_ext(uint16_t proto, const struct rte_mbuf *m, uint32_t *off, +@@ -352,7 +441,9 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, + + if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_UDP) { + hdr_lens->l4_len = sizeof(struct rte_udp_hdr); +- return pkt_type; ++ if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0) ++ return pkt_type; ++ pkt_type |= ptype_tunnel_with_udp(&proto, m, &off, hdr_lens); + } else if ((pkt_type & RTE_PTYPE_L4_MASK) == RTE_PTYPE_L4_TCP) { + const struct rte_tcp_hdr *th; + struct rte_tcp_hdr th_copy; +@@ -374,7 +465,7 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, + if ((layers & RTE_PTYPE_TUNNEL_MASK) == 0) + return pkt_type; + +- pkt_type |= ptype_tunnel(&proto, m, &off); ++ pkt_type |= ptype_tunnel_without_udp(&proto, m, &off); + hdr_lens->tunnel_len = off - prev_off; + } + +@@ -384,15 +475,16 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, + if ((layers & RTE_PTYPE_INNER_L2_MASK) == 0) + return pkt_type; + +- hdr_lens->inner_l2_len = 0; +- if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB)) { ++ if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_TEB) || ++ proto == rte_cpu_to_be_16(RTE_GENEVE_TYPE_ETH) || ++ proto == RTE_VXLAN_GPE_TYPE_ETH) { + eh = rte_pktmbuf_read(m, off, sizeof(*eh), &eh_copy); + if (unlikely(eh == NULL)) + return pkt_type; + pkt_type |= RTE_PTYPE_INNER_L2_ETHER; + proto = eh->ether_type; + off += sizeof(*eh); +- hdr_lens->inner_l2_len = sizeof(*eh); ++ hdr_lens->inner_l2_len += sizeof(*eh); + } + + if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_VLAN)) { +@@ -425,7 +517,8 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, + if ((layers & RTE_PTYPE_INNER_L3_MASK) == 0) + return pkt_type; + +- if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4)) { ++ if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4) || ++ proto == RTE_VXLAN_GPE_TYPE_IPV4) { + const struct rte_ipv4_hdr *ip4h; + struct rte_ipv4_hdr ip4h_copy; + +@@ -448,7 +541,8 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m, + } + proto = ip4h->next_proto_id; + pkt_type |= ptype_inner_l4(proto); +- } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6)) { ++ } else if (proto == rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6) || ++ proto == RTE_VXLAN_GPE_TYPE_IPV6) { + const struct rte_ipv6_hdr *ip6h; + struct rte_ipv6_hdr ip6h_copy; + int frag = 0; +-- +2.25.1 + diff --git a/0101-app-testpmd-use-packet-type-parsing-API.patch b/0101-app-testpmd-use-packet-type-parsing-API.patch new file mode 100644 index 0000000000000000000000000000000000000000..385254fd40b1725866f886137aebe29fbc9317c2 --- /dev/null +++ b/0101-app-testpmd-use-packet-type-parsing-API.patch @@ -0,0 +1,594 @@ +From f220b230f88e45f8671d82243e4add6250e53131 Mon Sep 17 00:00:00 2001 +From: Jie Hai +Date: Fri, 14 Feb 2025 09:56:38 +0800 +Subject: [PATCH] app/testpmd: use packet type parsing API + +[ upstream commit 76730c7b9b5a35d1a74d45a08153a03bdb1b26f8 ] + +1. Use rte_net_get_ptype() to parse packets instead. +2. Support TSO for packets with IPv6 extension header. + +Signed-off-by: Jie Hai +--- + app/test-pmd/csumonly.c | 522 ++++++++++------------------------------ + 1 file changed, 128 insertions(+), 394 deletions(-) + +diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c +index 21210af..4b3be71 100644 +--- a/app/test-pmd/csumonly.c ++++ b/app/test-pmd/csumonly.c +@@ -46,6 +46,7 @@ + #include + #endif + #include ++#include + + #include "testpmd.h" + +@@ -104,88 +105,6 @@ get_udptcp_checksum(struct rte_mbuf *m, void *l3_hdr, uint16_t l4_off, + return rte_ipv6_udptcp_cksum_mbuf(m, l3_hdr, l4_off); + } + +-/* Parse an IPv4 header to fill l3_len, l4_len, and l4_proto */ +-static void +-parse_ipv4(struct rte_ipv4_hdr *ipv4_hdr, struct testpmd_offload_info *info) +-{ +- struct rte_tcp_hdr *tcp_hdr; +- +- info->l3_len = rte_ipv4_hdr_len(ipv4_hdr); +- info->l4_proto = ipv4_hdr->next_proto_id; +- +- /* only fill l4_len for TCP, it's useful for TSO */ +- if (info->l4_proto == IPPROTO_TCP) { +- tcp_hdr = (struct rte_tcp_hdr *) +- ((char *)ipv4_hdr + info->l3_len); +- info->l4_len = (tcp_hdr->data_off & 0xf0) >> 2; +- } else if (info->l4_proto == IPPROTO_UDP) +- info->l4_len = sizeof(struct rte_udp_hdr); +- else +- info->l4_len = 0; +-} +- +-/* Parse an IPv6 header to fill l3_len, l4_len, and l4_proto */ +-static void +-parse_ipv6(struct rte_ipv6_hdr *ipv6_hdr, struct testpmd_offload_info *info) +-{ +- struct rte_tcp_hdr *tcp_hdr; +- +- info->l3_len = sizeof(struct rte_ipv6_hdr); +- info->l4_proto = ipv6_hdr->proto; +- +- /* only fill l4_len for TCP, it's useful for TSO */ +- if (info->l4_proto == IPPROTO_TCP) { +- tcp_hdr = (struct rte_tcp_hdr *) +- ((char *)ipv6_hdr + info->l3_len); +- info->l4_len = (tcp_hdr->data_off & 0xf0) >> 2; +- } else if (info->l4_proto == IPPROTO_UDP) +- info->l4_len = sizeof(struct rte_udp_hdr); +- else +- info->l4_len = 0; +-} +- +-/* +- * Parse an ethernet header to fill the ethertype, l2_len, l3_len and +- * ipproto. This function is able to recognize IPv4/IPv6 with optional VLAN +- * headers. The l4_len argument is only set in case of TCP (useful for TSO). +- */ +-static void +-parse_ethernet(struct rte_ether_hdr *eth_hdr, struct testpmd_offload_info *info) +-{ +- struct rte_ipv4_hdr *ipv4_hdr; +- struct rte_ipv6_hdr *ipv6_hdr; +- struct rte_vlan_hdr *vlan_hdr; +- +- info->l2_len = sizeof(struct rte_ether_hdr); +- info->ethertype = eth_hdr->ether_type; +- +- while (info->ethertype == _htons(RTE_ETHER_TYPE_VLAN) || +- info->ethertype == _htons(RTE_ETHER_TYPE_QINQ)) { +- vlan_hdr = (struct rte_vlan_hdr *) +- ((char *)eth_hdr + info->l2_len); +- info->l2_len += sizeof(struct rte_vlan_hdr); +- info->ethertype = vlan_hdr->eth_proto; +- } +- +- switch (info->ethertype) { +- case _htons(RTE_ETHER_TYPE_IPV4): +- ipv4_hdr = (struct rte_ipv4_hdr *) +- ((char *)eth_hdr + info->l2_len); +- parse_ipv4(ipv4_hdr, info); +- break; +- case _htons(RTE_ETHER_TYPE_IPV6): +- ipv6_hdr = (struct rte_ipv6_hdr *) +- ((char *)eth_hdr + info->l2_len); +- parse_ipv6(ipv6_hdr, info); +- break; +- default: +- info->l4_len = 0; +- info->l3_len = 0; +- info->l4_proto = 0; +- break; +- } +-} +- + /* Fill in outer layers length */ + static void + update_tunnel_outer(struct testpmd_offload_info *info) +@@ -195,262 +114,7 @@ update_tunnel_outer(struct testpmd_offload_info *info) + info->outer_l2_len = info->l2_len; + info->outer_l3_len = info->l3_len; + info->outer_l4_proto = info->l4_proto; +-} +- +-/* +- * Parse a GTP protocol header. +- * No optional fields and next extension header type. +- */ +-static void +-parse_gtp(struct rte_udp_hdr *udp_hdr, +- struct testpmd_offload_info *info) +-{ +- struct rte_ipv4_hdr *ipv4_hdr; +- struct rte_ipv6_hdr *ipv6_hdr; +- struct rte_gtp_hdr *gtp_hdr; +- uint8_t gtp_len = sizeof(*gtp_hdr); +- uint8_t ip_ver; +- +- /* Check udp destination port. */ +- if (udp_hdr->dst_port != _htons(RTE_GTPC_UDP_PORT) && +- udp_hdr->src_port != _htons(RTE_GTPC_UDP_PORT) && +- udp_hdr->dst_port != _htons(RTE_GTPU_UDP_PORT)) +- return; +- +- update_tunnel_outer(info); +- info->l2_len = 0; +- +- gtp_hdr = (struct rte_gtp_hdr *)((char *)udp_hdr + +- sizeof(struct rte_udp_hdr)); +- if (gtp_hdr->e || gtp_hdr->s || gtp_hdr->pn) +- gtp_len += sizeof(struct rte_gtp_hdr_ext_word); +- /* +- * Check message type. If message type is 0xff, it is +- * a GTP data packet. If not, it is a GTP control packet +- */ +- if (gtp_hdr->msg_type == 0xff) { +- ip_ver = *(uint8_t *)((char *)gtp_hdr + gtp_len); +- ip_ver = (ip_ver) & 0xf0; +- +- if (ip_ver == RTE_GTP_TYPE_IPV4) { +- ipv4_hdr = (struct rte_ipv4_hdr *)((char *)gtp_hdr + +- gtp_len); +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV4); +- parse_ipv4(ipv4_hdr, info); +- } else if (ip_ver == RTE_GTP_TYPE_IPV6) { +- ipv6_hdr = (struct rte_ipv6_hdr *)((char *)gtp_hdr + +- gtp_len); +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV6); +- parse_ipv6(ipv6_hdr, info); +- } +- } else { +- info->ethertype = 0; +- info->l4_len = 0; +- info->l3_len = 0; +- info->l4_proto = 0; +- } +- +- info->l2_len += gtp_len + sizeof(*udp_hdr); +-} +- +-/* Parse a vxlan header */ +-static void +-parse_vxlan(struct rte_udp_hdr *udp_hdr, +- struct testpmd_offload_info *info) +-{ +- struct rte_ether_hdr *eth_hdr; +- +- /* check udp destination port, RTE_VXLAN_DEFAULT_PORT (4789) is the +- * default vxlan port (rfc7348) or that the rx offload flag is set +- * (i40e only currently) +- */ +- if (udp_hdr->dst_port != _htons(RTE_VXLAN_DEFAULT_PORT)) +- return; +- +- update_tunnel_outer(info); +- +- eth_hdr = (struct rte_ether_hdr *)((char *)udp_hdr + +- sizeof(struct rte_udp_hdr) + +- sizeof(struct rte_vxlan_hdr)); +- +- parse_ethernet(eth_hdr, info); +- info->l2_len += RTE_ETHER_VXLAN_HLEN; /* add udp + vxlan */ +-} +- +-/* Parse a vxlan-gpe header */ +-static void +-parse_vxlan_gpe(struct rte_udp_hdr *udp_hdr, +- struct testpmd_offload_info *info) +-{ +- struct rte_ether_hdr *eth_hdr; +- struct rte_ipv4_hdr *ipv4_hdr; +- struct rte_ipv6_hdr *ipv6_hdr; +- struct rte_vxlan_gpe_hdr *vxlan_gpe_hdr; +- uint8_t vxlan_gpe_len = sizeof(*vxlan_gpe_hdr); +- +- /* Check udp destination port. */ +- if (udp_hdr->dst_port != _htons(vxlan_gpe_udp_port)) +- return; +- +- vxlan_gpe_hdr = (struct rte_vxlan_gpe_hdr *)((char *)udp_hdr + +- sizeof(struct rte_udp_hdr)); +- +- if (!vxlan_gpe_hdr->proto || vxlan_gpe_hdr->proto == +- RTE_VXLAN_GPE_TYPE_IPV4) { +- update_tunnel_outer(info); +- +- ipv4_hdr = (struct rte_ipv4_hdr *)((char *)vxlan_gpe_hdr + +- vxlan_gpe_len); +- +- parse_ipv4(ipv4_hdr, info); +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV4); +- info->l2_len = 0; +- +- } else if (vxlan_gpe_hdr->proto == RTE_VXLAN_GPE_TYPE_IPV6) { +- update_tunnel_outer(info); +- +- ipv6_hdr = (struct rte_ipv6_hdr *)((char *)vxlan_gpe_hdr + +- vxlan_gpe_len); +- +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV6); +- parse_ipv6(ipv6_hdr, info); +- info->l2_len = 0; +- +- } else if (vxlan_gpe_hdr->proto == RTE_VXLAN_GPE_TYPE_ETH) { +- update_tunnel_outer(info); +- +- eth_hdr = (struct rte_ether_hdr *)((char *)vxlan_gpe_hdr + +- vxlan_gpe_len); +- +- parse_ethernet(eth_hdr, info); +- } else +- return; +- +- info->l2_len += RTE_ETHER_VXLAN_GPE_HLEN; +-} +- +-/* Parse a geneve header */ +-static void +-parse_geneve(struct rte_udp_hdr *udp_hdr, +- struct testpmd_offload_info *info) +-{ +- struct rte_ether_hdr *eth_hdr; +- struct rte_ipv4_hdr *ipv4_hdr; +- struct rte_ipv6_hdr *ipv6_hdr; +- struct rte_geneve_hdr *geneve_hdr; +- uint16_t geneve_len; +- +- /* Check udp destination port. */ +- if (udp_hdr->dst_port != _htons(geneve_udp_port)) +- return; +- +- geneve_hdr = (struct rte_geneve_hdr *)((char *)udp_hdr + +- sizeof(struct rte_udp_hdr)); +- geneve_len = sizeof(struct rte_geneve_hdr) + geneve_hdr->opt_len * 4; +- if (!geneve_hdr->proto || geneve_hdr->proto == +- _htons(RTE_ETHER_TYPE_IPV4)) { +- update_tunnel_outer(info); +- ipv4_hdr = (struct rte_ipv4_hdr *)((char *)geneve_hdr + +- geneve_len); +- parse_ipv4(ipv4_hdr, info); +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV4); +- info->l2_len = 0; +- } else if (geneve_hdr->proto == _htons(RTE_ETHER_TYPE_IPV6)) { +- update_tunnel_outer(info); +- ipv6_hdr = (struct rte_ipv6_hdr *)((char *)geneve_hdr + +- geneve_len); +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV6); +- parse_ipv6(ipv6_hdr, info); +- info->l2_len = 0; +- +- } else if (geneve_hdr->proto == _htons(RTE_GENEVE_TYPE_ETH)) { +- update_tunnel_outer(info); +- eth_hdr = (struct rte_ether_hdr *)((char *)geneve_hdr + +- geneve_len); +- parse_ethernet(eth_hdr, info); +- } else +- return; +- +- info->l2_len += +- (sizeof(struct rte_udp_hdr) + sizeof(struct rte_geneve_hdr) + +- ((struct rte_geneve_hdr *)geneve_hdr)->opt_len * 4); +-} +- +-/* Parse a gre header */ +-static void +-parse_gre(struct simple_gre_hdr *gre_hdr, struct testpmd_offload_info *info) +-{ +- struct rte_ether_hdr *eth_hdr; +- struct rte_ipv4_hdr *ipv4_hdr; +- struct rte_ipv6_hdr *ipv6_hdr; +- uint8_t gre_len = 0; +- +- gre_len += sizeof(struct simple_gre_hdr); +- +- if (gre_hdr->flags & _htons(GRE_KEY_PRESENT)) +- gre_len += GRE_EXT_LEN; +- if (gre_hdr->flags & _htons(GRE_SEQUENCE_PRESENT)) +- gre_len += GRE_EXT_LEN; +- if (gre_hdr->flags & _htons(GRE_CHECKSUM_PRESENT)) +- gre_len += GRE_EXT_LEN; +- +- if (gre_hdr->proto == _htons(RTE_ETHER_TYPE_IPV4)) { +- update_tunnel_outer(info); +- +- ipv4_hdr = (struct rte_ipv4_hdr *)((char *)gre_hdr + gre_len); +- +- parse_ipv4(ipv4_hdr, info); +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV4); +- info->l2_len = 0; +- +- } else if (gre_hdr->proto == _htons(RTE_ETHER_TYPE_IPV6)) { +- update_tunnel_outer(info); +- +- ipv6_hdr = (struct rte_ipv6_hdr *)((char *)gre_hdr + gre_len); +- +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV6); +- parse_ipv6(ipv6_hdr, info); +- info->l2_len = 0; +- +- } else if (gre_hdr->proto == _htons(RTE_ETHER_TYPE_TEB)) { +- update_tunnel_outer(info); +- +- eth_hdr = (struct rte_ether_hdr *)((char *)gre_hdr + gre_len); +- +- parse_ethernet(eth_hdr, info); +- } else +- return; +- +- info->l2_len += gre_len; +-} +- +- +-/* Parse an encapsulated ip or ipv6 header */ +-static void +-parse_encap_ip(void *encap_ip, struct testpmd_offload_info *info) +-{ +- struct rte_ipv4_hdr *ipv4_hdr = encap_ip; +- struct rte_ipv6_hdr *ipv6_hdr = encap_ip; +- uint8_t ip_version; +- +- ip_version = (ipv4_hdr->version_ihl & 0xf0) >> 4; +- +- if (ip_version != 4 && ip_version != 6) +- return; +- +- info->is_tunnel = 1; +- info->outer_ethertype = info->ethertype; +- info->outer_l2_len = info->l2_len; +- info->outer_l3_len = info->l3_len; +- +- if (ip_version == 4) { +- parse_ipv4(ipv4_hdr, info); +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV4); +- } else { +- parse_ipv6(ipv6_hdr, info); +- info->ethertype = _htons(RTE_ETHER_TYPE_IPV6); +- } +- info->l2_len = 0; ++ info->l4_proto = 0; + } + + /* if possible, calculate the checksum of a packet in hw or sw, +@@ -810,6 +474,109 @@ pkts_ip_csum_recalc(struct rte_mbuf **pkts_burst, const uint16_t nb_pkts, uint64 + } + #endif + ++static uint32_t ++get_ethertype_by_ptype(struct rte_ether_hdr *eth_hdr, uint32_t ptype) ++{ ++ struct rte_vlan_hdr *vlan_hdr; ++ uint16_t ethertype; ++ ++ switch (ptype) { ++ case RTE_PTYPE_L3_IPV4: ++ case RTE_PTYPE_L3_IPV4_EXT: ++ case RTE_PTYPE_L3_IPV4_EXT_UNKNOWN: ++ case RTE_PTYPE_INNER_L3_IPV4: ++ case RTE_PTYPE_INNER_L3_IPV4_EXT: ++ case RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN: ++ return _htons(RTE_ETHER_TYPE_IPV4); ++ case RTE_PTYPE_L3_IPV6: ++ case RTE_PTYPE_L3_IPV6_EXT: ++ case RTE_PTYPE_L3_IPV6_EXT_UNKNOWN: ++ case RTE_PTYPE_INNER_L3_IPV6: ++ case RTE_PTYPE_INNER_L3_IPV6_EXT: ++ case RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN: ++ return _htons(RTE_ETHER_TYPE_IPV6); ++ default: ++ ethertype = eth_hdr->ether_type; ++ while (eth_hdr->ether_type == _htons(RTE_ETHER_TYPE_VLAN) || ++ eth_hdr->ether_type == _htons(RTE_ETHER_TYPE_QINQ)) { ++ vlan_hdr = (struct rte_vlan_hdr *) ++ ((char *)eth_hdr + sizeof(*eth_hdr)); ++ ethertype = vlan_hdr->eth_proto; ++ } ++ return ethertype; ++ } ++} ++ ++static uint64_t ++get_tunnel_ol_flags_by_ptype(uint32_t ptype) ++{ ++ switch ((ptype & RTE_PTYPE_TUNNEL_MASK)) { ++ case RTE_PTYPE_TUNNEL_GTPC: ++ case RTE_PTYPE_TUNNEL_GTPU: ++ return RTE_MBUF_F_TX_TUNNEL_GTP; ++ case RTE_PTYPE_TUNNEL_VXLAN_GPE: ++ return RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE; ++ case RTE_PTYPE_TUNNEL_VXLAN: ++ return RTE_MBUF_F_TX_TUNNEL_VXLAN; ++ case RTE_PTYPE_TUNNEL_GENEVE: ++ return RTE_MBUF_F_TX_TUNNEL_GENEVE; ++ case RTE_PTYPE_TUNNEL_NVGRE: ++ case RTE_PTYPE_TUNNEL_GRE: ++ return RTE_MBUF_F_TX_TUNNEL_GRE; ++ case RTE_PTYPE_TUNNEL_IP: ++ return RTE_MBUF_F_TX_TUNNEL_IPIP; ++ default: ++ printf("unrecognized tunnel ptype: %x\n", ++ (ptype & RTE_PTYPE_TUNNEL_MASK)); ++ return 0; ++ } ++} ++ ++static void ++parse_inner_l4_proto(void *outer_l3_hdr, ++ struct testpmd_offload_info *info) ++{ ++ struct rte_ipv4_hdr *ipv4_hdr = outer_l3_hdr; ++ struct rte_ipv6_hdr *ipv6_hdr = outer_l3_hdr; ++ if (info->ethertype == _htons(RTE_ETHER_TYPE_IPV4)) ++ info->l4_proto = ipv4_hdr->next_proto_id; ++ else ++ info->l4_proto = ipv6_hdr->proto; ++} ++ ++static uint8_t ++parse_l4_proto(const struct rte_mbuf *m, uint32_t off, uint32_t ptype) ++{ ++ int frag = 0, ret; ++ ++ if (RTE_ETH_IS_IPV4_HDR(ptype)) { ++ const struct rte_ipv4_hdr *ip4h; ++ struct rte_ipv4_hdr ip4h_copy; ++ ip4h = rte_pktmbuf_read(m, off, sizeof(*ip4h), &ip4h_copy); ++ if (unlikely(ip4h == NULL)) ++ return 0; ++ ++ return ip4h->next_proto_id; ++ } else if (RTE_ETH_IS_IPV6_HDR(ptype)) { ++ const struct rte_ipv6_hdr *ip6h; ++ struct rte_ipv6_hdr ip6h_copy; ++ ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy); ++ if (unlikely(ip6h == NULL)) ++ return 0; ++ ++ if ((ptype & RTE_PTYPE_INNER_L3_MASK) == ++ RTE_PTYPE_INNER_L3_IPV6_EXT) { ++ ret = rte_net_skip_ip6_ext(ip6h->proto, m, &off, &frag); ++ if (ret < 0) ++ return 0; ++ return ret; ++ } ++ ++ return ip6h->proto; ++ } ++ return 0; ++} ++ + /* + * Receive a burst of packets, and for each packet: + * - parse packet, and try to recognize a supported packet type (1) +@@ -867,6 +634,8 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) + uint32_t rx_bad_outer_l4_csum; + uint32_t rx_bad_outer_ip_csum; + struct testpmd_offload_info info; ++ struct rte_net_hdr_lens hdr_lens = {0}; ++ uint32_t ptype; + + /* receive a burst of packet */ + nb_rx = common_fwd_stream_receive(fs, pkts_burst, nb_pkt_per_burst); +@@ -923,70 +692,35 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) + rte_ether_addr_copy(&ports[fs->tx_port].eth_addr, + ð_hdr->src_addr); + } +- parse_ethernet(eth_hdr, &info); +- l3_hdr = (char *)eth_hdr + info.l2_len; + ++ ptype = rte_net_get_ptype(m, &hdr_lens, RTE_PTYPE_ALL_MASK); ++ info.l2_len = hdr_lens.l2_len; ++ info.l3_len = hdr_lens.l3_len; ++ info.l4_len = hdr_lens.l4_len; ++ info.ethertype = get_ethertype_by_ptype(eth_hdr, ++ ptype & RTE_PTYPE_L3_MASK); ++ info.l4_proto = parse_l4_proto(m, info.l2_len, ptype); ++ ++ l3_hdr = (char *)eth_hdr + info.l2_len; + /* check if it's a supported tunnel */ +- if (txp->parse_tunnel) { +- if (info.l4_proto == IPPROTO_UDP) { +- struct rte_udp_hdr *udp_hdr; +- +- udp_hdr = (struct rte_udp_hdr *) +- ((char *)l3_hdr + info.l3_len); +- parse_gtp(udp_hdr, &info); +- if (info.is_tunnel) { +- tx_ol_flags |= RTE_MBUF_F_TX_TUNNEL_GTP; +- goto tunnel_update; +- } +- parse_vxlan_gpe(udp_hdr, &info); +- if (info.is_tunnel) { +- tx_ol_flags |= +- RTE_MBUF_F_TX_TUNNEL_VXLAN_GPE; +- goto tunnel_update; +- } +- parse_vxlan(udp_hdr, &info); +- if (info.is_tunnel) { +- tx_ol_flags |= +- RTE_MBUF_F_TX_TUNNEL_VXLAN; +- goto tunnel_update; +- } +- parse_geneve(udp_hdr, &info); +- if (info.is_tunnel) { +- tx_ol_flags |= +- RTE_MBUF_F_TX_TUNNEL_GENEVE; +- goto tunnel_update; +- } +- /* Always keep last. */ +- if (unlikely(RTE_ETH_IS_TUNNEL_PKT( +- m->packet_type) != 0)) { +- TESTPMD_LOG(DEBUG, "Unknown tunnel packet. UDP dst port: %hu", +- udp_hdr->dst_port); +- } +- } else if (info.l4_proto == IPPROTO_GRE) { +- struct simple_gre_hdr *gre_hdr; +- +- gre_hdr = (struct simple_gre_hdr *) +- ((char *)l3_hdr + info.l3_len); +- parse_gre(gre_hdr, &info); +- if (info.is_tunnel) +- tx_ol_flags |= RTE_MBUF_F_TX_TUNNEL_GRE; +- } else if (info.l4_proto == IPPROTO_IPIP) { +- void *encap_ip_hdr; +- +- encap_ip_hdr = (char *)l3_hdr + info.l3_len; +- parse_encap_ip(encap_ip_hdr, &info); +- if (info.is_tunnel) +- tx_ol_flags |= RTE_MBUF_F_TX_TUNNEL_IPIP; +- } ++ if (txp->parse_tunnel && RTE_ETH_IS_TUNNEL_PKT(ptype) != 0) { ++ info.is_tunnel = 1; ++ update_tunnel_outer(&info); ++ info.l2_len = hdr_lens.inner_l2_len + hdr_lens.tunnel_len; ++ info.l3_len = hdr_lens.inner_l3_len; ++ info.l4_len = hdr_lens.inner_l4_len; ++ eth_hdr = (struct rte_ether_hdr *)(char *)l3_hdr + ++ info.outer_l3_len + hdr_lens.tunnel_len; ++ info.ethertype = get_ethertype_by_ptype(eth_hdr, ++ ptype & RTE_PTYPE_INNER_L3_MASK); ++ tx_ol_flags |= get_tunnel_ol_flags_by_ptype(ptype); + } +- +-tunnel_update: + /* update l3_hdr and outer_l3_hdr if a tunnel was parsed */ + if (info.is_tunnel) { + outer_l3_hdr = l3_hdr; + l3_hdr = (char *)l3_hdr + info.outer_l3_len + info.l2_len; ++ parse_inner_l4_proto(l3_hdr, &info); + } +- + /* step 2: depending on user command line configuration, + * recompute checksum either in software or flag the + * mbuf to offload the calculation to the NIC. If TSO +-- +2.25.1 + diff --git a/0102-app-testpmd-fix-VLAN-parsing-in-checksum-engine.patch b/0102-app-testpmd-fix-VLAN-parsing-in-checksum-engine.patch new file mode 100644 index 0000000000000000000000000000000000000000..ca6a61733b72141bbd151cf31b004c3d627d8f1b --- /dev/null +++ b/0102-app-testpmd-fix-VLAN-parsing-in-checksum-engine.patch @@ -0,0 +1,67 @@ +From c2a19057ed633a50c9a682dde72a65233891273e Mon Sep 17 00:00:00 2001 +From: Raslan Darawsheh +Date: Mon, 24 Mar 2025 11:33:49 +0200 +Subject: [PATCH] app/testpmd: fix VLAN parsing in checksum engine +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 8bit + +[ upstream commit 3e00b30e9b208092f896672046a3ae39b878955b ] + +When processing VLAN or QinQ packets, an infinite loop occurred, +preventing the csum forward engine from proceeding and causing +testpmd to hang during shutdown attempts. + +Updated the `get_ethertype_by_ptype` function to correctly parse +VLAN headers. + +Fixes: 76730c7b9b5a ("app/testpmd: use packet type parsing API") + +Signed-off-by: Raslan Darawsheh +Reviewed-by: Morten Brørup +--- + app/test-pmd/csumonly.c | 14 +++++++++----- + 1 file changed, 9 insertions(+), 5 deletions(-) + +diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c +index 4b3be71..f2fd63b 100644 +--- a/app/test-pmd/csumonly.c ++++ b/app/test-pmd/csumonly.c +@@ -59,6 +59,8 @@ + #define GRE_SUPPORTED_FIELDS (GRE_CHECKSUM_PRESENT | GRE_KEY_PRESENT |\ + GRE_SEQUENCE_PRESENT) + ++#define MAX_VLAN_HEADERS 8 ++ + /* We cannot use rte_cpu_to_be_16() on a constant in a switch/case */ + #if RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN + #define _htons(x) ((uint16_t)((((x) & 0x00ffU) << 8) | (((x) & 0xff00U) >> 8))) +@@ -477,7 +479,7 @@ pkts_ip_csum_recalc(struct rte_mbuf **pkts_burst, const uint16_t nb_pkts, uint64 + static uint32_t + get_ethertype_by_ptype(struct rte_ether_hdr *eth_hdr, uint32_t ptype) + { +- struct rte_vlan_hdr *vlan_hdr; ++ struct rte_vlan_hdr *vlan_hdr, *max_vlans; + uint16_t ethertype; + + switch (ptype) { +@@ -497,10 +499,12 @@ get_ethertype_by_ptype(struct rte_ether_hdr *eth_hdr, uint32_t ptype) + return _htons(RTE_ETHER_TYPE_IPV6); + default: + ethertype = eth_hdr->ether_type; +- while (eth_hdr->ether_type == _htons(RTE_ETHER_TYPE_VLAN) || +- eth_hdr->ether_type == _htons(RTE_ETHER_TYPE_QINQ)) { +- vlan_hdr = (struct rte_vlan_hdr *) +- ((char *)eth_hdr + sizeof(*eth_hdr)); ++ vlan_hdr = RTE_PTR_ADD(eth_hdr, offsetof(struct rte_ether_hdr, ether_type)); ++ max_vlans = vlan_hdr + MAX_VLAN_HEADERS; ++ while ((ethertype == _htons(RTE_ETHER_TYPE_VLAN) || ++ ethertype == _htons(RTE_ETHER_TYPE_QINQ)) && ++ vlan_hdr < max_vlans) { ++ vlan_hdr++; + ethertype = vlan_hdr->eth_proto; + } + return ethertype; +-- +2.25.1 + diff --git a/0103-net-fix-offset-in-GENEVE-packet-parsing.patch b/0103-net-fix-offset-in-GENEVE-packet-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..9dc52d328d8e4fe952848dbc2858653a8a178533 --- /dev/null +++ b/0103-net-fix-offset-in-GENEVE-packet-parsing.patch @@ -0,0 +1,37 @@ +From 461025d95ad3687f062915d22310db7c72a2e1a6 Mon Sep 17 00:00:00 2001 +From: Sunil Kumar Kori +Date: Wed, 21 May 2025 10:41:42 +0530 +Subject: [PATCH] net: fix offset in GENEVE packet parsing + +[ upstream commit 0a70cf3308f99bd3c32925e5fb0ec465ad4390e8 ] + +While parsing packet headers, offset must be added to get next +header but for geneve header parsing offset is overwritten. +Also inner_l2_len is not set in case of geneve packets. + +Fixes: 64ed7f854cf4 ("net: add tunnel packet type parsing") +Cc: stable@dpdk.org + +Signed-off-by: Sunil Kumar Kori +Acked-by: Dengdui Huang +--- + lib/net/rte_net.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c +index 0c32e78..12fdee0 100644 +--- a/lib/net/rte_net.c ++++ b/lib/net/rte_net.c +@@ -250,7 +250,8 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m, + if (unlikely(gnh == NULL)) + return 0; + geneve_len = sizeof(*gnh) + gnh->opt_len * 4; +- *off = geneve_len; ++ *off += geneve_len; ++ hdr_lens->inner_l2_len = sizeof(struct rte_udp_hdr) + geneve_len; + *proto = gnh->proto; + if (gnh->proto == 0) + *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); +-- +2.25.1 + diff --git a/0104-app-testpmd-fix-packet-type-parsing.patch b/0104-app-testpmd-fix-packet-type-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..a6cdc90e1033e886886f3e4e20b7a158b6e85967 --- /dev/null +++ b/0104-app-testpmd-fix-packet-type-parsing.patch @@ -0,0 +1,51 @@ +From 19fa302e172b430c706dd6d196fc82e103ca3fa2 Mon Sep 17 00:00:00 2001 +From: Sunil Kumar Kori +Date: Wed, 21 May 2025 10:41:43 +0530 +Subject: [PATCH] app/testpmd: fix packet type parsing + +[ upstream commit 2e0f1e6ec53d5360e8bb7b9dcbfe63839d8a6d9d ] + +hdr_lens is used to maintain header lengths after parsing packets. +When port receives different type of packets (say first is VXLAN +packet and second is GRE packet). + +For first packet, L2/L3/L4 lengths are set for inner and outer header +alongwith tunnel_len. + +Now for second packet, tunnel_len is added more than its size it +contains stale value which further leads to wrong header pointers. + +Hence clearing stale information before processing each packet. + +Fixes: 76730c7b9b5a ("app/testpmd: use packet type parsing API") +Cc: stable@dpdk.org + +Signed-off-by: Sunil Kumar Kori +--- + app/test-pmd/csumonly.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c +index f2fd63b..7fe3d0f 100644 +--- a/app/test-pmd/csumonly.c ++++ b/app/test-pmd/csumonly.c +@@ -638,7 +638,6 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) + uint32_t rx_bad_outer_l4_csum; + uint32_t rx_bad_outer_ip_csum; + struct testpmd_offload_info info; +- struct rte_net_hdr_lens hdr_lens = {0}; + uint32_t ptype; + + /* receive a burst of packet */ +@@ -665,6 +664,8 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) + #endif + + for (i = 0; i < nb_rx; i++) { ++ struct rte_net_hdr_lens hdr_lens = {0}; ++ + if (likely(i < nb_rx - 1)) + rte_prefetch0(rte_pktmbuf_mtod(pkts_burst[i + 1], + void *)); +-- +2.25.1 + diff --git a/0105-net-fix-GTP-packet-parsing.patch b/0105-net-fix-GTP-packet-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b51b9b2a7020aada54934873a6854442c99995b --- /dev/null +++ b/0105-net-fix-GTP-packet-parsing.patch @@ -0,0 +1,43 @@ +From 4f00c80258d2061b7288a6431571d013757b4569 Mon Sep 17 00:00:00 2001 +From: Dengdui Huang +Date: Tue, 3 Jun 2025 20:06:22 +0800 +Subject: [PATCH] net: fix GTP packet parsing + +[ upstream commit b1f3a7a8c375fbb66be48aed078222686d16fdb5 ] + +After parsing the GTP packet header, the next protocol type should +be converted from RTE_GTP_TYPE_IPV4/IPV6 to RTE_ETHER_TYPE_IPV4/IPV6. +Otherwise, the next protocol cannot be parsed. + +Bugzilla ID: 1672 +Fixes: 64ed7f854cf4 ("net: add tunnel packet type parsing") +Cc: stable@dpdk.org + +Signed-off-by: Dengdui Huang +Acked-by: Jie Hai +--- + lib/net/rte_net.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c +index 12fdee0..61f9585 100644 +--- a/lib/net/rte_net.c ++++ b/lib/net/rte_net.c +@@ -230,7 +230,13 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m, + */ + if (gh->msg_type == 0xff) { + ip_ver = *(const uint8_t *)((const char *)gh + gtp_len); +- *proto = (ip_ver) & 0xf0; ++ ip_ver = (ip_ver) & 0xf0; ++ if (ip_ver == RTE_GTP_TYPE_IPV4) ++ *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV4); ++ else if (ip_ver == RTE_GTP_TYPE_IPV6) ++ *proto = rte_cpu_to_be_16(RTE_ETHER_TYPE_IPV6); ++ else ++ *proto = 0; + } else { + *proto = 0; + } +-- +2.25.1 + diff --git a/0106-net-add-tunnel-length-in-UDP-tunnel-parsing.patch b/0106-net-add-tunnel-length-in-UDP-tunnel-parsing.patch new file mode 100644 index 0000000000000000000000000000000000000000..0a14fcb0f494b8a41aa75c2035ac0fae74edf60e --- /dev/null +++ b/0106-net-add-tunnel-length-in-UDP-tunnel-parsing.patch @@ -0,0 +1,78 @@ +From 4a357e0a748e15abb2647fd48e33ed8f899b7178 Mon Sep 17 00:00:00 2001 +From: Dengdui Huang +Date: Mon, 16 Jun 2025 16:27:01 +0800 +Subject: [PATCH] net: add tunnel length in UDP tunnel parsing + +[ upstream commit a5854045c38865c44459446565dc749aa29dffba ] + +Currently, the tunnel length info is not available when +get the tunnel packet type with UDP port. This patch +adds the parsing of the tunnel length info. + +Additionally, adding comments for the inner_l2_len field +and the tunnel_len field would help in understanding their. + +Fixes: 64ed7f854cf4 ("net: add tunnel packet type parsing") +Cc: stable@dpdk.org + +Signed-off-by: Dengdui Huang +--- + lib/net/rte_net.c | 4 ++++ + lib/net/rte_net.h | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c +index 61f9585..1339613 100644 +--- a/lib/net/rte_net.c ++++ b/lib/net/rte_net.c +@@ -196,6 +196,7 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m, + switch (port_no) { + case RTE_VXLAN_DEFAULT_PORT: { + *off += sizeof(struct rte_vxlan_hdr); ++ hdr_lens->tunnel_len = sizeof(struct rte_vxlan_hdr); + hdr_lens->inner_l2_len = RTE_ETHER_VXLAN_HLEN; + *proto = RTE_VXLAN_GPE_TYPE_ETH; /* just for eth header parse. */ + return RTE_PTYPE_TUNNEL_VXLAN; +@@ -207,6 +208,7 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m, + if (unlikely(vgh == NULL)) + return 0; + *off += sizeof(struct rte_vxlan_gpe_hdr); ++ hdr_lens->tunnel_len = sizeof(struct rte_vxlan_gpe_hdr); + hdr_lens->inner_l2_len = RTE_ETHER_VXLAN_GPE_HLEN; + *proto = vgh->proto; + +@@ -242,6 +244,7 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m, + } + *off += gtp_len; + hdr_lens->inner_l2_len = gtp_len + sizeof(struct rte_udp_hdr); ++ hdr_lens->tunnel_len = gtp_len; + if (port_no == RTE_GTPC_UDP_PORT) + return RTE_PTYPE_TUNNEL_GTPC; + else if (port_no == RTE_GTPU_UDP_PORT) +@@ -257,6 +260,7 @@ ptype_tunnel_with_udp(uint16_t *proto, const struct rte_mbuf *m, + return 0; + geneve_len = sizeof(*gnh) + gnh->opt_len * 4; + *off += geneve_len; ++ hdr_lens->tunnel_len = geneve_len; + hdr_lens->inner_l2_len = sizeof(struct rte_udp_hdr) + geneve_len; + *proto = gnh->proto; + if (gnh->proto == 0) +diff --git a/lib/net/rte_net.h b/lib/net/rte_net.h +index ef3ff4c..a925fe0 100644 +--- a/lib/net/rte_net.h ++++ b/lib/net/rte_net.h +@@ -19,9 +19,11 @@ extern "C" { + */ + struct rte_net_hdr_lens { + uint8_t l2_len; ++ /* Outer_L4_len + ... + inner L2_len for tunneling pkt. */ + uint8_t inner_l2_len; + uint16_t l3_len; + uint16_t inner_l3_len; ++ /* Protocol header of tunnel packets */ + uint16_t tunnel_len; + uint8_t l4_len; + uint8_t inner_l4_len; +-- +2.25.1 + diff --git a/0107-app-testpmd-fix-tunnel-inner-info.patch b/0107-app-testpmd-fix-tunnel-inner-info.patch new file mode 100644 index 0000000000000000000000000000000000000000..785580df59fbc2320a20e0cb266e82e9577b5a1c --- /dev/null +++ b/0107-app-testpmd-fix-tunnel-inner-info.patch @@ -0,0 +1,41 @@ +From 22777c820ca639786fae895aafa6209a36d08070 Mon Sep 17 00:00:00 2001 +From: Dengdui Huang +Date: Mon, 16 Jun 2025 16:27:02 +0800 +Subject: [PATCH] app/testpmd: fix tunnel inner info + +[ upstream commit a738c43ffaee9ba5d8eccb0e881e7c816d3c6415 ] + +The l2_len field of tunnel packets already includes the tunnel_len field. +Additionally, the current offset used for the internal Ethernet header is +incorrect. This patch fixes these issues. + +Fixes: 76730c7b9b5a ("app/testpmd: use packet type parsing API") +Cc: stable@dpdk.org + +Signed-off-by: Dengdui Huang +--- + app/test-pmd/csumonly.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/app/test-pmd/csumonly.c b/app/test-pmd/csumonly.c +index 7fe3d0f..4891cb8 100644 +--- a/app/test-pmd/csumonly.c ++++ b/app/test-pmd/csumonly.c +@@ -711,11 +711,11 @@ pkt_burst_checksum_forward(struct fwd_stream *fs) + if (txp->parse_tunnel && RTE_ETH_IS_TUNNEL_PKT(ptype) != 0) { + info.is_tunnel = 1; + update_tunnel_outer(&info); +- info.l2_len = hdr_lens.inner_l2_len + hdr_lens.tunnel_len; ++ info.l2_len = hdr_lens.inner_l2_len; + info.l3_len = hdr_lens.inner_l3_len; + info.l4_len = hdr_lens.inner_l4_len; +- eth_hdr = (struct rte_ether_hdr *)(char *)l3_hdr + +- info.outer_l3_len + hdr_lens.tunnel_len; ++ eth_hdr = (struct rte_ether_hdr *)((char *)l3_hdr + ++ hdr_lens.l3_len + hdr_lens.l4_len + hdr_lens.tunnel_len); + info.ethertype = get_ethertype_by_ptype(eth_hdr, + ptype & RTE_PTYPE_INNER_L3_MASK); + tx_ol_flags |= get_tunnel_ol_flags_by_ptype(ptype); +-- +2.25.1 + diff --git a/dpdk.spec b/dpdk.spec index d07f4d20be720eecfe6dd53c33a7b93d31375cdc..00078cb866fc40884bfbe2d01c7112a4c6cac790 100644 --- a/dpdk.spec +++ b/dpdk.spec @@ -11,7 +11,7 @@ Name: dpdk Version: 23.11 -Release: 33 +Release: 34 URL: http://dpdk.org Source: https://fast.dpdk.org/rel/dpdk-%{version}.tar.xz @@ -132,6 +132,14 @@ Patch6096: 0096-net-hns3-fix-Rx-packet-without-CRC-data.patch Patch6097: 0097-net-hns3-allow-use-of-Rx-vector-mode-with-VLAN-filte.patch Patch6098: 0098-net-hns3-allow-use-of-Tx-vector-when-fast-free-not-enable.patch Patch6099: 0099-net-hns3-check-requirement-for-hardware-GRO.patch +Patch6100: 0100-net-add-tunnel-packet-type-parsing.patch +Patch6101: 0101-app-testpmd-use-packet-type-parsing-API.patch +Patch6102: 0102-app-testpmd-fix-VLAN-parsing-in-checksum-engine.patch +Patch6103: 0103-net-fix-offset-in-GENEVE-packet-parsing.patch +Patch6104: 0104-app-testpmd-fix-packet-type-parsing.patch +Patch6105: 0105-net-fix-GTP-packet-parsing.patch +Patch6106: 0106-net-add-tunnel-length-in-UDP-tunnel-parsing.patch +Patch6107: 0107-app-testpmd-fix-tunnel-inner-info.patch BuildRequires: meson BuildRequires: python3-pyelftools @@ -336,6 +344,18 @@ fi /usr/sbin/depmod %changelog +* Tue Jul 15 2025 huangdengdui - 23.11-34 + Sync some patches about support TSO for packets with + IPv6 extension header and modifications are as follow: + - net: add tunnel packet type parsing + - app/testpmd: use packet type parsing API + - app/testpmd: fix VLAN parsing in checksum engine + - net: fix offset in GENEVE packet parsing + - app/testpmd: fix packet type parsing + - net: fix GTP packet parsing + - net: add tunnel length in UDP tunnel parsing + - app/testpmd: fix tunnel inner info + * Thu Jun 12 2025 huangdengdui - 23.11-33 Sync some bugfixes for hns3 pmd and modifications are as follow: - net/hns3: fix Rx packet without CRC data