* [PATCH v2 1/2] net: add ptype parse for tunnel packets
2025-01-24 9:43 ` [PATCH v2 0/2] parse ptype for tunnel packets Jie Hai
@ 2025-01-24 9:43 ` Jie Hai
2025-01-24 9:43 ` [PATCH v2 2/2] app/test-pmd: use ptype API parse packets Jie Hai
1 sibling, 0 replies; 7+ messages in thread
From: Jie Hai @ 2025-01-24 9:43 UTC (permalink / raw)
To: dev, thomas, ferruh.yigit, aman.deep.singh
Cc: lihuisong, fengchengwen, haijie1, huangdengdui
Add packet types parse for vxlan/vxlan-gpe/gtp/geneve packets.
Signed-off-by: Jie Hai <haijie1@huawei.com>
---
lib/net/rte_net.c | 111 ++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 102 insertions(+), 9 deletions(-)
diff --git a/lib/net/rte_net.c b/lib/net/rte_net.c
index d680accc1631..f1cd75fdb69b 100644
--- a/lib/net/rte_net.c
+++ b/lib/net/rte_net.c
@@ -14,6 +14,9 @@
#include <rte_sctp.h>
#include <rte_gre.h>
#include <rte_mpls.h>
+#include <rte_geneve.h>
+#include <rte_vxlan.h>
+#include <rte_gtp.h>
#include <rte_net.h>
#include <rte_os_shim.h>
@@ -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;
@@ -456,7 +550,6 @@ uint32_t rte_net_get_ptype(const struct rte_mbuf *m,
ip6h = rte_pktmbuf_read(m, off, sizeof(*ip6h), &ip6h_copy);
if (unlikely(ip6h == NULL))
return pkt_type;
-
proto = ip6h->proto;
hdr_lens->inner_l3_len = sizeof(*ip6h);
off += hdr_lens->inner_l3_len;
--
2.22.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 2/2] app/test-pmd: use ptype API parse packets
2025-01-24 9:43 ` [PATCH v2 0/2] parse ptype for tunnel packets Jie Hai
2025-01-24 9:43 ` [PATCH v2 1/2] net: add ptype parse " Jie Hai
@ 2025-01-24 9:43 ` Jie Hai
1 sibling, 0 replies; 7+ messages in thread
From: Jie Hai @ 2025-01-24 9:43 UTC (permalink / raw)
To: dev, thomas, ferruh.yigit, aman.deep.singh
Cc: lihuisong, fengchengwen, haijie1, huangdengdui
1. Use rte_net_get_ptype() to parse packets instead.
2. Support TSO for packets with ipv6 extension header.
Signed-off-by: Jie Hai <haijie1@huawei.com>
---
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 d77a140641f3..2dcd6efedcb1 100644
--- a/app/test-pmd/csumonly.c
+++ b/app/test-pmd/csumonly.c
@@ -46,6 +46,7 @@
#include <rte_gso.h>
#endif
#include <rte_geneve.h>
+#include <rte_net.h>
#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,
@@ -799,6 +463,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)
@@ -856,6 +623,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);
@@ -924,70 +693,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.22.0
^ permalink raw reply [flat|nested] 7+ messages in thread