DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH 00/25] add the extend rte_flow offload support of nfp PMD
@ 2022-10-18  3:22 Chaoyong He
  2022-10-18  3:22 ` [PATCH 01/25] net/nfp: add the offload support of IPv4 VXLAN item Chaoyong He
                   ` (26 more replies)
  0 siblings, 27 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

This is the third patch series to add the support of rte_flow offload for
nfp PMD, includes:
Add the offload support of decap/encap of VXLAN
Add the offload support of decap/encap of GENEVE
Add the offload support of decap/encap of NVGRE

Depends-on: series-25268 ("add the basic rte_flow offload support of nfp PMD")

Chaoyong He (25):
  net/nfp: add the offload support of IPv4 VXLAN item
  net/nfp: add the offload support of IPv6 VXLAN item
  net/nfp: prepare for the encap action of IPv4 tunnel
  net/nfp: prepare for the encap action of IPv6 tunnel
  net/nfp: add the offload support of IPv4 VXLAN encap action
  net/nfp: add the offload support of IPv6 VXLAN encap action
  net/nfp: prepare for the decap action of IPv4 UDP tunnel
  net/nfp: prepare for the decap action of IPv6 UDP tunnel
  net/nfp: add the offload support of IPv4 VXLAN decap action
  net/nfp: add the offload support of IPv6 VXLAN decap action
  net/nfp: add the offload support of IPv4 GENEVE encap action
  net/nfp: add the offload support of IPv6 GENEVE encap action
  net/nfp: add the offload support of IPv4 GENEVE item
  net/nfp: add the offload support of IPv6 GENEVE item
  net/nfp: add the offload support of IPv4 GENEVE decap action
  net/nfp: add the offload support of IPv6 GENEVE decap action
  net/nfp: add the offload support of IPv4 NVGRE encap action
  net/nfp: add the offload support of IPv6 NVGRE encap action
  net/nfp: prepare for the decap action of IPv4 GRE tunnel
  net/nfp: prepare for the decap action of IPv6 GRE tunnel
  net/nfp: add the offload support of IPv4 NVGRE item
  net/nfp: add the offload support of IPv6 NVGRE item
  net/nfp: add the offload support of IPv4 NVGRE decap action
  net/nfp: add the offload support of IPv6 NVGRE decap action
  net/nfp: add the support of new tunnel solution

 doc/guides/nics/features/nfp.ini         |   10 +
 doc/guides/rel_notes/release_22_11.rst   |    3 +
 drivers/net/nfp/flower/nfp_flower.c      |   14 +
 drivers/net/nfp/flower/nfp_flower.h      |   24 +
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  222 ++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  415 +++++++
 drivers/net/nfp/nfp_flow.c               | 2003 +++++++++++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |   56 +
 8 files changed, 2678 insertions(+), 69 deletions(-)

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 01/25] net/nfp: add the offload support of IPv4 VXLAN item
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 02/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (25 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding data structure and logics, to support
the offload of IPv4 VXLAN item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini         |   1 +
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  35 +++++
 drivers/net/nfp/nfp_flow.c               | 243 ++++++++++++++++++++++++++-----
 3 files changed, 246 insertions(+), 33 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 1ad6c2c..40b9a4d 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -36,6 +36,7 @@ sctp                 = Y
 tcp                  = Y
 udp                  = Y
 vlan                 = Y
+vxlan                = Y
 
 [rte_flow actions]
 count                = Y
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 6bf8ff7..08e2873 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -324,6 +324,41 @@ struct nfp_flower_ipv6 {
 	uint8_t ipv6_dst[16];
 };
 
+struct nfp_flower_tun_ipv4 {
+	rte_be32_t src;
+	rte_be32_t dst;
+};
+
+struct nfp_flower_tun_ip_ext {
+	uint8_t tos;
+	uint8_t ttl;
+};
+
+/*
+ * Flow Frame IPv4 UDP TUNNEL --> Tunnel details (5W/20B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_src                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_dst                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           Reserved            |      tos      |      ttl      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            Reserved                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     VNI                       |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv4_udp_tun {
+	struct nfp_flower_tun_ipv4 ipv4;
+	rte_be16_t reserved1;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be32_t reserved2;
+	rte_be32_t tun_id;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 823b020..5f6f800 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -38,7 +38,8 @@ struct nfp_flow_item_proc {
 			char **mbuf_off,
 			const struct rte_flow_item *item,
 			const struct nfp_flow_item_proc *proc,
-			bool is_mask);
+			bool is_mask,
+			bool is_outer_layer);
 	/* List of possible subsequent items. */
 	const enum rte_flow_item_type *const next_item;
 };
@@ -503,6 +504,7 @@ struct nfp_mask_id_entry {
 		struct nfp_fl_key_ls *key_ls)
 {
 	struct rte_eth_dev *ethdev;
+	bool outer_ip4_flag = false;
 	const struct rte_flow_item *item;
 	struct nfp_flower_representor *representor;
 	const struct rte_flow_item_port_id *port_id;
@@ -538,6 +540,8 @@ struct nfp_mask_id_entry {
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV4 detected");
 			key_ls->key_layer |= NFP_FLOWER_LAYER_IPV4;
 			key_ls->key_size += sizeof(struct nfp_flower_ipv4);
+			if (!outer_ip4_flag)
+				outer_ip4_flag = true;
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV6 detected");
@@ -559,6 +563,21 @@ struct nfp_mask_id_entry {
 			key_ls->key_layer |= NFP_FLOWER_LAYER_TP;
 			key_ls->key_size += sizeof(struct nfp_flower_tp_ports);
 			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_VXLAN detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_VXLAN;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_VXLAN;
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -737,12 +756,25 @@ struct nfp_mask_id_entry {
 	return ret;
 }
 
+static bool
+nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
+{
+	struct nfp_flower_meta_tci *meta_tci;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_VXLAN)
+		return true;
+
+	return false;
+}
+
 static int
 nfp_flow_merge_eth(__rte_unused struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_mac_mpls *eth;
 	const struct rte_flow_item_eth *spec;
@@ -778,7 +810,8 @@ struct nfp_mask_id_entry {
 		__rte_unused char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_vlan *spec;
@@ -807,41 +840,58 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		bool is_outer_layer)
 {
 	struct nfp_flower_ipv4 *ipv4;
 	const struct rte_ipv4_hdr *hdr;
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv4 *spec;
 	const struct rte_flow_item_ipv4 *mask;
+	struct nfp_flower_ipv4_udp_tun *ipv4_udp_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 
-	if (spec == NULL) {
-		PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
-		goto ipv4_end;
-	}
+	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
+			return 0;
+		}
 
-	/*
-	 * reserve space for L4 info.
-	 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
-	 */
-	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
-		*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 
-	hdr = is_mask ? &mask->hdr : &spec->hdr;
-	ipv4 = (struct nfp_flower_ipv4 *)*mbuf_off;
+		ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
+		ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
+		ipv4_udp_tun->ipv4.src   = hdr->src_addr;
+		ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+	} else {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
+			goto ipv4_end;
+		}
+
+		/*
+		 * reserve space for L4 info.
+		 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
+		 */
+		if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+			*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv4 = (struct nfp_flower_ipv4 *)*mbuf_off;
 
-	ipv4->ip_ext.tos   = hdr->type_of_service;
-	ipv4->ip_ext.proto = hdr->next_proto_id;
-	ipv4->ip_ext.ttl   = hdr->time_to_live;
-	ipv4->ipv4_src     = hdr->src_addr;
-	ipv4->ipv4_dst     = hdr->dst_addr;
+		ipv4->ip_ext.tos   = hdr->type_of_service;
+		ipv4->ip_ext.proto = hdr->next_proto_id;
+		ipv4->ip_ext.ttl   = hdr->time_to_live;
+		ipv4->ipv4_src     = hdr->src_addr;
+		ipv4->ipv4_dst     = hdr->dst_addr;
 
 ipv4_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4);
+		*mbuf_off += sizeof(struct nfp_flower_ipv4);
+	}
 
 	return 0;
 }
@@ -851,7 +901,8 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_ipv6 *ipv6;
 	const struct rte_ipv6_hdr *hdr;
@@ -896,7 +947,8 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	uint8_t tcp_flags;
 	struct nfp_flower_tp_ports *ports;
@@ -968,7 +1020,8 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		bool is_outer_layer)
 {
 	char *ports_off;
 	struct nfp_flower_tp_ports *ports;
@@ -982,6 +1035,12 @@ struct nfp_mask_id_entry {
 		return 0;
 	}
 
+	/* Don't add L4 info if working on a inner layer pattern */
+	if (!is_outer_layer) {
+		PMD_DRV_LOG(INFO, "Detected inner layer UDP, skipping.");
+		return 0;
+	}
+
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4) {
 		ports_off = *mbuf_off - sizeof(struct nfp_flower_ipv4) -
@@ -1009,7 +1068,8 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	char *ports_off;
 	struct nfp_flower_tp_ports *ports;
@@ -1045,10 +1105,42 @@ struct nfp_mask_id_entry {
 	return 0;
 }
 
+static int
+nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	const struct rte_vxlan_hdr *hdr;
+	struct nfp_flower_ipv4_udp_tun *tun4;
+	const struct rte_flow_item_vxlan *spec;
+	const struct rte_flow_item_vxlan *mask;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge vxlan: no item->spec!");
+		goto vxlan_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	hdr = is_mask ? &mask->hdr : &spec->hdr;
+
+	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+	tun4->tun_id = hdr->vx_vni;
+
+vxlan_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+
+	return 0;
+}
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
-		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH,
+			RTE_FLOW_ITEM_TYPE_IPV4),
 	},
 	[RTE_FLOW_ITEM_TYPE_ETH] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VLAN,
@@ -1131,6 +1223,7 @@ struct nfp_mask_id_entry {
 		.merge = nfp_flow_merge_tcp,
 	},
 	[RTE_FLOW_ITEM_TYPE_UDP] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN),
 		.mask_support = &(const struct rte_flow_item_udp){
 			.hdr = {
 				.src_port = RTE_BE16(0xffff),
@@ -1152,6 +1245,17 @@ struct nfp_mask_id_entry {
 		.mask_sz = sizeof(struct rte_flow_item_sctp),
 		.merge = nfp_flow_merge_sctp,
 	},
+	[RTE_FLOW_ITEM_TYPE_VXLAN] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &(const struct rte_flow_item_vxlan){
+			.hdr = {
+				.vx_vni = RTE_BE32(0xffffff00),
+			},
+		},
+		.mask_default = &rte_flow_item_vxlan_mask,
+		.mask_sz = sizeof(struct rte_flow_item_vxlan),
+		.merge = nfp_flow_merge_vxlan,
+	},
 };
 
 static int
@@ -1205,21 +1309,53 @@ struct nfp_mask_id_entry {
 	return ret;
 }
 
+static bool
+nfp_flow_is_tun_item(const struct rte_flow_item *item)
+{
+	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN)
+		return true;
+
+	return false;
+}
+
+static bool
+nfp_flow_inner_item_get(const struct rte_flow_item items[],
+		const struct rte_flow_item **inner_item)
+{
+	const struct rte_flow_item *item;
+
+	*inner_item = items;
+
+	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
+		if (nfp_flow_is_tun_item(item)) {
+			*inner_item = ++item;
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static int
 nfp_flow_compile_item_proc(const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow,
 		char **mbuf_off_exact,
-		char **mbuf_off_mask)
+		char **mbuf_off_mask,
+		bool is_outer_layer)
 {
 	int i;
 	int ret = 0;
+	bool continue_flag = true;
 	const struct rte_flow_item *item;
 	const struct nfp_flow_item_proc *proc_list;
 
 	proc_list = nfp_flow_item_proc_list;
-	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
+	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END && continue_flag; ++item) {
 		const struct nfp_flow_item_proc *proc = NULL;
 
+		if (nfp_flow_is_tun_item(item))
+			continue_flag = false;
+
 		for (i = 0; proc_list->next_item && proc_list->next_item[i]; ++i) {
 			if (proc_list->next_item[i] == item->type) {
 				proc = &nfp_flow_item_proc_list[item->type];
@@ -1248,14 +1384,14 @@ struct nfp_mask_id_entry {
 		}
 
 		ret = proc->merge(nfp_flow, mbuf_off_exact, item,
-				proc, false);
+				proc, false, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d exact merge failed", item->type);
 			break;
 		}
 
 		ret = proc->merge(nfp_flow, mbuf_off_mask, item,
-				proc, true);
+				proc, true, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d mask merge failed", item->type);
 			break;
@@ -1275,6 +1411,9 @@ struct nfp_mask_id_entry {
 	int ret;
 	char *mbuf_off_mask;
 	char *mbuf_off_exact;
+	bool is_tun_flow = false;
+	bool is_outer_layer = true;
+	const struct rte_flow_item *loop_item;
 
 	mbuf_off_exact = nfp_flow->payload.unmasked_data +
 			sizeof(struct nfp_flower_meta_tci) +
@@ -1283,14 +1422,29 @@ struct nfp_mask_id_entry {
 			sizeof(struct nfp_flower_meta_tci) +
 			sizeof(struct nfp_flower_in_port);
 
+	/* Check if this is a tunnel flow and get the inner item*/
+	is_tun_flow = nfp_flow_inner_item_get(items, &loop_item);
+	if (is_tun_flow)
+		is_outer_layer = false;
+
 	/* Go over items */
-	ret = nfp_flow_compile_item_proc(items, nfp_flow,
-			&mbuf_off_exact, &mbuf_off_mask);
+	ret = nfp_flow_compile_item_proc(loop_item, nfp_flow,
+			&mbuf_off_exact, &mbuf_off_mask, is_outer_layer);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "nfp flow item compile failed.");
 		return -EINVAL;
 	}
 
+	/* Go over inner items */
+	if (is_tun_flow) {
+		ret = nfp_flow_compile_item_proc(items, nfp_flow,
+				&mbuf_off_exact, &mbuf_off_mask, true);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "nfp flow outer item compile failed.");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
@@ -2123,12 +2277,35 @@ struct nfp_mask_id_entry {
 	return 0;
 }
 
+static int
+nfp_flow_tunnel_match(__rte_unused struct rte_eth_dev *dev,
+		__rte_unused struct rte_flow_tunnel *tunnel,
+		__rte_unused struct rte_flow_item **pmd_items,
+		uint32_t *num_of_items,
+		__rte_unused struct rte_flow_error *err)
+{
+	*num_of_items = 0;
+
+	return 0;
+}
+
+static int
+nfp_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev,
+		__rte_unused struct rte_flow_item *pmd_items,
+		__rte_unused uint32_t num_of_items,
+		__rte_unused struct rte_flow_error *err)
+{
+	return 0;
+}
+
 static const struct rte_flow_ops nfp_flow_ops = {
 	.validate                    = nfp_flow_validate,
 	.create                      = nfp_flow_create,
 	.destroy                     = nfp_flow_destroy,
 	.flush                       = nfp_flow_flush,
 	.query                       = nfp_flow_query,
+	.tunnel_match                = nfp_flow_tunnel_match,
+	.tunnel_item_release         = nfp_flow_tunnel_item_release,
 };
 
 int
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 02/25] net/nfp: add the offload support of IPv6 VXLAN item
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
  2022-10-18  3:22 ` [PATCH 01/25] net/nfp: add the offload support of IPv4 VXLAN item Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 03/25] net/nfp: prepare for the encap action of IPv4 tunnel Chaoyong He
                   ` (24 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding data structure and logics, to support
the offload of IPv6 VXLAN item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  42 ++++++++++++
 drivers/net/nfp/nfp_flow.c               | 113 ++++++++++++++++++++++++-------
 2 files changed, 129 insertions(+), 26 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 08e2873..996ba3b 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -329,6 +329,11 @@ struct nfp_flower_tun_ipv4 {
 	rte_be32_t dst;
 };
 
+struct nfp_flower_tun_ipv6 {
+	uint8_t ipv6_src[16];
+	uint8_t ipv6_dst[16];
+};
+
 struct nfp_flower_tun_ip_ext {
 	uint8_t tos;
 	uint8_t ttl;
@@ -359,6 +364,43 @@ struct nfp_flower_ipv4_udp_tun {
 	rte_be32_t tun_id;
 };
 
+/*
+ * Flow Frame IPv6 UDP TUNNEL --> Tunnel details (11W/44B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           Reserved            |      tos      |      ttl      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            Reserved                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     VNI                       |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv6_udp_tun {
+	struct nfp_flower_tun_ipv6 ipv6;
+	rte_be16_t reserved1;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be32_t reserved2;
+	rte_be32_t tun_id;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 5f6f800..1673518 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -505,6 +505,7 @@ struct nfp_mask_id_entry {
 {
 	struct rte_eth_dev *ethdev;
 	bool outer_ip4_flag = false;
+	bool outer_ip6_flag = false;
 	const struct rte_flow_item *item;
 	struct nfp_flower_representor *representor;
 	const struct rte_flow_item_port_id *port_id;
@@ -547,6 +548,8 @@ struct nfp_mask_id_entry {
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV6 detected");
 			key_ls->key_layer |= NFP_FLOWER_LAYER_IPV6;
 			key_ls->key_size += sizeof(struct nfp_flower_ipv6);
+			if (!outer_ip6_flag)
+				outer_ip6_flag = true;
 			break;
 		case RTE_FLOW_ITEM_TYPE_TCP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_TCP detected");
@@ -565,8 +568,9 @@ struct nfp_mask_id_entry {
 			break;
 		case RTE_FLOW_ITEM_TYPE_VXLAN:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_VXLAN detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_VXLAN;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_VXLAN;
 			if (outer_ip4_flag) {
@@ -576,6 +580,19 @@ struct nfp_mask_id_entry {
 				 * in `struct nfp_flower_ipv4_udp_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for VXLAN tunnel.");
+				return -EINVAL;
 			}
 			break;
 		default:
@@ -902,42 +919,61 @@ struct nfp_mask_id_entry {
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
 		bool is_mask,
-		__rte_unused bool is_outer_layer)
+		bool is_outer_layer)
 {
 	struct nfp_flower_ipv6 *ipv6;
 	const struct rte_ipv6_hdr *hdr;
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv6 *spec;
 	const struct rte_flow_item_ipv6 *mask;
+	struct nfp_flower_ipv6_udp_tun *ipv6_udp_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 
-	if (spec == NULL) {
-		PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
-		goto ipv6_end;
-	}
+	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
+			return 0;
+		}
 
-	/*
-	 * reserve space for L4 info.
-	 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
-	 */
-	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
-		*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+
+		ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
+				RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+		ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
+		memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
+				sizeof(ipv6_udp_tun->ipv6.ipv6_src));
+		memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
+				sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+	} else {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
+			goto ipv6_end;
+		}
 
-	hdr = is_mask ? &mask->hdr : &spec->hdr;
-	ipv6 = (struct nfp_flower_ipv6 *)*mbuf_off;
+		/*
+		 * reserve space for L4 info.
+		 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv6
+		 */
+		if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+			*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv6 = (struct nfp_flower_ipv6 *)*mbuf_off;
 
-	ipv6->ip_ext.tos   = (hdr->vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
-			RTE_IPV6_HDR_TC_SHIFT;
-	ipv6->ip_ext.proto = hdr->proto;
-	ipv6->ip_ext.ttl   = hdr->hop_limits;
-	memcpy(ipv6->ipv6_src, hdr->src_addr, sizeof(ipv6->ipv6_src));
-	memcpy(ipv6->ipv6_dst, hdr->dst_addr, sizeof(ipv6->ipv6_dst));
+		ipv6->ip_ext.tos   = (hdr->vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
+				RTE_IPV6_HDR_TC_SHIFT;
+		ipv6->ip_ext.proto = hdr->proto;
+		ipv6->ip_ext.ttl   = hdr->hop_limits;
+		memcpy(ipv6->ipv6_src, hdr->src_addr, sizeof(ipv6->ipv6_src));
+		memcpy(ipv6->ipv6_dst, hdr->dst_addr, sizeof(ipv6->ipv6_dst));
 
 ipv6_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv6);
+		*mbuf_off += sizeof(struct nfp_flower_ipv6);
+	}
 
 	return 0;
 }
@@ -1106,7 +1142,7 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
+nfp_flow_merge_vxlan(struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1115,8 +1151,15 @@ struct nfp_mask_id_entry {
 {
 	const struct rte_vxlan_hdr *hdr;
 	struct nfp_flower_ipv4_udp_tun *tun4;
+	struct nfp_flower_ipv6_udp_tun *tun6;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_vxlan *spec;
 	const struct rte_flow_item_vxlan *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1127,11 +1170,21 @@ struct nfp_mask_id_entry {
 	mask = item->mask ? item->mask : proc->mask_default;
 	hdr = is_mask ? &mask->hdr : &spec->hdr;
 
-	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
-	tun4->tun_id = hdr->vx_vni;
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+		tun6->tun_id = hdr->vx_vni;
+	} else {
+		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+		tun4->tun_id = hdr->vx_vni;
+	}
 
 vxlan_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6))
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_udp_tun);
+	else
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 
 	return 0;
 }
@@ -1140,7 +1193,8 @@ struct nfp_mask_id_entry {
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH,
-			RTE_FLOW_ITEM_TYPE_IPV4),
+			RTE_FLOW_ITEM_TYPE_IPV4,
+			RTE_FLOW_ITEM_TYPE_IPV6),
 	},
 	[RTE_FLOW_ITEM_TYPE_ETH] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VLAN,
@@ -1413,6 +1467,7 @@ struct nfp_mask_id_entry {
 	char *mbuf_off_exact;
 	bool is_tun_flow = false;
 	bool is_outer_layer = true;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item *loop_item;
 
 	mbuf_off_exact = nfp_flow->payload.unmasked_data +
@@ -1422,6 +1477,12 @@ struct nfp_mask_id_entry {
 			sizeof(struct nfp_flower_meta_tci) +
 			sizeof(struct nfp_flower_in_port);
 
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) {
+		mbuf_off_exact += sizeof(struct nfp_flower_ext_meta);
+		mbuf_off_mask += sizeof(struct nfp_flower_ext_meta);
+	}
+
 	/* Check if this is a tunnel flow and get the inner item*/
 	is_tun_flow = nfp_flow_inner_item_get(items, &loop_item);
 	if (is_tun_flow)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 03/25] net/nfp: prepare for the encap action of IPv4 tunnel
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
  2022-10-18  3:22 ` [PATCH 01/25] net/nfp: add the offload support of IPv4 VXLAN item Chaoyong He
  2022-10-18  3:22 ` [PATCH 02/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 04/25] net/nfp: prepare for the encap action of IPv6 tunnel Chaoyong He
                   ` (23 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the encap action of IPv4 tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c | 29 ++++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 93 ++++++++++++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 88 ++++++++++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.h               | 27 ++++++++++
 4 files changed, 237 insertions(+)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 15d8381..7021d1f 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -246,3 +246,32 @@
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v4 *payload)
+{
+	uint16_t cnt;
+	size_t msg_len;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_neigh_v4 *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v4 tun neigh");
+		return -ENOMEM;
+	}
+
+	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v4);
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, msg_len);
+	memcpy(msg, payload, msg_len);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 996ba3b..e44e311 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -129,6 +129,36 @@ struct nfp_flower_cmsg_port_mod {
 	rte_be16_t mtu;
 };
 
+struct nfp_flower_tun_neigh {
+	uint8_t dst_mac[RTE_ETHER_ADDR_LEN];
+	uint8_t src_mac[RTE_ETHER_ADDR_LEN];
+	rte_be32_t port_id;
+};
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V4
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                           DST_IPV4                            |
+ *          +---------------------------------------------------------------+
+ *        1 |                           SRC_IPV4                            |
+ *          +---------------------------------------------------------------+
+ *        2 |                      DST_MAC_B5_B4_B3_B2                      |
+ *          +-------------------------------+-------------------------------+
+ *        3 |             DST_MAC_B1_B0     |        SRC_MAC_B5_B4          |
+ *          +-------------------------------+-------------------------------+
+ *        4 |                       SRC_MAC_B3_B2_B1_B0                     |
+ *          +---------------------------------------------------------------+
+ *        5 |                    Egress Port (NFP internal)                 |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_neigh_v4 {
+	rte_be32_t dst_ipv4;
+	rte_be32_t src_ipv4;
+	struct nfp_flower_tun_neigh common;
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -574,6 +604,67 @@ struct nfp_fl_act_set_tport {
 	rte_be16_t dst_port;
 };
 
+/*
+ * Pre-tunnel
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  -  |  opcode |       |jump_id|              -      |M|   - |V|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |         ipv6_daddr_127_96     /     ipv4_daddr                |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_95_64                          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_63_32                          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_31_0                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_fl_act_pre_tun {
+	struct nfp_fl_act_head head;
+	rte_be16_t flags;
+	union {
+		rte_be32_t ipv4_dst;
+		uint8_t ipv6_dst[16];
+	};
+};
+
+/*
+ * Set tunnel
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | res |  opcode |  res  | len_lw|           reserved            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            tun_id0                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            tun_id1                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                      reserved                 |  type |r| idx |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           ipv4_flags          |      ttl      |      tos      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         reserved_cvs1                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |          reserved_cvs2        |        reserved_cvs3          |
+ * |            var_flags          |            var_np             |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_fl_act_set_tun {
+	struct nfp_fl_act_head head;
+	rte_be16_t reserved;
+	rte_be64_t tun_id;
+	rte_be32_t tun_type_index;
+	rte_be16_t tun_flags;
+	uint8_t    ttl;
+	uint8_t    tos;
+	rte_be16_t outer_vlan_tpid;
+	rte_be16_t outer_vlan_tci;
+	uint8_t    tun_len;      /* Only valid for NFP_FL_TUNNEL_GENEVE */
+	uint8_t    reserved2;
+	rte_be16_t tun_proto;    /* Only valid for NFP_FL_TUNNEL_GENEVE */
+} __rte_packed;
+
 int nfp_flower_cmsg_mac_repr(struct nfp_app_fw_flower *app_fw_flower);
 int nfp_flower_cmsg_repr_reify(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_representor *repr);
@@ -583,5 +674,7 @@ int nfp_flower_cmsg_flow_delete(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
 int nfp_flower_cmsg_flow_add(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
+int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 1673518..6efb95a 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1790,6 +1790,91 @@ struct nfp_mask_id_entry {
 	tc_hl->reserved = 0;
 }
 
+__rte_unused static void
+nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
+		rte_be32_t ipv4_dst)
+{
+	pre_tun->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
+	pre_tun->head.len_lw  = sizeof(struct nfp_fl_act_pre_tun) >> NFP_FL_LW_SIZ;
+	pre_tun->ipv4_dst     = ipv4_dst;
+}
+
+__rte_unused static void
+nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
+		enum nfp_flower_tun_type tun_type,
+		uint64_t tun_id,
+		uint8_t ttl,
+		uint8_t tos)
+{
+	/* Currently only support one pre-tunnel, so index is always 0. */
+	uint8_t pretun_idx = 0;
+	uint32_t tun_type_index;
+
+	tun_type_index = ((tun_type << 4) & 0xf0) | (pretun_idx & 0x07);
+
+	set_tun->head.jump_id   = NFP_FL_ACTION_OPCODE_SET_TUNNEL;
+	set_tun->head.len_lw    = sizeof(struct nfp_fl_act_set_tun) >> NFP_FL_LW_SIZ;
+	set_tun->tun_type_index = rte_cpu_to_be_32(tun_type_index);
+	set_tun->tun_id         = rte_cpu_to_be_64(tun_id);
+	set_tun->ttl            = ttl;
+	set_tun->tos            = tos;
+}
+
+__rte_unused static int
+nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun,
+		const struct rte_ether_hdr *eth,
+		const struct rte_flow_item_ipv4 *ipv4)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	tun->payload.v6_flag = 0;
+	tun->payload.dst.dst_ipv4 = ipv4->hdr.dst_addr;
+	tun->payload.src.src_ipv4 = ipv4->hdr.src_addr;
+	memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	port = (struct nfp_flower_in_port *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4->hdr.dst_addr;
+	payload.src_ipv4 = ipv4->hdr.src_addr;
+	memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
+__rte_unused static int
+nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
@@ -2491,6 +2576,9 @@ struct nfp_mask_id_entry {
 		goto free_mask_table;
 	}
 
+	/* neighbor next list */
+	LIST_INIT(&priv->nn_list);
+
 	return 0;
 
 free_mask_table:
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index b3bd949..14da800 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -89,6 +89,11 @@ enum nfp_flower_tun_type {
 	NFP_FL_TUN_GENEVE = 4,
 };
 
+enum nfp_flow_type {
+	NFP_FLOW_COMMON,
+	NFP_FLOW_ENCAP,
+};
+
 struct nfp_fl_key_ls {
 	uint32_t key_layer_two;
 	uint8_t key_layer;
@@ -117,6 +122,24 @@ struct nfp_fl_payload {
 	char *action_data;
 };
 
+struct nfp_fl_tun {
+	LIST_ENTRY(nfp_fl_tun) next;
+	uint8_t ref_cnt;
+	struct nfp_fl_tun_entry {
+		uint8_t v6_flag;
+		uint8_t dst_addr[RTE_ETHER_ADDR_LEN];
+		uint8_t src_addr[RTE_ETHER_ADDR_LEN];
+		union {
+			rte_be32_t dst_ipv4;
+			uint8_t dst_ipv6[16];
+		} dst;
+		union {
+			rte_be32_t src_ipv4;
+			uint8_t src_ipv6[16];
+		} src;
+	} payload;
+};
+
 #define CIRC_CNT(head, tail, size)     (((head) - (tail)) & ((size) - 1))
 #define CIRC_SPACE(head, tail, size)   CIRC_CNT((tail), ((head) + 1), (size))
 struct circ_buf {
@@ -160,12 +183,16 @@ struct nfp_flow_priv {
 	struct nfp_fl_stats_id stats_ids; /**< The stats id ring. */
 	struct nfp_fl_stats *stats; /**< Store stats of flow. */
 	rte_spinlock_t stats_lock; /** < Lock the update of 'stats' field. */
+	/* neighbor next */
+	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
 
 struct rte_flow {
 	struct nfp_fl_payload payload;
+	struct nfp_fl_tun tun;
 	size_t length;
 	bool install_flag;
+	enum nfp_flow_type type;
 };
 
 int nfp_flow_priv_init(struct nfp_pf_dev *pf_dev);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 04/25] net/nfp: prepare for the encap action of IPv6 tunnel
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (2 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 03/25] net/nfp: prepare for the encap action of IPv4 tunnel Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 05/25] net/nfp: add the offload support of IPv4 VXLAN encap action Chaoyong He
                   ` (22 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the encap action of IPv6 tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  29 +++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  40 ++++++++++++
 drivers/net/nfp/nfp_flow.c               | 105 ++++++++++++++++++++++++++++++-
 3 files changed, 173 insertions(+), 1 deletion(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 7021d1f..8983178 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -275,3 +275,32 @@
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v6 *payload)
+{
+	uint16_t cnt;
+	size_t msg_len;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_neigh_v6 *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v6 tun neigh");
+		return -ENOMEM;
+	}
+
+	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v6);
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6, msg_len);
+	memcpy(msg, payload, msg_len);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index e44e311..d1e0562 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -160,6 +160,42 @@ struct nfp_flower_cmsg_tun_neigh_v4 {
 };
 
 /*
+ * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                          DST_IPV6 [0]                         |
+ *          +---------------------------------------------------------------+
+ *        1 |                          DST_IPV6 [1]                         |
+ *          +---------------------------------------------------------------+
+ *        2 |                          DST_IPV6 [2]                         |
+ *          +---------------------------------------------------------------+
+ *        3 |                          DST_IPV6 [3]                         |
+ *          +---------------------------------------------------------------+
+ *        4 |                          SRC_IPV6 [0]                         |
+ *          +---------------------------------------------------------------+
+ *        5 |                          SRC_IPV6 [1]                         |
+ *          +---------------------------------------------------------------+
+ *        6 |                          SRC_IPV6 [2]                         |
+ *          +---------------------------------------------------------------+
+ *        7 |                          SRC_IPV6 [3]                         |
+ *          +---------------------------------------------------------------+
+ *        8 |                       DST_MAC_B5_B4_B3_B2                     |
+ *          +-------------------------------+-------------------------------+
+ *        9 |             DST_MAC_B1_B0     |        SRC_MAC_B5_B4          |
+ *          +-------------------------------+-------------------------------+
+ *       10 |                       SRC_MAC_B3_B2_B1_B0                     |
+ *          +---------------+---------------+---------------+---------------+
+ *       11 |                    Egress Port (NFP internal)                 |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_neigh_v6 {
+	uint8_t dst_ipv6[16];
+	uint8_t src_ipv6[16];
+	struct nfp_flower_tun_neigh common;
+};
+
+/*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
@@ -629,6 +665,8 @@ struct nfp_fl_act_pre_tun {
 	};
 };
 
+#define NFP_FL_PRE_TUN_IPV6    (1 << 0)
+
 /*
  * Set tunnel
  *    3                   2                   1
@@ -676,5 +714,7 @@ int nfp_flower_cmsg_flow_add(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
 int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
+int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 6efb95a..b8e666c 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1800,6 +1800,16 @@ struct nfp_mask_id_entry {
 }
 
 __rte_unused static void
+nfp_flow_pre_tun_v6_process(struct nfp_fl_act_pre_tun *pre_tun,
+		const uint8_t ipv6_dst[])
+{
+	pre_tun->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
+	pre_tun->head.len_lw  = sizeof(struct nfp_fl_act_pre_tun) >> NFP_FL_LW_SIZ;
+	pre_tun->flags        = rte_cpu_to_be_16(NFP_FL_PRE_TUN_IPV6);
+	memcpy(pre_tun->ipv6_dst, ipv6_dst, sizeof(pre_tun->ipv6_dst));
+}
+
+__rte_unused static void
 nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
 		enum nfp_flower_tun_type tun_type,
 		uint64_t tun_id,
@@ -1863,7 +1873,7 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
 {
@@ -1875,6 +1885,99 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun,
+		const struct rte_ether_hdr *eth,
+		const struct rte_flow_item_ipv6 *ipv6)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	tun->payload.v6_flag = 1;
+	memcpy(tun->payload.dst.dst_ipv6, ipv6->hdr.dst_addr, sizeof(tun->payload.dst.dst_ipv6));
+	memcpy(tun->payload.src.src_ipv6, ipv6->hdr.src_addr, sizeof(tun->payload.src.src_ipv6));
+	memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	port = (struct nfp_flower_in_port *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6->hdr.dst_addr, sizeof(payload.dst_ipv6));
+	memcpy(payload.src_ipv6, ipv6->hdr.src_addr, sizeof(payload.src_ipv6));
+	memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
+static int
+nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t *ipv6)
+{
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6, sizeof(payload.dst_ipv6));
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
+__rte_unused static int
+nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	bool flag = false;
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+
+	tun = &nfp_flow->tun;
+	LIST_FOREACH(tmp, &app_fw_flower->flow_priv->nn_list, next) {
+		ret = memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry));
+		if (ret == 0) {
+			tmp->ref_cnt--;
+			flag = true;
+			break;
+		}
+	}
+
+	if (!flag) {
+		PMD_DRV_LOG(DEBUG, "Can't find nn entry in the nn list");
+		return -EINVAL;
+	}
+
+	if (tmp->ref_cnt == 0) {
+		LIST_REMOVE(tmp, next);
+		if (tmp->payload.v6_flag != 0) {
+			return nfp_flower_del_tun_neigh_v6(app_fw_flower,
+					tmp->payload.dst.dst_ipv6);
+		} else {
+			return nfp_flower_del_tun_neigh_v4(app_fw_flower,
+					tmp->payload.dst.dst_ipv4);
+		}
+	}
+
+	return 0;
+}
+
 static int
 nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 05/25] net/nfp: add the offload support of IPv4 VXLAN encap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (3 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 04/25] net/nfp: prepare for the encap action of IPv6 tunnel Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 06/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (21 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv4 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |   1 +
 drivers/net/nfp/nfp_flow.c       | 132 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 128 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 40b9a4d..fbfd5ba 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -58,3 +58,4 @@ set_mac_src          = Y
 set_tp_dst           = Y
 set_tp_src           = Y
 set_ttl              = Y
+vxlan_encap          = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index b8e666c..2f04fdf 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -10,8 +10,10 @@
 #include <rte_malloc.h>
 
 #include "nfp_common.h"
+#include "nfp_ctrl.h"
 #include "nfp_flow.h"
 #include "nfp_logs.h"
+#include "nfp_rxtx.h"
 #include "flower/nfp_flower.h"
 #include "flower/nfp_flower_cmsg.h"
 #include "flower/nfp_flower_ctrl.h"
@@ -19,6 +21,17 @@
 #include "nfpcore/nfp_mip.h"
 #include "nfpcore/nfp_rtsym.h"
 
+/*
+ * Maximum number of items in struct rte_flow_action_vxlan_encap.
+ * ETH / IPv4(6) / UDP / VXLAN / END
+ */
+#define ACTION_VXLAN_ENCAP_ITEMS_NUM 5
+
+struct vxlan_data {
+	struct rte_flow_action_vxlan_encap conf;
+	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
+};
+
 /* Static initializer for a list of subsequent item types */
 #define NEXT_ITEM(...) \
 	((const enum rte_flow_item_type []){ \
@@ -742,6 +755,11 @@ struct nfp_mask_id_entry {
 				tc_hl_flag = true;
 			}
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP detected");
+			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
+			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1790,7 +1808,7 @@ struct nfp_mask_id_entry {
 	tc_hl->reserved = 0;
 }
 
-__rte_unused static void
+static void
 nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
 		rte_be32_t ipv4_dst)
 {
@@ -1809,7 +1827,7 @@ struct nfp_mask_id_entry {
 	memcpy(pre_tun->ipv6_dst, ipv6_dst, sizeof(pre_tun->ipv6_dst));
 }
 
-__rte_unused static void
+static void
 nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
 		enum nfp_flower_tun_type tun_type,
 		uint64_t tun_id,
@@ -1830,7 +1848,7 @@ struct nfp_mask_id_entry {
 	set_tun->tos            = tos;
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct nfp_fl_tun *tun,
@@ -1940,7 +1958,7 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -1979,7 +1997,81 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
+nfp_flow_action_vxlan_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct vxlan_data *vxlan_data,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	const struct rte_flow_item_eth *eth;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_vxlan *vxlan;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth   = (const struct rte_flow_item_eth *)vxlan_data->items[0].spec;
+	ipv4  = (const struct rte_flow_item_ipv4 *)vxlan_data->items[1].spec;
+	vxlan = (const struct rte_flow_item_vxlan *)vxlan_data->items[3].spec;
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_VXLAN, vxlan->hdr.vx_vni,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_flags = vxlan->hdr.vx_flags;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, &eth->hdr, ipv4);
+}
+
+static int
+nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	size_t act_len;
+	size_t act_pre_size;
+	const struct vxlan_data *vxlan_data;
+
+	vxlan_data = action->conf;
+	if (vxlan_data->items[0].type != RTE_FLOW_ITEM_TYPE_ETH ||
+			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 ||
+			vxlan_data->items[2].type != RTE_FLOW_ITEM_TYPE_UDP ||
+			vxlan_data->items[3].type != RTE_FLOW_ITEM_TYPE_VXLAN ||
+			vxlan_data->items[4].type != RTE_FLOW_ITEM_TYPE_END) {
+		PMD_DRV_LOG(ERR, "Not an valid vxlan action conf.");
+		return -EINVAL;
+	}
+
+	/*
+	 * Pre_tunnel action must be the first on the action list.
+	 * If other actions already exist, they need to be pushed forward.
+	 */
+	act_len = act_data - actions;
+	if (act_len != 0) {
+		act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+		memmove(actions + act_pre_size, actions, act_len);
+	}
+
+	if (vxlan_data->items[1].type == RTE_FLOW_ITEM_TYPE_IPV4)
+		return nfp_flow_action_vxlan_encap_v4(app_fw_flower, act_data,
+				actions, vxlan_data, nfp_flow_meta, tun);
+
+	return 0;
+}
+
+static int
+nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
 		struct rte_flow *nfp_flow)
 {
@@ -2142,6 +2234,20 @@ struct nfp_mask_id_entry {
 				tc_hl_flag = true;
 			}
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP");
+			ret = nfp_flow_action_vxlan_encap(representor->app_fw_flower,
+					position, action_data, action, nfp_flow_meta,
+					&nfp_flow->tun);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process"
+						" RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP");
+				return ret;
+			}
+			position += sizeof(struct nfp_fl_act_pre_tun);
+			position += sizeof(struct nfp_fl_act_set_tun);
+			nfp_flow->type = NFP_FLOW_ENCAP;
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
 			return -ENOTSUP;
@@ -2418,6 +2524,22 @@ struct nfp_mask_id_entry {
 		goto exit;
 	}
 
+	switch (nfp_flow->type) {
+	case NFP_FLOW_COMMON:
+		break;
+	case NFP_FLOW_ENCAP:
+		/* Delete the entry from nn table */
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid nfp flow type %d.", nfp_flow->type);
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret != 0)
+		goto exit;
+
 	/* Delete the flow from hardware */
 	if (nfp_flow->install_flag) {
 		ret = nfp_flower_cmsg_flow_delete(app_fw_flower, nfp_flow);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 06/25] net/nfp: add the offload support of IPv6 VXLAN encap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (4 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 05/25] net/nfp: add the offload support of IPv4 VXLAN encap action Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 07/25] net/nfp: prepare for the decap action of IPv4 UDP tunnel Chaoyong He
                   ` (20 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv6 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/rel_notes/release_22_11.rst |  1 +
 drivers/net/nfp/nfp_flow.c             | 48 ++++++++++++++++++++++++++++++----
 2 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index c2bf721..351fb02 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -184,6 +184,7 @@ New Features
     * Set the port number
     * Set the TTL
     * Set the DSCP of IPv4 and IPv6
+    * Encap of VXLAN tunnel
 
 * **Updated NXP dpaa2 driver.**
 
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 2f04fdf..b9c37b6 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1817,7 +1817,7 @@ struct nfp_mask_id_entry {
 	pre_tun->ipv4_dst     = ipv4_dst;
 }
 
-__rte_unused static void
+static void
 nfp_flow_pre_tun_v6_process(struct nfp_fl_act_pre_tun *pre_tun,
 		const uint8_t ipv6_dst[])
 {
@@ -1903,7 +1903,7 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct nfp_fl_tun *tun,
@@ -2032,6 +2032,42 @@ struct nfp_mask_id_entry {
 }
 
 static int
+nfp_flow_action_vxlan_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct vxlan_data *vxlan_data,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	const struct rte_flow_item_eth *eth;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_vxlan *vxlan;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth   = (const struct rte_flow_item_eth *)vxlan_data->items[0].spec;
+	ipv6  = (const struct rte_flow_item_ipv6 *)vxlan_data->items[1].spec;
+	vxlan = (const struct rte_flow_item_vxlan *)vxlan_data->items[3].spec;
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_VXLAN, vxlan->hdr.vx_vni,
+			ipv6->hdr.hop_limits,
+			(ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff);
+	set_tun->tun_flags = vxlan->hdr.vx_flags;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, &eth->hdr, ipv6);
+}
+
+static int
 nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
 		char *actions,
@@ -2045,7 +2081,8 @@ struct nfp_mask_id_entry {
 
 	vxlan_data = action->conf;
 	if (vxlan_data->items[0].type != RTE_FLOW_ITEM_TYPE_ETH ||
-			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 ||
+			(vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 &&
+			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV6) ||
 			vxlan_data->items[2].type != RTE_FLOW_ITEM_TYPE_UDP ||
 			vxlan_data->items[3].type != RTE_FLOW_ITEM_TYPE_VXLAN ||
 			vxlan_data->items[4].type != RTE_FLOW_ITEM_TYPE_END) {
@@ -2066,8 +2103,9 @@ struct nfp_mask_id_entry {
 	if (vxlan_data->items[1].type == RTE_FLOW_ITEM_TYPE_IPV4)
 		return nfp_flow_action_vxlan_encap_v4(app_fw_flower, act_data,
 				actions, vxlan_data, nfp_flow_meta, tun);
-
-	return 0;
+	else
+		return nfp_flow_action_vxlan_encap_v6(app_fw_flower, act_data,
+				actions, vxlan_data, nfp_flow_meta, tun);
 }
 
 static int
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 07/25] net/nfp: prepare for the decap action of IPv4 UDP tunnel
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (5 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 06/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 08/25] net/nfp: prepare for the decap action of IPv6 " Chaoyong He
                   ` (19 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the decap action of IPv4 UDP tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c | 118 ++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  94 +++++++
 drivers/net/nfp/nfp_flow.c               | 461 ++++++++++++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |  17 ++
 4 files changed, 675 insertions(+), 15 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 8983178..f18f3de 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -304,3 +304,121 @@
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower)
+{
+	uint16_t cnt;
+	uint32_t count = 0;
+	struct rte_mbuf *mbuf;
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+	struct nfp_flower_cmsg_tun_ipv4_addr *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v4 tun addr");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_IPS, sizeof(*msg));
+
+	priv = app_fw_flower->flow_priv;
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (count >= NFP_FL_IPV4_ADDRS_MAX) {
+			rte_spinlock_unlock(&priv->ipv4_off_lock);
+			PMD_DRV_LOG(ERR, "IPv4 offload exceeds limit.");
+			return -ERANGE;
+		}
+		msg->ipv4_addr[count] = entry->ipv4_addr;
+		count++;
+	}
+	msg->count = rte_cpu_to_be_32(count);
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		uint16_t mac_idx,
+		bool is_del)
+{
+	uint16_t cnt;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_pre_tun_rule *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for pre tunnel rule");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, sizeof(*msg));
+
+	meta_tci = (struct nfp_flower_meta_tci *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata));
+	if (meta_tci->tci)
+		msg->vlan_tci = meta_tci->tci;
+	else
+		msg->vlan_tci = 0xffff;
+
+	if (is_del)
+		msg->flags = rte_cpu_to_be_32(NFP_TUN_PRE_TUN_RULE_DEL);
+
+	msg->port_idx = rte_cpu_to_be_16(mac_idx);
+	msg->host_ctx_id = nfp_flow_meta->host_ctx_id;
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+nfp_flower_cmsg_tun_mac_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_ether_addr *mac,
+		uint16_t mac_idx,
+		bool is_del)
+{
+	uint16_t cnt;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_mac *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for tunnel mac");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_MAC, sizeof(*msg));
+
+	msg->count = rte_cpu_to_be_16(1);
+	msg->index = rte_cpu_to_be_16(mac_idx);
+	rte_ether_addr_copy(mac, &msg->addr);
+	if (is_del)
+		msg->flags = rte_cpu_to_be_16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index d1e0562..0933dac 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -195,6 +195,91 @@ struct nfp_flower_cmsg_tun_neigh_v6 {
 	struct nfp_flower_tun_neigh common;
 };
 
+#define NFP_TUN_PRE_TUN_RULE_DEL    (1 << 0)
+#define NFP_TUN_PRE_TUN_IDX_BIT     (1 << 3)
+#define NFP_TUN_PRE_TUN_IPV6_BIT    (1 << 7)
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE
+ * Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ * -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *       +---------------------------------------------------------------+
+ *     0 |                             FLAGS                             |
+ *       +---------------------------------------------------------------+
+ *     1 |         MAC_IDX               |            VLAN_ID            |
+ *       +---------------------------------------------------------------+
+ *     2 |                           HOST_CTX                            |
+ *       +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_pre_tun_rule {
+	rte_be32_t flags;
+	rte_be16_t port_idx;
+	rte_be16_t vlan_tci;
+	rte_be32_t host_ctx_id;
+};
+
+#define NFP_TUN_MAC_OFFLOAD_DEL_FLAG  0x2
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_MAC
+ *     Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *    Word  +-----------------------+---+-+-+---------------+---------------+
+ *       0  |              spare    |NBI|D|F| Amount of MAC’s in this msg   |
+ *          +---------------+-------+---+-+-+---------------+---------------+
+ *       1  |            Index 0            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       2  |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       3  |            Index 1            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       4  |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *                                        ...
+ *          +---------------+---------------+---------------+---------------+
+ *     2N-1 |            Index N            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *     2N   |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *
+ *    F:   Flush bit. Set if entire table must be flushed. Rest of info in cmsg
+ *        will be ignored. Not implemented.
+ *    D:   Delete bit. Set if entry must be deleted instead of added
+ *    NBI: Network Block Interface. Set to 0
+ *    The amount of MAC’s per control message is limited only by the packet
+ *    buffer size. A 2048B buffer can fit 253 MAC address and a 10240B buffer
+ *    1277 MAC addresses.
+ */
+struct nfp_flower_cmsg_tun_mac {
+	rte_be16_t flags;
+	rte_be16_t count;           /**< Should always be 1 */
+	rte_be16_t index;
+	struct rte_ether_addr addr;
+};
+
+#define NFP_FL_IPV4_ADDRS_MAX        32
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_IPS
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                    Number of IP Addresses                     |
+ *          +---------------------------------------------------------------+
+ *        1 |                        IP Address #1                          |
+ *          +---------------------------------------------------------------+
+ *        2 |                        IP Address #2                          |
+ *          +---------------------------------------------------------------+
+ *          |                             ...                               |
+ *          +---------------------------------------------------------------+
+ *       32 |                        IP Address #32                         |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_ipv4_addr {
+	rte_be32_t count;
+	rte_be32_t ipv4_addr[NFP_FL_IPV4_ADDRS_MAX];
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -716,5 +801,14 @@ int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
 int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
+int nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower);
+int nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		uint16_t mac_idx,
+		bool is_del);
+int nfp_flower_cmsg_tun_mac_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_ether_addr *mac,
+		uint16_t mac_idx,
+		bool is_del);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index b9c37b6..816c733 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -47,7 +47,8 @@ struct nfp_flow_item_proc {
 	/* Size in bytes for @p mask_support and @p mask_default. */
 	const unsigned int mask_sz;
 	/* Merge a pattern item into a flow rule handle. */
-	int (*merge)(struct rte_flow *nfp_flow,
+	int (*merge)(struct nfp_app_fw_flower *app_fw_flower,
+			struct rte_flow *nfp_flow,
 			char **mbuf_off,
 			const struct rte_flow_item *item,
 			const struct nfp_flow_item_proc *proc,
@@ -63,6 +64,12 @@ struct nfp_mask_id_entry {
 	uint8_t mask_id;
 };
 
+struct nfp_pre_tun_entry {
+	uint16_t mac_index;
+	uint16_t ref_cnt;
+	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
+} __rte_aligned(32);
+
 static inline struct nfp_flow_priv *
 nfp_flow_dev_to_priv(struct rte_eth_dev *dev)
 {
@@ -417,6 +424,83 @@ struct nfp_mask_id_entry {
 	return 0;
 }
 
+__rte_unused static int
+nfp_tun_add_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+	struct nfp_ipv4_addr_entry *tmp_entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (entry->ipv4_addr == ipv4) {
+			entry->ref_count++;
+			rte_spinlock_unlock(&priv->ipv4_off_lock);
+			return 0;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	tmp_entry = rte_zmalloc("nfp_ipv4_off", sizeof(struct nfp_ipv4_addr_entry), 0);
+	if (tmp_entry == NULL) {
+		PMD_DRV_LOG(ERR, "Mem error when offloading IP address.");
+		return -ENOMEM;
+	}
+
+	tmp_entry->ipv4_addr = ipv4;
+	tmp_entry->ref_count = 1;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_INSERT_HEAD(&priv->ipv4_off_list, tmp_entry, next);
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	return nfp_flower_cmsg_tun_off_v4(app_fw_flower);
+}
+
+static int
+nfp_tun_del_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (entry->ipv4_addr == ipv4) {
+			entry->ref_count--;
+			if (entry->ref_count == 0) {
+				LIST_REMOVE(entry, next);
+				rte_free(entry);
+				rte_spinlock_unlock(&priv->ipv4_off_lock);
+				return nfp_flower_cmsg_tun_off_v4(app_fw_flower);
+			}
+			break;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	return 0;
+}
+
+static int
+nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	struct nfp_flower_ipv4_udp_tun *udp4;
+
+	udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+			sizeof(struct nfp_flower_ipv4_udp_tun));
+	ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+
+	return ret;
+}
+
 static void
 nfp_flower_compile_meta_tci(char *mbuf_off, struct nfp_fl_key_ls *key_layer)
 {
@@ -653,6 +737,9 @@ struct nfp_mask_id_entry {
 		case RTE_FLOW_ACTION_TYPE_RSS:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RSS detected");
 			break;
+		case RTE_FLOW_ACTION_TYPE_JUMP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_JUMP detected");
+			break;
 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_PORT_ID detected");
 			key_ls->act_size += sizeof(struct nfp_fl_act_output);
@@ -804,7 +891,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_eth(__rte_unused struct rte_flow *nfp_flow,
+nfp_flow_merge_eth(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -841,7 +929,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_vlan(struct rte_flow *nfp_flow,
+nfp_flow_merge_vlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		__rte_unused char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -871,7 +960,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_ipv4(struct rte_flow *nfp_flow,
+nfp_flow_merge_ipv4(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -932,7 +1022,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_ipv6(struct rte_flow *nfp_flow,
+nfp_flow_merge_ipv6(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -997,7 +1088,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_tcp(struct rte_flow *nfp_flow,
+nfp_flow_merge_tcp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1070,7 +1162,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_udp(struct rte_flow *nfp_flow,
+nfp_flow_merge_udp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1118,7 +1211,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_sctp(struct rte_flow *nfp_flow,
+nfp_flow_merge_sctp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1160,7 +1254,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_vxlan(struct rte_flow *nfp_flow,
+nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1409,7 +1504,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_compile_item_proc(const struct rte_flow_item items[],
+nfp_flow_compile_item_proc(struct nfp_flower_representor *repr,
+		const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow,
 		char **mbuf_off_exact,
 		char **mbuf_off_mask,
@@ -1420,6 +1516,7 @@ struct nfp_mask_id_entry {
 	bool continue_flag = true;
 	const struct rte_flow_item *item;
 	const struct nfp_flow_item_proc *proc_list;
+	struct nfp_app_fw_flower *app_fw_flower = repr->app_fw_flower;
 
 	proc_list = nfp_flow_item_proc_list;
 	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END && continue_flag; ++item) {
@@ -1455,14 +1552,14 @@ struct nfp_mask_id_entry {
 			break;
 		}
 
-		ret = proc->merge(nfp_flow, mbuf_off_exact, item,
+		ret = proc->merge(app_fw_flower, nfp_flow, mbuf_off_exact, item,
 				proc, false, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d exact merge failed", item->type);
 			break;
 		}
 
-		ret = proc->merge(nfp_flow, mbuf_off_mask, item,
+		ret = proc->merge(app_fw_flower, nfp_flow, mbuf_off_mask, item,
 				proc, true, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d mask merge failed", item->type);
@@ -1476,7 +1573,7 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
+nfp_flow_compile_items(struct nfp_flower_representor *representor,
 		const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow)
 {
@@ -1507,7 +1604,7 @@ struct nfp_mask_id_entry {
 		is_outer_layer = false;
 
 	/* Go over items */
-	ret = nfp_flow_compile_item_proc(loop_item, nfp_flow,
+	ret = nfp_flow_compile_item_proc(representor, loop_item, nfp_flow,
 			&mbuf_off_exact, &mbuf_off_mask, is_outer_layer);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "nfp flow item compile failed.");
@@ -1516,7 +1613,7 @@ struct nfp_mask_id_entry {
 
 	/* Go over inner items */
 	if (is_tun_flow) {
-		ret = nfp_flow_compile_item_proc(items, nfp_flow,
+		ret = nfp_flow_compile_item_proc(representor, items, nfp_flow,
 				&mbuf_off_exact, &mbuf_off_mask, true);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow outer item compile failed.");
@@ -1891,6 +1988,59 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_ipv4 *ipv4;
+	struct nfp_flower_mac_mpls *eth;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	port = (struct nfp_flower_in_port *)(meta_tci + 1);
+	eth = (struct nfp_flower_mac_mpls *)(port + 1);
+
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+		ipv4 = (struct nfp_flower_ipv4 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls) +
+				sizeof(struct nfp_flower_tp_ports));
+	else
+		ipv4 = (struct nfp_flower_ipv4 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls));
+
+	tun = &nfp_flow->tun;
+	tun->payload.v6_flag = 0;
+	tun->payload.dst.dst_ipv4 = ipv4->ipv4_src;
+	tun->payload.src.src_ipv4 = ipv4->ipv4_dst;
+	memcpy(tun->payload.dst_addr, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4->ipv4_src;
+	payload.src_ipv4 = ipv4->ipv4_dst;
+	memcpy(payload.common.dst_mac, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
@@ -2108,6 +2258,200 @@ struct nfp_mask_id_entry {
 				actions, vxlan_data, nfp_flow_meta, tun);
 }
 
+static struct nfp_pre_tun_entry *
+nfp_pre_tun_table_search(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int index;
+	uint32_t hash_key;
+	struct nfp_pre_tun_entry *mac_index;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	index = rte_hash_lookup_data(priv->pre_tun_table, &hash_key, (void **)&mac_index);
+	if (index < 0) {
+		PMD_DRV_LOG(DEBUG, "Data NOT found in the hash table");
+		return NULL;
+	}
+
+	return mac_index;
+}
+
+static bool
+nfp_pre_tun_table_add(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int ret;
+	uint32_t hash_key;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	ret = rte_hash_add_key_data(priv->pre_tun_table, &hash_key, hash_data);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Add to pre tunnel table failed");
+		return false;
+	}
+
+	return true;
+}
+
+static bool
+nfp_pre_tun_table_delete(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int ret;
+	uint32_t hash_key;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	ret = rte_hash_del_key(priv->pre_tun_table, &hash_key);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "Delete from pre tunnel table failed");
+		return false;
+	}
+
+	return true;
+}
+
+__rte_unused static int
+nfp_pre_tun_table_check_add(struct nfp_flower_representor *repr,
+		uint16_t *index)
+{
+	uint16_t i;
+	uint32_t entry_size;
+	uint16_t mac_index = 1;
+	struct nfp_flow_priv *priv;
+	struct nfp_pre_tun_entry *entry;
+	struct nfp_pre_tun_entry *find_entry;
+
+	priv = repr->app_fw_flower->flow_priv;
+	if (priv->pre_tun_cnt >= NFP_TUN_PRE_TUN_RULE_LIMIT) {
+		PMD_DRV_LOG(ERR, "Pre tunnel table has full");
+		return -EINVAL;
+	}
+
+	entry_size = sizeof(struct nfp_pre_tun_entry);
+	entry = rte_zmalloc("nfp_pre_tun", entry_size, 0);
+	if (entry == NULL) {
+		PMD_DRV_LOG(ERR, "Memory alloc failed for pre tunnel table");
+		return -ENOMEM;
+	}
+
+	entry->ref_cnt = 1U;
+	memcpy(entry->mac_addr, repr->mac_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	/* 0 is considered a failed match */
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0)
+			continue;
+		entry->mac_index = i;
+		find_entry = nfp_pre_tun_table_search(priv, (char *)entry, entry_size);
+		if (find_entry != NULL) {
+			find_entry->ref_cnt++;
+			*index = find_entry->mac_index;
+			rte_free(entry);
+			return 0;
+		}
+	}
+
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0) {
+			priv->pre_tun_bitmap[i] = 1U;
+			mac_index = i;
+			break;
+		}
+	}
+
+	entry->mac_index = mac_index;
+	if (!nfp_pre_tun_table_add(priv, (char *)entry, entry_size)) {
+		rte_free(entry);
+		return -EINVAL;
+	}
+
+	*index = entry->mac_index;
+	priv->pre_tun_cnt++;
+	return 0;
+}
+
+static int
+nfp_pre_tun_table_check_del(struct nfp_flower_representor *repr,
+		struct rte_flow *nfp_flow)
+{
+	uint16_t i;
+	int ret = 0;
+	uint32_t entry_size;
+	uint16_t nfp_mac_idx;
+	struct nfp_flow_priv *priv;
+	struct nfp_pre_tun_entry *entry;
+	struct nfp_pre_tun_entry *find_entry;
+	struct nfp_fl_rule_metadata *nfp_flow_meta;
+
+	priv = repr->app_fw_flower->flow_priv;
+	if (priv->pre_tun_cnt == 1)
+		return 0;
+
+	entry_size = sizeof(struct nfp_pre_tun_entry);
+	entry = rte_zmalloc("nfp_pre_tun", entry_size, 0);
+	if (entry == NULL) {
+		PMD_DRV_LOG(ERR, "Memory alloc failed for pre tunnel table");
+		return -ENOMEM;
+	}
+
+	entry->ref_cnt = 1U;
+	memcpy(entry->mac_addr, repr->mac_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	/* 0 is considered a failed match */
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0)
+			continue;
+		entry->mac_index = i;
+		find_entry = nfp_pre_tun_table_search(priv, (char *)entry, entry_size);
+		if (find_entry != NULL) {
+			find_entry->ref_cnt--;
+			if (find_entry->ref_cnt != 0)
+				goto free_entry;
+			priv->pre_tun_bitmap[i] = 0;
+			break;
+		}
+	}
+
+	nfp_flow_meta = nfp_flow->payload.meta;
+	nfp_mac_idx = (find_entry->mac_index << 8) |
+			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
+			NFP_TUN_PRE_TUN_IDX_BIT;
+	ret = nfp_flower_cmsg_tun_mac_rule(repr->app_fw_flower, &repr->mac_addr,
+			nfp_mac_idx, true);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send tunnel mac rule failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
+			nfp_mac_idx, true);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	find_entry->ref_cnt = 1U;
+	if (!nfp_pre_tun_table_delete(priv, (char *)find_entry, entry_size)) {
+		PMD_DRV_LOG(ERR, "Delete entry from pre tunnel table failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	rte_free(entry);
+	rte_free(find_entry);
+	priv->pre_tun_cnt--;
+
+free_entry:
+	rte_free(entry);
+
+	return ret;
+}
+
 static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
@@ -2149,6 +2493,9 @@ struct nfp_mask_id_entry {
 		case RTE_FLOW_ACTION_TYPE_RSS:
 			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_RSS");
 			break;
+		case RTE_FLOW_ACTION_TYPE_JUMP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_JUMP");
+			break;
 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
 			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_PORT_ID");
 			ret = nfp_flow_action_output(position, action, nfp_flow_meta);
@@ -2569,6 +2916,15 @@ struct nfp_mask_id_entry {
 		/* Delete the entry from nn table */
 		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
 		break;
+	case NFP_FLOW_DECAP:
+		/* Delete the entry from nn table */
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		if (ret != 0)
+			goto exit;
+
+		/* Delete the entry in pre tunnel table */
+		ret = nfp_pre_tun_table_check_del(representor, nfp_flow);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Invalid nfp flow type %d.", nfp_flow->type);
 		ret = -EINVAL;
@@ -2578,6 +2934,10 @@ struct nfp_mask_id_entry {
 	if (ret != 0)
 		goto exit;
 
+	/* Delete the ip off */
+	if (nfp_flow_is_tunnel(nfp_flow))
+		nfp_tun_check_ip_off_del(representor, nfp_flow);
+
 	/* Delete the flow from hardware */
 	if (nfp_flow->install_flag) {
 		ret = nfp_flower_cmsg_flow_delete(app_fw_flower, nfp_flow);
@@ -2707,6 +3067,49 @@ struct nfp_mask_id_entry {
 	return 0;
 }
 
+static int
+nfp_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
+		struct rte_flow_tunnel *tunnel,
+		struct rte_flow_action **pmd_actions,
+		uint32_t *num_of_actions,
+		__rte_unused struct rte_flow_error *err)
+{
+	struct rte_flow_action *nfp_action;
+
+	nfp_action = rte_zmalloc("nfp_tun_action", sizeof(struct rte_flow_action), 0);
+	if (nfp_action == NULL) {
+		PMD_DRV_LOG(ERR, "Alloc memory for nfp tunnel action failed.");
+		return -ENOMEM;
+	}
+
+	switch (tunnel->type) {
+	default:
+		*pmd_actions = NULL;
+		*num_of_actions = 0;
+		rte_free(nfp_action);
+		break;
+	}
+
+	return 0;
+}
+
+static int
+nfp_flow_tunnel_action_decap_release(__rte_unused struct rte_eth_dev *dev,
+		struct rte_flow_action *pmd_actions,
+		uint32_t num_of_actions,
+		__rte_unused struct rte_flow_error *err)
+{
+	uint32_t i;
+	struct rte_flow_action *nfp_action;
+
+	for (i = 0; i < num_of_actions; i++) {
+		nfp_action = &pmd_actions[i];
+		rte_free(nfp_action);
+	}
+
+	return 0;
+}
+
 static const struct rte_flow_ops nfp_flow_ops = {
 	.validate                    = nfp_flow_validate,
 	.create                      = nfp_flow_create,
@@ -2715,6 +3118,8 @@ struct nfp_mask_id_entry {
 	.query                       = nfp_flow_query,
 	.tunnel_match                = nfp_flow_tunnel_match,
 	.tunnel_item_release         = nfp_flow_tunnel_item_release,
+	.tunnel_decap_set            = nfp_flow_tunnel_decap_set,
+	.tunnel_action_decap_release = nfp_flow_tunnel_action_decap_release,
 };
 
 int
@@ -2759,6 +3164,15 @@ struct nfp_mask_id_entry {
 		.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
 	};
 
+	struct rte_hash_parameters pre_tun_hash_params = {
+		.name       = "pre_tunnel_table",
+		.entries    = 32,
+		.hash_func  = rte_jhash,
+		.socket_id  = rte_socket_id(),
+		.key_len    = sizeof(uint32_t),
+		.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
+	};
+
 	ctx_count = nfp_rtsym_read_le(pf_dev->sym_tbl,
 			"CONFIG_FC_HOST_CTX_COUNT", &ret);
 	if (ret < 0) {
@@ -2839,11 +3253,27 @@ struct nfp_mask_id_entry {
 		goto free_mask_table;
 	}
 
+	/* pre tunnel table */
+	priv->pre_tun_cnt = 1;
+	pre_tun_hash_params.hash_func_init_val = priv->hash_seed;
+	priv->pre_tun_table = rte_hash_create(&pre_tun_hash_params);
+	if (priv->pre_tun_table == NULL) {
+		PMD_INIT_LOG(ERR, "Pre tunnel table creation failed");
+		ret = -ENOMEM;
+		goto free_flow_table;
+	}
+
+	/* ipv4 off list */
+	rte_spinlock_init(&priv->ipv4_off_lock);
+	LIST_INIT(&priv->ipv4_off_list);
+
 	/* neighbor next list */
 	LIST_INIT(&priv->nn_list);
 
 	return 0;
 
+free_flow_table:
+	rte_hash_free(priv->flow_table);
 free_mask_table:
 	rte_free(priv->mask_table);
 free_stats:
@@ -2867,6 +3297,7 @@ struct nfp_mask_id_entry {
 	app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
 	priv = app_fw_flower->flow_priv;
 
+	rte_hash_free(priv->pre_tun_table);
 	rte_hash_free(priv->flow_table);
 	rte_hash_free(priv->mask_table);
 	rte_free(priv->stats);
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index 14da800..84a3005 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -6,6 +6,7 @@
 #ifndef _NFP_FLOW_H_
 #define _NFP_FLOW_H_
 
+#include <sys/queue.h>
 #include <ethdev_driver.h>
 
 #define NFP_FLOWER_LAYER_EXT_META   (1 << 0)
@@ -92,6 +93,7 @@ enum nfp_flower_tun_type {
 enum nfp_flow_type {
 	NFP_FLOW_COMMON,
 	NFP_FLOW_ENCAP,
+	NFP_FLOW_DECAP,
 };
 
 struct nfp_fl_key_ls {
@@ -168,6 +170,14 @@ struct nfp_fl_stats {
 	uint64_t bytes;
 };
 
+struct nfp_ipv4_addr_entry {
+	LIST_ENTRY(nfp_ipv4_addr_entry) next;
+	rte_be32_t ipv4_addr;
+	int ref_count;
+};
+
+#define NFP_TUN_PRE_TUN_RULE_LIMIT  32
+
 struct nfp_flow_priv {
 	uint32_t hash_seed; /**< Hash seed for hash tables in this structure. */
 	uint64_t flower_version; /**< Flow version, always increase. */
@@ -183,6 +193,13 @@ struct nfp_flow_priv {
 	struct nfp_fl_stats_id stats_ids; /**< The stats id ring. */
 	struct nfp_fl_stats *stats; /**< Store stats of flow. */
 	rte_spinlock_t stats_lock; /** < Lock the update of 'stats' field. */
+	/* pre tunnel rule */
+	uint16_t pre_tun_cnt; /**< The size of pre tunnel rule */
+	uint8_t pre_tun_bitmap[NFP_TUN_PRE_TUN_RULE_LIMIT]; /**< Bitmap of pre tunnel rule */
+	struct rte_hash *pre_tun_table; /**< Hash table to store pre tunnel rule */
+	/* IPv4 off */
+	LIST_HEAD(, nfp_ipv4_addr_entry) ipv4_off_list; /**< Store ipv4 off */
+	rte_spinlock_t ipv4_off_lock; /**< Lock the ipv4 off list */
 	/* neighbor next */
 	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 08/25] net/nfp: prepare for the decap action of IPv6 UDP tunnel
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (6 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 07/25] net/nfp: prepare for the decap action of IPv4 UDP tunnel Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 09/25] net/nfp: add the offload support of IPv4 VXLAN decap action Chaoyong He
                   ` (18 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the decap action of IPv6 UDP tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  42 +++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  24 +++++
 drivers/net/nfp/nfp_flow.c               | 145 ++++++++++++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |   9 ++
 4 files changed, 217 insertions(+), 3 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index f18f3de..76815cf 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -348,6 +348,48 @@
 }
 
 int
+nfp_flower_cmsg_tun_off_v6(struct nfp_app_fw_flower *app_fw_flower)
+{
+	uint16_t cnt;
+	uint32_t count = 0;
+	struct rte_mbuf *mbuf;
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+	struct nfp_flower_cmsg_tun_ipv6_addr *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v6 tun addr");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_IPS_V6, sizeof(*msg));
+
+	priv = app_fw_flower->flow_priv;
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (count >= NFP_FL_IPV6_ADDRS_MAX) {
+			rte_spinlock_unlock(&priv->ipv6_off_lock);
+			PMD_DRV_LOG(ERR, "IPv6 offload exceeds limit.");
+			return -ERANGE;
+		}
+		memcpy(&msg->ipv6_addr[count * 16], entry->ipv6_addr, 16UL);
+		count++;
+	}
+	msg->count = rte_cpu_to_be_32(count);
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
 nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		uint16_t mac_idx,
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 0933dac..61f2f83 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -280,6 +280,29 @@ struct nfp_flower_cmsg_tun_ipv4_addr {
 	rte_be32_t ipv4_addr[NFP_FL_IPV4_ADDRS_MAX];
 };
 
+#define NFP_FL_IPV6_ADDRS_MAX        4
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_IP_V6
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                    Number of IP Addresses                     |
+ *          +---------------------------------------------------------------+
+ *        1 |                        IP Address1 #1                         |
+ *          +---------------------------------------------------------------+
+ *        2 |                        IP Address1 #2                         |
+ *          +---------------------------------------------------------------+
+ *          |                             ...                               |
+ *          +---------------------------------------------------------------+
+ *       16 |                        IP Address4 #4                         |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_ipv6_addr {
+	rte_be32_t count;
+	uint8_t ipv6_addr[NFP_FL_IPV6_ADDRS_MAX * 16];
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -802,6 +825,7 @@ int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
 int nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower);
+int nfp_flower_cmsg_tun_off_v6(struct nfp_app_fw_flower *app_fw_flower);
 int nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		uint16_t mac_idx,
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 816c733..cc63aa5 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -487,16 +487,95 @@ struct nfp_pre_tun_entry {
 	return 0;
 }
 
+__rte_unused static int
+nfp_tun_add_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t ipv6[])
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+	struct nfp_ipv6_addr_entry *tmp_entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (!memcmp(entry->ipv6_addr, ipv6, sizeof(entry->ipv6_addr))) {
+			entry->ref_count++;
+			rte_spinlock_unlock(&priv->ipv6_off_lock);
+			return 0;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	tmp_entry = rte_zmalloc("nfp_ipv6_off", sizeof(struct nfp_ipv6_addr_entry), 0);
+	if (tmp_entry == NULL) {
+		PMD_DRV_LOG(ERR, "Mem error when offloading IP6 address.");
+		return -ENOMEM;
+	}
+	memcpy(tmp_entry->ipv6_addr, ipv6, sizeof(tmp_entry->ipv6_addr));
+	tmp_entry->ref_count = 1;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_INSERT_HEAD(&priv->ipv6_off_list, tmp_entry, next);
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	return nfp_flower_cmsg_tun_off_v6(app_fw_flower);
+}
+
+static int
+nfp_tun_del_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t ipv6[])
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (!memcmp(entry->ipv6_addr, ipv6, sizeof(entry->ipv6_addr))) {
+			entry->ref_count--;
+			if (entry->ref_count == 0) {
+				LIST_REMOVE(entry, next);
+				rte_free(entry);
+				rte_spinlock_unlock(&priv->ipv6_off_lock);
+				return nfp_flower_cmsg_tun_off_v6(app_fw_flower);
+			}
+			break;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	return 0;
+}
+
 static int
 nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
 		struct rte_flow *nfp_flow)
 {
 	int ret;
+	uint32_t key_layer2 = 0;
 	struct nfp_flower_ipv4_udp_tun *udp4;
+	struct nfp_flower_ipv6_udp_tun *udp6;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 
-	udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
-			sizeof(struct nfp_flower_ipv4_udp_tun));
-	ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
+
+	if (ext_meta != NULL)
+		key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
+
+	if (key_layer2 & NFP_FLOWER_LAYER2_TUN_IPV6) {
+		udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
+				sizeof(struct nfp_flower_ipv6_udp_tun));
+		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+	} else {
+		udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+				sizeof(struct nfp_flower_ipv4_udp_tun));
+		ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+	}
 
 	return ret;
 }
@@ -2096,6 +2175,59 @@ struct nfp_pre_tun_entry {
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_ipv6 *ipv6;
+	struct nfp_flower_mac_mpls *eth;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	port = (struct nfp_flower_in_port *)(meta_tci + 1);
+	eth = (struct nfp_flower_mac_mpls *)(port + 1);
+
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+		ipv6 = (struct nfp_flower_ipv6 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls) +
+				sizeof(struct nfp_flower_tp_ports));
+	else
+		ipv6 = (struct nfp_flower_ipv6 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls));
+
+	tun = &nfp_flow->tun;
+	tun->payload.v6_flag = 1;
+	memcpy(tun->payload.dst.dst_ipv6, ipv6->ipv6_src, sizeof(tun->payload.dst.dst_ipv6));
+	memcpy(tun->payload.src.src_ipv6, ipv6->ipv6_dst, sizeof(tun->payload.src.src_ipv6));
+	memcpy(tun->payload.dst_addr, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6->ipv6_src, sizeof(payload.dst_ipv6));
+	memcpy(payload.src_ipv6, ipv6->ipv6_dst, sizeof(payload.src_ipv6));
+	memcpy(payload.common.dst_mac, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
 		uint8_t *ipv6)
@@ -2419,6 +2551,9 @@ struct nfp_pre_tun_entry {
 	nfp_mac_idx = (find_entry->mac_index << 8) |
 			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
 			NFP_TUN_PRE_TUN_IDX_BIT;
+	if (nfp_flow->tun.payload.v6_flag != 0)
+		nfp_mac_idx |= NFP_TUN_PRE_TUN_IPV6_BIT;
+
 	ret = nfp_flower_cmsg_tun_mac_rule(repr->app_fw_flower, &repr->mac_addr,
 			nfp_mac_idx, true);
 	if (ret != 0) {
@@ -3267,6 +3402,10 @@ struct nfp_pre_tun_entry {
 	rte_spinlock_init(&priv->ipv4_off_lock);
 	LIST_INIT(&priv->ipv4_off_list);
 
+	/* ipv6 off list */
+	rte_spinlock_init(&priv->ipv6_off_lock);
+	LIST_INIT(&priv->ipv6_off_list);
+
 	/* neighbor next list */
 	LIST_INIT(&priv->nn_list);
 
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index 84a3005..1b4a51f 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -176,6 +176,12 @@ struct nfp_ipv4_addr_entry {
 	int ref_count;
 };
 
+struct nfp_ipv6_addr_entry {
+	LIST_ENTRY(nfp_ipv6_addr_entry) next;
+	uint8_t ipv6_addr[16];
+	int ref_count;
+};
+
 #define NFP_TUN_PRE_TUN_RULE_LIMIT  32
 
 struct nfp_flow_priv {
@@ -200,6 +206,9 @@ struct nfp_flow_priv {
 	/* IPv4 off */
 	LIST_HEAD(, nfp_ipv4_addr_entry) ipv4_off_list; /**< Store ipv4 off */
 	rte_spinlock_t ipv4_off_lock; /**< Lock the ipv4 off list */
+	/* IPv6 off */
+	LIST_HEAD(, nfp_ipv6_addr_entry) ipv6_off_list; /**< Store ipv6 off */
+	rte_spinlock_t ipv6_off_lock; /**< Lock the ipv6 off list */
 	/* neighbor next */
 	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 09/25] net/nfp: add the offload support of IPv4 VXLAN decap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (7 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 08/25] net/nfp: prepare for the decap action of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 10/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (17 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv4 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 75 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index fbfd5ba..3b5b052 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -58,4 +58,5 @@ set_mac_src          = Y
 set_tp_dst           = Y
 set_tp_src           = Y
 set_ttl              = Y
+vxlan_decap          = Y
 vxlan_encap          = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index cc63aa5..0578679 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -424,7 +424,7 @@ struct nfp_pre_tun_entry {
 	return 0;
 }
 
-__rte_unused static int
+static int
 nfp_tun_add_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
 {
@@ -926,6 +926,9 @@ struct nfp_pre_tun_entry {
 			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
 			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1333,7 +1336,7 @@ struct nfp_pre_tun_entry {
 }
 
 static int
-nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_vxlan(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1341,6 +1344,7 @@ struct nfp_pre_tun_entry {
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	const struct rte_vxlan_hdr *hdr;
 	struct nfp_flower_ipv4_udp_tun *tun4;
 	struct nfp_flower_ipv6_udp_tun *tun6;
@@ -1369,6 +1373,8 @@ struct nfp_pre_tun_entry {
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = hdr->vx_vni;
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 vxlan_end:
@@ -1378,7 +1384,7 @@ struct nfp_pre_tun_entry {
 	else
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 
-	return 0;
+	return ret;
 }
 
 /* Graph of supported items and associated process function */
@@ -2067,7 +2073,7 @@ struct nfp_pre_tun_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -2445,7 +2451,7 @@ struct nfp_pre_tun_entry {
 	return true;
 }
 
-__rte_unused static int
+static int
 nfp_pre_tun_table_check_add(struct nfp_flower_representor *repr,
 		uint16_t *index)
 {
@@ -2588,6 +2594,49 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
+		__rte_unused const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	uint16_t nfp_mac_idx = 0;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_app_fw_flower *app_fw_flower;
+
+	ret = nfp_pre_tun_table_check_add(repr, &nfp_mac_idx);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Pre tunnel table add failed");
+		return -EINVAL;
+	}
+
+	nfp_mac_idx = (nfp_mac_idx << 8) |
+			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
+			NFP_TUN_PRE_TUN_IDX_BIT;
+
+	app_fw_flower = repr->app_fw_flower;
+	ret = nfp_flower_cmsg_tun_mac_rule(app_fw_flower, &repr->mac_addr,
+			nfp_mac_idx, false);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send tunnel mac rule failed");
+		return -EINVAL;
+	}
+
+	ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
+			nfp_mac_idx, false);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+		return -EINVAL;
+	}
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
+		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
+	else
+		return -ENOTSUP;
+}
+
+static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
 		struct rte_flow *nfp_flow)
@@ -2768,6 +2817,17 @@ struct nfp_pre_tun_entry {
 			position += sizeof(struct nfp_fl_act_set_tun);
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			PMD_DRV_LOG(DEBUG, "process RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP");
+			ret = nfp_flow_action_tunnel_decap(representor, action,
+					nfp_flow_meta, nfp_flow);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process tunnel decap");
+				return ret;
+			}
+			nfp_flow->type = NFP_FLOW_DECAP;
+			nfp_flow->install_flag = false;
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
 			return -ENOTSUP;
@@ -3218,6 +3278,11 @@ struct nfp_pre_tun_entry {
 	}
 
 	switch (tunnel->type) {
+	case RTE_FLOW_ITEM_TYPE_VXLAN:
+		nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
+		*pmd_actions = nfp_action;
+		*num_of_actions = 1;
+		break;
 	default:
 		*pmd_actions = NULL;
 		*num_of_actions = 0;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 10/25] net/nfp: add the offload support of IPv6 VXLAN decap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (8 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 09/25] net/nfp: add the offload support of IPv4 VXLAN decap action Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 11/25] net/nfp: add the offload support of IPv4 GENEVE encap action Chaoyong He
                   ` (16 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv6 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/rel_notes/release_22_11.rst |  2 +-
 drivers/net/nfp/nfp_flow.c             | 18 ++++++++++++++----
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index 351fb02..49e92cc 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -184,7 +184,7 @@ New Features
     * Set the port number
     * Set the TTL
     * Set the DSCP of IPv4 and IPv6
-    * Encap of VXLAN tunnel
+    * Encap and decap of VXLAN tunnel
 
 * **Updated NXP dpaa2 driver.**
 
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 0578679..e212e96 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -487,7 +487,7 @@ struct nfp_pre_tun_entry {
 	return 0;
 }
 
-__rte_unused static int
+static int
 nfp_tun_add_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
 		uint8_t ipv6[])
 {
@@ -1370,6 +1370,8 @@ struct nfp_pre_tun_entry {
 			NFP_FLOWER_LAYER2_TUN_IPV6)) {
 		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
 		tun6->tun_id = hdr->vx_vni;
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = hdr->vx_vni;
@@ -2181,7 +2183,7 @@ struct nfp_pre_tun_entry {
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -2595,7 +2597,7 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
-		__rte_unused const struct rte_flow_action *action,
+		const struct rte_flow_action *action,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
@@ -2613,6 +2615,8 @@ struct nfp_pre_tun_entry {
 	nfp_mac_idx = (nfp_mac_idx << 8) |
 			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
 			NFP_TUN_PRE_TUN_IDX_BIT;
+	if (action->conf != NULL)
+		nfp_mac_idx |= NFP_TUN_PRE_TUN_IPV6_BIT;
 
 	app_fw_flower = repr->app_fw_flower;
 	ret = nfp_flower_cmsg_tun_mac_rule(app_fw_flower, &repr->mac_addr,
@@ -2633,7 +2637,7 @@ struct nfp_pre_tun_entry {
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
 		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
 	else
-		return -ENOTSUP;
+		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow);
 }
 
 static int
@@ -2827,6 +2831,8 @@ struct nfp_pre_tun_entry {
 			}
 			nfp_flow->type = NFP_FLOW_DECAP;
 			nfp_flow->install_flag = false;
+			if (action->conf != NULL)
+				nfp_flow->tun.payload.v6_flag = 1;
 			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
@@ -3277,6 +3283,9 @@ struct nfp_pre_tun_entry {
 		return -ENOMEM;
 	}
 
+	if (tunnel->is_ipv6)
+		nfp_action->conf = (void *)~0;
+
 	switch (tunnel->type) {
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
 		nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
@@ -3304,6 +3313,7 @@ struct nfp_pre_tun_entry {
 
 	for (i = 0; i < num_of_actions; i++) {
 		nfp_action = &pmd_actions[i];
+		nfp_action->conf = NULL;
 		rte_free(nfp_action);
 	}
 
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 11/25] net/nfp: add the offload support of IPv4 GENEVE encap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (9 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 10/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 12/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (15 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv4 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |   1 +
 drivers/net/nfp/nfp_flow.c       | 107 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 3b5b052..171b633 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -46,6 +46,7 @@ of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
 of_set_vlan_vid      = Y
+raw_encap            = Y
 port_id              = Y
 set_ipv4_dscp        = Y
 set_ipv4_dst         = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index e212e96..265c7e8 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -38,6 +38,12 @@ struct vxlan_data {
 		__VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
 	})
 
+/* Data length of various conf of raw encap action */
+#define GENEVE_V4_LEN    (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv4_hdr) + \
+				sizeof(struct rte_udp_hdr) + \
+				sizeof(struct rte_flow_item_geneve))
+
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
 	/* Bit-mask for fields supported by this PMD. */
@@ -926,6 +932,11 @@ struct nfp_pre_tun_entry {
 			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
 			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_ENCAP detected");
+			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
+			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
 			break;
@@ -2641,6 +2652,88 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_geneve_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint64_t tun_id;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_udp *udp;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_geneve *geneve;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv4   = (const struct rte_flow_item_ipv4 *)(eth + 1);
+	udp    = (const struct rte_flow_item_udp *)(ipv4 + 1);
+	geneve = (const struct rte_flow_item_geneve *)(udp + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tun_id = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GENEVE, tun_id,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_proto = geneve->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv4);
+}
+
+static int
+nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	int ret;
+	size_t act_len;
+	size_t act_pre_size;
+	const struct rte_flow_action_raw_encap *raw_encap;
+
+	raw_encap = action->conf;
+	if (raw_encap->data == NULL) {
+		PMD_DRV_LOG(ERR, "The raw encap action conf is NULL.");
+		return -EINVAL;
+	}
+
+	/* Pre_tunnel action must be the first on action list.
+	 * If other actions already exist, they need to be
+	 * pushed forward.
+	 */
+	act_len = act_data - actions;
+	if (act_len != 0) {
+		act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+		memmove(actions + act_pre_size, actions, act_len);
+	}
+
+	switch (raw_encap->size) {
+	case GENEVE_V4_LEN:
+		ret = nfp_flow_action_geneve_encap_v4(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
 		struct rte_flow *nfp_flow)
@@ -2821,6 +2914,20 @@ struct nfp_pre_tun_entry {
 			position += sizeof(struct nfp_fl_act_set_tun);
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_RAW_ENCAP");
+			ret = nfp_flow_action_raw_encap(representor->app_fw_flower,
+					position, action_data, action, nfp_flow_meta,
+					&nfp_flow->tun);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process"
+						" RTE_FLOW_ACTION_TYPE_RAW_ENCAP");
+				return ret;
+			}
+			position += sizeof(struct nfp_fl_act_pre_tun);
+			position += sizeof(struct nfp_fl_act_set_tun);
+			nfp_flow->type = NFP_FLOW_ENCAP;
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "process RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP");
 			ret = nfp_flow_action_tunnel_decap(representor, action,
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 12/25] net/nfp: add the offload support of IPv6 GENEVE encap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (10 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 11/25] net/nfp: add the offload support of IPv4 GENEVE encap action Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 13/25] net/nfp: add the offload support of IPv4 GENEVE item Chaoyong He
                   ` (14 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv6 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/rel_notes/release_22_11.rst |  1 +
 drivers/net/nfp/nfp_flow.c             | 49 ++++++++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index 49e92cc..92a0d64 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -185,6 +185,7 @@ New Features
     * Set the TTL
     * Set the DSCP of IPv4 and IPv6
     * Encap and decap of VXLAN tunnel
+    * Encap of GENEVE tunnel
 
 * **Updated NXP dpaa2 driver.**
 
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 265c7e8..d93883a 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -43,6 +43,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv4_hdr) + \
 				sizeof(struct rte_udp_hdr) + \
 				sizeof(struct rte_flow_item_geneve))
+#define GENEVE_V6_LEN    (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv6_hdr) + \
+				sizeof(struct rte_udp_hdr) + \
+				sizeof(struct rte_flow_item_geneve))
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2691,6 +2695,47 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_geneve_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint8_t tos;
+	uint64_t tun_id;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_udp *udp;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_geneve *geneve;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv6   = (const struct rte_flow_item_ipv6 *)(eth + 1);
+	udp    = (const struct rte_flow_item_udp *)(ipv6 + 1);
+	geneve = (const struct rte_flow_item_geneve *)(udp + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tos = (ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff;
+	tun_id = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GENEVE, tun_id,
+			ipv6->hdr.hop_limits, tos);
+	set_tun->tun_proto = geneve->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv6);
+}
+
+static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
 		char *actions,
@@ -2724,6 +2769,10 @@ struct nfp_pre_tun_entry {
 		ret = nfp_flow_action_geneve_encap_v4(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case GENEVE_V6_LEN:
+		ret = nfp_flow_action_geneve_encap_v6(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 13/25] net/nfp: add the offload support of IPv4 GENEVE item
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (11 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 12/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 14/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (13 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv4 GENEVE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 75 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 171b633..4c0d1ab 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -28,6 +28,7 @@ Usage doc            = Y
 
 [rte_flow items]
 eth                  = Y
+geneve               = Y
 ipv4                 = Y
 ipv6                 = Y
 ipv6_frag_ext        = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index d93883a..da3ac69 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -781,6 +781,23 @@ struct nfp_pre_tun_entry {
 				return -EINVAL;
 			}
 			break;
+		case RTE_FLOW_ITEM_TYPE_GENEVE:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GENEVE detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_GENEVE;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;
+			key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -978,12 +995,22 @@ struct nfp_pre_tun_entry {
 static bool
 nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
 {
+	uint32_t key_layer2;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_meta_tci *meta_tci;
 
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_VXLAN)
 		return true;
 
+	if (!(meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META))
+		return false;
+
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
+	key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
+	if (key_layer2 & NFP_FLOWER_LAYER2_GENEVE)
+		return true;
+
 	return false;
 }
 
@@ -1404,6 +1431,39 @@ struct nfp_pre_tun_entry {
 	return ret;
 }
 
+static int
+nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	struct nfp_flower_ipv4_udp_tun *tun4;
+	const struct rte_flow_item_geneve *spec;
+	const struct rte_flow_item_geneve *mask;
+	const struct rte_flow_item_geneve *geneve;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge geneve: no item->spec!");
+		goto geneve_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	geneve = is_mask ? mask : spec;
+
+	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+	tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+			(geneve->vni[1] << 8) | (geneve->vni[2]));
+
+geneve_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+
+	return 0;
+}
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
@@ -1492,7 +1552,8 @@ struct nfp_pre_tun_entry {
 		.merge = nfp_flow_merge_tcp,
 	},
 	[RTE_FLOW_ITEM_TYPE_UDP] = {
-		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN),
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN,
+			RTE_FLOW_ITEM_TYPE_GENEVE),
 		.mask_support = &(const struct rte_flow_item_udp){
 			.hdr = {
 				.src_port = RTE_BE16(0xffff),
@@ -1525,6 +1586,15 @@ struct nfp_pre_tun_entry {
 		.mask_sz = sizeof(struct rte_flow_item_vxlan),
 		.merge = nfp_flow_merge_vxlan,
 	},
+	[RTE_FLOW_ITEM_TYPE_GENEVE] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &(const struct rte_flow_item_geneve){
+			.vni = "\xff\xff\xff",
+		},
+		.mask_default = &rte_flow_item_geneve_mask,
+		.mask_sz = sizeof(struct rte_flow_item_geneve),
+		.merge = nfp_flow_merge_geneve,
+	},
 };
 
 static int
@@ -1581,7 +1651,8 @@ struct nfp_pre_tun_entry {
 static bool
 nfp_flow_is_tun_item(const struct rte_flow_item *item)
 {
-	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN)
+	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
+			item->type == RTE_FLOW_ITEM_TYPE_GENEVE)
 		return true;
 
 	return false;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 14/25] net/nfp: add the offload support of IPv6 GENEVE item
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (12 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 13/25] net/nfp: add the offload support of IPv4 GENEVE item Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 15/25] net/nfp: add the offload support of IPv4 GENEVE decap action Chaoyong He
                   ` (12 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv6 GENEVE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 43 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index da3ac69..36dbf27 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -783,8 +783,9 @@ struct nfp_pre_tun_entry {
 			break;
 		case RTE_FLOW_ITEM_TYPE_GENEVE:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GENEVE detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_GENEVE;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
 			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;
@@ -796,6 +797,17 @@ struct nfp_pre_tun_entry {
 				 * in `struct nfp_flower_ipv4_udp_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for GENEVE tunnel.");
+				return -EINVAL;
 			}
 			break;
 		default:
@@ -1433,7 +1445,7 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1441,9 +1453,16 @@ struct nfp_pre_tun_entry {
 		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_ipv4_udp_tun *tun4;
+	struct nfp_flower_ipv6_udp_tun *tun6;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_geneve *spec;
 	const struct rte_flow_item_geneve *mask;
 	const struct rte_flow_item_geneve *geneve;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1454,12 +1473,24 @@ struct nfp_pre_tun_entry {
 	mask = item->mask ? item->mask : proc->mask_default;
 	geneve = is_mask ? mask : spec;
 
-	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
-	tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
-			(geneve->vni[1] << 8) | (geneve->vni[2]));
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+		tun6->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+				(geneve->vni[1] << 8) | (geneve->vni[2]));
+	} else {
+		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+				(geneve->vni[1] << 8) | (geneve->vni[2]));
+	}
 
 geneve_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_udp_tun);
+	} else {
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	}
 
 	return 0;
 }
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 15/25] net/nfp: add the offload support of IPv4 GENEVE decap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (13 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 14/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 16/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (11 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv4 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 4c0d1ab..7453109 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -47,6 +47,7 @@ of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
 of_set_vlan_vid      = Y
+raw_decap            = Y
 raw_encap            = Y
 port_id              = Y
 set_ipv4_dscp        = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 36dbf27..a8287a1 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -973,6 +973,9 @@ struct nfp_pre_tun_entry {
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_DECAP detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1444,7 +1447,7 @@ struct nfp_pre_tun_entry {
 }
 
 static int
-nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_geneve(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1452,6 +1455,7 @@ struct nfp_pre_tun_entry {
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	struct nfp_flower_ipv4_udp_tun *tun4;
 	struct nfp_flower_ipv6_udp_tun *tun6;
 	struct nfp_flower_meta_tci *meta_tci;
@@ -1482,6 +1486,8 @@ struct nfp_pre_tun_entry {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
 				(geneve->vni[1] << 8) | (geneve->vni[2]));
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 geneve_end:
@@ -1492,7 +1498,7 @@ struct nfp_pre_tun_entry {
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 	}
 
-	return 0;
+	return ret;
 }
 
 /* Graph of supported items and associated process function */
@@ -3080,6 +3086,7 @@ struct nfp_pre_tun_entry {
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
 			PMD_DRV_LOG(DEBUG, "process RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP");
 			ret = nfp_flow_action_tunnel_decap(representor, action,
 					nfp_flow_meta, nfp_flow);
@@ -3550,6 +3557,11 @@ struct nfp_pre_tun_entry {
 		*pmd_actions = nfp_action;
 		*num_of_actions = 1;
 		break;
+	case RTE_FLOW_ITEM_TYPE_GENEVE:
+		nfp_action->type = RTE_FLOW_ACTION_TYPE_RAW_DECAP;
+		*pmd_actions = nfp_action;
+		*num_of_actions = 1;
+		break;
 	default:
 		*pmd_actions = NULL;
 		*num_of_actions = 0;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 16/25] net/nfp: add the offload support of IPv6 GENEVE decap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (14 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 15/25] net/nfp: add the offload support of IPv4 GENEVE decap action Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 17/25] net/nfp: add the offload support of IPv4 NVGRE encap action Chaoyong He
                   ` (10 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv6 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/rel_notes/release_22_11.rst | 2 +-
 drivers/net/nfp/nfp_flow.c             | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index 92a0d64..4adad3c 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -185,7 +185,7 @@ New Features
     * Set the TTL
     * Set the DSCP of IPv4 and IPv6
     * Encap and decap of VXLAN tunnel
-    * Encap of GENEVE tunnel
+    * Encap and decap of GENEVE tunnel
 
 * **Updated NXP dpaa2 driver.**
 
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index a8287a1..f42cf77 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1482,6 +1482,8 @@ struct nfp_pre_tun_entry {
 		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
 		tun6->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
 				(geneve->vni[1] << 8) | (geneve->vni[2]));
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 17/25] net/nfp: add the offload support of IPv4 NVGRE encap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (15 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 16/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 18/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (9 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action of IPv4 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 43 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 7453109..5a3d0a8 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -43,6 +43,7 @@ vxlan                = Y
 count                = Y
 dec_ttl              = Y
 drop                 = Y
+nvgre_encap          = Y
 of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index f42cf77..823b02a 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -47,6 +47,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv6_hdr) + \
 				sizeof(struct rte_udp_hdr) + \
 				sizeof(struct rte_flow_item_geneve))
+#define NVGRE_V4_LEN     (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv4_hdr) + \
+				sizeof(struct rte_flow_item_gre) + \
+				sizeof(rte_be32_t))    /* gre key */
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2846,6 +2850,41 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_nvgre_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_gre *gre;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth  = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv4 = (const struct rte_flow_item_ipv4 *)(eth + 1);
+	gre  = (const struct rte_flow_item_gre *)(ipv4 + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GRE, 0,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_proto = gre->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv4);
+}
+
+static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
 		char *actions,
@@ -2883,6 +2922,10 @@ struct nfp_pre_tun_entry {
 		ret = nfp_flow_action_geneve_encap_v6(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case NVGRE_V4_LEN:
+		ret = nfp_flow_action_nvgre_encap_v4(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 18/25] net/nfp: add the offload support of IPv6 NVGRE encap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (16 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 17/25] net/nfp: add the offload support of IPv4 NVGRE encap action Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 19/25] net/nfp: prepare for the decap action of IPv4 GRE tunnel Chaoyong He
                   ` (8 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action of IPv6 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/rel_notes/release_22_11.rst |  1 +
 drivers/net/nfp/nfp_flow.c             | 45 ++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index 4adad3c..e2f7295 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -186,6 +186,7 @@ New Features
     * Set the DSCP of IPv4 and IPv6
     * Encap and decap of VXLAN tunnel
     * Encap and decap of GENEVE tunnel
+    * Encap of NVGRE tunnel
 
 * **Updated NXP dpaa2 driver.**
 
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 823b02a..adba6c3 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -51,6 +51,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv4_hdr) + \
 				sizeof(struct rte_flow_item_gre) + \
 				sizeof(rte_be32_t))    /* gre key */
+#define NVGRE_V6_LEN     (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv6_hdr) + \
+				sizeof(struct rte_flow_item_gre) + \
+				sizeof(rte_be32_t))    /* gre key */
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2885,6 +2889,43 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_nvgre_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint8_t tos;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_gre *gre;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv6   = (const struct rte_flow_item_ipv6 *)(eth + 1);
+	gre    = (const struct rte_flow_item_gre *)(ipv6 + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tos = (ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff;
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GRE, 0,
+			ipv6->hdr.hop_limits, tos);
+	set_tun->tun_proto = gre->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv6);
+}
+
+static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
 		char *actions,
@@ -2926,6 +2967,10 @@ struct nfp_pre_tun_entry {
 		ret = nfp_flow_action_nvgre_encap_v4(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case NVGRE_V6_LEN:
+		ret = nfp_flow_action_nvgre_encap_v6(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 19/25] net/nfp: prepare for the decap action of IPv4 GRE tunnel
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (17 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 18/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 20/25] net/nfp: prepare for the decap action of IPv6 " Chaoyong He
                   ` (7 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and logics, prepare for
the decap action of IPv4 GRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 29 +++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 40 +++++++++++++++++++++++++-------
 drivers/net/nfp/nfp_flow.h               |  3 +++
 3 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 61f2f83..8bca7c2 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -575,6 +575,35 @@ struct nfp_flower_ipv6_udp_tun {
 	rte_be32_t tun_id;
 };
 
+/*
+ * Flow Frame GRE TUNNEL --> Tunnel details (6W/24B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_src                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_dst                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           tun_flags           |       tos     |       ttl     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |            Reserved           |           Ethertype           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                              Key                              |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                           Reserved                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv4_gre_tun {
+	struct nfp_flower_tun_ipv4 ipv4;
+	rte_be16_t tun_flags;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be16_t reserved1;
+	rte_be16_t ethertype;
+	rte_be32_t tun_key;
+	rte_be32_t reserved2;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index adba6c3..0c0e321 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -575,6 +575,7 @@ struct nfp_pre_tun_entry {
 	uint32_t key_layer2 = 0;
 	struct nfp_flower_ipv4_udp_tun *udp4;
 	struct nfp_flower_ipv6_udp_tun *udp6;
+	struct nfp_flower_ipv4_gre_tun *gre4;
 	struct nfp_flower_meta_tci *meta_tci;
 	struct nfp_flower_ext_meta *ext_meta = NULL;
 
@@ -590,9 +591,15 @@ struct nfp_pre_tun_entry {
 				sizeof(struct nfp_flower_ipv6_udp_tun));
 		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
 	} else {
-		udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
-				sizeof(struct nfp_flower_ipv4_udp_tun));
-		ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
+			gre4 = (struct nfp_flower_ipv4_gre_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv4_gre_tun));
+			ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, gre4->ipv4.dst);
+		} else {
+			udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv4_udp_tun));
+			ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+		}
 	}
 
 	return ret;
@@ -1031,7 +1038,7 @@ struct nfp_pre_tun_entry {
 
 	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 	key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
-	if (key_layer2 & NFP_FLOWER_LAYER2_GENEVE)
+	if (key_layer2 & (NFP_FLOWER_LAYER2_GENEVE | NFP_FLOWER_LAYER2_GRE))
 		return true;
 
 	return false;
@@ -1120,11 +1127,15 @@ struct nfp_pre_tun_entry {
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv4 *spec;
 	const struct rte_flow_item_ipv4 *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 	struct nfp_flower_ipv4_udp_tun *ipv4_udp_tun;
+	struct nfp_flower_ipv4_gre_tun *ipv4_gre_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
 		if (spec == NULL) {
@@ -1133,12 +1144,23 @@ struct nfp_pre_tun_entry {
 		}
 
 		hdr = is_mask ? &mask->hdr : &spec->hdr;
-		ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 
-		ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
-		ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
-		ipv4_udp_tun->ipv4.src   = hdr->src_addr;
-		ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+		if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+				NFP_FLOWER_LAYER2_GRE)) {
+			ipv4_gre_tun = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+
+			ipv4_gre_tun->ip_ext.tos = hdr->type_of_service;
+			ipv4_gre_tun->ip_ext.ttl = hdr->time_to_live;
+			ipv4_gre_tun->ipv4.src   = hdr->src_addr;
+			ipv4_gre_tun->ipv4.dst   = hdr->dst_addr;
+		} else {
+			ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+
+			ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
+			ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
+			ipv4_udp_tun->ipv4.src   = hdr->src_addr;
+			ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+		}
 	} else {
 		if (spec == NULL) {
 			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index 1b4a51f..e879283 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -48,6 +48,9 @@
 #define NFP_FL_SC_ACT_POPV      0x6A000000
 #define NFP_FL_SC_ACT_NULL      0x00000000
 
+/* GRE Tunnel flags */
+#define NFP_FL_GRE_FLAG_KEY         (1 << 2)
+
 /* Action opcodes */
 #define NFP_FL_ACTION_OPCODE_OUTPUT             0
 #define NFP_FL_ACTION_OPCODE_PUSH_VLAN          1
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 20/25] net/nfp: prepare for the decap action of IPv6 GRE tunnel
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (18 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 19/25] net/nfp: prepare for the decap action of IPv4 GRE tunnel Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 21/25] net/nfp: add the offload support of IPv4 NVGRE item Chaoyong He
                   ` (6 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and logics, prepare for
the decap action of IPv6 GRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 41 ++++++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 49 ++++++++++++++++++++++++--------
 2 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 8bca7c2..a48da67 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -604,6 +604,47 @@ struct nfp_flower_ipv4_gre_tun {
 	rte_be32_t reserved2;
 };
 
+/*
+ * Flow Frame GRE TUNNEL V6 --> Tunnel details (12W/48B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           tun_flags           |       tos     |       ttl     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |            Reserved           |           Ethertype           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                              Key                              |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                           Reserved                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv6_gre_tun {
+	struct nfp_flower_tun_ipv6 ipv6;
+	rte_be16_t tun_flags;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be16_t reserved1;
+	rte_be16_t ethertype;
+	rte_be32_t tun_key;
+	rte_be32_t reserved2;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 0c0e321..3f06657 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -576,6 +576,7 @@ struct nfp_pre_tun_entry {
 	struct nfp_flower_ipv4_udp_tun *udp4;
 	struct nfp_flower_ipv6_udp_tun *udp6;
 	struct nfp_flower_ipv4_gre_tun *gre4;
+	struct nfp_flower_ipv6_gre_tun *gre6;
 	struct nfp_flower_meta_tci *meta_tci;
 	struct nfp_flower_ext_meta *ext_meta = NULL;
 
@@ -587,9 +588,15 @@ struct nfp_pre_tun_entry {
 		key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
 
 	if (key_layer2 & NFP_FLOWER_LAYER2_TUN_IPV6) {
-		udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
-				sizeof(struct nfp_flower_ipv6_udp_tun));
-		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
+			gre6 = (struct nfp_flower_ipv6_gre_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv6_gre_tun));
+			ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, gre6->ipv6.ipv6_dst);
+		} else {
+			udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv6_udp_tun));
+			ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+		}
 	} else {
 		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
 			gre4 = (struct nfp_flower_ipv4_gre_tun *)(nfp_flow->payload.mask_data -
@@ -1204,11 +1211,15 @@ struct nfp_pre_tun_entry {
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv6 *spec;
 	const struct rte_flow_item_ipv6 *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 	struct nfp_flower_ipv6_udp_tun *ipv6_udp_tun;
+	struct nfp_flower_ipv6_gre_tun *ipv6_gre_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
 		if (spec == NULL) {
@@ -1217,15 +1228,29 @@ struct nfp_pre_tun_entry {
 		}
 
 		hdr = is_mask ? &mask->hdr : &spec->hdr;
-		ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
-
-		ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
-				RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
-		ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
-		memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
-				sizeof(ipv6_udp_tun->ipv6.ipv6_src));
-		memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
-				sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+
+		if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+				NFP_FLOWER_LAYER2_GRE)) {
+			ipv6_gre_tun = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+
+			ipv6_gre_tun->ip_ext.tos = (hdr->vtc_flow &
+					RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+			ipv6_gre_tun->ip_ext.ttl = hdr->hop_limits;
+			memcpy(ipv6_gre_tun->ipv6.ipv6_src, hdr->src_addr,
+					sizeof(ipv6_gre_tun->ipv6.ipv6_src));
+			memcpy(ipv6_gre_tun->ipv6.ipv6_dst, hdr->dst_addr,
+					sizeof(ipv6_gre_tun->ipv6.ipv6_dst));
+		} else {
+			ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+
+			ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
+					RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+			ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
+			memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
+					sizeof(ipv6_udp_tun->ipv6.ipv6_src));
+			memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
+					sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+		}
 	} else {
 		if (spec == NULL) {
 			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 21/25] net/nfp: add the offload support of IPv4 NVGRE item
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (19 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 20/25] net/nfp: prepare for the decap action of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 22/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (5 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv4 NVGRE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  2 +
 drivers/net/nfp/nfp_flow.c       | 99 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 5a3d0a8..4c6d2d5 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -29,6 +29,8 @@ Usage doc            = Y
 [rte_flow items]
 eth                  = Y
 geneve               = Y
+gre                  = Y
+gre_key              = Y
 ipv4                 = Y
 ipv6                 = Y
 ipv6_frag_ext        = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 3f06657..94d7a27 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -832,6 +832,26 @@ struct nfp_pre_tun_entry {
 				return -EINVAL;
 			}
 			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_GRE;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GRE;
+			key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_gre_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_gre_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE_KEY detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -1558,6 +1578,62 @@ struct nfp_pre_tun_entry {
 	return ret;
 }
 
+static int
+nfp_flow_merge_gre(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		__rte_unused const struct rte_flow_item *item,
+		__rte_unused const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	struct nfp_flower_ipv4_gre_tun *tun4;
+
+	/* NVGRE is the only supported GRE tunnel type */
+	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+	if (is_mask)
+		tun4->ethertype = rte_cpu_to_be_16(~0);
+	else
+		tun4->ethertype = rte_cpu_to_be_16(0x6558);
+
+	return 0;
+}
+
+static int
+nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		__rte_unused const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	rte_be32_t tun_key;
+	const rte_be32_t *spec;
+	const rte_be32_t *mask;
+	struct nfp_flower_ipv4_gre_tun *tun4;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge gre key: no item->spec!");
+		goto gre_key_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	tun_key = is_mask ? *mask : *spec;
+
+	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+	tun4->tun_key = tun_key;
+	tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+
+gre_key_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
+
+	return 0;
+}
+
+const rte_be32_t nfp_flow_item_gre_key = 0xffffffff;
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
@@ -1598,7 +1674,8 @@ struct nfp_pre_tun_entry {
 	[RTE_FLOW_ITEM_TYPE_IPV4] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_TCP,
 			RTE_FLOW_ITEM_TYPE_UDP,
-			RTE_FLOW_ITEM_TYPE_SCTP),
+			RTE_FLOW_ITEM_TYPE_SCTP,
+			RTE_FLOW_ITEM_TYPE_GRE),
 		.mask_support = &(const struct rte_flow_item_ipv4){
 			.hdr = {
 				.type_of_service = 0xff,
@@ -1689,6 +1766,23 @@ struct nfp_pre_tun_entry {
 		.mask_sz = sizeof(struct rte_flow_item_geneve),
 		.merge = nfp_flow_merge_geneve,
 	},
+	[RTE_FLOW_ITEM_TYPE_GRE] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_GRE_KEY),
+		.mask_support = &(const struct rte_flow_item_gre){
+			.c_rsvd0_ver = RTE_BE16(0xa000),
+			.protocol = RTE_BE16(0xffff),
+		},
+		.mask_default = &rte_flow_item_gre_mask,
+		.mask_sz = sizeof(struct rte_flow_item_gre),
+		.merge = nfp_flow_merge_gre,
+	},
+	[RTE_FLOW_ITEM_TYPE_GRE_KEY] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &nfp_flow_item_gre_key,
+		.mask_default = &nfp_flow_item_gre_key,
+		.mask_sz = sizeof(rte_be32_t),
+		.merge = nfp_flow_merge_gre_key,
+	},
 };
 
 static int
@@ -1746,7 +1840,8 @@ struct nfp_pre_tun_entry {
 nfp_flow_is_tun_item(const struct rte_flow_item *item)
 {
 	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
-			item->type == RTE_FLOW_ITEM_TYPE_GENEVE)
+			item->type == RTE_FLOW_ITEM_TYPE_GENEVE ||
+			item->type == RTE_FLOW_ITEM_TYPE_GRE_KEY)
 		return true;
 
 	return false;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 22/25] net/nfp: add the offload support of IPv6 NVGRE item
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (20 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 21/25] net/nfp: add the offload support of IPv4 NVGRE item Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 23/25] net/nfp: add the offload support of IPv4 NVGRE decap action Chaoyong He
                   ` (4 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv6 NVGRE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 73 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 59 insertions(+), 14 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 94d7a27..9464211 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -834,8 +834,9 @@ struct nfp_pre_tun_entry {
 			break;
 		case RTE_FLOW_ITEM_TYPE_GRE:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_GRE;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
 			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GRE;
@@ -847,6 +848,17 @@ struct nfp_pre_tun_entry {
 				 * in `struct nfp_flower_ipv4_gre_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_gre_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_gre_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for GRE tunnel.");
+				return -1;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
@@ -1580,38 +1592,59 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flow_merge_gre(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		__rte_unused const struct rte_flow_item *item,
 		__rte_unused const struct nfp_flow_item_proc *proc,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_ipv4_gre_tun *tun4;
+	struct nfp_flower_ipv6_gre_tun *tun6;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	/* NVGRE is the only supported GRE tunnel type */
-	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
-	if (is_mask)
-		tun4->ethertype = rte_cpu_to_be_16(~0);
-	else
-		tun4->ethertype = rte_cpu_to_be_16(0x6558);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6) {
+		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+		if (is_mask)
+			tun6->ethertype = rte_cpu_to_be_16(~0);
+		else
+			tun6->ethertype = rte_cpu_to_be_16(0x6558);
+	} else {
+		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+		if (is_mask)
+			tun4->ethertype = rte_cpu_to_be_16(~0);
+		else
+			tun4->ethertype = rte_cpu_to_be_16(0x6558);
+	}
 
 	return 0;
 }
 
 static int
 nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
-		__rte_unused const struct nfp_flow_item_proc *proc,
+		const struct nfp_flow_item_proc *proc,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
 	rte_be32_t tun_key;
 	const rte_be32_t *spec;
 	const rte_be32_t *mask;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_ipv4_gre_tun *tun4;
+	struct nfp_flower_ipv6_gre_tun *tun6;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1622,12 +1655,23 @@ struct nfp_pre_tun_entry {
 	mask = item->mask ? item->mask : proc->mask_default;
 	tun_key = is_mask ? *mask : *spec;
 
-	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
-	tun4->tun_key = tun_key;
-	tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6) {
+		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+		tun6->tun_key = tun_key;
+		tun6->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	} else {
+		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+		tun4->tun_key = tun_key;
+		tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	}
 
 gre_key_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_gre_tun);
+	else
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
 
 	return 0;
 }
@@ -1693,7 +1737,8 @@ struct nfp_pre_tun_entry {
 	[RTE_FLOW_ITEM_TYPE_IPV6] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_TCP,
 			RTE_FLOW_ITEM_TYPE_UDP,
-			RTE_FLOW_ITEM_TYPE_SCTP),
+			RTE_FLOW_ITEM_TYPE_SCTP,
+			RTE_FLOW_ITEM_TYPE_GRE),
 		.mask_support = &(const struct rte_flow_item_ipv6){
 			.hdr = {
 				.vtc_flow   = RTE_BE32(0x0ff00000),
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 23/25] net/nfp: add the offload support of IPv4 NVGRE decap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (21 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 22/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 24/25] net/nfp: add the offload support of IPv6 " Chaoyong He
                   ` (3 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action of IPv4 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini | 1 +
 drivers/net/nfp/nfp_flow.c       | 8 ++++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 4c6d2d5..9f7a680 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -45,6 +45,7 @@ vxlan                = Y
 count                = Y
 dec_ttl              = Y
 drop                 = Y
+nvgre_decap          = Y
 nvgre_encap          = Y
 of_pop_vlan          = Y
 of_push_vlan         = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 9464211..514e221 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1627,7 +1627,7 @@ struct nfp_pre_tun_entry {
 }
 
 static int
-nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_gre_key(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1635,6 +1635,7 @@ struct nfp_pre_tun_entry {
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	rte_be32_t tun_key;
 	const rte_be32_t *spec;
 	const rte_be32_t *mask;
@@ -1664,6 +1665,8 @@ struct nfp_pre_tun_entry {
 		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
 		tun4->tun_key = tun_key;
 		tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 gre_key_end:
@@ -1673,7 +1676,7 @@ struct nfp_pre_tun_entry {
 	else
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
 
-	return 0;
+	return ret;
 }
 
 const rte_be32_t nfp_flow_item_gre_key = 0xffffffff;
@@ -3835,6 +3838,7 @@ struct nfp_pre_tun_entry {
 		*num_of_actions = 1;
 		break;
 	case RTE_FLOW_ITEM_TYPE_GENEVE:
+	case RTE_FLOW_ITEM_TYPE_GRE:
 		nfp_action->type = RTE_FLOW_ACTION_TYPE_RAW_DECAP;
 		*pmd_actions = nfp_action;
 		*num_of_actions = 1;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 24/25] net/nfp: add the offload support of IPv6 NVGRE decap action
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (22 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 23/25] net/nfp: add the offload support of IPv4 NVGRE decap action Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-18  3:22 ` [PATCH 25/25] net/nfp: add the support of new tunnel solution Chaoyong He
                   ` (2 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action of IPv6 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/rel_notes/release_22_11.rst | 2 +-
 drivers/net/nfp/nfp_flow.c             | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index e2f7295..4f3edab 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -186,7 +186,7 @@ New Features
     * Set the DSCP of IPv4 and IPv6
     * Encap and decap of VXLAN tunnel
     * Encap and decap of GENEVE tunnel
-    * Encap of NVGRE tunnel
+    * Encap and decap of NVGRE tunnel
 
 * **Updated NXP dpaa2 driver.**
 
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 514e221..1ccc6ef 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1661,6 +1661,8 @@ struct nfp_pre_tun_entry {
 		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
 		tun6->tun_key = tun_key;
 		tun6->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
 		tun4->tun_key = tun_key;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH 25/25] net/nfp: add the support of new tunnel solution
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (23 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 24/25] net/nfp: add the offload support of IPv6 " Chaoyong He
@ 2022-10-18  3:22 ` Chaoyong He
  2022-10-21 13:37 ` [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-18  3:22 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

The new version of flower firmware application add the support of
a new tunnel solution.

It changes the structure of tunnel neighbor, and use a feature flag
to indicate which tunnel solution is used.

Add the logic of read extra features from firmware, and store it in
the app private structure.

Adjust the data structure and related logic to make the PMD support
both version of tunnel solutions.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower.c      |  14 ++++
 drivers/net/nfp/flower/nfp_flower.h      |  24 +++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.c |   4 ++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  17 +++++
 drivers/net/nfp/nfp_flow.c               | 118 +++++++++++++++++++++++++------
 5 files changed, 157 insertions(+), 20 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c
index 168bf0c..d2a8f9b 100644
--- a/drivers/net/nfp/flower/nfp_flower.c
+++ b/drivers/net/nfp/flower/nfp_flower.c
@@ -1073,6 +1073,8 @@
 nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
 {
 	int ret;
+	int err;
+	uint64_t ext_features;
 	unsigned int numa_node;
 	struct nfp_net_hw *pf_hw;
 	struct nfp_net_hw *ctrl_hw;
@@ -1114,6 +1116,18 @@
 		goto vnic_cleanup;
 	}
 
+	/* Read the extra features */
+	ext_features = nfp_rtsym_read_le(pf_dev->sym_tbl, "_abi_flower_extra_features",
+			&err);
+	if (err != 0) {
+		PMD_INIT_LOG(ERR, "Couldn't read extra features from fw");
+		ret = -EIO;
+		goto pf_cpp_area_cleanup;
+	}
+
+	/* Store the extra features */
+	app_fw_flower->ext_features = ext_features;
+
 	/* Fill in the PF vNIC and populate app struct */
 	app_fw_flower->pf_hw = pf_hw;
 	pf_hw->ctrl_bar = pf_dev->ctrl_bar;
diff --git a/drivers/net/nfp/flower/nfp_flower.h b/drivers/net/nfp/flower/nfp_flower.h
index b90391c..dc0eb36 100644
--- a/drivers/net/nfp/flower/nfp_flower.h
+++ b/drivers/net/nfp/flower/nfp_flower.h
@@ -6,6 +6,21 @@
 #ifndef _NFP_FLOWER_H_
 #define _NFP_FLOWER_H_
 
+/* Extra features bitmap. */
+#define NFP_FL_FEATS_GENEVE             RTE_BIT64(0)
+#define NFP_FL_NBI_MTU_SETTING          RTE_BIT64(1)
+#define NFP_FL_FEATS_GENEVE_OPT         RTE_BIT64(2)
+#define NFP_FL_FEATS_VLAN_PCP           RTE_BIT64(3)
+#define NFP_FL_FEATS_VF_RLIM            RTE_BIT64(4)
+#define NFP_FL_FEATS_FLOW_MOD           RTE_BIT64(5)
+#define NFP_FL_FEATS_PRE_TUN_RULES      RTE_BIT64(6)
+#define NFP_FL_FEATS_IPV6_TUN           RTE_BIT64(7)
+#define NFP_FL_FEATS_VLAN_QINQ          RTE_BIT64(8)
+#define NFP_FL_FEATS_QOS_PPS            RTE_BIT64(9)
+#define NFP_FL_FEATS_QOS_METER          RTE_BIT64(10)
+#define NFP_FL_FEATS_DECAP_V2           RTE_BIT64(11)
+#define NFP_FL_FEATS_HOST_ACK           RTE_BIT64(31)
+
 /*
  * Flower fallback and ctrl path always adds and removes
  * 8 bytes of prepended data. Tx descriptors must point
@@ -52,9 +67,18 @@ struct nfp_app_fw_flower {
 	/* PF representor */
 	struct nfp_flower_representor *pf_repr;
 
+	/* Flower extra features */
+	uint64_t ext_features;
+
 	struct nfp_flow_priv *flow_priv;
 };
 
+static inline bool
+nfp_flower_support_decap_v2(const struct nfp_app_fw_flower *app_fw_flower)
+{
+	return app_fw_flower->ext_features & NFP_FL_FEATS_DECAP_V2;
+}
+
 int nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev);
 int nfp_secondary_init_app_fw_flower(struct nfp_cpp *cpp);
 uint16_t nfp_flower_pf_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 76815cf..babdd8e 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -263,6 +263,8 @@
 	}
 
 	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v4);
+	if (!nfp_flower_support_decap_v2(app_fw_flower))
+		msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
 	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, msg_len);
 	memcpy(msg, payload, msg_len);
 
@@ -292,6 +294,8 @@
 	}
 
 	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v6);
+	if (!nfp_flower_support_decap_v2(app_fw_flower))
+		msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
 	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6, msg_len);
 	memcpy(msg, payload, msg_len);
 
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index a48da67..04601cb 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -136,6 +136,21 @@ struct nfp_flower_tun_neigh {
 };
 
 /*
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |         VLAN_TPID             |            VLAN_ID            |
+ *          +---------------------------------------------------------------+
+ *        1 |                           HOST_CTX                            |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_tun_neigh_ext {
+	rte_be16_t vlan_tpid;
+	rte_be16_t vlan_tci;
+	rte_be32_t host_ctx;
+};
+
+/*
  * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V4
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
@@ -157,6 +172,7 @@ struct nfp_flower_cmsg_tun_neigh_v4 {
 	rte_be32_t dst_ipv4;
 	rte_be32_t src_ipv4;
 	struct nfp_flower_tun_neigh common;
+	struct nfp_flower_tun_neigh_ext ext;
 };
 
 /*
@@ -193,6 +209,7 @@ struct nfp_flower_cmsg_tun_neigh_v6 {
 	uint8_t dst_ipv6[16];
 	uint8_t src_ipv6[16];
 	struct nfp_flower_tun_neigh common;
+	struct nfp_flower_tun_neigh_ext ext;
 };
 
 #define NFP_TUN_PRE_TUN_RULE_DEL    (1 << 0)
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 1ccc6ef..ac60e90 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -2402,8 +2402,10 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
+	bool exists = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
 	struct nfp_flow_priv *priv;
@@ -2437,11 +2439,17 @@ struct nfp_pre_tun_entry {
 	LIST_FOREACH(tmp, &priv->nn_list, next) {
 		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
 			tmp->ref_cnt++;
-			return 0;
+			exists = true;
+			break;
 		}
 	}
 
-	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	if (exists) {
+		if (!nfp_flower_support_decap_v2(app_fw_flower))
+			return 0;
+	} else {
+		LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	}
 
 	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
 	payload.dst_ipv4 = ipv4->ipv4_src;
@@ -2450,6 +2458,17 @@ struct nfp_pre_tun_entry {
 	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
 	payload.common.port_id = port->in_port;
 
+	if (nfp_flower_support_decap_v2(app_fw_flower)) {
+		if (meta_tci->tci != 0) {
+			payload.ext.vlan_tci = meta_tci->tci;
+			payload.ext.vlan_tpid = 0x88a8;
+		} else {
+			payload.ext.vlan_tci = 0xffff;
+			payload.ext.vlan_tpid = 0xffff;
+		}
+		payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
+	}
+
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
@@ -2510,8 +2529,10 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
+	bool exists = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
 	struct nfp_flow_priv *priv;
@@ -2545,11 +2566,17 @@ struct nfp_pre_tun_entry {
 	LIST_FOREACH(tmp, &priv->nn_list, next) {
 		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
 			tmp->ref_cnt++;
-			return 0;
+			exists = true;
+			break;
 		}
 	}
 
-	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	if (exists) {
+		if (!nfp_flower_support_decap_v2(app_fw_flower))
+			return 0;
+	} else {
+		LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	}
 
 	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
 	memcpy(payload.dst_ipv6, ipv6->ipv6_src, sizeof(payload.dst_ipv6));
@@ -2558,6 +2585,17 @@ struct nfp_pre_tun_entry {
 	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
 	payload.common.port_id = port->in_port;
 
+	if (nfp_flower_support_decap_v2(app_fw_flower)) {
+		if (meta_tci->tci != 0) {
+			payload.ext.vlan_tci = meta_tci->tci;
+			payload.ext.vlan_tpid = 0x88a8;
+		} else {
+			payload.ext.vlan_tci = 0xffff;
+			payload.ext.vlan_tpid = 0xffff;
+		}
+		payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
+	}
+
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
@@ -2575,12 +2613,14 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
-		struct rte_flow *nfp_flow)
+		struct rte_flow *nfp_flow,
+		bool decap_flag)
 {
 	int ret;
 	bool flag = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
+	struct nfp_flower_in_port *port;
 
 	tun = &nfp_flow->tun;
 	LIST_FOREACH(tmp, &app_fw_flower->flow_priv->nn_list, next) {
@@ -2608,6 +2648,40 @@ struct nfp_pre_tun_entry {
 		}
 	}
 
+	if (!decap_flag)
+		return 0;
+
+	port = (struct nfp_flower_in_port *)(nfp_flow->payload.unmasked_data +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	if (tmp->payload.v6_flag != 0) {
+		struct nfp_flower_cmsg_tun_neigh_v6 nn_v6;
+		memset(&nn_v6, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+		memcpy(nn_v6.dst_ipv6, tmp->payload.dst.dst_ipv6, sizeof(nn_v6.dst_ipv6));
+		memcpy(nn_v6.src_ipv6, tmp->payload.src.src_ipv6, sizeof(nn_v6.src_ipv6));
+		memcpy(nn_v6.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
+		memcpy(nn_v6.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
+		nn_v6.common.port_id = port->in_port;
+
+		ret = nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &nn_v6);
+	} else {
+		struct nfp_flower_cmsg_tun_neigh_v4 nn_v4;
+		memset(&nn_v4, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+		nn_v4.dst_ipv4 = tmp->payload.dst.dst_ipv4;
+		nn_v4.src_ipv4 = tmp->payload.src.src_ipv4;
+		memcpy(nn_v4.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
+		memcpy(nn_v4.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
+		nn_v4.common.port_id = port->in_port;
+
+		ret = nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &nn_v4);
+	}
+
+	if (ret != 0) {
+		PMD_DRV_LOG(DEBUG, "Failed to send the nn entry");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -2895,12 +2969,14 @@ struct nfp_pre_tun_entry {
 		goto free_entry;
 	}
 
-	ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
-			nfp_mac_idx, true);
-	if (ret != 0) {
-		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
-		ret = -EINVAL;
-		goto free_entry;
+	if (!nfp_flower_support_decap_v2(repr->app_fw_flower)) {
+		ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
+				nfp_mac_idx, true);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+			ret = -EINVAL;
+			goto free_entry;
+		}
 	}
 
 	find_entry->ref_cnt = 1U;
@@ -2951,18 +3027,20 @@ struct nfp_pre_tun_entry {
 		return -EINVAL;
 	}
 
-	ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
-			nfp_mac_idx, false);
-	if (ret != 0) {
-		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
-		return -EINVAL;
+	if (!nfp_flower_support_decap_v2(app_fw_flower)) {
+		ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
+				nfp_mac_idx, false);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+			return -EINVAL;
+		}
 	}
 
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
-		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
+		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
 	else
-		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow);
+		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
 }
 
 static int
@@ -3662,11 +3740,11 @@ struct nfp_pre_tun_entry {
 		break;
 	case NFP_FLOW_ENCAP:
 		/* Delete the entry from nn table */
-		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, false);
 		break;
 	case NFP_FLOW_DECAP:
 		/* Delete the entry from nn table */
-		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, true);
 		if (ret != 0)
 			goto exit;
 
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH 00/25] add the extend rte_flow offload support of nfp PMD
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (24 preceding siblings ...)
  2022-10-18  3:22 ` [PATCH 25/25] net/nfp: add the support of new tunnel solution Chaoyong He
@ 2022-10-21 13:37 ` Ferruh Yigit
  2022-10-21 13:39   ` Ferruh Yigit
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
  26 siblings, 1 reply; 88+ messages in thread
From: Ferruh Yigit @ 2022-10-21 13:37 UTC (permalink / raw)
  To: Chaoyong He, dev; +Cc: oss-drivers, niklas.soderlund

On 10/18/2022 4:22 AM, Chaoyong He wrote:
> This is the third patch series to add the support of rte_flow offload for
> nfp PMD, includes:
> Add the offload support of decap/encap of VXLAN
> Add the offload support of decap/encap of GENEVE
> Add the offload support of decap/encap of NVGRE
> 
> Depends-on: series-25268 ("add the basic rte_flow offload support of nfp PMD")
> 
> Chaoyong He (25):
>    net/nfp: add the offload support of IPv4 VXLAN item
>    net/nfp: add the offload support of IPv6 VXLAN item
>    net/nfp: prepare for the encap action of IPv4 tunnel
>    net/nfp: prepare for the encap action of IPv6 tunnel
>    net/nfp: add the offload support of IPv4 VXLAN encap action
>    net/nfp: add the offload support of IPv6 VXLAN encap action
>    net/nfp: prepare for the decap action of IPv4 UDP tunnel
>    net/nfp: prepare for the decap action of IPv6 UDP tunnel
>    net/nfp: add the offload support of IPv4 VXLAN decap action
>    net/nfp: add the offload support of IPv6 VXLAN decap action
>    net/nfp: add the offload support of IPv4 GENEVE encap action
>    net/nfp: add the offload support of IPv6 GENEVE encap action
>    net/nfp: add the offload support of IPv4 GENEVE item
>    net/nfp: add the offload support of IPv6 GENEVE item
>    net/nfp: add the offload support of IPv4 GENEVE decap action
>    net/nfp: add the offload support of IPv6 GENEVE decap action
>    net/nfp: add the offload support of IPv4 NVGRE encap action
>    net/nfp: add the offload support of IPv6 NVGRE encap action
>    net/nfp: prepare for the decap action of IPv4 GRE tunnel
>    net/nfp: prepare for the decap action of IPv6 GRE tunnel
>    net/nfp: add the offload support of IPv4 NVGRE item
>    net/nfp: add the offload support of IPv6 NVGRE item
>    net/nfp: add the offload support of IPv4 NVGRE decap action
>    net/nfp: add the offload support of IPv6 NVGRE decap action
>    net/nfp: add the support of new tunnel solution

Can you please rebase the set on top of latest head?

Also please adjust the commit log/title in a consistent way with 
previous set.

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH 00/25] add the extend rte_flow offload support of nfp PMD
  2022-10-21 13:37 ` [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
@ 2022-10-21 13:39   ` Ferruh Yigit
  0 siblings, 0 replies; 88+ messages in thread
From: Ferruh Yigit @ 2022-10-21 13:39 UTC (permalink / raw)
  To: Chaoyong He, dev; +Cc: oss-drivers, niklas.soderlund

On 10/21/2022 2:37 PM, Ferruh Yigit wrote:
> On 10/18/2022 4:22 AM, Chaoyong He wrote:
>> This is the third patch series to add the support of rte_flow offload for
>> nfp PMD, includes:
>> Add the offload support of decap/encap of VXLAN
>> Add the offload support of decap/encap of GENEVE
>> Add the offload support of decap/encap of NVGRE
>>
>> Depends-on: series-25268 ("add the basic rte_flow offload support of 
>> nfp PMD")
>>
>> Chaoyong He (25):
>>    net/nfp: add the offload support of IPv4 VXLAN item
>>    net/nfp: add the offload support of IPv6 VXLAN item
>>    net/nfp: prepare for the encap action of IPv4 tunnel
>>    net/nfp: prepare for the encap action of IPv6 tunnel
>>    net/nfp: add the offload support of IPv4 VXLAN encap action
>>    net/nfp: add the offload support of IPv6 VXLAN encap action
>>    net/nfp: prepare for the decap action of IPv4 UDP tunnel
>>    net/nfp: prepare for the decap action of IPv6 UDP tunnel
>>    net/nfp: add the offload support of IPv4 VXLAN decap action
>>    net/nfp: add the offload support of IPv6 VXLAN decap action
>>    net/nfp: add the offload support of IPv4 GENEVE encap action
>>    net/nfp: add the offload support of IPv6 GENEVE encap action
>>    net/nfp: add the offload support of IPv4 GENEVE item
>>    net/nfp: add the offload support of IPv6 GENEVE item
>>    net/nfp: add the offload support of IPv4 GENEVE decap action
>>    net/nfp: add the offload support of IPv6 GENEVE decap action
>>    net/nfp: add the offload support of IPv4 NVGRE encap action
>>    net/nfp: add the offload support of IPv6 NVGRE encap action
>>    net/nfp: prepare for the decap action of IPv4 GRE tunnel
>>    net/nfp: prepare for the decap action of IPv6 GRE tunnel
>>    net/nfp: add the offload support of IPv4 NVGRE item
>>    net/nfp: add the offload support of IPv6 NVGRE item
>>    net/nfp: add the offload support of IPv4 NVGRE decap action
>>    net/nfp: add the offload support of IPv6 NVGRE decap action
>>    net/nfp: add the support of new tunnel solution
> 
> Can you please rebase the set on top of latest head?
> 
> Also please adjust the commit log/title in a consistent way with 
> previous set.

Can you please run `./devtools/check-doc-vs-code.sh` script and be sure 
it is not listing any mismatch in next version?

^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 00/25] add the extend rte_flow offload support of nfp PMD
  2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
                   ` (25 preceding siblings ...)
  2022-10-21 13:37 ` [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
@ 2022-10-22  8:24 ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 01/25] net/nfp: support IPv4 VXLAN flow item Chaoyong He
                     ` (26 more replies)
  26 siblings, 27 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

This is the third patch series to add the support of rte_flow offload for
nfp PMD, includes:
Add the offload support of decap/encap of VXLAN
Add the offload support of decap/encap of GENEVE
Add the offload support of decap/encap of NVGRE

Changes since v1
- Delete the modificaiton of release note.
- Modify the commit title.
- Rebase to the lastest logic.

Chaoyong He (25):
  net/nfp: support IPv4 VXLAN flow item
  net/nfp: support IPv6 VXLAN flow item
  net/nfp: prepare for IPv4 tunnel encap flow action
  net/nfp: prepare for IPv6 tunnel encap flow action
  net/nfp: support IPv4 VXLAN encap flow action
  net/nfp: support IPv6 VXLAN encap flow action
  net/nfp: prepare for IPv4 UDP tunnel decap flow action
  net/nfp: prepare for IPv6 UDP tunnel decap flow action
  net/nfp: support IPv4 VXLAN decap flow action
  net/nfp: support IPv6 VXLAN decap flow action
  net/nfp: support IPv4 GENEVE encap flow action
  net/nfp: support IPv6 GENEVE encap flow action
  net/nfp: support IPv4 GENEVE flow item
  net/nfp: support IPv6 GENEVE flow item
  net/nfp: support IPv4 GENEVE decap flow action
  net/nfp: support IPv6 GENEVE decap flow action
  net/nfp: support IPv4 NVGRE encap flow action
  net/nfp: support IPv6 NVGRE encap flow action
  net/nfp: prepare for IPv4 GRE tunnel decap flow action
  net/nfp: prepare for IPv6 GRE tunnel decap flow action
  net/nfp: support IPv4 NVGRE flow item
  net/nfp: support IPv6 NVGRE flow item
  net/nfp: support IPv4 NVGRE decap flow action
  net/nfp: support IPv6 NVGRE decap flow action
  net/nfp: support new tunnel solution

 doc/guides/nics/features/nfp.ini         |   10 +
 drivers/net/nfp/flower/nfp_flower.c      |   14 +
 drivers/net/nfp/flower/nfp_flower.h      |   24 +
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  222 ++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  415 +++++++
 drivers/net/nfp/nfp_flow.c               | 2003 +++++++++++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |   56 +
 7 files changed, 2675 insertions(+), 69 deletions(-)

-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 01/25] net/nfp: support IPv4 VXLAN flow item
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 02/25] net/nfp: support IPv6 " Chaoyong He
                     ` (25 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding data structure and logics, to support
the offload of IPv4 VXLAN item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini         |   1 +
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  35 +++++
 drivers/net/nfp/nfp_flow.c               | 243 ++++++++++++++++++++++++++-----
 3 files changed, 246 insertions(+), 33 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 0184980..faaa7da 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -35,6 +35,7 @@ sctp                 = Y
 tcp                  = Y
 udp                  = Y
 vlan                 = Y
+vxlan                = Y
 
 [rte_flow actions]
 count                = Y
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 6bf8ff7..08e2873 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -324,6 +324,41 @@ struct nfp_flower_ipv6 {
 	uint8_t ipv6_dst[16];
 };
 
+struct nfp_flower_tun_ipv4 {
+	rte_be32_t src;
+	rte_be32_t dst;
+};
+
+struct nfp_flower_tun_ip_ext {
+	uint8_t tos;
+	uint8_t ttl;
+};
+
+/*
+ * Flow Frame IPv4 UDP TUNNEL --> Tunnel details (5W/20B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_src                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_dst                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           Reserved            |      tos      |      ttl      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            Reserved                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     VNI                       |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv4_udp_tun {
+	struct nfp_flower_tun_ipv4 ipv4;
+	rte_be16_t reserved1;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be32_t reserved2;
+	rte_be32_t tun_id;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 69fc8be..0e1e5ea 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -38,7 +38,8 @@ struct nfp_flow_item_proc {
 			char **mbuf_off,
 			const struct rte_flow_item *item,
 			const struct nfp_flow_item_proc *proc,
-			bool is_mask);
+			bool is_mask,
+			bool is_outer_layer);
 	/* List of possible subsequent items. */
 	const enum rte_flow_item_type *const next_item;
 };
@@ -491,6 +492,7 @@ struct nfp_mask_id_entry {
 		struct nfp_fl_key_ls *key_ls)
 {
 	struct rte_eth_dev *ethdev;
+	bool outer_ip4_flag = false;
 	const struct rte_flow_item *item;
 	struct nfp_flower_representor *representor;
 	const struct rte_flow_item_port_id *port_id;
@@ -526,6 +528,8 @@ struct nfp_mask_id_entry {
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV4 detected");
 			key_ls->key_layer |= NFP_FLOWER_LAYER_IPV4;
 			key_ls->key_size += sizeof(struct nfp_flower_ipv4);
+			if (!outer_ip4_flag)
+				outer_ip4_flag = true;
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV6 detected");
@@ -547,6 +551,21 @@ struct nfp_mask_id_entry {
 			key_ls->key_layer |= NFP_FLOWER_LAYER_TP;
 			key_ls->key_size += sizeof(struct nfp_flower_tp_ports);
 			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_VXLAN detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_VXLAN;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_VXLAN;
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -719,12 +738,25 @@ struct nfp_mask_id_entry {
 	return ret;
 }
 
+static bool
+nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
+{
+	struct nfp_flower_meta_tci *meta_tci;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_VXLAN)
+		return true;
+
+	return false;
+}
+
 static int
 nfp_flow_merge_eth(__rte_unused struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_mac_mpls *eth;
 	const struct rte_flow_item_eth *spec;
@@ -760,7 +792,8 @@ struct nfp_mask_id_entry {
 		__rte_unused char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_vlan *spec;
@@ -789,41 +822,58 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		bool is_outer_layer)
 {
 	struct nfp_flower_ipv4 *ipv4;
 	const struct rte_ipv4_hdr *hdr;
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv4 *spec;
 	const struct rte_flow_item_ipv4 *mask;
+	struct nfp_flower_ipv4_udp_tun *ipv4_udp_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 
-	if (spec == NULL) {
-		PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
-		goto ipv4_end;
-	}
+	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
+			return 0;
+		}
 
-	/*
-	 * reserve space for L4 info.
-	 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
-	 */
-	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
-		*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 
-	hdr = is_mask ? &mask->hdr : &spec->hdr;
-	ipv4 = (struct nfp_flower_ipv4 *)*mbuf_off;
+		ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
+		ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
+		ipv4_udp_tun->ipv4.src   = hdr->src_addr;
+		ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+	} else {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
+			goto ipv4_end;
+		}
+
+		/*
+		 * reserve space for L4 info.
+		 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
+		 */
+		if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+			*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv4 = (struct nfp_flower_ipv4 *)*mbuf_off;
 
-	ipv4->ip_ext.tos   = hdr->type_of_service;
-	ipv4->ip_ext.proto = hdr->next_proto_id;
-	ipv4->ip_ext.ttl   = hdr->time_to_live;
-	ipv4->ipv4_src     = hdr->src_addr;
-	ipv4->ipv4_dst     = hdr->dst_addr;
+		ipv4->ip_ext.tos   = hdr->type_of_service;
+		ipv4->ip_ext.proto = hdr->next_proto_id;
+		ipv4->ip_ext.ttl   = hdr->time_to_live;
+		ipv4->ipv4_src     = hdr->src_addr;
+		ipv4->ipv4_dst     = hdr->dst_addr;
 
 ipv4_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4);
+		*mbuf_off += sizeof(struct nfp_flower_ipv4);
+	}
 
 	return 0;
 }
@@ -833,7 +883,8 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_ipv6 *ipv6;
 	const struct rte_ipv6_hdr *hdr;
@@ -878,7 +929,8 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	uint8_t tcp_flags;
 	struct nfp_flower_tp_ports *ports;
@@ -950,7 +1002,8 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		bool is_outer_layer)
 {
 	char *ports_off;
 	struct nfp_flower_tp_ports *ports;
@@ -964,6 +1017,12 @@ struct nfp_mask_id_entry {
 		return 0;
 	}
 
+	/* Don't add L4 info if working on a inner layer pattern */
+	if (!is_outer_layer) {
+		PMD_DRV_LOG(INFO, "Detected inner layer UDP, skipping.");
+		return 0;
+	}
+
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4) {
 		ports_off = *mbuf_off - sizeof(struct nfp_flower_ipv4) -
@@ -991,7 +1050,8 @@ struct nfp_mask_id_entry {
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	char *ports_off;
 	struct nfp_flower_tp_ports *ports;
@@ -1027,10 +1087,42 @@ struct nfp_mask_id_entry {
 	return 0;
 }
 
+static int
+nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	const struct rte_vxlan_hdr *hdr;
+	struct nfp_flower_ipv4_udp_tun *tun4;
+	const struct rte_flow_item_vxlan *spec;
+	const struct rte_flow_item_vxlan *mask;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge vxlan: no item->spec!");
+		goto vxlan_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	hdr = is_mask ? &mask->hdr : &spec->hdr;
+
+	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+	tun4->tun_id = hdr->vx_vni;
+
+vxlan_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+
+	return 0;
+}
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
-		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH,
+			RTE_FLOW_ITEM_TYPE_IPV4),
 	},
 	[RTE_FLOW_ITEM_TYPE_ETH] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VLAN,
@@ -1113,6 +1205,7 @@ struct nfp_mask_id_entry {
 		.merge = nfp_flow_merge_tcp,
 	},
 	[RTE_FLOW_ITEM_TYPE_UDP] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN),
 		.mask_support = &(const struct rte_flow_item_udp){
 			.hdr = {
 				.src_port = RTE_BE16(0xffff),
@@ -1134,6 +1227,17 @@ struct nfp_mask_id_entry {
 		.mask_sz = sizeof(struct rte_flow_item_sctp),
 		.merge = nfp_flow_merge_sctp,
 	},
+	[RTE_FLOW_ITEM_TYPE_VXLAN] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &(const struct rte_flow_item_vxlan){
+			.hdr = {
+				.vx_vni = RTE_BE32(0xffffff00),
+			},
+		},
+		.mask_default = &rte_flow_item_vxlan_mask,
+		.mask_sz = sizeof(struct rte_flow_item_vxlan),
+		.merge = nfp_flow_merge_vxlan,
+	},
 };
 
 static int
@@ -1187,21 +1291,53 @@ struct nfp_mask_id_entry {
 	return ret;
 }
 
+static bool
+nfp_flow_is_tun_item(const struct rte_flow_item *item)
+{
+	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN)
+		return true;
+
+	return false;
+}
+
+static bool
+nfp_flow_inner_item_get(const struct rte_flow_item items[],
+		const struct rte_flow_item **inner_item)
+{
+	const struct rte_flow_item *item;
+
+	*inner_item = items;
+
+	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
+		if (nfp_flow_is_tun_item(item)) {
+			*inner_item = ++item;
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static int
 nfp_flow_compile_item_proc(const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow,
 		char **mbuf_off_exact,
-		char **mbuf_off_mask)
+		char **mbuf_off_mask,
+		bool is_outer_layer)
 {
 	int i;
 	int ret = 0;
+	bool continue_flag = true;
 	const struct rte_flow_item *item;
 	const struct nfp_flow_item_proc *proc_list;
 
 	proc_list = nfp_flow_item_proc_list;
-	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
+	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END && continue_flag; ++item) {
 		const struct nfp_flow_item_proc *proc = NULL;
 
+		if (nfp_flow_is_tun_item(item))
+			continue_flag = false;
+
 		for (i = 0; proc_list->next_item && proc_list->next_item[i]; ++i) {
 			if (proc_list->next_item[i] == item->type) {
 				proc = &nfp_flow_item_proc_list[item->type];
@@ -1230,14 +1366,14 @@ struct nfp_mask_id_entry {
 		}
 
 		ret = proc->merge(nfp_flow, mbuf_off_exact, item,
-				proc, false);
+				proc, false, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d exact merge failed", item->type);
 			break;
 		}
 
 		ret = proc->merge(nfp_flow, mbuf_off_mask, item,
-				proc, true);
+				proc, true, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d mask merge failed", item->type);
 			break;
@@ -1257,6 +1393,9 @@ struct nfp_mask_id_entry {
 	int ret;
 	char *mbuf_off_mask;
 	char *mbuf_off_exact;
+	bool is_tun_flow = false;
+	bool is_outer_layer = true;
+	const struct rte_flow_item *loop_item;
 
 	mbuf_off_exact = nfp_flow->payload.unmasked_data +
 			sizeof(struct nfp_flower_meta_tci) +
@@ -1265,14 +1404,29 @@ struct nfp_mask_id_entry {
 			sizeof(struct nfp_flower_meta_tci) +
 			sizeof(struct nfp_flower_in_port);
 
+	/* Check if this is a tunnel flow and get the inner item*/
+	is_tun_flow = nfp_flow_inner_item_get(items, &loop_item);
+	if (is_tun_flow)
+		is_outer_layer = false;
+
 	/* Go over items */
-	ret = nfp_flow_compile_item_proc(items, nfp_flow,
-			&mbuf_off_exact, &mbuf_off_mask);
+	ret = nfp_flow_compile_item_proc(loop_item, nfp_flow,
+			&mbuf_off_exact, &mbuf_off_mask, is_outer_layer);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "nfp flow item compile failed.");
 		return -EINVAL;
 	}
 
+	/* Go over inner items */
+	if (is_tun_flow) {
+		ret = nfp_flow_compile_item_proc(items, nfp_flow,
+				&mbuf_off_exact, &mbuf_off_mask, true);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "nfp flow outer item compile failed.");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
@@ -2119,12 +2273,35 @@ struct nfp_mask_id_entry {
 	return 0;
 }
 
+static int
+nfp_flow_tunnel_match(__rte_unused struct rte_eth_dev *dev,
+		__rte_unused struct rte_flow_tunnel *tunnel,
+		__rte_unused struct rte_flow_item **pmd_items,
+		uint32_t *num_of_items,
+		__rte_unused struct rte_flow_error *err)
+{
+	*num_of_items = 0;
+
+	return 0;
+}
+
+static int
+nfp_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev,
+		__rte_unused struct rte_flow_item *pmd_items,
+		__rte_unused uint32_t num_of_items,
+		__rte_unused struct rte_flow_error *err)
+{
+	return 0;
+}
+
 static const struct rte_flow_ops nfp_flow_ops = {
 	.validate                    = nfp_flow_validate,
 	.create                      = nfp_flow_create,
 	.destroy                     = nfp_flow_destroy,
 	.flush                       = nfp_flow_flush,
 	.query                       = nfp_flow_query,
+	.tunnel_match                = nfp_flow_tunnel_match,
+	.tunnel_item_release         = nfp_flow_tunnel_item_release,
 };
 
 int
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 02/25] net/nfp: support IPv6 VXLAN flow item
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 01/25] net/nfp: support IPv4 VXLAN flow item Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 03/25] net/nfp: prepare for IPv4 tunnel encap flow action Chaoyong He
                     ` (24 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding data structure and logics, to support
the offload of IPv6 VXLAN item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  42 ++++++++++++
 drivers/net/nfp/nfp_flow.c               | 113 ++++++++++++++++++++++++-------
 2 files changed, 129 insertions(+), 26 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 08e2873..996ba3b 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -329,6 +329,11 @@ struct nfp_flower_tun_ipv4 {
 	rte_be32_t dst;
 };
 
+struct nfp_flower_tun_ipv6 {
+	uint8_t ipv6_src[16];
+	uint8_t ipv6_dst[16];
+};
+
 struct nfp_flower_tun_ip_ext {
 	uint8_t tos;
 	uint8_t ttl;
@@ -359,6 +364,43 @@ struct nfp_flower_ipv4_udp_tun {
 	rte_be32_t tun_id;
 };
 
+/*
+ * Flow Frame IPv6 UDP TUNNEL --> Tunnel details (11W/44B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           Reserved            |      tos      |      ttl      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            Reserved                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     VNI                       |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv6_udp_tun {
+	struct nfp_flower_tun_ipv6 ipv6;
+	rte_be16_t reserved1;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be32_t reserved2;
+	rte_be32_t tun_id;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 0e1e5ea..bbd9dba 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -493,6 +493,7 @@ struct nfp_mask_id_entry {
 {
 	struct rte_eth_dev *ethdev;
 	bool outer_ip4_flag = false;
+	bool outer_ip6_flag = false;
 	const struct rte_flow_item *item;
 	struct nfp_flower_representor *representor;
 	const struct rte_flow_item_port_id *port_id;
@@ -535,6 +536,8 @@ struct nfp_mask_id_entry {
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV6 detected");
 			key_ls->key_layer |= NFP_FLOWER_LAYER_IPV6;
 			key_ls->key_size += sizeof(struct nfp_flower_ipv6);
+			if (!outer_ip6_flag)
+				outer_ip6_flag = true;
 			break;
 		case RTE_FLOW_ITEM_TYPE_TCP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_TCP detected");
@@ -553,8 +556,9 @@ struct nfp_mask_id_entry {
 			break;
 		case RTE_FLOW_ITEM_TYPE_VXLAN:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_VXLAN detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_VXLAN;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_VXLAN;
 			if (outer_ip4_flag) {
@@ -564,6 +568,19 @@ struct nfp_mask_id_entry {
 				 * in `struct nfp_flower_ipv4_udp_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for VXLAN tunnel.");
+				return -EINVAL;
 			}
 			break;
 		default:
@@ -884,42 +901,61 @@ struct nfp_mask_id_entry {
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
 		bool is_mask,
-		__rte_unused bool is_outer_layer)
+		bool is_outer_layer)
 {
 	struct nfp_flower_ipv6 *ipv6;
 	const struct rte_ipv6_hdr *hdr;
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv6 *spec;
 	const struct rte_flow_item_ipv6 *mask;
+	struct nfp_flower_ipv6_udp_tun *ipv6_udp_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 
-	if (spec == NULL) {
-		PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
-		goto ipv6_end;
-	}
+	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
+			return 0;
+		}
 
-	/*
-	 * reserve space for L4 info.
-	 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
-	 */
-	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
-		*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+
+		ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
+				RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+		ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
+		memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
+				sizeof(ipv6_udp_tun->ipv6.ipv6_src));
+		memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
+				sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+	} else {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
+			goto ipv6_end;
+		}
 
-	hdr = is_mask ? &mask->hdr : &spec->hdr;
-	ipv6 = (struct nfp_flower_ipv6 *)*mbuf_off;
+		/*
+		 * reserve space for L4 info.
+		 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv6
+		 */
+		if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+			*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv6 = (struct nfp_flower_ipv6 *)*mbuf_off;
 
-	ipv6->ip_ext.tos   = (hdr->vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
-			RTE_IPV6_HDR_TC_SHIFT;
-	ipv6->ip_ext.proto = hdr->proto;
-	ipv6->ip_ext.ttl   = hdr->hop_limits;
-	memcpy(ipv6->ipv6_src, hdr->src_addr, sizeof(ipv6->ipv6_src));
-	memcpy(ipv6->ipv6_dst, hdr->dst_addr, sizeof(ipv6->ipv6_dst));
+		ipv6->ip_ext.tos   = (hdr->vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
+				RTE_IPV6_HDR_TC_SHIFT;
+		ipv6->ip_ext.proto = hdr->proto;
+		ipv6->ip_ext.ttl   = hdr->hop_limits;
+		memcpy(ipv6->ipv6_src, hdr->src_addr, sizeof(ipv6->ipv6_src));
+		memcpy(ipv6->ipv6_dst, hdr->dst_addr, sizeof(ipv6->ipv6_dst));
 
 ipv6_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv6);
+		*mbuf_off += sizeof(struct nfp_flower_ipv6);
+	}
 
 	return 0;
 }
@@ -1088,7 +1124,7 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
+nfp_flow_merge_vxlan(struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1097,8 +1133,15 @@ struct nfp_mask_id_entry {
 {
 	const struct rte_vxlan_hdr *hdr;
 	struct nfp_flower_ipv4_udp_tun *tun4;
+	struct nfp_flower_ipv6_udp_tun *tun6;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_vxlan *spec;
 	const struct rte_flow_item_vxlan *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1109,11 +1152,21 @@ struct nfp_mask_id_entry {
 	mask = item->mask ? item->mask : proc->mask_default;
 	hdr = is_mask ? &mask->hdr : &spec->hdr;
 
-	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
-	tun4->tun_id = hdr->vx_vni;
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+		tun6->tun_id = hdr->vx_vni;
+	} else {
+		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+		tun4->tun_id = hdr->vx_vni;
+	}
 
 vxlan_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6))
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_udp_tun);
+	else
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 
 	return 0;
 }
@@ -1122,7 +1175,8 @@ struct nfp_mask_id_entry {
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH,
-			RTE_FLOW_ITEM_TYPE_IPV4),
+			RTE_FLOW_ITEM_TYPE_IPV4,
+			RTE_FLOW_ITEM_TYPE_IPV6),
 	},
 	[RTE_FLOW_ITEM_TYPE_ETH] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VLAN,
@@ -1395,6 +1449,7 @@ struct nfp_mask_id_entry {
 	char *mbuf_off_exact;
 	bool is_tun_flow = false;
 	bool is_outer_layer = true;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item *loop_item;
 
 	mbuf_off_exact = nfp_flow->payload.unmasked_data +
@@ -1404,6 +1459,12 @@ struct nfp_mask_id_entry {
 			sizeof(struct nfp_flower_meta_tci) +
 			sizeof(struct nfp_flower_in_port);
 
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) {
+		mbuf_off_exact += sizeof(struct nfp_flower_ext_meta);
+		mbuf_off_mask += sizeof(struct nfp_flower_ext_meta);
+	}
+
 	/* Check if this is a tunnel flow and get the inner item*/
 	is_tun_flow = nfp_flow_inner_item_get(items, &loop_item);
 	if (is_tun_flow)
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 03/25] net/nfp: prepare for IPv4 tunnel encap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 01/25] net/nfp: support IPv4 VXLAN flow item Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 02/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 04/25] net/nfp: prepare for IPv6 " Chaoyong He
                     ` (23 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the encap action of IPv4 tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c | 29 ++++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 93 ++++++++++++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 88 ++++++++++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.h               | 27 ++++++++++
 4 files changed, 237 insertions(+)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 15d8381..7021d1f 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -246,3 +246,32 @@
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v4 *payload)
+{
+	uint16_t cnt;
+	size_t msg_len;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_neigh_v4 *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v4 tun neigh");
+		return -ENOMEM;
+	}
+
+	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v4);
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, msg_len);
+	memcpy(msg, payload, msg_len);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 996ba3b..e44e311 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -129,6 +129,36 @@ struct nfp_flower_cmsg_port_mod {
 	rte_be16_t mtu;
 };
 
+struct nfp_flower_tun_neigh {
+	uint8_t dst_mac[RTE_ETHER_ADDR_LEN];
+	uint8_t src_mac[RTE_ETHER_ADDR_LEN];
+	rte_be32_t port_id;
+};
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V4
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                           DST_IPV4                            |
+ *          +---------------------------------------------------------------+
+ *        1 |                           SRC_IPV4                            |
+ *          +---------------------------------------------------------------+
+ *        2 |                      DST_MAC_B5_B4_B3_B2                      |
+ *          +-------------------------------+-------------------------------+
+ *        3 |             DST_MAC_B1_B0     |        SRC_MAC_B5_B4          |
+ *          +-------------------------------+-------------------------------+
+ *        4 |                       SRC_MAC_B3_B2_B1_B0                     |
+ *          +---------------------------------------------------------------+
+ *        5 |                    Egress Port (NFP internal)                 |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_neigh_v4 {
+	rte_be32_t dst_ipv4;
+	rte_be32_t src_ipv4;
+	struct nfp_flower_tun_neigh common;
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -574,6 +604,67 @@ struct nfp_fl_act_set_tport {
 	rte_be16_t dst_port;
 };
 
+/*
+ * Pre-tunnel
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  -  |  opcode |       |jump_id|              -      |M|   - |V|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |         ipv6_daddr_127_96     /     ipv4_daddr                |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_95_64                          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_63_32                          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_31_0                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_fl_act_pre_tun {
+	struct nfp_fl_act_head head;
+	rte_be16_t flags;
+	union {
+		rte_be32_t ipv4_dst;
+		uint8_t ipv6_dst[16];
+	};
+};
+
+/*
+ * Set tunnel
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | res |  opcode |  res  | len_lw|           reserved            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            tun_id0                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            tun_id1                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                      reserved                 |  type |r| idx |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           ipv4_flags          |      ttl      |      tos      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         reserved_cvs1                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |          reserved_cvs2        |        reserved_cvs3          |
+ * |            var_flags          |            var_np             |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_fl_act_set_tun {
+	struct nfp_fl_act_head head;
+	rte_be16_t reserved;
+	rte_be64_t tun_id;
+	rte_be32_t tun_type_index;
+	rte_be16_t tun_flags;
+	uint8_t    ttl;
+	uint8_t    tos;
+	rte_be16_t outer_vlan_tpid;
+	rte_be16_t outer_vlan_tci;
+	uint8_t    tun_len;      /* Only valid for NFP_FL_TUNNEL_GENEVE */
+	uint8_t    reserved2;
+	rte_be16_t tun_proto;    /* Only valid for NFP_FL_TUNNEL_GENEVE */
+} __rte_packed;
+
 int nfp_flower_cmsg_mac_repr(struct nfp_app_fw_flower *app_fw_flower);
 int nfp_flower_cmsg_repr_reify(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_representor *repr);
@@ -583,5 +674,7 @@ int nfp_flower_cmsg_flow_delete(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
 int nfp_flower_cmsg_flow_add(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
+int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index bbd9dba..f71f8b1 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1772,6 +1772,91 @@ struct nfp_mask_id_entry {
 	tc_hl->reserved = 0;
 }
 
+__rte_unused static void
+nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
+		rte_be32_t ipv4_dst)
+{
+	pre_tun->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
+	pre_tun->head.len_lw  = sizeof(struct nfp_fl_act_pre_tun) >> NFP_FL_LW_SIZ;
+	pre_tun->ipv4_dst     = ipv4_dst;
+}
+
+__rte_unused static void
+nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
+		enum nfp_flower_tun_type tun_type,
+		uint64_t tun_id,
+		uint8_t ttl,
+		uint8_t tos)
+{
+	/* Currently only support one pre-tunnel, so index is always 0. */
+	uint8_t pretun_idx = 0;
+	uint32_t tun_type_index;
+
+	tun_type_index = ((tun_type << 4) & 0xf0) | (pretun_idx & 0x07);
+
+	set_tun->head.jump_id   = NFP_FL_ACTION_OPCODE_SET_TUNNEL;
+	set_tun->head.len_lw    = sizeof(struct nfp_fl_act_set_tun) >> NFP_FL_LW_SIZ;
+	set_tun->tun_type_index = rte_cpu_to_be_32(tun_type_index);
+	set_tun->tun_id         = rte_cpu_to_be_64(tun_id);
+	set_tun->ttl            = ttl;
+	set_tun->tos            = tos;
+}
+
+__rte_unused static int
+nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun,
+		const struct rte_ether_hdr *eth,
+		const struct rte_flow_item_ipv4 *ipv4)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	tun->payload.v6_flag = 0;
+	tun->payload.dst.dst_ipv4 = ipv4->hdr.dst_addr;
+	tun->payload.src.src_ipv4 = ipv4->hdr.src_addr;
+	memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	port = (struct nfp_flower_in_port *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4->hdr.dst_addr;
+	payload.src_ipv4 = ipv4->hdr.src_addr;
+	memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
+__rte_unused static int
+nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
@@ -2487,6 +2572,9 @@ struct nfp_mask_id_entry {
 		goto free_mask_table;
 	}
 
+	/* neighbor next list */
+	LIST_INIT(&priv->nn_list);
+
 	return 0;
 
 free_mask_table:
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index 0ad89e5..892dbc0 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -90,6 +90,11 @@ enum nfp_flower_tun_type {
 	NFP_FL_TUN_GENEVE = 4,
 };
 
+enum nfp_flow_type {
+	NFP_FLOW_COMMON,
+	NFP_FLOW_ENCAP,
+};
+
 struct nfp_fl_key_ls {
 	uint32_t key_layer_two;
 	uint8_t key_layer;
@@ -118,6 +123,24 @@ struct nfp_fl_payload {
 	char *action_data;
 };
 
+struct nfp_fl_tun {
+	LIST_ENTRY(nfp_fl_tun) next;
+	uint8_t ref_cnt;
+	struct nfp_fl_tun_entry {
+		uint8_t v6_flag;
+		uint8_t dst_addr[RTE_ETHER_ADDR_LEN];
+		uint8_t src_addr[RTE_ETHER_ADDR_LEN];
+		union {
+			rte_be32_t dst_ipv4;
+			uint8_t dst_ipv6[16];
+		} dst;
+		union {
+			rte_be32_t src_ipv4;
+			uint8_t src_ipv6[16];
+		} src;
+	} payload;
+};
+
 #define CIRC_CNT(head, tail, size)     (((head) - (tail)) & ((size) - 1))
 #define CIRC_SPACE(head, tail, size)   CIRC_CNT((tail), ((head) + 1), (size))
 struct circ_buf {
@@ -161,13 +184,17 @@ struct nfp_flow_priv {
 	struct nfp_fl_stats_id stats_ids; /**< The stats id ring. */
 	struct nfp_fl_stats *stats; /**< Store stats of flow. */
 	rte_spinlock_t stats_lock; /** < Lock the update of 'stats' field. */
+	/* neighbor next */
+	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
 
 struct rte_flow {
 	struct nfp_fl_payload payload;
+	struct nfp_fl_tun tun;
 	size_t length;
 	uint32_t hash_key;
 	bool install_flag;
+	enum nfp_flow_type type;
 };
 
 int nfp_flow_priv_init(struct nfp_pf_dev *pf_dev);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 04/25] net/nfp: prepare for IPv6 tunnel encap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (2 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 03/25] net/nfp: prepare for IPv4 tunnel encap flow action Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 05/25] net/nfp: support IPv4 VXLAN " Chaoyong He
                     ` (22 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the encap action of IPv6 tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  29 +++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  40 ++++++++++++
 drivers/net/nfp/nfp_flow.c               | 105 ++++++++++++++++++++++++++++++-
 3 files changed, 173 insertions(+), 1 deletion(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 7021d1f..8983178 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -275,3 +275,32 @@
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v6 *payload)
+{
+	uint16_t cnt;
+	size_t msg_len;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_neigh_v6 *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v6 tun neigh");
+		return -ENOMEM;
+	}
+
+	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v6);
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6, msg_len);
+	memcpy(msg, payload, msg_len);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index e44e311..d1e0562 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -160,6 +160,42 @@ struct nfp_flower_cmsg_tun_neigh_v4 {
 };
 
 /*
+ * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                          DST_IPV6 [0]                         |
+ *          +---------------------------------------------------------------+
+ *        1 |                          DST_IPV6 [1]                         |
+ *          +---------------------------------------------------------------+
+ *        2 |                          DST_IPV6 [2]                         |
+ *          +---------------------------------------------------------------+
+ *        3 |                          DST_IPV6 [3]                         |
+ *          +---------------------------------------------------------------+
+ *        4 |                          SRC_IPV6 [0]                         |
+ *          +---------------------------------------------------------------+
+ *        5 |                          SRC_IPV6 [1]                         |
+ *          +---------------------------------------------------------------+
+ *        6 |                          SRC_IPV6 [2]                         |
+ *          +---------------------------------------------------------------+
+ *        7 |                          SRC_IPV6 [3]                         |
+ *          +---------------------------------------------------------------+
+ *        8 |                       DST_MAC_B5_B4_B3_B2                     |
+ *          +-------------------------------+-------------------------------+
+ *        9 |             DST_MAC_B1_B0     |        SRC_MAC_B5_B4          |
+ *          +-------------------------------+-------------------------------+
+ *       10 |                       SRC_MAC_B3_B2_B1_B0                     |
+ *          +---------------+---------------+---------------+---------------+
+ *       11 |                    Egress Port (NFP internal)                 |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_neigh_v6 {
+	uint8_t dst_ipv6[16];
+	uint8_t src_ipv6[16];
+	struct nfp_flower_tun_neigh common;
+};
+
+/*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
@@ -629,6 +665,8 @@ struct nfp_fl_act_pre_tun {
 	};
 };
 
+#define NFP_FL_PRE_TUN_IPV6    (1 << 0)
+
 /*
  * Set tunnel
  *    3                   2                   1
@@ -676,5 +714,7 @@ int nfp_flower_cmsg_flow_add(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
 int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
+int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index f71f8b1..e1b892f 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1782,6 +1782,16 @@ struct nfp_mask_id_entry {
 }
 
 __rte_unused static void
+nfp_flow_pre_tun_v6_process(struct nfp_fl_act_pre_tun *pre_tun,
+		const uint8_t ipv6_dst[])
+{
+	pre_tun->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
+	pre_tun->head.len_lw  = sizeof(struct nfp_fl_act_pre_tun) >> NFP_FL_LW_SIZ;
+	pre_tun->flags        = rte_cpu_to_be_16(NFP_FL_PRE_TUN_IPV6);
+	memcpy(pre_tun->ipv6_dst, ipv6_dst, sizeof(pre_tun->ipv6_dst));
+}
+
+__rte_unused static void
 nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
 		enum nfp_flower_tun_type tun_type,
 		uint64_t tun_id,
@@ -1845,7 +1855,7 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
 {
@@ -1857,6 +1867,99 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun,
+		const struct rte_ether_hdr *eth,
+		const struct rte_flow_item_ipv6 *ipv6)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	tun->payload.v6_flag = 1;
+	memcpy(tun->payload.dst.dst_ipv6, ipv6->hdr.dst_addr, sizeof(tun->payload.dst.dst_ipv6));
+	memcpy(tun->payload.src.src_ipv6, ipv6->hdr.src_addr, sizeof(tun->payload.src.src_ipv6));
+	memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	port = (struct nfp_flower_in_port *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6->hdr.dst_addr, sizeof(payload.dst_ipv6));
+	memcpy(payload.src_ipv6, ipv6->hdr.src_addr, sizeof(payload.src_ipv6));
+	memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
+static int
+nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t *ipv6)
+{
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6, sizeof(payload.dst_ipv6));
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
+__rte_unused static int
+nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	bool flag = false;
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+
+	tun = &nfp_flow->tun;
+	LIST_FOREACH(tmp, &app_fw_flower->flow_priv->nn_list, next) {
+		ret = memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry));
+		if (ret == 0) {
+			tmp->ref_cnt--;
+			flag = true;
+			break;
+		}
+	}
+
+	if (!flag) {
+		PMD_DRV_LOG(DEBUG, "Can't find nn entry in the nn list");
+		return -EINVAL;
+	}
+
+	if (tmp->ref_cnt == 0) {
+		LIST_REMOVE(tmp, next);
+		if (tmp->payload.v6_flag != 0) {
+			return nfp_flower_del_tun_neigh_v6(app_fw_flower,
+					tmp->payload.dst.dst_ipv6);
+		} else {
+			return nfp_flower_del_tun_neigh_v4(app_fw_flower,
+					tmp->payload.dst.dst_ipv4);
+		}
+	}
+
+	return 0;
+}
+
 static int
 nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 05/25] net/nfp: support IPv4 VXLAN encap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (3 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 04/25] net/nfp: prepare for IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 06/25] net/nfp: support IPv6 " Chaoyong He
                     ` (21 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv4 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |   1 +
 drivers/net/nfp/nfp_flow.c       | 132 +++++++++++++++++++++++++++++++++++++--
 2 files changed, 128 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index faaa7da..ff97787 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -56,3 +56,4 @@ set_mac_src          = Y
 set_tp_dst           = Y
 set_tp_src           = Y
 set_ttl              = Y
+vxlan_encap          = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index e1b892f..d2e779c 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -10,8 +10,10 @@
 #include <rte_malloc.h>
 
 #include "nfp_common.h"
+#include "nfp_ctrl.h"
 #include "nfp_flow.h"
 #include "nfp_logs.h"
+#include "nfp_rxtx.h"
 #include "flower/nfp_flower.h"
 #include "flower/nfp_flower_cmsg.h"
 #include "flower/nfp_flower_ctrl.h"
@@ -19,6 +21,17 @@
 #include "nfpcore/nfp_mip.h"
 #include "nfpcore/nfp_rtsym.h"
 
+/*
+ * Maximum number of items in struct rte_flow_action_vxlan_encap.
+ * ETH / IPv4(6) / UDP / VXLAN / END
+ */
+#define ACTION_VXLAN_ENCAP_ITEMS_NUM 5
+
+struct vxlan_data {
+	struct rte_flow_action_vxlan_encap conf;
+	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
+};
+
 /* Static initializer for a list of subsequent item types */
 #define NEXT_ITEM(...) \
 	((const enum rte_flow_item_type []){ \
@@ -724,6 +737,11 @@ struct nfp_mask_id_entry {
 				tc_hl_flag = true;
 			}
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP detected");
+			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
+			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1772,7 +1790,7 @@ struct nfp_mask_id_entry {
 	tc_hl->reserved = 0;
 }
 
-__rte_unused static void
+static void
 nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
 		rte_be32_t ipv4_dst)
 {
@@ -1791,7 +1809,7 @@ struct nfp_mask_id_entry {
 	memcpy(pre_tun->ipv6_dst, ipv6_dst, sizeof(pre_tun->ipv6_dst));
 }
 
-__rte_unused static void
+static void
 nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
 		enum nfp_flower_tun_type tun_type,
 		uint64_t tun_id,
@@ -1812,7 +1830,7 @@ struct nfp_mask_id_entry {
 	set_tun->tos            = tos;
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct nfp_fl_tun *tun,
@@ -1922,7 +1940,7 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -1961,7 +1979,81 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
+nfp_flow_action_vxlan_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct vxlan_data *vxlan_data,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	const struct rte_flow_item_eth *eth;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_vxlan *vxlan;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth   = (const struct rte_flow_item_eth *)vxlan_data->items[0].spec;
+	ipv4  = (const struct rte_flow_item_ipv4 *)vxlan_data->items[1].spec;
+	vxlan = (const struct rte_flow_item_vxlan *)vxlan_data->items[3].spec;
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_VXLAN, vxlan->hdr.vx_vni,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_flags = vxlan->hdr.vx_flags;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, &eth->hdr, ipv4);
+}
+
+static int
+nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	size_t act_len;
+	size_t act_pre_size;
+	const struct vxlan_data *vxlan_data;
+
+	vxlan_data = action->conf;
+	if (vxlan_data->items[0].type != RTE_FLOW_ITEM_TYPE_ETH ||
+			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 ||
+			vxlan_data->items[2].type != RTE_FLOW_ITEM_TYPE_UDP ||
+			vxlan_data->items[3].type != RTE_FLOW_ITEM_TYPE_VXLAN ||
+			vxlan_data->items[4].type != RTE_FLOW_ITEM_TYPE_END) {
+		PMD_DRV_LOG(ERR, "Not an valid vxlan action conf.");
+		return -EINVAL;
+	}
+
+	/*
+	 * Pre_tunnel action must be the first on the action list.
+	 * If other actions already exist, they need to be pushed forward.
+	 */
+	act_len = act_data - actions;
+	if (act_len != 0) {
+		act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+		memmove(actions + act_pre_size, actions, act_len);
+	}
+
+	if (vxlan_data->items[1].type == RTE_FLOW_ITEM_TYPE_IPV4)
+		return nfp_flow_action_vxlan_encap_v4(app_fw_flower, act_data,
+				actions, vxlan_data, nfp_flow_meta, tun);
+
+	return 0;
+}
+
+static int
+nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
 		struct rte_flow *nfp_flow)
 {
@@ -2118,6 +2210,20 @@ struct nfp_mask_id_entry {
 				tc_hl_flag = true;
 			}
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP");
+			ret = nfp_flow_action_vxlan_encap(representor->app_fw_flower,
+					position, action_data, action, nfp_flow_meta,
+					&nfp_flow->tun);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process"
+						" RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP");
+				return ret;
+			}
+			position += sizeof(struct nfp_fl_act_pre_tun);
+			position += sizeof(struct nfp_fl_act_set_tun);
+			nfp_flow->type = NFP_FLOW_ENCAP;
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
 			return -ENOTSUP;
@@ -2410,6 +2516,22 @@ struct nfp_mask_id_entry {
 		goto exit;
 	}
 
+	switch (nfp_flow->type) {
+	case NFP_FLOW_COMMON:
+		break;
+	case NFP_FLOW_ENCAP:
+		/* Delete the entry from nn table */
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid nfp flow type %d.", nfp_flow->type);
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret != 0)
+		goto exit;
+
 	/* Delete the flow from hardware */
 	if (nfp_flow->install_flag) {
 		ret = nfp_flower_cmsg_flow_delete(app_fw_flower, nfp_flow);
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 06/25] net/nfp: support IPv6 VXLAN encap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (4 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 05/25] net/nfp: support IPv4 VXLAN " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 07/25] net/nfp: prepare for IPv4 UDP tunnel decap " Chaoyong He
                     ` (20 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv6 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 48 +++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 43 insertions(+), 5 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index d2e779c..9ee02b0 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1799,7 +1799,7 @@ struct nfp_mask_id_entry {
 	pre_tun->ipv4_dst     = ipv4_dst;
 }
 
-__rte_unused static void
+static void
 nfp_flow_pre_tun_v6_process(struct nfp_fl_act_pre_tun *pre_tun,
 		const uint8_t ipv6_dst[])
 {
@@ -1885,7 +1885,7 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct nfp_fl_tun *tun,
@@ -2014,6 +2014,42 @@ struct nfp_mask_id_entry {
 }
 
 static int
+nfp_flow_action_vxlan_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct vxlan_data *vxlan_data,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	const struct rte_flow_item_eth *eth;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_vxlan *vxlan;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth   = (const struct rte_flow_item_eth *)vxlan_data->items[0].spec;
+	ipv6  = (const struct rte_flow_item_ipv6 *)vxlan_data->items[1].spec;
+	vxlan = (const struct rte_flow_item_vxlan *)vxlan_data->items[3].spec;
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_VXLAN, vxlan->hdr.vx_vni,
+			ipv6->hdr.hop_limits,
+			(ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff);
+	set_tun->tun_flags = vxlan->hdr.vx_flags;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, &eth->hdr, ipv6);
+}
+
+static int
 nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
 		char *actions,
@@ -2027,7 +2063,8 @@ struct nfp_mask_id_entry {
 
 	vxlan_data = action->conf;
 	if (vxlan_data->items[0].type != RTE_FLOW_ITEM_TYPE_ETH ||
-			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 ||
+			(vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 &&
+			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV6) ||
 			vxlan_data->items[2].type != RTE_FLOW_ITEM_TYPE_UDP ||
 			vxlan_data->items[3].type != RTE_FLOW_ITEM_TYPE_VXLAN ||
 			vxlan_data->items[4].type != RTE_FLOW_ITEM_TYPE_END) {
@@ -2048,8 +2085,9 @@ struct nfp_mask_id_entry {
 	if (vxlan_data->items[1].type == RTE_FLOW_ITEM_TYPE_IPV4)
 		return nfp_flow_action_vxlan_encap_v4(app_fw_flower, act_data,
 				actions, vxlan_data, nfp_flow_meta, tun);
-
-	return 0;
+	else
+		return nfp_flow_action_vxlan_encap_v6(app_fw_flower, act_data,
+				actions, vxlan_data, nfp_flow_meta, tun);
 }
 
 static int
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 07/25] net/nfp: prepare for IPv4 UDP tunnel decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (5 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 06/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 08/25] net/nfp: prepare for IPv6 " Chaoyong He
                     ` (19 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the decap action of IPv4 UDP tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c | 118 ++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  94 +++++++
 drivers/net/nfp/nfp_flow.c               | 461 ++++++++++++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |  17 ++
 4 files changed, 675 insertions(+), 15 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 8983178..f18f3de 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -304,3 +304,121 @@
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower)
+{
+	uint16_t cnt;
+	uint32_t count = 0;
+	struct rte_mbuf *mbuf;
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+	struct nfp_flower_cmsg_tun_ipv4_addr *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v4 tun addr");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_IPS, sizeof(*msg));
+
+	priv = app_fw_flower->flow_priv;
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (count >= NFP_FL_IPV4_ADDRS_MAX) {
+			rte_spinlock_unlock(&priv->ipv4_off_lock);
+			PMD_DRV_LOG(ERR, "IPv4 offload exceeds limit.");
+			return -ERANGE;
+		}
+		msg->ipv4_addr[count] = entry->ipv4_addr;
+		count++;
+	}
+	msg->count = rte_cpu_to_be_32(count);
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		uint16_t mac_idx,
+		bool is_del)
+{
+	uint16_t cnt;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_pre_tun_rule *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for pre tunnel rule");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, sizeof(*msg));
+
+	meta_tci = (struct nfp_flower_meta_tci *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata));
+	if (meta_tci->tci)
+		msg->vlan_tci = meta_tci->tci;
+	else
+		msg->vlan_tci = 0xffff;
+
+	if (is_del)
+		msg->flags = rte_cpu_to_be_32(NFP_TUN_PRE_TUN_RULE_DEL);
+
+	msg->port_idx = rte_cpu_to_be_16(mac_idx);
+	msg->host_ctx_id = nfp_flow_meta->host_ctx_id;
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+nfp_flower_cmsg_tun_mac_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_ether_addr *mac,
+		uint16_t mac_idx,
+		bool is_del)
+{
+	uint16_t cnt;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_mac *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for tunnel mac");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_MAC, sizeof(*msg));
+
+	msg->count = rte_cpu_to_be_16(1);
+	msg->index = rte_cpu_to_be_16(mac_idx);
+	rte_ether_addr_copy(mac, &msg->addr);
+	if (is_del)
+		msg->flags = rte_cpu_to_be_16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index d1e0562..0933dac 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -195,6 +195,91 @@ struct nfp_flower_cmsg_tun_neigh_v6 {
 	struct nfp_flower_tun_neigh common;
 };
 
+#define NFP_TUN_PRE_TUN_RULE_DEL    (1 << 0)
+#define NFP_TUN_PRE_TUN_IDX_BIT     (1 << 3)
+#define NFP_TUN_PRE_TUN_IPV6_BIT    (1 << 7)
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE
+ * Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ * -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *       +---------------------------------------------------------------+
+ *     0 |                             FLAGS                             |
+ *       +---------------------------------------------------------------+
+ *     1 |         MAC_IDX               |            VLAN_ID            |
+ *       +---------------------------------------------------------------+
+ *     2 |                           HOST_CTX                            |
+ *       +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_pre_tun_rule {
+	rte_be32_t flags;
+	rte_be16_t port_idx;
+	rte_be16_t vlan_tci;
+	rte_be32_t host_ctx_id;
+};
+
+#define NFP_TUN_MAC_OFFLOAD_DEL_FLAG  0x2
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_MAC
+ *     Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *    Word  +-----------------------+---+-+-+---------------+---------------+
+ *       0  |              spare    |NBI|D|F| Amount of MAC’s in this msg   |
+ *          +---------------+-------+---+-+-+---------------+---------------+
+ *       1  |            Index 0            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       2  |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       3  |            Index 1            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       4  |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *                                        ...
+ *          +---------------+---------------+---------------+---------------+
+ *     2N-1 |            Index N            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *     2N   |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *
+ *    F:   Flush bit. Set if entire table must be flushed. Rest of info in cmsg
+ *        will be ignored. Not implemented.
+ *    D:   Delete bit. Set if entry must be deleted instead of added
+ *    NBI: Network Block Interface. Set to 0
+ *    The amount of MAC’s per control message is limited only by the packet
+ *    buffer size. A 2048B buffer can fit 253 MAC address and a 10240B buffer
+ *    1277 MAC addresses.
+ */
+struct nfp_flower_cmsg_tun_mac {
+	rte_be16_t flags;
+	rte_be16_t count;           /**< Should always be 1 */
+	rte_be16_t index;
+	struct rte_ether_addr addr;
+};
+
+#define NFP_FL_IPV4_ADDRS_MAX        32
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_IPS
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                    Number of IP Addresses                     |
+ *          +---------------------------------------------------------------+
+ *        1 |                        IP Address #1                          |
+ *          +---------------------------------------------------------------+
+ *        2 |                        IP Address #2                          |
+ *          +---------------------------------------------------------------+
+ *          |                             ...                               |
+ *          +---------------------------------------------------------------+
+ *       32 |                        IP Address #32                         |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_ipv4_addr {
+	rte_be32_t count;
+	rte_be32_t ipv4_addr[NFP_FL_IPV4_ADDRS_MAX];
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -716,5 +801,14 @@ int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
 int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
+int nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower);
+int nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		uint16_t mac_idx,
+		bool is_del);
+int nfp_flower_cmsg_tun_mac_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_ether_addr *mac,
+		uint16_t mac_idx,
+		bool is_del);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 9ee02b0..c088d24 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -47,7 +47,8 @@ struct nfp_flow_item_proc {
 	/* Size in bytes for @p mask_support and @p mask_default. */
 	const unsigned int mask_sz;
 	/* Merge a pattern item into a flow rule handle. */
-	int (*merge)(struct rte_flow *nfp_flow,
+	int (*merge)(struct nfp_app_fw_flower *app_fw_flower,
+			struct rte_flow *nfp_flow,
 			char **mbuf_off,
 			const struct rte_flow_item *item,
 			const struct nfp_flow_item_proc *proc,
@@ -63,6 +64,12 @@ struct nfp_mask_id_entry {
 	uint8_t mask_id;
 };
 
+struct nfp_pre_tun_entry {
+	uint16_t mac_index;
+	uint16_t ref_cnt;
+	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
+} __rte_aligned(32);
+
 static inline struct nfp_flow_priv *
 nfp_flow_dev_to_priv(struct rte_eth_dev *dev)
 {
@@ -406,6 +413,83 @@ struct nfp_mask_id_entry {
 	return 0;
 }
 
+__rte_unused static int
+nfp_tun_add_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+	struct nfp_ipv4_addr_entry *tmp_entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (entry->ipv4_addr == ipv4) {
+			entry->ref_count++;
+			rte_spinlock_unlock(&priv->ipv4_off_lock);
+			return 0;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	tmp_entry = rte_zmalloc("nfp_ipv4_off", sizeof(struct nfp_ipv4_addr_entry), 0);
+	if (tmp_entry == NULL) {
+		PMD_DRV_LOG(ERR, "Mem error when offloading IP address.");
+		return -ENOMEM;
+	}
+
+	tmp_entry->ipv4_addr = ipv4;
+	tmp_entry->ref_count = 1;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_INSERT_HEAD(&priv->ipv4_off_list, tmp_entry, next);
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	return nfp_flower_cmsg_tun_off_v4(app_fw_flower);
+}
+
+static int
+nfp_tun_del_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (entry->ipv4_addr == ipv4) {
+			entry->ref_count--;
+			if (entry->ref_count == 0) {
+				LIST_REMOVE(entry, next);
+				rte_free(entry);
+				rte_spinlock_unlock(&priv->ipv4_off_lock);
+				return nfp_flower_cmsg_tun_off_v4(app_fw_flower);
+			}
+			break;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	return 0;
+}
+
+static int
+nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	struct nfp_flower_ipv4_udp_tun *udp4;
+
+	udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+			sizeof(struct nfp_flower_ipv4_udp_tun));
+	ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+
+	return ret;
+}
+
 static void
 nfp_flower_compile_meta_tci(char *mbuf_off, struct nfp_fl_key_ls *key_layer)
 {
@@ -635,6 +719,9 @@ struct nfp_mask_id_entry {
 		case RTE_FLOW_ACTION_TYPE_COUNT:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_COUNT detected");
 			break;
+		case RTE_FLOW_ACTION_TYPE_JUMP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_JUMP detected");
+			break;
 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_PORT_ID detected");
 			key_ls->act_size += sizeof(struct nfp_fl_act_output);
@@ -786,7 +873,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_eth(__rte_unused struct rte_flow *nfp_flow,
+nfp_flow_merge_eth(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -823,7 +911,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_vlan(struct rte_flow *nfp_flow,
+nfp_flow_merge_vlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		__rte_unused char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -853,7 +942,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_ipv4(struct rte_flow *nfp_flow,
+nfp_flow_merge_ipv4(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -914,7 +1004,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_ipv6(struct rte_flow *nfp_flow,
+nfp_flow_merge_ipv6(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -979,7 +1070,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_tcp(struct rte_flow *nfp_flow,
+nfp_flow_merge_tcp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1052,7 +1144,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_udp(struct rte_flow *nfp_flow,
+nfp_flow_merge_udp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1100,7 +1193,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_sctp(struct rte_flow *nfp_flow,
+nfp_flow_merge_sctp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1142,7 +1236,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_merge_vxlan(struct rte_flow *nfp_flow,
+nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1391,7 +1486,8 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_compile_item_proc(const struct rte_flow_item items[],
+nfp_flow_compile_item_proc(struct nfp_flower_representor *repr,
+		const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow,
 		char **mbuf_off_exact,
 		char **mbuf_off_mask,
@@ -1402,6 +1498,7 @@ struct nfp_mask_id_entry {
 	bool continue_flag = true;
 	const struct rte_flow_item *item;
 	const struct nfp_flow_item_proc *proc_list;
+	struct nfp_app_fw_flower *app_fw_flower = repr->app_fw_flower;
 
 	proc_list = nfp_flow_item_proc_list;
 	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END && continue_flag; ++item) {
@@ -1437,14 +1534,14 @@ struct nfp_mask_id_entry {
 			break;
 		}
 
-		ret = proc->merge(nfp_flow, mbuf_off_exact, item,
+		ret = proc->merge(app_fw_flower, nfp_flow, mbuf_off_exact, item,
 				proc, false, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d exact merge failed", item->type);
 			break;
 		}
 
-		ret = proc->merge(nfp_flow, mbuf_off_mask, item,
+		ret = proc->merge(app_fw_flower, nfp_flow, mbuf_off_mask, item,
 				proc, true, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d mask merge failed", item->type);
@@ -1458,7 +1555,7 @@ struct nfp_mask_id_entry {
 }
 
 static int
-nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
+nfp_flow_compile_items(struct nfp_flower_representor *representor,
 		const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow)
 {
@@ -1489,7 +1586,7 @@ struct nfp_mask_id_entry {
 		is_outer_layer = false;
 
 	/* Go over items */
-	ret = nfp_flow_compile_item_proc(loop_item, nfp_flow,
+	ret = nfp_flow_compile_item_proc(representor, loop_item, nfp_flow,
 			&mbuf_off_exact, &mbuf_off_mask, is_outer_layer);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "nfp flow item compile failed.");
@@ -1498,7 +1595,7 @@ struct nfp_mask_id_entry {
 
 	/* Go over inner items */
 	if (is_tun_flow) {
-		ret = nfp_flow_compile_item_proc(items, nfp_flow,
+		ret = nfp_flow_compile_item_proc(representor, items, nfp_flow,
 				&mbuf_off_exact, &mbuf_off_mask, true);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow outer item compile failed.");
@@ -1873,6 +1970,59 @@ struct nfp_mask_id_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_ipv4 *ipv4;
+	struct nfp_flower_mac_mpls *eth;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	port = (struct nfp_flower_in_port *)(meta_tci + 1);
+	eth = (struct nfp_flower_mac_mpls *)(port + 1);
+
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+		ipv4 = (struct nfp_flower_ipv4 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls) +
+				sizeof(struct nfp_flower_tp_ports));
+	else
+		ipv4 = (struct nfp_flower_ipv4 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls));
+
+	tun = &nfp_flow->tun;
+	tun->payload.v6_flag = 0;
+	tun->payload.dst.dst_ipv4 = ipv4->ipv4_src;
+	tun->payload.src.src_ipv4 = ipv4->ipv4_dst;
+	memcpy(tun->payload.dst_addr, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4->ipv4_src;
+	payload.src_ipv4 = ipv4->ipv4_dst;
+	memcpy(payload.common.dst_mac, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
@@ -2090,6 +2240,200 @@ struct nfp_mask_id_entry {
 				actions, vxlan_data, nfp_flow_meta, tun);
 }
 
+static struct nfp_pre_tun_entry *
+nfp_pre_tun_table_search(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int index;
+	uint32_t hash_key;
+	struct nfp_pre_tun_entry *mac_index;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	index = rte_hash_lookup_data(priv->pre_tun_table, &hash_key, (void **)&mac_index);
+	if (index < 0) {
+		PMD_DRV_LOG(DEBUG, "Data NOT found in the hash table");
+		return NULL;
+	}
+
+	return mac_index;
+}
+
+static bool
+nfp_pre_tun_table_add(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int ret;
+	uint32_t hash_key;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	ret = rte_hash_add_key_data(priv->pre_tun_table, &hash_key, hash_data);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Add to pre tunnel table failed");
+		return false;
+	}
+
+	return true;
+}
+
+static bool
+nfp_pre_tun_table_delete(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int ret;
+	uint32_t hash_key;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	ret = rte_hash_del_key(priv->pre_tun_table, &hash_key);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "Delete from pre tunnel table failed");
+		return false;
+	}
+
+	return true;
+}
+
+__rte_unused static int
+nfp_pre_tun_table_check_add(struct nfp_flower_representor *repr,
+		uint16_t *index)
+{
+	uint16_t i;
+	uint32_t entry_size;
+	uint16_t mac_index = 1;
+	struct nfp_flow_priv *priv;
+	struct nfp_pre_tun_entry *entry;
+	struct nfp_pre_tun_entry *find_entry;
+
+	priv = repr->app_fw_flower->flow_priv;
+	if (priv->pre_tun_cnt >= NFP_TUN_PRE_TUN_RULE_LIMIT) {
+		PMD_DRV_LOG(ERR, "Pre tunnel table has full");
+		return -EINVAL;
+	}
+
+	entry_size = sizeof(struct nfp_pre_tun_entry);
+	entry = rte_zmalloc("nfp_pre_tun", entry_size, 0);
+	if (entry == NULL) {
+		PMD_DRV_LOG(ERR, "Memory alloc failed for pre tunnel table");
+		return -ENOMEM;
+	}
+
+	entry->ref_cnt = 1U;
+	memcpy(entry->mac_addr, repr->mac_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	/* 0 is considered a failed match */
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0)
+			continue;
+		entry->mac_index = i;
+		find_entry = nfp_pre_tun_table_search(priv, (char *)entry, entry_size);
+		if (find_entry != NULL) {
+			find_entry->ref_cnt++;
+			*index = find_entry->mac_index;
+			rte_free(entry);
+			return 0;
+		}
+	}
+
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0) {
+			priv->pre_tun_bitmap[i] = 1U;
+			mac_index = i;
+			break;
+		}
+	}
+
+	entry->mac_index = mac_index;
+	if (!nfp_pre_tun_table_add(priv, (char *)entry, entry_size)) {
+		rte_free(entry);
+		return -EINVAL;
+	}
+
+	*index = entry->mac_index;
+	priv->pre_tun_cnt++;
+	return 0;
+}
+
+static int
+nfp_pre_tun_table_check_del(struct nfp_flower_representor *repr,
+		struct rte_flow *nfp_flow)
+{
+	uint16_t i;
+	int ret = 0;
+	uint32_t entry_size;
+	uint16_t nfp_mac_idx;
+	struct nfp_flow_priv *priv;
+	struct nfp_pre_tun_entry *entry;
+	struct nfp_pre_tun_entry *find_entry;
+	struct nfp_fl_rule_metadata *nfp_flow_meta;
+
+	priv = repr->app_fw_flower->flow_priv;
+	if (priv->pre_tun_cnt == 1)
+		return 0;
+
+	entry_size = sizeof(struct nfp_pre_tun_entry);
+	entry = rte_zmalloc("nfp_pre_tun", entry_size, 0);
+	if (entry == NULL) {
+		PMD_DRV_LOG(ERR, "Memory alloc failed for pre tunnel table");
+		return -ENOMEM;
+	}
+
+	entry->ref_cnt = 1U;
+	memcpy(entry->mac_addr, repr->mac_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	/* 0 is considered a failed match */
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0)
+			continue;
+		entry->mac_index = i;
+		find_entry = nfp_pre_tun_table_search(priv, (char *)entry, entry_size);
+		if (find_entry != NULL) {
+			find_entry->ref_cnt--;
+			if (find_entry->ref_cnt != 0)
+				goto free_entry;
+			priv->pre_tun_bitmap[i] = 0;
+			break;
+		}
+	}
+
+	nfp_flow_meta = nfp_flow->payload.meta;
+	nfp_mac_idx = (find_entry->mac_index << 8) |
+			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
+			NFP_TUN_PRE_TUN_IDX_BIT;
+	ret = nfp_flower_cmsg_tun_mac_rule(repr->app_fw_flower, &repr->mac_addr,
+			nfp_mac_idx, true);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send tunnel mac rule failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
+			nfp_mac_idx, true);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	find_entry->ref_cnt = 1U;
+	if (!nfp_pre_tun_table_delete(priv, (char *)find_entry, entry_size)) {
+		PMD_DRV_LOG(ERR, "Delete entry from pre tunnel table failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	rte_free(entry);
+	rte_free(find_entry);
+	priv->pre_tun_cnt--;
+
+free_entry:
+	rte_free(entry);
+
+	return ret;
+}
+
 static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
@@ -2125,6 +2469,9 @@ struct nfp_mask_id_entry {
 		case RTE_FLOW_ACTION_TYPE_COUNT:
 			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_COUNT");
 			break;
+		case RTE_FLOW_ACTION_TYPE_JUMP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_JUMP");
+			break;
 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
 			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_PORT_ID");
 			ret = nfp_flow_action_output(position, action, nfp_flow_meta);
@@ -2561,6 +2908,15 @@ struct nfp_mask_id_entry {
 		/* Delete the entry from nn table */
 		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
 		break;
+	case NFP_FLOW_DECAP:
+		/* Delete the entry from nn table */
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		if (ret != 0)
+			goto exit;
+
+		/* Delete the entry in pre tunnel table */
+		ret = nfp_pre_tun_table_check_del(representor, nfp_flow);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Invalid nfp flow type %d.", nfp_flow->type);
 		ret = -EINVAL;
@@ -2570,6 +2926,10 @@ struct nfp_mask_id_entry {
 	if (ret != 0)
 		goto exit;
 
+	/* Delete the ip off */
+	if (nfp_flow_is_tunnel(nfp_flow))
+		nfp_tun_check_ip_off_del(representor, nfp_flow);
+
 	/* Delete the flow from hardware */
 	if (nfp_flow->install_flag) {
 		ret = nfp_flower_cmsg_flow_delete(app_fw_flower, nfp_flow);
@@ -2703,6 +3063,49 @@ struct nfp_mask_id_entry {
 	return 0;
 }
 
+static int
+nfp_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
+		struct rte_flow_tunnel *tunnel,
+		struct rte_flow_action **pmd_actions,
+		uint32_t *num_of_actions,
+		__rte_unused struct rte_flow_error *err)
+{
+	struct rte_flow_action *nfp_action;
+
+	nfp_action = rte_zmalloc("nfp_tun_action", sizeof(struct rte_flow_action), 0);
+	if (nfp_action == NULL) {
+		PMD_DRV_LOG(ERR, "Alloc memory for nfp tunnel action failed.");
+		return -ENOMEM;
+	}
+
+	switch (tunnel->type) {
+	default:
+		*pmd_actions = NULL;
+		*num_of_actions = 0;
+		rte_free(nfp_action);
+		break;
+	}
+
+	return 0;
+}
+
+static int
+nfp_flow_tunnel_action_decap_release(__rte_unused struct rte_eth_dev *dev,
+		struct rte_flow_action *pmd_actions,
+		uint32_t num_of_actions,
+		__rte_unused struct rte_flow_error *err)
+{
+	uint32_t i;
+	struct rte_flow_action *nfp_action;
+
+	for (i = 0; i < num_of_actions; i++) {
+		nfp_action = &pmd_actions[i];
+		rte_free(nfp_action);
+	}
+
+	return 0;
+}
+
 static const struct rte_flow_ops nfp_flow_ops = {
 	.validate                    = nfp_flow_validate,
 	.create                      = nfp_flow_create,
@@ -2711,6 +3114,8 @@ struct nfp_mask_id_entry {
 	.query                       = nfp_flow_query,
 	.tunnel_match                = nfp_flow_tunnel_match,
 	.tunnel_item_release         = nfp_flow_tunnel_item_release,
+	.tunnel_decap_set            = nfp_flow_tunnel_decap_set,
+	.tunnel_action_decap_release = nfp_flow_tunnel_action_decap_release,
 };
 
 int
@@ -2755,6 +3160,15 @@ struct nfp_mask_id_entry {
 		.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
 	};
 
+	struct rte_hash_parameters pre_tun_hash_params = {
+		.name       = "pre_tunnel_table",
+		.entries    = 32,
+		.hash_func  = rte_jhash,
+		.socket_id  = rte_socket_id(),
+		.key_len    = sizeof(uint32_t),
+		.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
+	};
+
 	ctx_count = nfp_rtsym_read_le(pf_dev->sym_tbl,
 			"CONFIG_FC_HOST_CTX_COUNT", &ret);
 	if (ret < 0) {
@@ -2835,11 +3249,27 @@ struct nfp_mask_id_entry {
 		goto free_mask_table;
 	}
 
+	/* pre tunnel table */
+	priv->pre_tun_cnt = 1;
+	pre_tun_hash_params.hash_func_init_val = priv->hash_seed;
+	priv->pre_tun_table = rte_hash_create(&pre_tun_hash_params);
+	if (priv->pre_tun_table == NULL) {
+		PMD_INIT_LOG(ERR, "Pre tunnel table creation failed");
+		ret = -ENOMEM;
+		goto free_flow_table;
+	}
+
+	/* ipv4 off list */
+	rte_spinlock_init(&priv->ipv4_off_lock);
+	LIST_INIT(&priv->ipv4_off_list);
+
 	/* neighbor next list */
 	LIST_INIT(&priv->nn_list);
 
 	return 0;
 
+free_flow_table:
+	rte_hash_free(priv->flow_table);
 free_mask_table:
 	rte_free(priv->mask_table);
 free_stats:
@@ -2863,6 +3293,7 @@ struct nfp_mask_id_entry {
 	app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
 	priv = app_fw_flower->flow_priv;
 
+	rte_hash_free(priv->pre_tun_table);
 	rte_hash_free(priv->flow_table);
 	rte_hash_free(priv->mask_table);
 	rte_free(priv->stats);
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index 892dbc0..f536da2 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -6,6 +6,7 @@
 #ifndef _NFP_FLOW_H_
 #define _NFP_FLOW_H_
 
+#include <sys/queue.h>
 #include <rte_bitops.h>
 #include <ethdev_driver.h>
 
@@ -93,6 +94,7 @@ enum nfp_flower_tun_type {
 enum nfp_flow_type {
 	NFP_FLOW_COMMON,
 	NFP_FLOW_ENCAP,
+	NFP_FLOW_DECAP,
 };
 
 struct nfp_fl_key_ls {
@@ -169,6 +171,14 @@ struct nfp_fl_stats {
 	uint64_t bytes;
 };
 
+struct nfp_ipv4_addr_entry {
+	LIST_ENTRY(nfp_ipv4_addr_entry) next;
+	rte_be32_t ipv4_addr;
+	int ref_count;
+};
+
+#define NFP_TUN_PRE_TUN_RULE_LIMIT  32
+
 struct nfp_flow_priv {
 	uint32_t hash_seed; /**< Hash seed for hash tables in this structure. */
 	uint64_t flower_version; /**< Flow version, always increase. */
@@ -184,6 +194,13 @@ struct nfp_flow_priv {
 	struct nfp_fl_stats_id stats_ids; /**< The stats id ring. */
 	struct nfp_fl_stats *stats; /**< Store stats of flow. */
 	rte_spinlock_t stats_lock; /** < Lock the update of 'stats' field. */
+	/* pre tunnel rule */
+	uint16_t pre_tun_cnt; /**< The size of pre tunnel rule */
+	uint8_t pre_tun_bitmap[NFP_TUN_PRE_TUN_RULE_LIMIT]; /**< Bitmap of pre tunnel rule */
+	struct rte_hash *pre_tun_table; /**< Hash table to store pre tunnel rule */
+	/* IPv4 off */
+	LIST_HEAD(, nfp_ipv4_addr_entry) ipv4_off_list; /**< Store ipv4 off */
+	rte_spinlock_t ipv4_off_lock; /**< Lock the ipv4 off list */
 	/* neighbor next */
 	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 08/25] net/nfp: prepare for IPv6 UDP tunnel decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (6 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 07/25] net/nfp: prepare for IPv4 UDP tunnel decap " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 09/25] net/nfp: support IPv4 VXLAN " Chaoyong He
                     ` (18 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the decap action of IPv6 UDP tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  42 +++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  24 +++++
 drivers/net/nfp/nfp_flow.c               | 145 ++++++++++++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |   9 ++
 4 files changed, 217 insertions(+), 3 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index f18f3de..76815cf 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -348,6 +348,48 @@
 }
 
 int
+nfp_flower_cmsg_tun_off_v6(struct nfp_app_fw_flower *app_fw_flower)
+{
+	uint16_t cnt;
+	uint32_t count = 0;
+	struct rte_mbuf *mbuf;
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+	struct nfp_flower_cmsg_tun_ipv6_addr *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v6 tun addr");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_IPS_V6, sizeof(*msg));
+
+	priv = app_fw_flower->flow_priv;
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (count >= NFP_FL_IPV6_ADDRS_MAX) {
+			rte_spinlock_unlock(&priv->ipv6_off_lock);
+			PMD_DRV_LOG(ERR, "IPv6 offload exceeds limit.");
+			return -ERANGE;
+		}
+		memcpy(&msg->ipv6_addr[count * 16], entry->ipv6_addr, 16UL);
+		count++;
+	}
+	msg->count = rte_cpu_to_be_32(count);
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
 nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		uint16_t mac_idx,
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 0933dac..61f2f83 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -280,6 +280,29 @@ struct nfp_flower_cmsg_tun_ipv4_addr {
 	rte_be32_t ipv4_addr[NFP_FL_IPV4_ADDRS_MAX];
 };
 
+#define NFP_FL_IPV6_ADDRS_MAX        4
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_IP_V6
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                    Number of IP Addresses                     |
+ *          +---------------------------------------------------------------+
+ *        1 |                        IP Address1 #1                         |
+ *          +---------------------------------------------------------------+
+ *        2 |                        IP Address1 #2                         |
+ *          +---------------------------------------------------------------+
+ *          |                             ...                               |
+ *          +---------------------------------------------------------------+
+ *       16 |                        IP Address4 #4                         |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_ipv6_addr {
+	rte_be32_t count;
+	uint8_t ipv6_addr[NFP_FL_IPV6_ADDRS_MAX * 16];
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -802,6 +825,7 @@ int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
 int nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower);
+int nfp_flower_cmsg_tun_off_v6(struct nfp_app_fw_flower *app_fw_flower);
 int nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		uint16_t mac_idx,
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index c088d24..ad484b9 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -476,16 +476,95 @@ struct nfp_pre_tun_entry {
 	return 0;
 }
 
+__rte_unused static int
+nfp_tun_add_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t ipv6[])
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+	struct nfp_ipv6_addr_entry *tmp_entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (!memcmp(entry->ipv6_addr, ipv6, sizeof(entry->ipv6_addr))) {
+			entry->ref_count++;
+			rte_spinlock_unlock(&priv->ipv6_off_lock);
+			return 0;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	tmp_entry = rte_zmalloc("nfp_ipv6_off", sizeof(struct nfp_ipv6_addr_entry), 0);
+	if (tmp_entry == NULL) {
+		PMD_DRV_LOG(ERR, "Mem error when offloading IP6 address.");
+		return -ENOMEM;
+	}
+	memcpy(tmp_entry->ipv6_addr, ipv6, sizeof(tmp_entry->ipv6_addr));
+	tmp_entry->ref_count = 1;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_INSERT_HEAD(&priv->ipv6_off_list, tmp_entry, next);
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	return nfp_flower_cmsg_tun_off_v6(app_fw_flower);
+}
+
+static int
+nfp_tun_del_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t ipv6[])
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (!memcmp(entry->ipv6_addr, ipv6, sizeof(entry->ipv6_addr))) {
+			entry->ref_count--;
+			if (entry->ref_count == 0) {
+				LIST_REMOVE(entry, next);
+				rte_free(entry);
+				rte_spinlock_unlock(&priv->ipv6_off_lock);
+				return nfp_flower_cmsg_tun_off_v6(app_fw_flower);
+			}
+			break;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	return 0;
+}
+
 static int
 nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
 		struct rte_flow *nfp_flow)
 {
 	int ret;
+	uint32_t key_layer2 = 0;
 	struct nfp_flower_ipv4_udp_tun *udp4;
+	struct nfp_flower_ipv6_udp_tun *udp6;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 
-	udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
-			sizeof(struct nfp_flower_ipv4_udp_tun));
-	ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
+
+	if (ext_meta != NULL)
+		key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
+
+	if (key_layer2 & NFP_FLOWER_LAYER2_TUN_IPV6) {
+		udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
+				sizeof(struct nfp_flower_ipv6_udp_tun));
+		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+	} else {
+		udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+				sizeof(struct nfp_flower_ipv4_udp_tun));
+		ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+	}
 
 	return ret;
 }
@@ -2078,6 +2157,59 @@ struct nfp_pre_tun_entry {
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_ipv6 *ipv6;
+	struct nfp_flower_mac_mpls *eth;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	port = (struct nfp_flower_in_port *)(meta_tci + 1);
+	eth = (struct nfp_flower_mac_mpls *)(port + 1);
+
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+		ipv6 = (struct nfp_flower_ipv6 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls) +
+				sizeof(struct nfp_flower_tp_ports));
+	else
+		ipv6 = (struct nfp_flower_ipv6 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls));
+
+	tun = &nfp_flow->tun;
+	tun->payload.v6_flag = 1;
+	memcpy(tun->payload.dst.dst_ipv6, ipv6->ipv6_src, sizeof(tun->payload.dst.dst_ipv6));
+	memcpy(tun->payload.src.src_ipv6, ipv6->ipv6_dst, sizeof(tun->payload.src.src_ipv6));
+	memcpy(tun->payload.dst_addr, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6->ipv6_src, sizeof(payload.dst_ipv6));
+	memcpy(payload.src_ipv6, ipv6->ipv6_dst, sizeof(payload.src_ipv6));
+	memcpy(payload.common.dst_mac, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
 		uint8_t *ipv6)
@@ -2401,6 +2533,9 @@ struct nfp_pre_tun_entry {
 	nfp_mac_idx = (find_entry->mac_index << 8) |
 			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
 			NFP_TUN_PRE_TUN_IDX_BIT;
+	if (nfp_flow->tun.payload.v6_flag != 0)
+		nfp_mac_idx |= NFP_TUN_PRE_TUN_IPV6_BIT;
+
 	ret = nfp_flower_cmsg_tun_mac_rule(repr->app_fw_flower, &repr->mac_addr,
 			nfp_mac_idx, true);
 	if (ret != 0) {
@@ -3263,6 +3398,10 @@ struct nfp_pre_tun_entry {
 	rte_spinlock_init(&priv->ipv4_off_lock);
 	LIST_INIT(&priv->ipv4_off_list);
 
+	/* ipv6 off list */
+	rte_spinlock_init(&priv->ipv6_off_lock);
+	LIST_INIT(&priv->ipv6_off_list);
+
 	/* neighbor next list */
 	LIST_INIT(&priv->nn_list);
 
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index f536da2..a6994e0 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -177,6 +177,12 @@ struct nfp_ipv4_addr_entry {
 	int ref_count;
 };
 
+struct nfp_ipv6_addr_entry {
+	LIST_ENTRY(nfp_ipv6_addr_entry) next;
+	uint8_t ipv6_addr[16];
+	int ref_count;
+};
+
 #define NFP_TUN_PRE_TUN_RULE_LIMIT  32
 
 struct nfp_flow_priv {
@@ -201,6 +207,9 @@ struct nfp_flow_priv {
 	/* IPv4 off */
 	LIST_HEAD(, nfp_ipv4_addr_entry) ipv4_off_list; /**< Store ipv4 off */
 	rte_spinlock_t ipv4_off_lock; /**< Lock the ipv4 off list */
+	/* IPv6 off */
+	LIST_HEAD(, nfp_ipv6_addr_entry) ipv6_off_list; /**< Store ipv6 off */
+	rte_spinlock_t ipv6_off_lock; /**< Lock the ipv6 off list */
 	/* neighbor next */
 	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 09/25] net/nfp: support IPv4 VXLAN decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (7 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 08/25] net/nfp: prepare for IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 10/25] net/nfp: support IPv6 " Chaoyong He
                     ` (17 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv4 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 75 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index ff97787..6788520 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -56,4 +56,5 @@ set_mac_src          = Y
 set_tp_dst           = Y
 set_tp_src           = Y
 set_ttl              = Y
+vxlan_decap          = Y
 vxlan_encap          = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index ad484b9..ce61446 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -413,7 +413,7 @@ struct nfp_pre_tun_entry {
 	return 0;
 }
 
-__rte_unused static int
+static int
 nfp_tun_add_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
 {
@@ -908,6 +908,9 @@ struct nfp_pre_tun_entry {
 			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
 			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1315,7 +1318,7 @@ struct nfp_pre_tun_entry {
 }
 
 static int
-nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_vxlan(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1323,6 +1326,7 @@ struct nfp_pre_tun_entry {
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	const struct rte_vxlan_hdr *hdr;
 	struct nfp_flower_ipv4_udp_tun *tun4;
 	struct nfp_flower_ipv6_udp_tun *tun6;
@@ -1351,6 +1355,8 @@ struct nfp_pre_tun_entry {
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = hdr->vx_vni;
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 vxlan_end:
@@ -1360,7 +1366,7 @@ struct nfp_pre_tun_entry {
 	else
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 
-	return 0;
+	return ret;
 }
 
 /* Graph of supported items and associated process function */
@@ -2049,7 +2055,7 @@ struct nfp_pre_tun_entry {
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -2427,7 +2433,7 @@ struct nfp_pre_tun_entry {
 	return true;
 }
 
-__rte_unused static int
+static int
 nfp_pre_tun_table_check_add(struct nfp_flower_representor *repr,
 		uint16_t *index)
 {
@@ -2570,6 +2576,49 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
+		__rte_unused const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	uint16_t nfp_mac_idx = 0;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_app_fw_flower *app_fw_flower;
+
+	ret = nfp_pre_tun_table_check_add(repr, &nfp_mac_idx);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Pre tunnel table add failed");
+		return -EINVAL;
+	}
+
+	nfp_mac_idx = (nfp_mac_idx << 8) |
+			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
+			NFP_TUN_PRE_TUN_IDX_BIT;
+
+	app_fw_flower = repr->app_fw_flower;
+	ret = nfp_flower_cmsg_tun_mac_rule(app_fw_flower, &repr->mac_addr,
+			nfp_mac_idx, false);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send tunnel mac rule failed");
+		return -EINVAL;
+	}
+
+	ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
+			nfp_mac_idx, false);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+		return -EINVAL;
+	}
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
+		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
+	else
+		return -ENOTSUP;
+}
+
+static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
 		struct rte_flow *nfp_flow)
@@ -2744,6 +2793,17 @@ struct nfp_pre_tun_entry {
 			position += sizeof(struct nfp_fl_act_set_tun);
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			PMD_DRV_LOG(DEBUG, "process RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP");
+			ret = nfp_flow_action_tunnel_decap(representor, action,
+					nfp_flow_meta, nfp_flow);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process tunnel decap");
+				return ret;
+			}
+			nfp_flow->type = NFP_FLOW_DECAP;
+			nfp_flow->install_flag = false;
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
 			return -ENOTSUP;
@@ -3214,6 +3274,11 @@ struct nfp_pre_tun_entry {
 	}
 
 	switch (tunnel->type) {
+	case RTE_FLOW_ITEM_TYPE_VXLAN:
+		nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
+		*pmd_actions = nfp_action;
+		*num_of_actions = 1;
+		break;
 	default:
 		*pmd_actions = NULL;
 		*num_of_actions = 0;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 10/25] net/nfp: support IPv6 VXLAN decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (8 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 09/25] net/nfp: support IPv4 VXLAN " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 11/25] net/nfp: support IPv4 GENEVE encap " Chaoyong He
                     ` (16 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv6 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index ce61446..1abb02b 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -476,7 +476,7 @@ struct nfp_pre_tun_entry {
 	return 0;
 }
 
-__rte_unused static int
+static int
 nfp_tun_add_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
 		uint8_t ipv6[])
 {
@@ -1352,6 +1352,8 @@ struct nfp_pre_tun_entry {
 			NFP_FLOWER_LAYER2_TUN_IPV6)) {
 		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
 		tun6->tun_id = hdr->vx_vni;
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = hdr->vx_vni;
@@ -2163,7 +2165,7 @@ struct nfp_pre_tun_entry {
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -2577,7 +2579,7 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
-		__rte_unused const struct rte_flow_action *action,
+		const struct rte_flow_action *action,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
@@ -2595,6 +2597,8 @@ struct nfp_pre_tun_entry {
 	nfp_mac_idx = (nfp_mac_idx << 8) |
 			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
 			NFP_TUN_PRE_TUN_IDX_BIT;
+	if (action->conf != NULL)
+		nfp_mac_idx |= NFP_TUN_PRE_TUN_IPV6_BIT;
 
 	app_fw_flower = repr->app_fw_flower;
 	ret = nfp_flower_cmsg_tun_mac_rule(app_fw_flower, &repr->mac_addr,
@@ -2615,7 +2619,7 @@ struct nfp_pre_tun_entry {
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
 		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
 	else
-		return -ENOTSUP;
+		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow);
 }
 
 static int
@@ -2803,6 +2807,8 @@ struct nfp_pre_tun_entry {
 			}
 			nfp_flow->type = NFP_FLOW_DECAP;
 			nfp_flow->install_flag = false;
+			if (action->conf != NULL)
+				nfp_flow->tun.payload.v6_flag = 1;
 			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
@@ -3273,6 +3279,9 @@ struct nfp_pre_tun_entry {
 		return -ENOMEM;
 	}
 
+	if (tunnel->is_ipv6)
+		nfp_action->conf = (void *)~0;
+
 	switch (tunnel->type) {
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
 		nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
@@ -3300,6 +3309,7 @@ struct nfp_pre_tun_entry {
 
 	for (i = 0; i < num_of_actions; i++) {
 		nfp_action = &pmd_actions[i];
+		nfp_action->conf = NULL;
 		rte_free(nfp_action);
 	}
 
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 11/25] net/nfp: support IPv4 GENEVE encap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (9 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 10/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 12/25] net/nfp: support IPv6 " Chaoyong He
                     ` (15 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv4 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |   1 +
 drivers/net/nfp/nfp_flow.c       | 107 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 6788520..95c97c2 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -44,6 +44,7 @@ of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
 of_set_vlan_vid      = Y
+raw_encap            = Y
 port_id              = Y
 set_ipv4_dscp        = Y
 set_ipv4_dst         = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 1abb02b..faa313e 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -38,6 +38,12 @@ struct vxlan_data {
 		__VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
 	})
 
+/* Data length of various conf of raw encap action */
+#define GENEVE_V4_LEN    (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv4_hdr) + \
+				sizeof(struct rte_udp_hdr) + \
+				sizeof(struct rte_flow_item_geneve))
+
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
 	/* Bit-mask for fields supported by this PMD. */
@@ -908,6 +914,11 @@ struct nfp_pre_tun_entry {
 			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
 			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_ENCAP detected");
+			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
+			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
 			break;
@@ -2623,6 +2634,88 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_geneve_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint64_t tun_id;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_udp *udp;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_geneve *geneve;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv4   = (const struct rte_flow_item_ipv4 *)(eth + 1);
+	udp    = (const struct rte_flow_item_udp *)(ipv4 + 1);
+	geneve = (const struct rte_flow_item_geneve *)(udp + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tun_id = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GENEVE, tun_id,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_proto = geneve->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv4);
+}
+
+static int
+nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	int ret;
+	size_t act_len;
+	size_t act_pre_size;
+	const struct rte_flow_action_raw_encap *raw_encap;
+
+	raw_encap = action->conf;
+	if (raw_encap->data == NULL) {
+		PMD_DRV_LOG(ERR, "The raw encap action conf is NULL.");
+		return -EINVAL;
+	}
+
+	/* Pre_tunnel action must be the first on action list.
+	 * If other actions already exist, they need to be
+	 * pushed forward.
+	 */
+	act_len = act_data - actions;
+	if (act_len != 0) {
+		act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+		memmove(actions + act_pre_size, actions, act_len);
+	}
+
+	switch (raw_encap->size) {
+	case GENEVE_V4_LEN:
+		ret = nfp_flow_action_geneve_encap_v4(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
 		struct rte_flow *nfp_flow)
@@ -2797,6 +2890,20 @@ struct nfp_pre_tun_entry {
 			position += sizeof(struct nfp_fl_act_set_tun);
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_RAW_ENCAP");
+			ret = nfp_flow_action_raw_encap(representor->app_fw_flower,
+					position, action_data, action, nfp_flow_meta,
+					&nfp_flow->tun);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process"
+						" RTE_FLOW_ACTION_TYPE_RAW_ENCAP");
+				return ret;
+			}
+			position += sizeof(struct nfp_fl_act_pre_tun);
+			position += sizeof(struct nfp_fl_act_set_tun);
+			nfp_flow->type = NFP_FLOW_ENCAP;
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "process RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP");
 			ret = nfp_flow_action_tunnel_decap(representor, action,
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 12/25] net/nfp: support IPv6 GENEVE encap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (10 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 11/25] net/nfp: support IPv4 GENEVE encap " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 13/25] net/nfp: support IPv4 GENEVE flow item Chaoyong He
                     ` (14 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv6 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index faa313e..ef19231 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -43,6 +43,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv4_hdr) + \
 				sizeof(struct rte_udp_hdr) + \
 				sizeof(struct rte_flow_item_geneve))
+#define GENEVE_V6_LEN    (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv6_hdr) + \
+				sizeof(struct rte_udp_hdr) + \
+				sizeof(struct rte_flow_item_geneve))
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2673,6 +2677,47 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_geneve_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint8_t tos;
+	uint64_t tun_id;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_udp *udp;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_geneve *geneve;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv6   = (const struct rte_flow_item_ipv6 *)(eth + 1);
+	udp    = (const struct rte_flow_item_udp *)(ipv6 + 1);
+	geneve = (const struct rte_flow_item_geneve *)(udp + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tos = (ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff;
+	tun_id = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GENEVE, tun_id,
+			ipv6->hdr.hop_limits, tos);
+	set_tun->tun_proto = geneve->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv6);
+}
+
+static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
 		char *actions,
@@ -2706,6 +2751,10 @@ struct nfp_pre_tun_entry {
 		ret = nfp_flow_action_geneve_encap_v4(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case GENEVE_V6_LEN:
+		ret = nfp_flow_action_geneve_encap_v6(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 13/25] net/nfp: support IPv4 GENEVE flow item
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (11 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 12/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 14/25] net/nfp: support IPv6 " Chaoyong He
                     ` (13 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv4 GENEVE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 75 ++++++++++++++++++++++++++++++++++++++--
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 95c97c2..14fb6e0 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -28,6 +28,7 @@ Usage doc            = Y
 
 [rte_flow items]
 eth                  = Y
+geneve               = Y
 ipv4                 = Y
 ipv6                 = Y
 port_id              = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index ef19231..a6adfa5 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -769,6 +769,23 @@ struct nfp_pre_tun_entry {
 				return -EINVAL;
 			}
 			break;
+		case RTE_FLOW_ITEM_TYPE_GENEVE:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GENEVE detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_GENEVE;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;
+			key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -960,12 +977,22 @@ struct nfp_pre_tun_entry {
 static bool
 nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
 {
+	uint32_t key_layer2;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_meta_tci *meta_tci;
 
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_VXLAN)
 		return true;
 
+	if (!(meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META))
+		return false;
+
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
+	key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
+	if (key_layer2 & NFP_FLOWER_LAYER2_GENEVE)
+		return true;
+
 	return false;
 }
 
@@ -1386,6 +1413,39 @@ struct nfp_pre_tun_entry {
 	return ret;
 }
 
+static int
+nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	struct nfp_flower_ipv4_udp_tun *tun4;
+	const struct rte_flow_item_geneve *spec;
+	const struct rte_flow_item_geneve *mask;
+	const struct rte_flow_item_geneve *geneve;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge geneve: no item->spec!");
+		goto geneve_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	geneve = is_mask ? mask : spec;
+
+	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+	tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+			(geneve->vni[1] << 8) | (geneve->vni[2]));
+
+geneve_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+
+	return 0;
+}
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
@@ -1474,7 +1534,8 @@ struct nfp_pre_tun_entry {
 		.merge = nfp_flow_merge_tcp,
 	},
 	[RTE_FLOW_ITEM_TYPE_UDP] = {
-		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN),
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN,
+			RTE_FLOW_ITEM_TYPE_GENEVE),
 		.mask_support = &(const struct rte_flow_item_udp){
 			.hdr = {
 				.src_port = RTE_BE16(0xffff),
@@ -1507,6 +1568,15 @@ struct nfp_pre_tun_entry {
 		.mask_sz = sizeof(struct rte_flow_item_vxlan),
 		.merge = nfp_flow_merge_vxlan,
 	},
+	[RTE_FLOW_ITEM_TYPE_GENEVE] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &(const struct rte_flow_item_geneve){
+			.vni = "\xff\xff\xff",
+		},
+		.mask_default = &rte_flow_item_geneve_mask,
+		.mask_sz = sizeof(struct rte_flow_item_geneve),
+		.merge = nfp_flow_merge_geneve,
+	},
 };
 
 static int
@@ -1563,7 +1633,8 @@ struct nfp_pre_tun_entry {
 static bool
 nfp_flow_is_tun_item(const struct rte_flow_item *item)
 {
-	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN)
+	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
+			item->type == RTE_FLOW_ITEM_TYPE_GENEVE)
 		return true;
 
 	return false;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 14/25] net/nfp: support IPv6 GENEVE flow item
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (12 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 13/25] net/nfp: support IPv4 GENEVE flow item Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 15/25] net/nfp: support IPv4 GENEVE decap flow action Chaoyong He
                     ` (12 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv6 GENEVE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 43 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index a6adfa5..48a47a6 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -771,8 +771,9 @@ struct nfp_pre_tun_entry {
 			break;
 		case RTE_FLOW_ITEM_TYPE_GENEVE:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GENEVE detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_GENEVE;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
 			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;
@@ -784,6 +785,17 @@ struct nfp_pre_tun_entry {
 				 * in `struct nfp_flower_ipv4_udp_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for GENEVE tunnel.");
+				return -EINVAL;
 			}
 			break;
 		default:
@@ -1415,7 +1427,7 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1423,9 +1435,16 @@ struct nfp_pre_tun_entry {
 		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_ipv4_udp_tun *tun4;
+	struct nfp_flower_ipv6_udp_tun *tun6;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_geneve *spec;
 	const struct rte_flow_item_geneve *mask;
 	const struct rte_flow_item_geneve *geneve;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1436,12 +1455,24 @@ struct nfp_pre_tun_entry {
 	mask = item->mask ? item->mask : proc->mask_default;
 	geneve = is_mask ? mask : spec;
 
-	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
-	tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
-			(geneve->vni[1] << 8) | (geneve->vni[2]));
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+		tun6->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+				(geneve->vni[1] << 8) | (geneve->vni[2]));
+	} else {
+		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+				(geneve->vni[1] << 8) | (geneve->vni[2]));
+	}
 
 geneve_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_udp_tun);
+	} else {
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	}
 
 	return 0;
 }
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 15/25] net/nfp: support IPv4 GENEVE decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (13 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 14/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 16/25] net/nfp: support IPv6 " Chaoyong He
                     ` (11 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv4 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 14fb6e0..c017be1 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -45,6 +45,7 @@ of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
 of_set_vlan_vid      = Y
+raw_decap            = Y
 raw_encap            = Y
 port_id              = Y
 set_ipv4_dscp        = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 48a47a6..223f2e7 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -955,6 +955,9 @@ struct nfp_pre_tun_entry {
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_DECAP detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1426,7 +1429,7 @@ struct nfp_pre_tun_entry {
 }
 
 static int
-nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_geneve(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1434,6 +1437,7 @@ struct nfp_pre_tun_entry {
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	struct nfp_flower_ipv4_udp_tun *tun4;
 	struct nfp_flower_ipv6_udp_tun *tun6;
 	struct nfp_flower_meta_tci *meta_tci;
@@ -1464,6 +1468,8 @@ struct nfp_pre_tun_entry {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
 				(geneve->vni[1] << 8) | (geneve->vni[2]));
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 geneve_end:
@@ -1474,7 +1480,7 @@ struct nfp_pre_tun_entry {
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 	}
 
-	return 0;
+	return ret;
 }
 
 /* Graph of supported items and associated process function */
@@ -3056,6 +3062,7 @@ struct nfp_pre_tun_entry {
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
 			PMD_DRV_LOG(DEBUG, "process RTE_FLOW_ACTION_TYPE_TUNNEL_DECAP");
 			ret = nfp_flow_action_tunnel_decap(representor, action,
 					nfp_flow_meta, nfp_flow);
@@ -3546,6 +3553,11 @@ struct nfp_pre_tun_entry {
 		*pmd_actions = nfp_action;
 		*num_of_actions = 1;
 		break;
+	case RTE_FLOW_ITEM_TYPE_GENEVE:
+		nfp_action->type = RTE_FLOW_ACTION_TYPE_RAW_DECAP;
+		*pmd_actions = nfp_action;
+		*num_of_actions = 1;
+		break;
 	default:
 		*pmd_actions = NULL;
 		*num_of_actions = 0;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 16/25] net/nfp: support IPv6 GENEVE decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (14 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 15/25] net/nfp: support IPv4 GENEVE decap flow action Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 17/25] net/nfp: support IPv4 NVGRE encap " Chaoyong He
                     ` (10 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv6 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 223f2e7..c7daa14 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1464,6 +1464,8 @@ struct nfp_pre_tun_entry {
 		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
 		tun6->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
 				(geneve->vni[1] << 8) | (geneve->vni[2]));
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 17/25] net/nfp: support IPv4 NVGRE encap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (15 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 16/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 18/25] net/nfp: support IPv6 " Chaoyong He
                     ` (9 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action of IPv4 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 43 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index c017be1..f6b658b 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -41,6 +41,7 @@ vxlan                = Y
 [rte_flow actions]
 count                = Y
 drop                 = Y
+nvgre_encap          = Y
 of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index c7daa14..00b4c6d 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -47,6 +47,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv6_hdr) + \
 				sizeof(struct rte_udp_hdr) + \
 				sizeof(struct rte_flow_item_geneve))
+#define NVGRE_V4_LEN     (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv4_hdr) + \
+				sizeof(struct rte_flow_item_gre) + \
+				sizeof(rte_be32_t))    /* gre key */
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2828,6 +2832,41 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_nvgre_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_gre *gre;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth  = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv4 = (const struct rte_flow_item_ipv4 *)(eth + 1);
+	gre  = (const struct rte_flow_item_gre *)(ipv4 + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GRE, 0,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_proto = gre->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv4);
+}
+
+static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
 		char *actions,
@@ -2865,6 +2904,10 @@ struct nfp_pre_tun_entry {
 		ret = nfp_flow_action_geneve_encap_v6(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case NVGRE_V4_LEN:
+		ret = nfp_flow_action_nvgre_encap_v4(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 18/25] net/nfp: support IPv6 NVGRE encap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (16 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 17/25] net/nfp: support IPv4 NVGRE encap " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 19/25] net/nfp: prepare for IPv4 GRE tunnel decap " Chaoyong He
                     ` (8 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action of IPv6 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 00b4c6d..fd64da8 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -51,6 +51,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv4_hdr) + \
 				sizeof(struct rte_flow_item_gre) + \
 				sizeof(rte_be32_t))    /* gre key */
+#define NVGRE_V6_LEN     (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv6_hdr) + \
+				sizeof(struct rte_flow_item_gre) + \
+				sizeof(rte_be32_t))    /* gre key */
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2867,6 +2871,43 @@ struct nfp_pre_tun_entry {
 }
 
 static int
+nfp_flow_action_nvgre_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint8_t tos;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_gre *gre;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv6   = (const struct rte_flow_item_ipv6 *)(eth + 1);
+	gre    = (const struct rte_flow_item_gre *)(ipv6 + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tos = (ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff;
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GRE, 0,
+			ipv6->hdr.hop_limits, tos);
+	set_tun->tun_proto = gre->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv6);
+}
+
+static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
 		char *actions,
@@ -2908,6 +2949,10 @@ struct nfp_pre_tun_entry {
 		ret = nfp_flow_action_nvgre_encap_v4(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case NVGRE_V6_LEN:
+		ret = nfp_flow_action_nvgre_encap_v6(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 19/25] net/nfp: prepare for IPv4 GRE tunnel decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (17 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 18/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 20/25] net/nfp: prepare for IPv6 " Chaoyong He
                     ` (7 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and logics, prepare for
the decap action of IPv4 GRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 29 +++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 40 +++++++++++++++++++++++++-------
 drivers/net/nfp/nfp_flow.h               |  3 +++
 3 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 61f2f83..8bca7c2 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -575,6 +575,35 @@ struct nfp_flower_ipv6_udp_tun {
 	rte_be32_t tun_id;
 };
 
+/*
+ * Flow Frame GRE TUNNEL --> Tunnel details (6W/24B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_src                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_dst                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           tun_flags           |       tos     |       ttl     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |            Reserved           |           Ethertype           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                              Key                              |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                           Reserved                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv4_gre_tun {
+	struct nfp_flower_tun_ipv4 ipv4;
+	rte_be16_t tun_flags;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be16_t reserved1;
+	rte_be16_t ethertype;
+	rte_be32_t tun_key;
+	rte_be32_t reserved2;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index fd64da8..01c6e9a 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -564,6 +564,7 @@ struct nfp_pre_tun_entry {
 	uint32_t key_layer2 = 0;
 	struct nfp_flower_ipv4_udp_tun *udp4;
 	struct nfp_flower_ipv6_udp_tun *udp6;
+	struct nfp_flower_ipv4_gre_tun *gre4;
 	struct nfp_flower_meta_tci *meta_tci;
 	struct nfp_flower_ext_meta *ext_meta = NULL;
 
@@ -579,9 +580,15 @@ struct nfp_pre_tun_entry {
 				sizeof(struct nfp_flower_ipv6_udp_tun));
 		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
 	} else {
-		udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
-				sizeof(struct nfp_flower_ipv4_udp_tun));
-		ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
+			gre4 = (struct nfp_flower_ipv4_gre_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv4_gre_tun));
+			ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, gre4->ipv4.dst);
+		} else {
+			udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv4_udp_tun));
+			ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+		}
 	}
 
 	return ret;
@@ -1013,7 +1020,7 @@ struct nfp_pre_tun_entry {
 
 	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 	key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
-	if (key_layer2 & NFP_FLOWER_LAYER2_GENEVE)
+	if (key_layer2 & (NFP_FLOWER_LAYER2_GENEVE | NFP_FLOWER_LAYER2_GRE))
 		return true;
 
 	return false;
@@ -1102,11 +1109,15 @@ struct nfp_pre_tun_entry {
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv4 *spec;
 	const struct rte_flow_item_ipv4 *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 	struct nfp_flower_ipv4_udp_tun *ipv4_udp_tun;
+	struct nfp_flower_ipv4_gre_tun *ipv4_gre_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
 		if (spec == NULL) {
@@ -1115,12 +1126,23 @@ struct nfp_pre_tun_entry {
 		}
 
 		hdr = is_mask ? &mask->hdr : &spec->hdr;
-		ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 
-		ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
-		ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
-		ipv4_udp_tun->ipv4.src   = hdr->src_addr;
-		ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+		if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+				NFP_FLOWER_LAYER2_GRE)) {
+			ipv4_gre_tun = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+
+			ipv4_gre_tun->ip_ext.tos = hdr->type_of_service;
+			ipv4_gre_tun->ip_ext.ttl = hdr->time_to_live;
+			ipv4_gre_tun->ipv4.src   = hdr->src_addr;
+			ipv4_gre_tun->ipv4.dst   = hdr->dst_addr;
+		} else {
+			ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+
+			ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
+			ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
+			ipv4_udp_tun->ipv4.src   = hdr->src_addr;
+			ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+		}
 	} else {
 		if (spec == NULL) {
 			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index a6994e0..b0c2aaf 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -49,6 +49,9 @@
 #define NFP_FL_SC_ACT_POPV      0x6A000000
 #define NFP_FL_SC_ACT_NULL      0x00000000
 
+/* GRE Tunnel flags */
+#define NFP_FL_GRE_FLAG_KEY         (1 << 2)
+
 /* Action opcodes */
 #define NFP_FL_ACTION_OPCODE_OUTPUT             0
 #define NFP_FL_ACTION_OPCODE_PUSH_VLAN          1
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 20/25] net/nfp: prepare for IPv6 GRE tunnel decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (18 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 19/25] net/nfp: prepare for IPv4 GRE tunnel decap " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 21/25] net/nfp: support IPv4 NVGRE flow item Chaoyong He
                     ` (6 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and logics, prepare for
the decap action of IPv6 GRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 41 ++++++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 49 ++++++++++++++++++++++++--------
 2 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 8bca7c2..a48da67 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -604,6 +604,47 @@ struct nfp_flower_ipv4_gre_tun {
 	rte_be32_t reserved2;
 };
 
+/*
+ * Flow Frame GRE TUNNEL V6 --> Tunnel details (12W/48B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           tun_flags           |       tos     |       ttl     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |            Reserved           |           Ethertype           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                              Key                              |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                           Reserved                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv6_gre_tun {
+	struct nfp_flower_tun_ipv6 ipv6;
+	rte_be16_t tun_flags;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be16_t reserved1;
+	rte_be16_t ethertype;
+	rte_be32_t tun_key;
+	rte_be32_t reserved2;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 01c6e9a..26d3854 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -565,6 +565,7 @@ struct nfp_pre_tun_entry {
 	struct nfp_flower_ipv4_udp_tun *udp4;
 	struct nfp_flower_ipv6_udp_tun *udp6;
 	struct nfp_flower_ipv4_gre_tun *gre4;
+	struct nfp_flower_ipv6_gre_tun *gre6;
 	struct nfp_flower_meta_tci *meta_tci;
 	struct nfp_flower_ext_meta *ext_meta = NULL;
 
@@ -576,9 +577,15 @@ struct nfp_pre_tun_entry {
 		key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
 
 	if (key_layer2 & NFP_FLOWER_LAYER2_TUN_IPV6) {
-		udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
-				sizeof(struct nfp_flower_ipv6_udp_tun));
-		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
+			gre6 = (struct nfp_flower_ipv6_gre_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv6_gre_tun));
+			ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, gre6->ipv6.ipv6_dst);
+		} else {
+			udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv6_udp_tun));
+			ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+		}
 	} else {
 		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
 			gre4 = (struct nfp_flower_ipv4_gre_tun *)(nfp_flow->payload.mask_data -
@@ -1186,11 +1193,15 @@ struct nfp_pre_tun_entry {
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv6 *spec;
 	const struct rte_flow_item_ipv6 *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 	struct nfp_flower_ipv6_udp_tun *ipv6_udp_tun;
+	struct nfp_flower_ipv6_gre_tun *ipv6_gre_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
 		if (spec == NULL) {
@@ -1199,15 +1210,29 @@ struct nfp_pre_tun_entry {
 		}
 
 		hdr = is_mask ? &mask->hdr : &spec->hdr;
-		ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
-
-		ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
-				RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
-		ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
-		memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
-				sizeof(ipv6_udp_tun->ipv6.ipv6_src));
-		memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
-				sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+
+		if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+				NFP_FLOWER_LAYER2_GRE)) {
+			ipv6_gre_tun = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+
+			ipv6_gre_tun->ip_ext.tos = (hdr->vtc_flow &
+					RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+			ipv6_gre_tun->ip_ext.ttl = hdr->hop_limits;
+			memcpy(ipv6_gre_tun->ipv6.ipv6_src, hdr->src_addr,
+					sizeof(ipv6_gre_tun->ipv6.ipv6_src));
+			memcpy(ipv6_gre_tun->ipv6.ipv6_dst, hdr->dst_addr,
+					sizeof(ipv6_gre_tun->ipv6.ipv6_dst));
+		} else {
+			ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+
+			ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
+					RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+			ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
+			memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
+					sizeof(ipv6_udp_tun->ipv6.ipv6_src));
+			memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
+					sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+		}
 	} else {
 		if (spec == NULL) {
 			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 21/25] net/nfp: support IPv4 NVGRE flow item
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (19 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 20/25] net/nfp: prepare for IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 22/25] net/nfp: support IPv6 " Chaoyong He
                     ` (5 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv4 NVGRE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  2 +
 drivers/net/nfp/nfp_flow.c       | 99 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index f6b658b..2acc809 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -29,6 +29,8 @@ Usage doc            = Y
 [rte_flow items]
 eth                  = Y
 geneve               = Y
+gre                  = Y
+gre_key              = Y
 ipv4                 = Y
 ipv6                 = Y
 port_id              = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 26d3854..0a43bf3 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -820,6 +820,26 @@ struct nfp_pre_tun_entry {
 				return -EINVAL;
 			}
 			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_GRE;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GRE;
+			key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_gre_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_gre_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE_KEY detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -1540,6 +1560,62 @@ struct nfp_pre_tun_entry {
 	return ret;
 }
 
+static int
+nfp_flow_merge_gre(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		__rte_unused const struct rte_flow_item *item,
+		__rte_unused const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	struct nfp_flower_ipv4_gre_tun *tun4;
+
+	/* NVGRE is the only supported GRE tunnel type */
+	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+	if (is_mask)
+		tun4->ethertype = rte_cpu_to_be_16(~0);
+	else
+		tun4->ethertype = rte_cpu_to_be_16(0x6558);
+
+	return 0;
+}
+
+static int
+nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		__rte_unused const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	rte_be32_t tun_key;
+	const rte_be32_t *spec;
+	const rte_be32_t *mask;
+	struct nfp_flower_ipv4_gre_tun *tun4;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge gre key: no item->spec!");
+		goto gre_key_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	tun_key = is_mask ? *mask : *spec;
+
+	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+	tun4->tun_key = tun_key;
+	tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+
+gre_key_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
+
+	return 0;
+}
+
+const rte_be32_t nfp_flow_item_gre_key = 0xffffffff;
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
@@ -1580,7 +1656,8 @@ struct nfp_pre_tun_entry {
 	[RTE_FLOW_ITEM_TYPE_IPV4] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_TCP,
 			RTE_FLOW_ITEM_TYPE_UDP,
-			RTE_FLOW_ITEM_TYPE_SCTP),
+			RTE_FLOW_ITEM_TYPE_SCTP,
+			RTE_FLOW_ITEM_TYPE_GRE),
 		.mask_support = &(const struct rte_flow_item_ipv4){
 			.hdr = {
 				.type_of_service = 0xff,
@@ -1671,6 +1748,23 @@ struct nfp_pre_tun_entry {
 		.mask_sz = sizeof(struct rte_flow_item_geneve),
 		.merge = nfp_flow_merge_geneve,
 	},
+	[RTE_FLOW_ITEM_TYPE_GRE] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_GRE_KEY),
+		.mask_support = &(const struct rte_flow_item_gre){
+			.c_rsvd0_ver = RTE_BE16(0xa000),
+			.protocol = RTE_BE16(0xffff),
+		},
+		.mask_default = &rte_flow_item_gre_mask,
+		.mask_sz = sizeof(struct rte_flow_item_gre),
+		.merge = nfp_flow_merge_gre,
+	},
+	[RTE_FLOW_ITEM_TYPE_GRE_KEY] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &nfp_flow_item_gre_key,
+		.mask_default = &nfp_flow_item_gre_key,
+		.mask_sz = sizeof(rte_be32_t),
+		.merge = nfp_flow_merge_gre_key,
+	},
 };
 
 static int
@@ -1728,7 +1822,8 @@ struct nfp_pre_tun_entry {
 nfp_flow_is_tun_item(const struct rte_flow_item *item)
 {
 	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
-			item->type == RTE_FLOW_ITEM_TYPE_GENEVE)
+			item->type == RTE_FLOW_ITEM_TYPE_GENEVE ||
+			item->type == RTE_FLOW_ITEM_TYPE_GRE_KEY)
 		return true;
 
 	return false;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 22/25] net/nfp: support IPv6 NVGRE flow item
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (20 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 21/25] net/nfp: support IPv4 NVGRE flow item Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 23/25] net/nfp: support IPv4 NVGRE decap flow action Chaoyong He
                     ` (4 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv6 NVGRE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 73 +++++++++++++++++++++++++++++++++++++---------
 1 file changed, 59 insertions(+), 14 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 0a43bf3..6f21c86 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -822,8 +822,9 @@ struct nfp_pre_tun_entry {
 			break;
 		case RTE_FLOW_ITEM_TYPE_GRE:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_GRE;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
 			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GRE;
@@ -835,6 +836,17 @@ struct nfp_pre_tun_entry {
 				 * in `struct nfp_flower_ipv4_gre_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_gre_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_gre_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for GRE tunnel.");
+				return -1;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
@@ -1562,38 +1574,59 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flow_merge_gre(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		__rte_unused const struct rte_flow_item *item,
 		__rte_unused const struct nfp_flow_item_proc *proc,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_ipv4_gre_tun *tun4;
+	struct nfp_flower_ipv6_gre_tun *tun6;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	/* NVGRE is the only supported GRE tunnel type */
-	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
-	if (is_mask)
-		tun4->ethertype = rte_cpu_to_be_16(~0);
-	else
-		tun4->ethertype = rte_cpu_to_be_16(0x6558);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6) {
+		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+		if (is_mask)
+			tun6->ethertype = rte_cpu_to_be_16(~0);
+		else
+			tun6->ethertype = rte_cpu_to_be_16(0x6558);
+	} else {
+		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+		if (is_mask)
+			tun4->ethertype = rte_cpu_to_be_16(~0);
+		else
+			tun4->ethertype = rte_cpu_to_be_16(0x6558);
+	}
 
 	return 0;
 }
 
 static int
 nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
-		__rte_unused const struct nfp_flow_item_proc *proc,
+		const struct nfp_flow_item_proc *proc,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
 	rte_be32_t tun_key;
 	const rte_be32_t *spec;
 	const rte_be32_t *mask;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_ipv4_gre_tun *tun4;
+	struct nfp_flower_ipv6_gre_tun *tun6;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1604,12 +1637,23 @@ struct nfp_pre_tun_entry {
 	mask = item->mask ? item->mask : proc->mask_default;
 	tun_key = is_mask ? *mask : *spec;
 
-	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
-	tun4->tun_key = tun_key;
-	tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6) {
+		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+		tun6->tun_key = tun_key;
+		tun6->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	} else {
+		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+		tun4->tun_key = tun_key;
+		tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	}
 
 gre_key_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_gre_tun);
+	else
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
 
 	return 0;
 }
@@ -1675,7 +1719,8 @@ struct nfp_pre_tun_entry {
 	[RTE_FLOW_ITEM_TYPE_IPV6] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_TCP,
 			RTE_FLOW_ITEM_TYPE_UDP,
-			RTE_FLOW_ITEM_TYPE_SCTP),
+			RTE_FLOW_ITEM_TYPE_SCTP,
+			RTE_FLOW_ITEM_TYPE_GRE),
 		.mask_support = &(const struct rte_flow_item_ipv6){
 			.hdr = {
 				.vtc_flow   = RTE_BE32(0x0ff00000),
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 23/25] net/nfp: support IPv4 NVGRE decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (21 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 22/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 24/25] net/nfp: support IPv6 " Chaoyong He
                     ` (3 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action of IPv4 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini | 1 +
 drivers/net/nfp/nfp_flow.c       | 8 ++++++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 2acc809..6400a7c 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -43,6 +43,7 @@ vxlan                = Y
 [rte_flow actions]
 count                = Y
 drop                 = Y
+nvgre_decap          = Y
 nvgre_encap          = Y
 of_pop_vlan          = Y
 of_push_vlan         = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 6f21c86..c577278 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1609,7 +1609,7 @@ struct nfp_pre_tun_entry {
 }
 
 static int
-nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_gre_key(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1617,6 +1617,7 @@ struct nfp_pre_tun_entry {
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	rte_be32_t tun_key;
 	const rte_be32_t *spec;
 	const rte_be32_t *mask;
@@ -1646,6 +1647,8 @@ struct nfp_pre_tun_entry {
 		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
 		tun4->tun_key = tun_key;
 		tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 gre_key_end:
@@ -1655,7 +1658,7 @@ struct nfp_pre_tun_entry {
 	else
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
 
-	return 0;
+	return ret;
 }
 
 const rte_be32_t nfp_flow_item_gre_key = 0xffffffff;
@@ -3831,6 +3834,7 @@ struct nfp_pre_tun_entry {
 		*num_of_actions = 1;
 		break;
 	case RTE_FLOW_ITEM_TYPE_GENEVE:
+	case RTE_FLOW_ITEM_TYPE_GRE:
 		nfp_action->type = RTE_FLOW_ACTION_TYPE_RAW_DECAP;
 		*pmd_actions = nfp_action;
 		*num_of_actions = 1;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 24/25] net/nfp: support IPv6 NVGRE decap flow action
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (22 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 23/25] net/nfp: support IPv4 NVGRE decap flow action Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-22  8:24   ` [PATCH v2 25/25] net/nfp: support new tunnel solution Chaoyong He
                     ` (2 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action of IPv6 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index c577278..4c6cfe4 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1643,6 +1643,8 @@ struct nfp_pre_tun_entry {
 		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
 		tun6->tun_key = tun_key;
 		tun6->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
 		tun4->tun_key = tun_key;
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v2 25/25] net/nfp: support new tunnel solution
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (23 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 24/25] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-22  8:24   ` Chaoyong He
  2022-10-24 15:09     ` Ferruh Yigit
  2022-10-24 15:07   ` [PATCH v2 00/25] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
  26 siblings, 1 reply; 88+ messages in thread
From: Chaoyong He @ 2022-10-22  8:24 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

The new version of flower firmware application add the support of
a new tunnel solution.

It changes the structure of tunnel neighbor, and use a feature flag
to indicate which tunnel solution is used.

Add the logic of read extra features from firmware, and store it in
the app private structure.

Adjust the data structure and related logic to make the PMD support
both version of tunnel solutions.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower.c      |  14 ++++
 drivers/net/nfp/flower/nfp_flower.h      |  24 +++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.c |   4 ++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  17 +++++
 drivers/net/nfp/nfp_flow.c               | 118 +++++++++++++++++++++++++------
 5 files changed, 157 insertions(+), 20 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c
index 41b0fe2..aa8199d 100644
--- a/drivers/net/nfp/flower/nfp_flower.c
+++ b/drivers/net/nfp/flower/nfp_flower.c
@@ -1074,6 +1074,8 @@
 nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
 {
 	int ret;
+	int err;
+	uint64_t ext_features;
 	unsigned int numa_node;
 	struct nfp_net_hw *pf_hw;
 	struct nfp_net_hw *ctrl_hw;
@@ -1115,6 +1117,18 @@
 		goto vnic_cleanup;
 	}
 
+	/* Read the extra features */
+	ext_features = nfp_rtsym_read_le(pf_dev->sym_tbl, "_abi_flower_extra_features",
+			&err);
+	if (err != 0) {
+		PMD_INIT_LOG(ERR, "Couldn't read extra features from fw");
+		ret = -EIO;
+		goto pf_cpp_area_cleanup;
+	}
+
+	/* Store the extra features */
+	app_fw_flower->ext_features = ext_features;
+
 	/* Fill in the PF vNIC and populate app struct */
 	app_fw_flower->pf_hw = pf_hw;
 	pf_hw->ctrl_bar = pf_dev->ctrl_bar;
diff --git a/drivers/net/nfp/flower/nfp_flower.h b/drivers/net/nfp/flower/nfp_flower.h
index 12a0fb5..ab8876d 100644
--- a/drivers/net/nfp/flower/nfp_flower.h
+++ b/drivers/net/nfp/flower/nfp_flower.h
@@ -6,6 +6,21 @@
 #ifndef _NFP_FLOWER_H_
 #define _NFP_FLOWER_H_
 
+/* Extra features bitmap. */
+#define NFP_FL_FEATS_GENEVE             RTE_BIT64(0)
+#define NFP_FL_NBI_MTU_SETTING          RTE_BIT64(1)
+#define NFP_FL_FEATS_GENEVE_OPT         RTE_BIT64(2)
+#define NFP_FL_FEATS_VLAN_PCP           RTE_BIT64(3)
+#define NFP_FL_FEATS_VF_RLIM            RTE_BIT64(4)
+#define NFP_FL_FEATS_FLOW_MOD           RTE_BIT64(5)
+#define NFP_FL_FEATS_PRE_TUN_RULES      RTE_BIT64(6)
+#define NFP_FL_FEATS_IPV6_TUN           RTE_BIT64(7)
+#define NFP_FL_FEATS_VLAN_QINQ          RTE_BIT64(8)
+#define NFP_FL_FEATS_QOS_PPS            RTE_BIT64(9)
+#define NFP_FL_FEATS_QOS_METER          RTE_BIT64(10)
+#define NFP_FL_FEATS_DECAP_V2           RTE_BIT64(11)
+#define NFP_FL_FEATS_HOST_ACK           RTE_BIT64(31)
+
 /*
  * Flower fallback and ctrl path always adds and removes
  * 8 bytes of prepended data. Tx descriptors must point
@@ -55,9 +70,18 @@ struct nfp_app_fw_flower {
 	/* service id of ctrl vnic service */
 	uint32_t ctrl_vnic_id;
 
+	/* Flower extra features */
+	uint64_t ext_features;
+
 	struct nfp_flow_priv *flow_priv;
 };
 
+static inline bool
+nfp_flower_support_decap_v2(const struct nfp_app_fw_flower *app_fw_flower)
+{
+	return app_fw_flower->ext_features & NFP_FL_FEATS_DECAP_V2;
+}
+
 int nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev);
 int nfp_secondary_init_app_fw_flower(struct nfp_cpp *cpp);
 uint16_t nfp_flower_pf_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 76815cf..babdd8e 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -263,6 +263,8 @@
 	}
 
 	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v4);
+	if (!nfp_flower_support_decap_v2(app_fw_flower))
+		msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
 	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, msg_len);
 	memcpy(msg, payload, msg_len);
 
@@ -292,6 +294,8 @@
 	}
 
 	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v6);
+	if (!nfp_flower_support_decap_v2(app_fw_flower))
+		msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
 	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6, msg_len);
 	memcpy(msg, payload, msg_len);
 
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index a48da67..04601cb 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -136,6 +136,21 @@ struct nfp_flower_tun_neigh {
 };
 
 /*
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |         VLAN_TPID             |            VLAN_ID            |
+ *          +---------------------------------------------------------------+
+ *        1 |                           HOST_CTX                            |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_tun_neigh_ext {
+	rte_be16_t vlan_tpid;
+	rte_be16_t vlan_tci;
+	rte_be32_t host_ctx;
+};
+
+/*
  * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V4
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
  *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
@@ -157,6 +172,7 @@ struct nfp_flower_cmsg_tun_neigh_v4 {
 	rte_be32_t dst_ipv4;
 	rte_be32_t src_ipv4;
 	struct nfp_flower_tun_neigh common;
+	struct nfp_flower_tun_neigh_ext ext;
 };
 
 /*
@@ -193,6 +209,7 @@ struct nfp_flower_cmsg_tun_neigh_v6 {
 	uint8_t dst_ipv6[16];
 	uint8_t src_ipv6[16];
 	struct nfp_flower_tun_neigh common;
+	struct nfp_flower_tun_neigh_ext ext;
 };
 
 #define NFP_TUN_PRE_TUN_RULE_DEL    (1 << 0)
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 4c6cfe4..01494e7 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -2384,8 +2384,10 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
+	bool exists = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
 	struct nfp_flow_priv *priv;
@@ -2419,11 +2421,17 @@ struct nfp_pre_tun_entry {
 	LIST_FOREACH(tmp, &priv->nn_list, next) {
 		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
 			tmp->ref_cnt++;
-			return 0;
+			exists = true;
+			break;
 		}
 	}
 
-	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	if (exists) {
+		if (!nfp_flower_support_decap_v2(app_fw_flower))
+			return 0;
+	} else {
+		LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	}
 
 	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
 	payload.dst_ipv4 = ipv4->ipv4_src;
@@ -2432,6 +2440,17 @@ struct nfp_pre_tun_entry {
 	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
 	payload.common.port_id = port->in_port;
 
+	if (nfp_flower_support_decap_v2(app_fw_flower)) {
+		if (meta_tci->tci != 0) {
+			payload.ext.vlan_tci = meta_tci->tci;
+			payload.ext.vlan_tpid = 0x88a8;
+		} else {
+			payload.ext.vlan_tci = 0xffff;
+			payload.ext.vlan_tpid = 0xffff;
+		}
+		payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
+	}
+
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
@@ -2492,8 +2511,10 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
+	bool exists = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
 	struct nfp_flow_priv *priv;
@@ -2527,11 +2548,17 @@ struct nfp_pre_tun_entry {
 	LIST_FOREACH(tmp, &priv->nn_list, next) {
 		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
 			tmp->ref_cnt++;
-			return 0;
+			exists = true;
+			break;
 		}
 	}
 
-	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	if (exists) {
+		if (!nfp_flower_support_decap_v2(app_fw_flower))
+			return 0;
+	} else {
+		LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	}
 
 	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
 	memcpy(payload.dst_ipv6, ipv6->ipv6_src, sizeof(payload.dst_ipv6));
@@ -2540,6 +2567,17 @@ struct nfp_pre_tun_entry {
 	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
 	payload.common.port_id = port->in_port;
 
+	if (nfp_flower_support_decap_v2(app_fw_flower)) {
+		if (meta_tci->tci != 0) {
+			payload.ext.vlan_tci = meta_tci->tci;
+			payload.ext.vlan_tpid = 0x88a8;
+		} else {
+			payload.ext.vlan_tci = 0xffff;
+			payload.ext.vlan_tpid = 0xffff;
+		}
+		payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
+	}
+
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
@@ -2557,12 +2595,14 @@ struct nfp_pre_tun_entry {
 
 static int
 nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
-		struct rte_flow *nfp_flow)
+		struct rte_flow *nfp_flow,
+		bool decap_flag)
 {
 	int ret;
 	bool flag = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
+	struct nfp_flower_in_port *port;
 
 	tun = &nfp_flow->tun;
 	LIST_FOREACH(tmp, &app_fw_flower->flow_priv->nn_list, next) {
@@ -2590,6 +2630,40 @@ struct nfp_pre_tun_entry {
 		}
 	}
 
+	if (!decap_flag)
+		return 0;
+
+	port = (struct nfp_flower_in_port *)(nfp_flow->payload.unmasked_data +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	if (tmp->payload.v6_flag != 0) {
+		struct nfp_flower_cmsg_tun_neigh_v6 nn_v6;
+		memset(&nn_v6, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+		memcpy(nn_v6.dst_ipv6, tmp->payload.dst.dst_ipv6, sizeof(nn_v6.dst_ipv6));
+		memcpy(nn_v6.src_ipv6, tmp->payload.src.src_ipv6, sizeof(nn_v6.src_ipv6));
+		memcpy(nn_v6.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
+		memcpy(nn_v6.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
+		nn_v6.common.port_id = port->in_port;
+
+		ret = nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &nn_v6);
+	} else {
+		struct nfp_flower_cmsg_tun_neigh_v4 nn_v4;
+		memset(&nn_v4, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+		nn_v4.dst_ipv4 = tmp->payload.dst.dst_ipv4;
+		nn_v4.src_ipv4 = tmp->payload.src.src_ipv4;
+		memcpy(nn_v4.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
+		memcpy(nn_v4.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
+		nn_v4.common.port_id = port->in_port;
+
+		ret = nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &nn_v4);
+	}
+
+	if (ret != 0) {
+		PMD_DRV_LOG(DEBUG, "Failed to send the nn entry");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -2877,12 +2951,14 @@ struct nfp_pre_tun_entry {
 		goto free_entry;
 	}
 
-	ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
-			nfp_mac_idx, true);
-	if (ret != 0) {
-		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
-		ret = -EINVAL;
-		goto free_entry;
+	if (!nfp_flower_support_decap_v2(repr->app_fw_flower)) {
+		ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
+				nfp_mac_idx, true);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+			ret = -EINVAL;
+			goto free_entry;
+		}
 	}
 
 	find_entry->ref_cnt = 1U;
@@ -2933,18 +3009,20 @@ struct nfp_pre_tun_entry {
 		return -EINVAL;
 	}
 
-	ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
-			nfp_mac_idx, false);
-	if (ret != 0) {
-		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
-		return -EINVAL;
+	if (!nfp_flower_support_decap_v2(app_fw_flower)) {
+		ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
+				nfp_mac_idx, false);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+			return -EINVAL;
+		}
 	}
 
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
-		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
+		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
 	else
-		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow);
+		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
 }
 
 static int
@@ -3654,11 +3732,11 @@ struct nfp_pre_tun_entry {
 		break;
 	case NFP_FLOW_ENCAP:
 		/* Delete the entry from nn table */
-		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, false);
 		break;
 	case NFP_FLOW_DECAP:
 		/* Delete the entry from nn table */
-		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, true);
 		if (ret != 0)
 			goto exit;
 
-- 
1.8.3.1


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v2 00/25] add the extend rte_flow offload support of nfp PMD
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (24 preceding siblings ...)
  2022-10-22  8:24   ` [PATCH v2 25/25] net/nfp: support new tunnel solution Chaoyong He
@ 2022-10-24 15:07   ` Ferruh Yigit
  2022-10-25  3:17     ` Chaoyong He
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
  26 siblings, 1 reply; 88+ messages in thread
From: Ferruh Yigit @ 2022-10-24 15:07 UTC (permalink / raw)
  To: Chaoyong He; +Cc: oss-drivers, niklas.soderlund, dev

On 10/22/2022 9:24 AM, Chaoyong He wrote:
> This is the third patch series to add the support of rte_flow offload for
> nfp PMD, includes:
> Add the offload support of decap/encap of VXLAN
> Add the offload support of decap/encap of GENEVE
> Add the offload support of decap/encap of NVGRE
> 
> Changes since v1
> - Delete the modificaiton of release note.
> - Modify the commit title.
> - Rebase to the lastest logic.
> 
> Chaoyong He (25):
>    net/nfp: support IPv4 VXLAN flow item
>    net/nfp: support IPv6 VXLAN flow item
>    net/nfp: prepare for IPv4 tunnel encap flow action
>    net/nfp: prepare for IPv6 tunnel encap flow action
>    net/nfp: support IPv4 VXLAN encap flow action
>    net/nfp: support IPv6 VXLAN encap flow action
>    net/nfp: prepare for IPv4 UDP tunnel decap flow action
>    net/nfp: prepare for IPv6 UDP tunnel decap flow action
>    net/nfp: support IPv4 VXLAN decap flow action
>    net/nfp: support IPv6 VXLAN decap flow action
>    net/nfp: support IPv4 GENEVE encap flow action
>    net/nfp: support IPv6 GENEVE encap flow action
>    net/nfp: support IPv4 GENEVE flow item
>    net/nfp: support IPv6 GENEVE flow item
>    net/nfp: support IPv4 GENEVE decap flow action
>    net/nfp: support IPv6 GENEVE decap flow action
>    net/nfp: support IPv4 NVGRE encap flow action
>    net/nfp: support IPv6 NVGRE encap flow action
>    net/nfp: prepare for IPv4 GRE tunnel decap flow action
>    net/nfp: prepare for IPv6 GRE tunnel decap flow action
>    net/nfp: support IPv4 NVGRE flow item
>    net/nfp: support IPv6 NVGRE flow item
>    net/nfp: support IPv4 NVGRE decap flow action
>    net/nfp: support IPv6 NVGRE decap flow action
>    net/nfp: support new tunnel solution
> 

Hi Chaoyong,

'./devtools/check-doc-vs-code.sh' tools reports some inconsistency, can 
you please fix it?


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v2 25/25] net/nfp: support new tunnel solution
  2022-10-22  8:24   ` [PATCH v2 25/25] net/nfp: support new tunnel solution Chaoyong He
@ 2022-10-24 15:09     ` Ferruh Yigit
  2022-10-25  1:44       ` Chaoyong He
  0 siblings, 1 reply; 88+ messages in thread
From: Ferruh Yigit @ 2022-10-24 15:09 UTC (permalink / raw)
  To: Chaoyong He, dev; +Cc: oss-drivers, niklas.soderlund

On 10/22/2022 9:24 AM, Chaoyong He wrote:
> The new version of flower firmware application add the support of
> a new tunnel solution.
> 
> It changes the structure of tunnel neighbor, and use a feature flag
> to indicate which tunnel solution is used.
> 
> Add the logic of read extra features from firmware, and store it in
> the app private structure.
> 
> Adjust the data structure and related logic to make the PMD support
> both version of tunnel solutions.
> 
> Signed-off-by: Chaoyong He<chaoyong.he@corigine.com>
> Reviewed-by: Niklas Söderlund<niklas.soderlund@corigine.com>
> ---
>   drivers/net/nfp/flower/nfp_flower.c      |  14 ++++
>   drivers/net/nfp/flower/nfp_flower.h      |  24 +++++++
>   drivers/net/nfp/flower/nfp_flower_cmsg.c |   4 ++
>   drivers/net/nfp/flower/nfp_flower_cmsg.h |  17 +++++
>   drivers/net/nfp/nfp_flow.c               | 118 +++++++++++++++++++++++++------
>   5 files changed, 157 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c
> index 41b0fe2..aa8199d 100644
> --- a/drivers/net/nfp/flower/nfp_flower.c
> +++ b/drivers/net/nfp/flower/nfp_flower.c
> @@ -1074,6 +1074,8 @@
>   nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
>   {
>   	int ret;
> +	int err;
> +	uint64_t ext_features;
>   	unsigned int numa_node;
>   	struct nfp_net_hw *pf_hw;
>   	struct nfp_net_hw *ctrl_hw;
> @@ -1115,6 +1117,18 @@
>   		goto vnic_cleanup;
>   	}
>   
> +	/* Read the extra features */
> +	ext_features = nfp_rtsym_read_le(pf_dev->sym_tbl, "_abi_flower_extra_features",
> +			&err);
> +	if (err != 0) {
> +		PMD_INIT_LOG(ERR, "Couldn't read extra features from fw");
> +		ret = -EIO;
> +		goto pf_cpp_area_cleanup;
> +	}

Hi Chaoyong,

It looks like there are two flavor of the flower firmware application, 
one with 'extra_features' other without it.
Does this worth documenting in the driver documentation and the release 
notes?

^ permalink raw reply	[flat|nested] 88+ messages in thread

* RE: [PATCH v2 25/25] net/nfp: support new tunnel solution
  2022-10-24 15:09     ` Ferruh Yigit
@ 2022-10-25  1:44       ` Chaoyong He
  2022-10-25  8:18         ` Ferruh Yigit
  0 siblings, 1 reply; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  1:44 UTC (permalink / raw)
  To: Ferruh Yigit, dev; +Cc: oss-drivers, Niklas Soderlund

> On 10/22/2022 9:24 AM, Chaoyong He wrote:
> > The new version of flower firmware application add the support of a
> > new tunnel solution.
> >
> > It changes the structure of tunnel neighbor, and use a feature flag to
> > indicate which tunnel solution is used.
> >
> > Add the logic of read extra features from firmware, and store it in
> > the app private structure.
> >
> > Adjust the data structure and related logic to make the PMD support
> > both version of tunnel solutions.
> >
> > Signed-off-by: Chaoyong He<chaoyong.he@corigine.com>
> > Reviewed-by: Niklas Söderlund<niklas.soderlund@corigine.com>
> > ---
> >   drivers/net/nfp/flower/nfp_flower.c      |  14 ++++
> >   drivers/net/nfp/flower/nfp_flower.h      |  24 +++++++
> >   drivers/net/nfp/flower/nfp_flower_cmsg.c |   4 ++
> >   drivers/net/nfp/flower/nfp_flower_cmsg.h |  17 +++++
> >   drivers/net/nfp/nfp_flow.c               | 118 +++++++++++++++++++++++++-
> -----
> >   5 files changed, 157 insertions(+), 20 deletions(-)
> >
> > diff --git a/drivers/net/nfp/flower/nfp_flower.c
> > b/drivers/net/nfp/flower/nfp_flower.c
> > index 41b0fe2..aa8199d 100644
> > --- a/drivers/net/nfp/flower/nfp_flower.c
> > +++ b/drivers/net/nfp/flower/nfp_flower.c
> > @@ -1074,6 +1074,8 @@
> >   nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
> >   {
> >   	int ret;
> > +	int err;
> > +	uint64_t ext_features;
> >   	unsigned int numa_node;
> >   	struct nfp_net_hw *pf_hw;
> >   	struct nfp_net_hw *ctrl_hw;
> > @@ -1115,6 +1117,18 @@
> >   		goto vnic_cleanup;
> >   	}
> >
> > +	/* Read the extra features */
> > +	ext_features = nfp_rtsym_read_le(pf_dev->sym_tbl,
> "_abi_flower_extra_features",
> > +			&err);
> > +	if (err != 0) {
> > +		PMD_INIT_LOG(ERR, "Couldn't read extra features from fw");
> > +		ret = -EIO;
> > +		goto pf_cpp_area_cleanup;
> > +	}
> 
> Hi Chaoyong,
> 
> It looks like there are two flavor of the flower firmware application, one with
> 'extra_features' other without it.
> Does this worth documenting in the driver documentation and the release
> notes?

Actually, it's just two different methods to process the tunnel decap action in the flower
firmware application.

The old version flower firmware application needs 'tunnel neighbor' and 'pre-tunnel' table
to get needed information to decap the tunnel packet.
While the new version flower firmware application extends the 'tunnel neighbor' table and
does not need 'pre-tunnel' table anymore when decap the tunnel packet.

The app which use the rte_flow know nothing about this difference.
So, should we still explain this in the documentation and the release notes? I'm not quite sure
about how details should we expose in these documents.

^ permalink raw reply	[flat|nested] 88+ messages in thread

* RE: [PATCH v2 00/25] add the extend rte_flow offload support of nfp PMD
  2022-10-24 15:07   ` [PATCH v2 00/25] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
@ 2022-10-25  3:17     ` Chaoyong He
  2022-10-25  3:29       ` Chaoyong He
  0 siblings, 1 reply; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  3:17 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: oss-drivers, Niklas Soderlund, dev

[-- Attachment #1: Type: text/plain, Size: 2187 bytes --]

> On 10/22/2022 9:24 AM, Chaoyong He wrote:
> > This is the third patch series to add the support of rte_flow offload
> > for nfp PMD, includes:
> > Add the offload support of decap/encap of VXLAN Add the offload
> > support of decap/encap of GENEVE Add the offload support of
> > decap/encap of NVGRE
> >
> > Changes since v1
> > - Delete the modificaiton of release note.
> > - Modify the commit title.
> > - Rebase to the lastest logic.
> >
> > Chaoyong He (25):
> >    net/nfp: support IPv4 VXLAN flow item
> >    net/nfp: support IPv6 VXLAN flow item
> >    net/nfp: prepare for IPv4 tunnel encap flow action
> >    net/nfp: prepare for IPv6 tunnel encap flow action
> >    net/nfp: support IPv4 VXLAN encap flow action
> >    net/nfp: support IPv6 VXLAN encap flow action
> >    net/nfp: prepare for IPv4 UDP tunnel decap flow action
> >    net/nfp: prepare for IPv6 UDP tunnel decap flow action
> >    net/nfp: support IPv4 VXLAN decap flow action
> >    net/nfp: support IPv6 VXLAN decap flow action
> >    net/nfp: support IPv4 GENEVE encap flow action
> >    net/nfp: support IPv6 GENEVE encap flow action
> >    net/nfp: support IPv4 GENEVE flow item
> >    net/nfp: support IPv6 GENEVE flow item
> >    net/nfp: support IPv4 GENEVE decap flow action
> >    net/nfp: support IPv6 GENEVE decap flow action
> >    net/nfp: support IPv4 NVGRE encap flow action
> >    net/nfp: support IPv6 NVGRE encap flow action
> >    net/nfp: prepare for IPv4 GRE tunnel decap flow action
> >    net/nfp: prepare for IPv6 GRE tunnel decap flow action
> >    net/nfp: support IPv4 NVGRE flow item
> >    net/nfp: support IPv6 NVGRE flow item
> >    net/nfp: support IPv4 NVGRE decap flow action
> >    net/nfp: support IPv6 NVGRE decap flow action
> >    net/nfp: support new tunnel solution
> >
> 
> Hi Chaoyong,
> 
> './devtools/check-doc-vs-code.sh' tools reports some inconsistency, can you
> please fix it?

Sorry, I can't quite understand the logic of this script.
I'm quite sure I have listed the items and actions we supported in the file 'doc/guides/nics/features/nfp.ini'.

And seems it report for every nic which support rte_flow?


[-- Attachment #2: full.log --]
[-- Type: application/octet-stream, Size: 32162 bytes --]

rte_flow doc out of sync for bnxt
	item 			    (typeof(item->type))bnxt_last)
	item 		    bnxt_end) {
	item 		case any:
	item 		case eth:
	item 		case gre:
	item 		case ipv4:
	item 		case ipv6:
	item 		case tcp:
	item 		case udp:
	item 		case vlan:
	item 		case vxlan:
	item 	case port_id: {
	item 	case port_representor: {
	item 	case represented_port: {
	item 	if (tunnel->type !
	item 	} else if (item->type
	item any
	item eth
	item gre
	item icmp
	item icmp6
	item ipv4
	item ipv6
	item port_id
	item port_representor
	item represented_port
	item tcp
	item udp
	item vlan
	item vxlan
	action 			    (typeof(action_item->type))bnxt_last)
	action 		    (typeof(action_item->type))bnxt_end) {
	action 		    bnxt_vxlan_decap) {
	action 		case rss:
	action 	action_item.type
	action 	case count:
	action 	case drop:
	action 	case mark:
	action 	case port_id: {
	action 	case port_representor: {
	action 	case represented_port: {
	action 	case rss:
	action 	case vf:
	action count
	action dec_ttl
	action drop
	action jump
	action mark
	action of_pop_vlan
	action of_push_vlan
	action of_set_vlan_pcp
	action of_set_vlan_vid
	action pf
	action port_id
	action port_representor
	action represented_port
	action rss
	action sample
	action set_ipv4_dst
	action set_ipv4_src
	action set_tp_dst
	action set_tp_src
	action vf
	action vxlan_decap
	action vxlan_encap
rte_flow doc out of sync for cnxk
	item any
	item arp_eth_ipv4
	item e_tag
	item esp
	item eth
	item geneve
	item gre
	item gre_key
	item gtpc
	item gtpu
	item higig2
	item icmp
	item ipv4
	item ipv6
	item ipv6_ext
	item ipv6_frag_ext
	item mark
	item mpls
	item nvgre
	item raw
	item sctp
	item tcp
	item udp
	item vlan
	item vxlan
	item vxlan_gpe
	action 				    meter) {
	action 			    actions->type !
	action 		case count:
	action 		case drop:
	action 		case flag:
	action 		case mark:
	action 		case meter:
	action 		case of_pop_vlan:
	action 		case of_push_vlan:
	action 		case of_set_vlan_pcp:
	action 		case of_set_vlan_vid:
	action 		case pf:
	action 		case port_id:
	action 		case queue:
	action 		case represented_port:
	action 		case rss:
	action 		case security:
	action 		case vf:
	action 	    drop)
	action 	 * flag vs rte_flow_action_type_mark
	action 	 * mark.
	action 	if (action->type !
	action 	if (action_fate_green
	action 	if (action_fate_red
	action 	if (action_fate_yellow
	action count
	action drop
	action flag
	action mark
	action meter
	action of_pop_vlan
	action of_push_vlan
	action of_set_vlan_pcp
	action of_set_vlan_vid
	action pf
	action port_id
	action queue
	action represented_port
	action rss
	action security
	action vf
rte_flow doc out of sync for cxgbe
	item 						       eth);
	item 						       ipv4);
	item 						       ipv6);
	item 						       tcp);
	item 						  "no eth "
	item 						  "no eth found");
	item 						  "no ipv4 "
	item 						  "no ipv6 "
	item 						"no tcp or "
	item 						"udp found");
	item 						udp);
	item 			    i->type !
	item eth
	item ipv4
	item ipv6
	item tcp
	item udp
	item vlan
	action 		case count:
	action 		case drop:
	action 		case mac_swap:
	action 		case of_pop_vlan:
	action 		case of_push_vlan:
	action 		case of_set_vlan_pcp:
	action 		case of_set_vlan_vid:
	action 		case queue:
	action 		case set_ipv4_dst:
	action 		case set_ipv4_src:
	action 		case set_ipv6_dst:
	action 		case set_ipv6_src:
	action 		case set_mac_dst:
	action 		case set_mac_src:
	action 		case set_tp_dst:
	action 		case set_tp_src:
	action 	case mac_swap:
	action 	case of_pop_vlan:
	action 	case of_push_vlan:
	action 	case of_set_vlan_pcp:
	action 	case of_set_vlan_vid:
	action 	case set_ipv4_dst:
	action 	case set_ipv4_src:
	action 	case set_ipv6_dst:
	action 	case set_ipv6_src:
	action 	case set_mac_dst:
	action 	case set_mac_src:
	action 	case set_tp_dst:
	action 	case set_tp_src:
	action 	if (action->type !
	action count
	action drop
	action mac_swap
	action of_pop_vlan
	action of_push_vlan
	action of_set_vlan_pcp
	action of_set_vlan_vid
	action queue
	action set_ipv4_dst
	action set_ipv4_src
	action set_ipv6_dst
	action set_ipv6_src
	action set_mac_dst
	action set_mac_src
	action set_tp_dst
	action set_tp_src
rte_flow doc out of sync for dpaa2
	item 						eth);
	item 					eth);
	item 				eth);
	item 			ipv4)) {
	item 			ipv6)) {
	item 		case eth:
	item 		case gre:
	item 		case icmp:
	item 		case ipv4:
	item 		case ipv6:
	item 		case raw:
	item 		case sctp:
	item 		case tcp:
	item 		case udp:
	item 		case vlan:
	item 		eth)) {
	item 		gre)) {
	item 		icmp)) {
	item 		proto.type
	item 		sctp)) {
	item 		tcp)) {
	item 		udp)) {
	item 		vlan)) {
	item 	case eth:
	item 	case gre:
	item 	case icmp:
	item 	case ipv4:
	item 	case ipv6:
	item 	case raw:
	item 	case sctp:
	item 	case tcp:
	item 	case udp:
	item 	case vlan:
	item 	eth,
	item 	gre,
	item 	icmp,
	item 	if (proto.type
	item 	if (type
	item 	ipv4,
	item 	ipv6,
	item 	proto.type
	item 	sctp,
	item 	tcp,
	item 	udp,
	item 	vlan,
	item #define dpaa2_flow_item_type_generic_ip (meta + 1)
	item eth
	item gre
	item icmp
	item ipv4
	item ipv6
	item meta
	item raw
	item sctp
	item tcp
	item udp
	item vlan
	action 			flow->action
	action 		case port_id:
	action 		case queue:
	action 		case represented_port:
	action 		case rss:
	action 	case port_id:
	action 	case queue:
	action 	case represented_port:
	action 	case rss:
	action 	if (action->type
	action 	port_id,
	action 	queue,
	action 	represented_port,
	action 	rss
	action 	} else if (action->type
	action drop
	action port_id
	action queue
	action represented_port
	action rss
rte_flow doc out of sync for e1000
	item 		    item->type !
	item 	    item->type
	item 	} else if (item->type
	item eth
	item ipv4
	item ipv6
	item raw
	item sctp
	item tcp
	item udp
	action 	    act->type !
	action 	if (act->type
	action drop
	action queue
	action rss
rte_flow doc out of sync for enic
	item 			       eth,
	item 			       geneve,
	item 			       ipv4,
	item 			       ipv6,
	item 			       udp,
	item 			       vlan,
	item 			       vxlan,
	item 		if (item->type
	item 	case gtp:
	item 	case gtpc:
	item 	case gtpu:
	item 	case ipv4:
	item 	case ipv6:
	item 	if (item->type
	item ecpri
	item eth
	item geneve
	item geneve_opt
	item gtp
	item gtpc
	item gtpu
	item ipv4
	item ipv6
	item raw
	item sctp
	item tcp
	item udp
	item vlan
	item vxlan
	action 		case count:
	action 		case count: {
	action 		case drop: {
	action 		case flag: {
	action 		case jump: {
	action 		case mark: {
	action 		case of_pop_vlan: {
	action 		case of_push_vlan: {
	action 		case of_set_vlan_pcp: {
	action 		case of_set_vlan_vid: {
	action 		case passthru: {
	action 		case port_id: {
	action 		case port_representor: {
	action 		case queue: {
	action 		case represented_port: {
	action 		case rss: {
	action 		case vxlan_decap: {
	action 		case vxlan_encap: {
	action 	count,
	action 	drop,
	action 	flag,
	action 	jump,
	action 	mark,
	action 	of_pop_vlan,
	action 	of_push_vlan,
	action 	of_set_vlan_pcp,
	action 	of_set_vlan_vid,
	action 	passthru,
	action 	port_id,
	action 	queue,
	action 	rss,
	action 	vxlan_decap,
	action 	vxlan_encap,
	action count
	action drop
	action flag
	action jump
	action mark
	action of_pop_vlan
	action of_push_vlan
	action of_set_vlan_pcp
	action of_set_vlan_vid
	action passthru
	action port_id
	action port_representor
	action queue
	action represented_port
	action rss
	action vxlan_decap
	action vxlan_encap
rte_flow doc out of sync for hinic
	item 			item->type !
	item 		if (item->type
	item any
	item eth
	item icmp
	item icmp6
	item ipv4
	item ipv6
	item tcp
	item udp
	item vxlan
	action 		act->type !
	action 	if (act->type
	action drop
	action queue
rte_flow doc out of sync for hns3
	item 		if (pattern->type
	item 	case eth:
	item 	case geneve:
	item 	case ipv4:
	item 	case ipv6:
	item 	case nvgre:
	item 	case sctp:
	item 	case tcp:
	item 	case udp:
	item 	case vlan:
	item 	case vxlan:
	item 	case vxlan_gpe:
	item 	eth,
	item 	geneve,
	item 	icmp
	item 	icmp,
	item 	if (item->type
	item 	if (type
	item 	ipv4,
	item 	ipv6
	item 	ipv6,
	item 	nvgre,
	item 	sctp,
	item 	tcp,
	item 	udp,
	item 	vlan
	item 	vlan,
	item 	vxlan,
	item 	vxlan_gpe
	item eth
	item geneve
	item icmp
	item ipv4
	item ipv6
	item nvgre
	item sctp
	item tcp
	item udp
	item vlan
	item vxlan
	item vxlan_gpe
	action 		case count:
	action 		case drop:
	action 		case flag:
	action 		case mark:
	action 		case queue:
	action 		case rss:
	action 		if (actions->type
	action 	if (action->type !
	action count
	action drop
	action flag
	action mark
	action queue
	action rss
rte_flow doc out of sync for i40e
	item 					bit_ull(ah))
	item 					bit_ull(esp) | \
	item 					bit_ull(gtpc))
	item 					bit_ull(ipv6) | \
	item 					bit_ull(ipv6))
	item 					bit_ull(ipv6_frag_ext))
	item 					bit_ull(l2tpv3oip) |\
	item 					bit_ull(sctp) | \
	item 					bit_ull(udp) | \
	item 					bit_ull(vlan))
	item 					if (l3
	item 					} else if (l3
	item 				if (l3
	item 				if (next_type
	item 				} else if (l3
	item 			else if (item_type
	item 			else if (l3
	item 			if (item_type
	item 			} else if (l3
	item 		case esp:
	item 		case eth:
	item 		case gre:
	item 		case gtpc:
	item 		case gtpu:
	item 		case ipv4:
	item 		case ipv6:
	item 		case l2tpv3oip:
	item 		case mpls:
	item 		case nvgre:
	item 		case raw:
	item 		case sctp:
	item 		case tcp:
	item 		case udp:
	item 		case vlan:
	item 		case vxlan:
	item 		if (item->last && item->type !
	item 		if (last_item_type
	item 	case esp:
	item 	case gtpc:
	item 	case gtpu:
	item 	case l2tpv3oip:
	item 	esp,
	item 	eth,
	item 	gre,
	item 	gtpc,
	item 	gtpu,
	item 	if (pattern_hdrs && last_item_type !
	item 	ipv4,
	item 	ipv6,
	item 	l2tpv3oip,
	item 	mpls,
	item 	nvgre,
	item 	raw,
	item 	sctp,
	item 	tcp,
	item 	udp,
	item 	vlan,
	item 	vxlan,
	item #define i40e_hash_eth_next_allow	(bit_ull(ipv4) | \
	item #define i40e_hash_gtpu_next_allow	(bit_ull(ipv4) | \
	item #define i40e_hash_ip_next_allow		(bit_ull(tcp) | \
	item #define i40e_hash_udp_next_allow	(bit_ull(gtpu) | \
	item #define i40e_hash_void_next_allow	bit_ull(eth)
	item ah
	item esp
	item eth
	item gre
	item gtpc
	item gtpu
	item ipv4
	item ipv6
	item ipv6_frag_ext
	item l2tpv3oip
	item mpls
	item nvgre
	item raw
	item sctp
	item tcp
	item udp
	item vlan
	item vxlan
	action 		case rss:
	action 	case drop:
	action 	case flag:
	action 	case mark:
	action 	case passthru:
	action 	case queue:
	action 	case rss:
	action 	if ((actions + i)->type
	action drop
	action flag
	action mark
	action passthru
	action pf
	action queue
	action rss
	action vf
rte_flow doc out of sync for iavf
	item 				    ipv6_frag_ext)) {
	item 				else if (l3
	item 				if (l3
	item 		case ah:
	item 		case ecpri:
	item 		case esp:
	item 		case eth:
	item 		case gre:
	item 		case gtp_psc:
	item 		case gtpu:
	item 		case ipv4:
	item 		case ipv6:
	item 		case ipv6_frag_ext:
	item 		case l2tpv2:
	item 		case l2tpv3oip:
	item 		case pfcp:
	item 		case ppp:
	item 		case raw:
	item 		case raw: {
	item 		case sctp:
	item 		case tcp:
	item 		case udp:
	item 		case vlan:
	item 		if (item->last && !(item_type
	item 	ah,
	item 	arp_eth_ipv4,
	item 	ecpri,
	item 	esp,
	item 	eth,
	item 	gre,
	item 	gtp_psc,
	item 	gtpc,
	item 	gtpu,
	item 	icmp,
	item 	icmp6,
	item 	ipv4,
	item 	ipv6,
	item 	ipv6_frag_ext,
	item 	l2tpv2,
	item 	l2tpv3oip,
	item 	pfcp,
	item 	ppp,
	item 	raw,
	item 	sctp,
	item 	tcp,
	item 	udp,
	item 	vlan,
	item ah
	item arp_eth_ipv4
	item ecpri
	item esp
	item eth
	item gre
	item gtp_psc
	item gtpc
	item gtpu
	item icmp
	item icmp6
	item ipv4
	item ipv6
	item ipv6_frag_ext
	item l2tpv2
	item l2tpv3oip
	item pfcp
	item ppp
	item raw
	item sctp
	item tcp
	item udp
	item vlan
	action 		case count:
	action 		case drop:
	action 		case mark:
	action 		case passthru:
	action 		case port_representor:
	action 		case queue:
	action 		case rss:
	action 	if (act->type !
	action count
	action drop
	action mark
	action passthru
	action port_representor
	action queue
	action rss
	action security
rte_flow doc out of sync for ice
	item 				    ipv6_frag_ext)) {
	item 				 l4
	item 				if (l3
	item 				if (l4
	item 			    l4
	item 			l4
	item 			} else if (l3
	item 		    item->type
	item 		case ah:
	item 		case any:
	item 		case esp:
	item 		case eth:
	item 		case gtp_psc:
	item 		case gtpu:
	item 		case ipv4:
	item 		case ipv6:
	item 		case ipv6_frag_ext:
	item 		case l2tpv3oip:
	item 		case nvgre:
	item 		case pfcp:
	item 		case pppoe_proto_id:
	item 		case pppoed:
	item 		case pppoes:
	item 		case raw:
	item 		case raw: {
	item 		case sctp:
	item 		case tcp:
	item 		case udp:
	item 		case vlan:
	item 		case vxlan:
	item 		if (item->last && !(item_type
	item 	ah,
	item 	any,
	item 	arp_eth_ipv4,
	item 	esp,
	item 	eth,
	item 	gtp_psc,
	item 	gtpu,
	item 	icmp,
	item 	icmp6,
	item 	ipv4,
	item 	ipv6,
	item 	ipv6_frag_ext,
	item 	l2tpv3oip,
	item 	nvgre,
	item 	pfcp,
	item 	pppoe_proto_id,
	item 	pppoed,
	item 	pppoes,
	item 	raw,
	item 	sctp,
	item 	tcp,
	item 	udp,
	item 	vlan,
	item 	vxlan,
	item ah
	item any
	item arp_eth_ipv4
	item esp
	item eth
	item gtp_psc
	item gtpu
	item icmp
	item icmp6
	item ipv4
	item ipv6
	item ipv6_frag_ext
	item l2tpv3oip
	item nvgre
	item pfcp
	item pppoe_proto_id
	item pppoed
	item pppoes
	item raw
	item sctp
	item tcp
	item udp
	item vlan
	item vxlan
	action 		case count:
	action 		case drop:
	action 		case mark:
	action 		case passthru:
	action 		case port_representor:
	action 		case queue:
	action 		case represented_port:
	action 		case rss:
	action 	if (act->type !
	action count
	action drop
	action mark
	action passthru
	action port_representor
	action queue
	action represented_port
	action rss
rte_flow doc out of sync for igc
	item eth
	item ipv4
	item ipv6
	item tcp
	item udp
	action 		case queue:
	action 		case rss:
	action queue
	action rss
rte_flow doc out of sync for ipn3ke
	item 					eth),
	item 					ipv4,
	item 					mpls),
	item 					nvgre),
	item 					tcp),
	item 					udp),
	item 					udp,
	item 					vlan),
	item 		case eth:
	item 		case ipv4:
	item 		case mpls:
	item 		case nvgre:
	item 		case tcp:
	item 		case udp:
	item 		case vlan:
	item 		case vxlan:
	item  * eth
	item  * ipv4
	item  * mpls
	item  * nvgre
	item  * tcp
	item  * udp
	item  * vlan
	item  * vxlan
	item eth
	item ipv4
	item mpls
	item nvgre
	item tcp
	item udp
	item vlan
	item vxlan
	action 		case drop:
	action 		case mark:
	action drop
	action mark
rte_flow doc out of sync for ixgbe
	item 					item->type
	item 					item->type !
	item 				item->type !
	item 			item->type !
	item 		(item->type !
	item 		if (item->type
	item 		if (next->type !
	item 		while (item->type !
	item 	    item->type
	item 	if ((item->type !
	item e_tag
	item eth
	item fuzzy
	item ipv4
	item ipv6
	item nvgre
	item raw
	item sctp
	item tcp
	item udp
	item vlan
	item vxlan
	action 			act->type !
	action 	    act->type !
	action 	 *  special case for flow action type security
	action 	if ((act->type !
	action  * special case for flow action type security.
	action drop
	action mark
	action pf
	action queue
	action rss
	action security
	action vf
rte_flow doc out of sync for mlx4
	item 				       ipv4),
	item 				       tcp),
	item 				.type
	item 			.type
	item 		if ((item->type !
	item eth
	item ipv4
	item tcp
	item udp
	item vlan
	action 			.type
	action 		case drop:
	action 		case queue:
	action 		case rss:
	action drop
	action queue
	action rss
rte_flow doc out of sync for mlx5
	item 						mlx5_vlan;
	item 					.type
	item 					mlx5_tag,
	item 				  mlx5_tunnel) {
	item 				mlx5_tag,
	item 				mlx5_tag;
	item 				mlx5_tx_queue,
	item 			    mlx5_tunnel;
	item 			*all_ports
	item 			if (items->type
	item 			node->type
	item 		       eth : rte_flow_item_type_end;
	item 		       vlan : rte_flow_item_type_end;
	item 		     mlx5_tag;
	item 		    item->type
	item 		    type
	item 		case conntrack:
	item 		case ecpri:
	item 		case esp:
	item 		case eth:
	item 		case flex:
	item 		case geneve:
	item 		case geneve_opt:
	item 		case gre:
	item 		case gre_key:
	item 		case gre_option:
	item 		case gtp:
	item 		case gtp_psc:
	item 		case icmp6:
	item 		case icmp:
	item 		case integrity:
	item 		case ipv4:
	item 		case ipv6:
	item 		case ipv6_frag_ext:
	item 		case mark:
	item 		case meta:
	item 		case mlx5_tag:
	item 		case mlx5_tunnel:
	item 		case mlx5_tx_queue:
	item 		case mpls:
	item 		case nvgre:
	item 		case port_id:
	item 		case represented_port:
	item 		case tag:
	item 		case tcp:
	item 		case udp:
	item 		case vlan:
	item 		case vxlan:
	item 		case vxlan_gpe:
	item 		if (item && item->type
	item 		if (tunnel_item->type
	item 		if (type
	item 		mlx5_assert(prev_item->type
	item 	    item->type !
	item 	 * represented_port and is meaningless without them.
	item 	case esp:
	item 	case eth:
	item 	case geneve:
	item 	case gre:
	item 	case gre_key:
	item 	case gtp:
	item 	case icmp6:
	item 	case icmp:
	item 	case ipv4:
	item 	case ipv6:
	item 	case ipv6_frag_ext:
	item 	case mpls:
	item 	case nvgre:
	item 	case tcp:
	item 	case udp:
	item 	case vlan:
	item 	case vxlan:
	item 	case vxlan_gpe:
	item 	dport
	item 	esw_mgr_port
	item 	if (item->type
	item 	if (item->type !
	item 	item.type
	item 	mlx5_assert(item->type
	item 	mlx5_end
	item 	mlx5_tag,
	item 	mlx5_tunnel,
	item 	mlx5_tx_queue,
	item 	mlx5_vlan,
	item conntrack
	item ecpri
	item esp
	item eth
	item flex
	item geneve
	item geneve_opt
	item gre
	item gre_key
	item gre_option
	item gtp
	item gtp_psc
	item icmp
	item icmp6
	item integrity
	item ipv4
	item ipv6
	item ipv6_frag_ext
	item mark
	item meta
	item mpls
	item nvgre
	item port_id
	item represented_port
	item tag
	item tcp
	item udp
	item vlan
	item vxlan
	item vxlan_gpe
	action 						mlx5_count;
	action 						mlx5_tag;
	action 					 of_set_vlan_pcp);
	action 					 of_set_vlan_vid);
	action 					.type
	action 					conntrack;
	action 					inc_tcp_ack ?
	action 					inc_tcp_seq ?
	action 					mlx5_age;
	action 					mlx5_copy_mreg,
	action 					sample,
	action 					set_ipv4_src ?
	action 					set_ipv6_src ?
	action 					set_mac_src ?
	action 					set_tp_src ?
	action 					set_ttl ?
	action 				      mlx5_jump;
	action 				    mlx5_tunnel_set) {
	action 				.type
	action 				if (act->type
	action 				jump,
	action 				mlx5_copy_mreg,
	action 				mlx5_default_miss,
	action 				mlx5_mark,
	action 				mlx5_tag,
	action 				mlx5_tag;
	action 				rss;
	action 			      mlx5_tunnel_set;
	action 			   mlx5_tag;
	action 			case drop:
	action 			case jump:
	action 			case mark:
	action 			case meter:
	action 			case modify_field:
	action 			case nvgre_encap:
	action 			case of_push_vlan:
	action 			case of_set_vlan_vid:
	action 			case port_id:
	action 			case queue:
	action 			case raw_decap:
	action 			case raw_encap:
	action 			case represented_port:
	action 			case rss:
	action 			case set_tag:
	action 			case vxlan_encap:
	action 			if (action->type !
	action 			if (actions->type
	action 			if (actions->type !
	action 			if (ptr->type
	action 		    (enum rte_flow_action_type)mlx5_rss,
	action 		(action + 1, of_set_vlan_pcp)))
	action 		(action + 1, of_set_vlan_vid)))
	action 		(enum rte_flow_action_type)mlx5_count;
	action 		.type
	action 		act_data.type
	action 		case age:
	action 		case conntrack:
	action 		case count:
	action 		case dec_tcp_ack:
	action 		case dec_tcp_seq:
	action 		case dec_ttl:
	action 		case drop:
	action 		case flag:
	action 		case inc_tcp_ack:
	action 		case inc_tcp_seq:
	action 		case jump:
	action 		case mark:
	action 		case meter:
	action 		case mlx5_age:
	action 		case mlx5_copy_mreg:
	action 		case mlx5_count:
	action 		case mlx5_default_miss:
	action 		case mlx5_jump:
	action 		case mlx5_mark:
	action 		case mlx5_rss:
	action 		case mlx5_tag:
	action 		case mlx5_tunnel_set:
	action 		case modify_field:
	action 		case nvgre_decap:
	action 		case nvgre_encap:
	action 		case of_pop_vlan:
	action 		case of_push_vlan:
	action 		case of_set_vlan_pcp:
	action 		case of_set_vlan_vid:
	action 		case port_id:
	action 		case queue:
	action 		case raw_decap:
	action 		case raw_encap:
	action 		case represented_port:
	action 		case rss:
	action 		case sample:
	action 		case set_ipv4_dscp:
	action 		case set_ipv4_dst:
	action 		case set_ipv4_src:
	action 		case set_ipv6_dscp:
	action 		case set_ipv6_dst:
	action 		case set_ipv6_src:
	action 		case set_mac_dst:
	action 		case set_mac_src:
	action 		case set_meta:
	action 		case set_tag:
	action 		case set_tp_dst:
	action 		case set_tp_src:
	action 		case set_ttl:
	action 		case vxlan_decap:
	action 		case vxlan_encap:
	action 		if (qrss->type
	action 		} else if (qrss->type
	action 	/* count mlx5_tag. */
	action 	case age:
	action 	case conntrack:
	action 	case count:
	action 	case dec_tcp_ack:
	action 	case dec_tcp_seq:
	action 	case dec_ttl:
	action 	case flag:
	action 	case inc_tcp_ack:
	action 	case inc_tcp_seq:
	action 	case mark:
	action 	case mlx5_rss:
	action 	case modify_field:
	action 	case nvgre_decap:
	action 	case nvgre_encap:
	action 	case of_pop_vlan:
	action 	case of_push_vlan:
	action 	case of_set_vlan_pcp:
	action 	case of_set_vlan_vid:
	action 	case port_id:
	action 	case port_id: {
	action 	case queue:
	action 	case raw_decap:
	action 	case raw_encap:
	action 	case represented_port:
	action 	case represented_port: {
	action 	case rss:
	action 	case set_ipv4_dscp:
	action 	case set_ipv4_dst:
	action 	case set_ipv4_src:
	action 	case set_ipv6_dscp:
	action 	case set_ipv6_dst:
	action 	case set_ipv6_src:
	action 	case set_mac_dst:
	action 	case set_mac_src:
	action 	case set_meta:
	action 	case set_tag:
	action 	case set_tp_dst:
	action 	case set_tp_src:
	action 	case set_ttl:
	action 	case vxlan_decap:
	action 	case vxlan_encap:
	action 	for (; app_actions->type !
	action 	if (action->type !
	action 	} else if (action->type
	action  * see @count
	action age
	action conntrack
	action count
	action dec_tcp_ack
	action dec_tcp_seq
	action dec_ttl
	action drop
	action flag
	action inc_tcp_ack
	action inc_tcp_seq
	action jump
	action mark
	action meter
	action modify_field
	action nvgre_decap
	action nvgre_encap
	action of_pop_vlan
	action of_push_vlan
	action of_set_vlan_pcp
	action of_set_vlan_vid
	action port_id
	action queue
	action raw_decap
	action raw_encap
	action represented_port
	action rss
	action sample
	action set_ipv4_dscp
	action set_ipv4_dst
	action set_ipv4_src
	action set_ipv6_dscp
	action set_ipv6_dst
	action set_ipv6_src
	action set_mac_dst
	action set_mac_src
	action set_meta
	action set_tag
	action set_tp_dst
	action set_tp_src
	action set_ttl
	action vxlan_decap
	action vxlan_encap
rte_flow doc out of sync for mvpp2
	item 	{ eth, mrvl_parse_eth },
	item 	{ ipv4, mrvl_parse_ip4 },
	item 	{ ipv6, mrvl_parse_ip6 },
	item 	{ raw, mrvl_parse_raw },
	item 	{ tcp, mrvl_parse_tcp },
	item 	{ udp, mrvl_parse_udp },
	item 	{ vlan, mrvl_parse_vlan },
	item eth
	item ipv4
	item ipv6
	item raw
	item tcp
	item udp
	item vlan
	action 		if (action->type
	action drop
	action meter
	action queue
rte_flow doc out of sync for nfp
	item 			geneve),
	item 			gre),
	item 			ipv4,
	item 			ipv6),
	item 			pmd_drv_log(debug, "eth detected");
	item 			pmd_drv_log(debug, "geneve detected");
	item 			pmd_drv_log(debug, "gre detected");
	item 			pmd_drv_log(debug, "gre_key detected");
	item 			pmd_drv_log(debug, "ipv4 detected");
	item 			pmd_drv_log(debug, "ipv6 detected");
	item 			pmd_drv_log(debug, "port_id detected");
	item 			pmd_drv_log(debug, "sctp detected");
	item 			pmd_drv_log(debug, "tcp detected");
	item 			pmd_drv_log(debug, "udp detected");
	item 			pmd_drv_log(debug, "vlan detected");
	item 			pmd_drv_log(debug, "vxlan detected");
	item 			sctp,
	item 			udp,
	item 		case eth:
	item 		case geneve:
	item 		case gre:
	item 		case gre_key:
	item 		case ipv4:
	item 		case ipv6:
	item 		case port_id:
	item 		case sctp:
	item 		case tcp:
	item 		case udp:
	item 		case vlan:
	item 		case vxlan:
	item 	case geneve:
	item 	case gre:
	item 	case vxlan:
	item 	if (item->type
	item eth
	item geneve
	item gre
	item gre_key
	item ipv4
	item ipv6
	item port_id
	item sctp
	item tcp
	item udp
	item vlan
	item vxlan
	action 						" of_push_vlan");
	action 						" port_id");
	action 						" raw_encap");
	action 						" vxlan_encap");
	action 			 * of_set_vlan_pcp and
	action 			 * of_set_vlan_vid
	action 			((action + 2)->type !
	action 			pmd_drv_log(debug, "count detected");
	action 			pmd_drv_log(debug, "drop detected");
	action 			pmd_drv_log(debug, "jump detected");
	action 			pmd_drv_log(debug, "of_pop_vlan detected");
	action 			pmd_drv_log(debug, "of_push_vlan detected");
	action 			pmd_drv_log(debug, "of_set_vlan_pcp detected");
	action 			pmd_drv_log(debug, "of_set_vlan_vid detected");
	action 			pmd_drv_log(debug, "port_id detected");
	action 			pmd_drv_log(debug, "process count");
	action 			pmd_drv_log(debug, "process drop");
	action 			pmd_drv_log(debug, "process jump");
	action 			pmd_drv_log(debug, "process of_pop_vlan");
	action 			pmd_drv_log(debug, "process of_push_vlan");
	action 			pmd_drv_log(debug, "process port_id");
	action 			pmd_drv_log(debug, "process raw_encap");
	action 			pmd_drv_log(debug, "process set_ipv4_dscp");
	action 			pmd_drv_log(debug, "process set_ipv4_dst");
	action 			pmd_drv_log(debug, "process set_ipv4_src");
	action 			pmd_drv_log(debug, "process set_ipv6_dscp");
	action 			pmd_drv_log(debug, "process set_ipv6_dst");
	action 			pmd_drv_log(debug, "process set_ipv6_src");
	action 			pmd_drv_log(debug, "process set_mac_dst");
	action 			pmd_drv_log(debug, "process set_mac_src");
	action 			pmd_drv_log(debug, "process set_tp_dst");
	action 			pmd_drv_log(debug, "process set_tp_src");
	action 			pmd_drv_log(debug, "process set_ttl");
	action 			pmd_drv_log(debug, "process tunnel_decap");
	action 			pmd_drv_log(debug, "process vxlan_encap");
	action 			pmd_drv_log(debug, "raw_decap detected");
	action 			pmd_drv_log(debug, "raw_encap detected");
	action 			pmd_drv_log(debug, "set_ipv4_dscp detected");
	action 			pmd_drv_log(debug, "set_ipv4_dst detected");
	action 			pmd_drv_log(debug, "set_ipv4_src detected");
	action 			pmd_drv_log(debug, "set_ipv6_dscp detected");
	action 			pmd_drv_log(debug, "set_ipv6_dst detected");
	action 			pmd_drv_log(debug, "set_ipv6_src detected");
	action 			pmd_drv_log(debug, "set_mac_dst detected");
	action 			pmd_drv_log(debug, "set_mac_src detected");
	action 			pmd_drv_log(debug, "set_tp_dst detected");
	action 			pmd_drv_log(debug, "set_tp_src detected");
	action 			pmd_drv_log(debug, "set_ttl detected");
	action 			pmd_drv_log(debug, "vxlan_decap detected");
	action 			pmd_drv_log(debug, "vxlan_encap detected");
	action 		case count:
	action 		case drop:
	action 		case jump:
	action 		case of_pop_vlan:
	action 		case of_push_vlan:
	action 		case of_set_vlan_pcp:
	action 		case of_set_vlan_vid:
	action 		case port_id:
	action 		case raw_decap:
	action 		case raw_encap:
	action 		case set_ipv4_dscp:
	action 		case set_ipv4_dst:
	action 		case set_ipv4_src:
	action 		case set_ipv6_dscp:
	action 		case set_ipv6_dst:
	action 		case set_ipv6_src:
	action 		case set_mac_dst:
	action 		case set_mac_src:
	action 		case set_tp_dst:
	action 		case set_tp_src:
	action 		case set_ttl:
	action 		case vxlan_decap:
	action 		case vxlan_encap:
	action 	if (((action + 1)->type !
	action count
	action drop
	action nvgre_decap
	action nvgre_encap
	action of_pop_vlan
	action of_push_vlan
	action of_set_vlan_pcp
	action of_set_vlan_vid
	action port_id
	action raw_decap
	action raw_encap
	action set_ipv4_dscp
	action set_ipv4_dst
	action set_ipv4_src
	action set_ipv6_dscp
	action set_ipv6_dst
	action set_ipv6_src
	action set_mac_dst
	action set_mac_src
	action set_tp_dst
	action set_tp_src
	action set_ttl
	action vxlan_decap
	action vxlan_encap
rte_flow doc out of sync for qede
	item 		case ipv4:
	item 		case ipv6:
	item 		case tcp:
	item 		case udp:
	item ipv4
	item ipv6
	item tcp
	item udp
	action 		case drop:
	action 		case queue:
	action drop
	action queue
rte_flow doc out of sync for sfc
	item 				    rte_bit64(ipv4) |
	item 				    rte_bit64(ipv6);
	item 			rte_bit64(vlan), 0
	item 			sfc_build_set_overflow(eth,
	item 			sfc_build_set_overflow(ipv4,
	item 			sfc_build_set_overflow(ipv6,
	item 			sfc_build_set_overflow(udp,
	item 			sfc_build_set_overflow(vlan,
	item 			sfc_build_set_overflow(vxlan,
	item 		case eth:
	item 		case geneve:
	item 		case ipv4:
	item 		case ipv6:
	item 		case mark:
	item 		case nvgre:
	item 		case udp:
	item 		case vlan:
	item 		case vxlan:
	item 	    item->type !
	item 	case port_representor:
	item 	case represented_port:
	item 	exp_items
	item 	ft_ctx->item.type
	item 	if (item->type
	item 	if (tunnel->type !
	item eth
	item geneve
	item ipv4
	item ipv6
	item mark
	item nvgre
	item port_id
	item port_representor
	item pppoed
	item pppoes
	item represented_port
	item tcp
	item udp
	item vlan
	item vxlan
	action 					   (1ul << drop);
	action 					   (1ul << flag);
	action 					   (1ul << rss) |
	action 			if (action->type !
	action 			sfc_build_set_overflow(drop,
	action 			sfc_build_set_overflow(flag,
	action 			sfc_build_set_overflow(mark,
	action 			sfc_build_set_overflow(queue,
	action 			sfc_build_set_overflow(rss,
	action 		case count:
	action 		case drop:
	action 		case flag:
	action 		case jump:
	action 		case mark:
	action 		case queue:
	action 		case rss:
	action 		if (action->type
	action 		sfc_build_set_overflow(count,
	action 		sfc_build_set_overflow(dec_ttl,
	action 		sfc_build_set_overflow(drop,
	action 		sfc_build_set_overflow(flag,
	action 		sfc_build_set_overflow(mark,
	action 		sfc_build_set_overflow(of_dec_nw_ttl,
	action 		sfc_build_set_overflow(of_pop_vlan,
	action 		sfc_build_set_overflow(of_push_vlan,
	action 		sfc_build_set_overflow(of_set_vlan_pcp,
	action 		sfc_build_set_overflow(of_set_vlan_vid,
	action 		sfc_build_set_overflow(pf,
	action 		sfc_build_set_overflow(port_id,
	action 		sfc_build_set_overflow(port_representor,
	action 		sfc_build_set_overflow(represented_port,
	action 		sfc_build_set_overflow(set_mac_dst,
	action 		sfc_build_set_overflow(set_mac_src,
	action 		sfc_build_set_overflow(vf,
	action 		sfc_build_set_overflow(vxlan_decap,
	action 		sfc_build_set_overflow(vxlan_encap,
	action 	    action->type !
	action 	case count:
	action 	case dec_ttl:
	action 	case drop:
	action 	case flag:
	action 	case jump:
	action 	case mark:
	action 	case of_dec_nw_ttl:
	action 	case of_pop_vlan:
	action 	case of_push_vlan:
	action 	case of_set_vlan_pcp:
	action 	case of_set_vlan_vid:
	action 	case pf:
	action 	case port_id:
	action 	case port_representor:
	action 	case represented_port:
	action 	case set_mac_dst:
	action 	case set_mac_src:
	action 	case vf:
	action 	case vxlan_decap:
	action 	case vxlan_encap:
	action 	const uint32_t fate_actions_mask
	action 	const uint32_t mark_actions_mask
	action 	ft_ctx->action.type
	action count
	action dec_ttl
	action drop
	action flag
	action jump
	action mark
	action of_dec_nw_ttl
	action of_pop_vlan
	action of_push_vlan
	action of_set_vlan_pcp
	action of_set_vlan_vid
	action pf
	action port_id
	action port_representor
	action queue
	action represented_port
	action rss
	action set_mac_dst
	action set_mac_src
	action vf
	action vxlan_decap
	action vxlan_encap
rte_flow doc out of sync for tap
	item 			       ipv6),
	item 			       tcp),
	item 			.type
	item 			ipv4,
	item 			ipv6),
	item 			vlan,
	item eth
	item ipv4
	item ipv6
	item tcp
	item udp
	item vlan
	action 			drop :
	action 			passthru;
	action 			{ .type
	action drop
	action passthru
	action queue
	action rss
rte_flow doc out of sync for txgbe
	item 					item->type
	item 					item->type !
	item 				item->type !
	item 			item->type !
	item 		if (item->type
	item 		if (next->type !
	item 		item->type !
	item 		while (item->type !
	item 	    item->type
	item e_tag
	item eth
	item fuzzy
	item ipv4
	item ipv6
	item nvgre
	item raw
	item sctp
	item tcp
	item udp
	item vlan
	item vxlan
	action 			act->type !
	action 	    act->type !
	action 	 *  special case for flow action type security
	action  * special case for flow action type security.
	action drop
	action mark
	action pf
	action queue
	action rss
	action security
	action vf

^ permalink raw reply	[flat|nested] 88+ messages in thread

* RE: [PATCH v2 00/25] add the extend rte_flow offload support of nfp PMD
  2022-10-25  3:17     ` Chaoyong He
@ 2022-10-25  3:29       ` Chaoyong He
  0 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  3:29 UTC (permalink / raw)
  To: Ferruh Yigit; +Cc: oss-drivers, Niklas Soderlund, dev

> > On 10/22/2022 9:24 AM, Chaoyong He wrote:
> > > This is the third patch series to add the support of rte_flow
> > > offload for nfp PMD, includes:
> > > Add the offload support of decap/encap of VXLAN Add the offload
> > > support of decap/encap of GENEVE Add the offload support of
> > > decap/encap of NVGRE
> > >
> > > Changes since v1
> > > - Delete the modificaiton of release note.
> > > - Modify the commit title.
> > > - Rebase to the lastest logic.
> > >
> > > Chaoyong He (25):
> > >    net/nfp: support IPv4 VXLAN flow item
> > >    net/nfp: support IPv6 VXLAN flow item
> > >    net/nfp: prepare for IPv4 tunnel encap flow action
> > >    net/nfp: prepare for IPv6 tunnel encap flow action
> > >    net/nfp: support IPv4 VXLAN encap flow action
> > >    net/nfp: support IPv6 VXLAN encap flow action
> > >    net/nfp: prepare for IPv4 UDP tunnel decap flow action
> > >    net/nfp: prepare for IPv6 UDP tunnel decap flow action
> > >    net/nfp: support IPv4 VXLAN decap flow action
> > >    net/nfp: support IPv6 VXLAN decap flow action
> > >    net/nfp: support IPv4 GENEVE encap flow action
> > >    net/nfp: support IPv6 GENEVE encap flow action
> > >    net/nfp: support IPv4 GENEVE flow item
> > >    net/nfp: support IPv6 GENEVE flow item
> > >    net/nfp: support IPv4 GENEVE decap flow action
> > >    net/nfp: support IPv6 GENEVE decap flow action
> > >    net/nfp: support IPv4 NVGRE encap flow action
> > >    net/nfp: support IPv6 NVGRE encap flow action
> > >    net/nfp: prepare for IPv4 GRE tunnel decap flow action
> > >    net/nfp: prepare for IPv6 GRE tunnel decap flow action
> > >    net/nfp: support IPv4 NVGRE flow item
> > >    net/nfp: support IPv6 NVGRE flow item
> > >    net/nfp: support IPv4 NVGRE decap flow action
> > >    net/nfp: support IPv6 NVGRE decap flow action
> > >    net/nfp: support new tunnel solution
> > >
> >
> > Hi Chaoyong,
> >
> > './devtools/check-doc-vs-code.sh' tools reports some inconsistency,
> > can you please fix it?
> 
> Sorry, I can't quite understand the logic of this script.
> I'm quite sure I have listed the items and actions we supported in the file
> 'doc/guides/nics/features/nfp.ini'.
> 
> And seems it report for every nic which support rte_flow?

Oh, I found the reason now.
The git version in my host is too low, I upgrade it and it can successfully run this script now.
I will revise it and sent out a new version patch, sorry for the bother.

^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 00/26] add the extend rte_flow offload support of nfp PMD
  2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
                     ` (25 preceding siblings ...)
  2022-10-24 15:07   ` [PATCH v2 00/25] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
@ 2022-10-25  7:58   ` Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 01/26] net/nfp: fix the app stuck by CPP bridge service Chaoyong He
                       ` (26 more replies)
  26 siblings, 27 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:58 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

This is the third patch series to add the support of rte_flow offload for
nfp PMD, includes:
Add the offload support of decap/encap of VXLAN
Add the offload support of decap/encap of GENEVE
Add the offload support of decap/encap of NVGRE

Changes since v2
- Fix the inconsistency in 'nfp.ini' file.
- Modify the commit message about the new solution of tunnel decap action.
- Add a commit which fix the CPP bridge service stuck the DPDK app.

Changes since v1
- Delete the modificaiton of release note.
- Modify the commit title.
- Rebase to the lastest logic.

Chaoyong He (26):
  net/nfp: fix the app stuck by CPP bridge service
  net/nfp: support IPv4 VXLAN flow item
  net/nfp: support IPv6 VXLAN flow item
  net/nfp: prepare for IPv4 tunnel encap flow action
  net/nfp: prepare for IPv6 tunnel encap flow action
  net/nfp: support IPv4 VXLAN encap flow action
  net/nfp: support IPv6 VXLAN encap flow action
  net/nfp: prepare for IPv4 UDP tunnel decap flow action
  net/nfp: prepare for IPv6 UDP tunnel decap flow action
  net/nfp: support IPv4 VXLAN decap flow action
  net/nfp: support IPv6 VXLAN decap flow action
  net/nfp: support IPv4 GENEVE encap flow action
  net/nfp: support IPv6 GENEVE encap flow action
  net/nfp: support IPv4 GENEVE flow item
  net/nfp: support IPv6 GENEVE flow item
  net/nfp: support IPv4 GENEVE decap flow action
  net/nfp: support IPv6 GENEVE decap flow action
  net/nfp: support IPv4 NVGRE encap flow action
  net/nfp: support IPv6 NVGRE encap flow action
  net/nfp: prepare for IPv4 GRE tunnel decap flow action
  net/nfp: prepare for IPv6 GRE tunnel decap flow action
  net/nfp: support IPv4 NVGRE flow item
  net/nfp: support IPv6 NVGRE flow item
  net/nfp: support IPv4 NVGRE decap flow action
  net/nfp: support IPv6 NVGRE decap flow action
  net/nfp: support new solution for tunnel decap action

 doc/guides/nics/features/nfp.ini         |    9 +
 drivers/net/nfp/flower/nfp_flower.c      |   14 +
 drivers/net/nfp/flower/nfp_flower.h      |   24 +
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  222 +++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  415 +++++
 drivers/net/nfp/nfp_cpp_bridge.c         |    6 +
 drivers/net/nfp/nfp_flow.c               | 2003 +++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |   56 +
 8 files changed, 2680 insertions(+), 69 deletions(-)

-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 01/26] net/nfp: fix the app stuck by CPP bridge service
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
@ 2022-10-25  7:58     ` Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 02/26] net/nfp: support IPv4 VXLAN flow item Chaoyong He
                       ` (25 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:58 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

The CPP (Command Pull Push) bridge service is needed for some debug
tools, but if no debug tools has ever been run, the initial logic of
CPP bridge service will block in accept() function call, and the
DPDK app can't exit normally.

Fixes: 678648abc64c ("net/nfp: fix service stuck on application exit")

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
---
 drivers/net/nfp/nfp_cpp_bridge.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/net/nfp/nfp_cpp_bridge.c b/drivers/net/nfp/nfp_cpp_bridge.c
index db4b781302..e650fe9930 100644
--- a/drivers/net/nfp/nfp_cpp_bridge.c
+++ b/drivers/net/nfp/nfp_cpp_bridge.c
@@ -379,6 +379,7 @@ nfp_cpp_bridge_service_func(void *args)
 	struct nfp_cpp *cpp;
 	struct nfp_pf_dev *pf_dev;
 	int sockfd, datafd, op, ret;
+	struct timeval timeout = {1, 0};
 
 	unlink("/tmp/nfp_cpp");
 	sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -388,6 +389,8 @@ nfp_cpp_bridge_service_func(void *args)
 		return -EIO;
 	}
 
+	setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
+
 	memset(&address, 0, sizeof(struct sockaddr));
 
 	address.sa_family = AF_UNIX;
@@ -415,6 +418,9 @@ nfp_cpp_bridge_service_func(void *args)
 	while (rte_service_runstate_get(pf_dev->cpp_bridge_id) != 0) {
 		datafd = accept(sockfd, NULL, NULL);
 		if (datafd < 0) {
+			if (errno == EAGAIN || errno == EWOULDBLOCK)
+				continue;
+
 			RTE_LOG(ERR, PMD, "%s: accept call error (%d)\n",
 					  __func__, errno);
 			RTE_LOG(ERR, PMD, "%s: service failed\n", __func__);
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 02/26] net/nfp: support IPv4 VXLAN flow item
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 01/26] net/nfp: fix the app stuck by CPP bridge service Chaoyong He
@ 2022-10-25  7:58     ` Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 03/26] net/nfp: support IPv6 " Chaoyong He
                       ` (24 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:58 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding data structure and logics, to support
the offload of IPv4 VXLAN item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini         |   1 +
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  35 ++++
 drivers/net/nfp/nfp_flow.c               | 243 ++++++++++++++++++++---
 3 files changed, 246 insertions(+), 33 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 0184980e88..faaa7da83c 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -35,6 +35,7 @@ sctp                 = Y
 tcp                  = Y
 udp                  = Y
 vlan                 = Y
+vxlan                = Y
 
 [rte_flow actions]
 count                = Y
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 6bf8ff7d56..08e2873808 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -324,6 +324,41 @@ struct nfp_flower_ipv6 {
 	uint8_t ipv6_dst[16];
 };
 
+struct nfp_flower_tun_ipv4 {
+	rte_be32_t src;
+	rte_be32_t dst;
+};
+
+struct nfp_flower_tun_ip_ext {
+	uint8_t tos;
+	uint8_t ttl;
+};
+
+/*
+ * Flow Frame IPv4 UDP TUNNEL --> Tunnel details (5W/20B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_src                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_dst                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           Reserved            |      tos      |      ttl      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            Reserved                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     VNI                       |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv4_udp_tun {
+	struct nfp_flower_tun_ipv4 ipv4;
+	rte_be16_t reserved1;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be32_t reserved2;
+	rte_be32_t tun_id;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 69fc8be7ed..0e1e5ea6b2 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -38,7 +38,8 @@ struct nfp_flow_item_proc {
 			char **mbuf_off,
 			const struct rte_flow_item *item,
 			const struct nfp_flow_item_proc *proc,
-			bool is_mask);
+			bool is_mask,
+			bool is_outer_layer);
 	/* List of possible subsequent items. */
 	const enum rte_flow_item_type *const next_item;
 };
@@ -491,6 +492,7 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 		struct nfp_fl_key_ls *key_ls)
 {
 	struct rte_eth_dev *ethdev;
+	bool outer_ip4_flag = false;
 	const struct rte_flow_item *item;
 	struct nfp_flower_representor *representor;
 	const struct rte_flow_item_port_id *port_id;
@@ -526,6 +528,8 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV4 detected");
 			key_ls->key_layer |= NFP_FLOWER_LAYER_IPV4;
 			key_ls->key_size += sizeof(struct nfp_flower_ipv4);
+			if (!outer_ip4_flag)
+				outer_ip4_flag = true;
 			break;
 		case RTE_FLOW_ITEM_TYPE_IPV6:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV6 detected");
@@ -547,6 +551,21 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 			key_ls->key_layer |= NFP_FLOWER_LAYER_TP;
 			key_ls->key_size += sizeof(struct nfp_flower_tp_ports);
 			break;
+		case RTE_FLOW_ITEM_TYPE_VXLAN:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_VXLAN detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_VXLAN;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_VXLAN;
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -719,12 +738,25 @@ nfp_flow_key_layers_calculate(const struct rte_flow_item items[],
 	return ret;
 }
 
+static bool
+nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
+{
+	struct nfp_flower_meta_tci *meta_tci;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_VXLAN)
+		return true;
+
+	return false;
+}
+
 static int
 nfp_flow_merge_eth(__rte_unused struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_mac_mpls *eth;
 	const struct rte_flow_item_eth *spec;
@@ -760,7 +792,8 @@ nfp_flow_merge_vlan(struct rte_flow *nfp_flow,
 		__rte_unused char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_vlan *spec;
@@ -789,41 +822,58 @@ nfp_flow_merge_ipv4(struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		bool is_outer_layer)
 {
 	struct nfp_flower_ipv4 *ipv4;
 	const struct rte_ipv4_hdr *hdr;
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv4 *spec;
 	const struct rte_flow_item_ipv4 *mask;
+	struct nfp_flower_ipv4_udp_tun *ipv4_udp_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 
-	if (spec == NULL) {
-		PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
-		goto ipv4_end;
-	}
+	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
+			return 0;
+		}
 
-	/*
-	 * reserve space for L4 info.
-	 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
-	 */
-	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
-		*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 
-	hdr = is_mask ? &mask->hdr : &spec->hdr;
-	ipv4 = (struct nfp_flower_ipv4 *)*mbuf_off;
+		ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
+		ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
+		ipv4_udp_tun->ipv4.src   = hdr->src_addr;
+		ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+	} else {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
+			goto ipv4_end;
+		}
+
+		/*
+		 * reserve space for L4 info.
+		 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
+		 */
+		if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+			*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv4 = (struct nfp_flower_ipv4 *)*mbuf_off;
 
-	ipv4->ip_ext.tos   = hdr->type_of_service;
-	ipv4->ip_ext.proto = hdr->next_proto_id;
-	ipv4->ip_ext.ttl   = hdr->time_to_live;
-	ipv4->ipv4_src     = hdr->src_addr;
-	ipv4->ipv4_dst     = hdr->dst_addr;
+		ipv4->ip_ext.tos   = hdr->type_of_service;
+		ipv4->ip_ext.proto = hdr->next_proto_id;
+		ipv4->ip_ext.ttl   = hdr->time_to_live;
+		ipv4->ipv4_src     = hdr->src_addr;
+		ipv4->ipv4_dst     = hdr->dst_addr;
 
 ipv4_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4);
+		*mbuf_off += sizeof(struct nfp_flower_ipv4);
+	}
 
 	return 0;
 }
@@ -833,7 +883,8 @@ nfp_flow_merge_ipv6(struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_ipv6 *ipv6;
 	const struct rte_ipv6_hdr *hdr;
@@ -878,7 +929,8 @@ nfp_flow_merge_tcp(struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	uint8_t tcp_flags;
 	struct nfp_flower_tp_ports *ports;
@@ -950,7 +1002,8 @@ nfp_flow_merge_udp(struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		bool is_outer_layer)
 {
 	char *ports_off;
 	struct nfp_flower_tp_ports *ports;
@@ -964,6 +1017,12 @@ nfp_flow_merge_udp(struct rte_flow *nfp_flow,
 		return 0;
 	}
 
+	/* Don't add L4 info if working on a inner layer pattern */
+	if (!is_outer_layer) {
+		PMD_DRV_LOG(INFO, "Detected inner layer UDP, skipping.");
+		return 0;
+	}
+
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4) {
 		ports_off = *mbuf_off - sizeof(struct nfp_flower_ipv4) -
@@ -991,7 +1050,8 @@ nfp_flow_merge_sctp(struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
-		bool is_mask)
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
 {
 	char *ports_off;
 	struct nfp_flower_tp_ports *ports;
@@ -1027,10 +1087,42 @@ nfp_flow_merge_sctp(struct rte_flow *nfp_flow,
 	return 0;
 }
 
+static int
+nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	const struct rte_vxlan_hdr *hdr;
+	struct nfp_flower_ipv4_udp_tun *tun4;
+	const struct rte_flow_item_vxlan *spec;
+	const struct rte_flow_item_vxlan *mask;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge vxlan: no item->spec!");
+		goto vxlan_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	hdr = is_mask ? &mask->hdr : &spec->hdr;
+
+	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+	tun4->tun_id = hdr->vx_vni;
+
+vxlan_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+
+	return 0;
+}
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
-		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH,
+			RTE_FLOW_ITEM_TYPE_IPV4),
 	},
 	[RTE_FLOW_ITEM_TYPE_ETH] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VLAN,
@@ -1113,6 +1205,7 @@ static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 		.merge = nfp_flow_merge_tcp,
 	},
 	[RTE_FLOW_ITEM_TYPE_UDP] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN),
 		.mask_support = &(const struct rte_flow_item_udp){
 			.hdr = {
 				.src_port = RTE_BE16(0xffff),
@@ -1134,6 +1227,17 @@ static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 		.mask_sz = sizeof(struct rte_flow_item_sctp),
 		.merge = nfp_flow_merge_sctp,
 	},
+	[RTE_FLOW_ITEM_TYPE_VXLAN] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &(const struct rte_flow_item_vxlan){
+			.hdr = {
+				.vx_vni = RTE_BE32(0xffffff00),
+			},
+		},
+		.mask_default = &rte_flow_item_vxlan_mask,
+		.mask_sz = sizeof(struct rte_flow_item_vxlan),
+		.merge = nfp_flow_merge_vxlan,
+	},
 };
 
 static int
@@ -1187,21 +1291,53 @@ nfp_flow_item_check(const struct rte_flow_item *item,
 	return ret;
 }
 
+static bool
+nfp_flow_is_tun_item(const struct rte_flow_item *item)
+{
+	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN)
+		return true;
+
+	return false;
+}
+
+static bool
+nfp_flow_inner_item_get(const struct rte_flow_item items[],
+		const struct rte_flow_item **inner_item)
+{
+	const struct rte_flow_item *item;
+
+	*inner_item = items;
+
+	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
+		if (nfp_flow_is_tun_item(item)) {
+			*inner_item = ++item;
+			return true;
+		}
+	}
+
+	return false;
+}
+
 static int
 nfp_flow_compile_item_proc(const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow,
 		char **mbuf_off_exact,
-		char **mbuf_off_mask)
+		char **mbuf_off_mask,
+		bool is_outer_layer)
 {
 	int i;
 	int ret = 0;
+	bool continue_flag = true;
 	const struct rte_flow_item *item;
 	const struct nfp_flow_item_proc *proc_list;
 
 	proc_list = nfp_flow_item_proc_list;
-	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END; ++item) {
+	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END && continue_flag; ++item) {
 		const struct nfp_flow_item_proc *proc = NULL;
 
+		if (nfp_flow_is_tun_item(item))
+			continue_flag = false;
+
 		for (i = 0; proc_list->next_item && proc_list->next_item[i]; ++i) {
 			if (proc_list->next_item[i] == item->type) {
 				proc = &nfp_flow_item_proc_list[item->type];
@@ -1230,14 +1366,14 @@ nfp_flow_compile_item_proc(const struct rte_flow_item items[],
 		}
 
 		ret = proc->merge(nfp_flow, mbuf_off_exact, item,
-				proc, false);
+				proc, false, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d exact merge failed", item->type);
 			break;
 		}
 
 		ret = proc->merge(nfp_flow, mbuf_off_mask, item,
-				proc, true);
+				proc, true, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d mask merge failed", item->type);
 			break;
@@ -1257,6 +1393,9 @@ nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
 	int ret;
 	char *mbuf_off_mask;
 	char *mbuf_off_exact;
+	bool is_tun_flow = false;
+	bool is_outer_layer = true;
+	const struct rte_flow_item *loop_item;
 
 	mbuf_off_exact = nfp_flow->payload.unmasked_data +
 			sizeof(struct nfp_flower_meta_tci) +
@@ -1265,14 +1404,29 @@ nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
 			sizeof(struct nfp_flower_meta_tci) +
 			sizeof(struct nfp_flower_in_port);
 
+	/* Check if this is a tunnel flow and get the inner item*/
+	is_tun_flow = nfp_flow_inner_item_get(items, &loop_item);
+	if (is_tun_flow)
+		is_outer_layer = false;
+
 	/* Go over items */
-	ret = nfp_flow_compile_item_proc(items, nfp_flow,
-			&mbuf_off_exact, &mbuf_off_mask);
+	ret = nfp_flow_compile_item_proc(loop_item, nfp_flow,
+			&mbuf_off_exact, &mbuf_off_mask, is_outer_layer);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "nfp flow item compile failed.");
 		return -EINVAL;
 	}
 
+	/* Go over inner items */
+	if (is_tun_flow) {
+		ret = nfp_flow_compile_item_proc(items, nfp_flow,
+				&mbuf_off_exact, &mbuf_off_mask, true);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "nfp flow outer item compile failed.");
+			return -EINVAL;
+		}
+	}
+
 	return 0;
 }
 
@@ -2119,12 +2273,35 @@ nfp_flow_query(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int
+nfp_flow_tunnel_match(__rte_unused struct rte_eth_dev *dev,
+		__rte_unused struct rte_flow_tunnel *tunnel,
+		__rte_unused struct rte_flow_item **pmd_items,
+		uint32_t *num_of_items,
+		__rte_unused struct rte_flow_error *err)
+{
+	*num_of_items = 0;
+
+	return 0;
+}
+
+static int
+nfp_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev,
+		__rte_unused struct rte_flow_item *pmd_items,
+		__rte_unused uint32_t num_of_items,
+		__rte_unused struct rte_flow_error *err)
+{
+	return 0;
+}
+
 static const struct rte_flow_ops nfp_flow_ops = {
 	.validate                    = nfp_flow_validate,
 	.create                      = nfp_flow_create,
 	.destroy                     = nfp_flow_destroy,
 	.flush                       = nfp_flow_flush,
 	.query                       = nfp_flow_query,
+	.tunnel_match                = nfp_flow_tunnel_match,
+	.tunnel_item_release         = nfp_flow_tunnel_item_release,
 };
 
 int
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 03/26] net/nfp: support IPv6 VXLAN flow item
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 01/26] net/nfp: fix the app stuck by CPP bridge service Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 02/26] net/nfp: support IPv4 VXLAN flow item Chaoyong He
@ 2022-10-25  7:58     ` Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 04/26] net/nfp: prepare for IPv4 tunnel encap flow action Chaoyong He
                       ` (23 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:58 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding data structure and logics, to support
the offload of IPv6 VXLAN item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  42 +++++++++
 drivers/net/nfp/nfp_flow.c               | 113 +++++++++++++++++------
 2 files changed, 129 insertions(+), 26 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 08e2873808..996ba3b982 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -329,6 +329,11 @@ struct nfp_flower_tun_ipv4 {
 	rte_be32_t dst;
 };
 
+struct nfp_flower_tun_ipv6 {
+	uint8_t ipv6_src[16];
+	uint8_t ipv6_dst[16];
+};
+
 struct nfp_flower_tun_ip_ext {
 	uint8_t tos;
 	uint8_t ttl;
@@ -359,6 +364,43 @@ struct nfp_flower_ipv4_udp_tun {
 	rte_be32_t tun_id;
 };
 
+/*
+ * Flow Frame IPv6 UDP TUNNEL --> Tunnel details (11W/44B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           Reserved            |      tos      |      ttl      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            Reserved                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     VNI                       |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv6_udp_tun {
+	struct nfp_flower_tun_ipv6 ipv6;
+	rte_be16_t reserved1;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be32_t reserved2;
+	rte_be32_t tun_id;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 0e1e5ea6b2..bbd9dbabde 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -493,6 +493,7 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 {
 	struct rte_eth_dev *ethdev;
 	bool outer_ip4_flag = false;
+	bool outer_ip6_flag = false;
 	const struct rte_flow_item *item;
 	struct nfp_flower_representor *representor;
 	const struct rte_flow_item_port_id *port_id;
@@ -535,6 +536,8 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_IPV6 detected");
 			key_ls->key_layer |= NFP_FLOWER_LAYER_IPV6;
 			key_ls->key_size += sizeof(struct nfp_flower_ipv6);
+			if (!outer_ip6_flag)
+				outer_ip6_flag = true;
 			break;
 		case RTE_FLOW_ITEM_TYPE_TCP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_TCP detected");
@@ -553,8 +556,9 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 			break;
 		case RTE_FLOW_ITEM_TYPE_VXLAN:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_VXLAN detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_VXLAN;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_VXLAN;
 			if (outer_ip4_flag) {
@@ -564,6 +568,19 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 				 * in `struct nfp_flower_ipv4_udp_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for VXLAN tunnel.");
+				return -EINVAL;
 			}
 			break;
 		default:
@@ -884,42 +901,61 @@ nfp_flow_merge_ipv6(struct rte_flow *nfp_flow,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
 		bool is_mask,
-		__rte_unused bool is_outer_layer)
+		bool is_outer_layer)
 {
 	struct nfp_flower_ipv6 *ipv6;
 	const struct rte_ipv6_hdr *hdr;
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv6 *spec;
 	const struct rte_flow_item_ipv6 *mask;
+	struct nfp_flower_ipv6_udp_tun *ipv6_udp_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 
-	if (spec == NULL) {
-		PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
-		goto ipv6_end;
-	}
+	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
+			return 0;
+		}
 
-	/*
-	 * reserve space for L4 info.
-	 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv4
-	 */
-	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
-		*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+
+		ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
+				RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+		ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
+		memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
+				sizeof(ipv6_udp_tun->ipv6.ipv6_src));
+		memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
+				sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+	} else {
+		if (spec == NULL) {
+			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
+			goto ipv6_end;
+		}
 
-	hdr = is_mask ? &mask->hdr : &spec->hdr;
-	ipv6 = (struct nfp_flower_ipv6 *)*mbuf_off;
+		/*
+		 * reserve space for L4 info.
+		 * rte_flow has ipv4 before L4 but NFP flower fw requires L4 before ipv6
+		 */
+		if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+			*mbuf_off += sizeof(struct nfp_flower_tp_ports);
+
+		hdr = is_mask ? &mask->hdr : &spec->hdr;
+		ipv6 = (struct nfp_flower_ipv6 *)*mbuf_off;
 
-	ipv6->ip_ext.tos   = (hdr->vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
-			RTE_IPV6_HDR_TC_SHIFT;
-	ipv6->ip_ext.proto = hdr->proto;
-	ipv6->ip_ext.ttl   = hdr->hop_limits;
-	memcpy(ipv6->ipv6_src, hdr->src_addr, sizeof(ipv6->ipv6_src));
-	memcpy(ipv6->ipv6_dst, hdr->dst_addr, sizeof(ipv6->ipv6_dst));
+		ipv6->ip_ext.tos   = (hdr->vtc_flow & RTE_IPV6_HDR_TC_MASK) >>
+				RTE_IPV6_HDR_TC_SHIFT;
+		ipv6->ip_ext.proto = hdr->proto;
+		ipv6->ip_ext.ttl   = hdr->hop_limits;
+		memcpy(ipv6->ipv6_src, hdr->src_addr, sizeof(ipv6->ipv6_src));
+		memcpy(ipv6->ipv6_dst, hdr->dst_addr, sizeof(ipv6->ipv6_dst));
 
 ipv6_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv6);
+		*mbuf_off += sizeof(struct nfp_flower_ipv6);
+	}
 
 	return 0;
 }
@@ -1088,7 +1124,7 @@ nfp_flow_merge_sctp(struct rte_flow *nfp_flow,
 }
 
 static int
-nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
+nfp_flow_merge_vxlan(struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1097,8 +1133,15 @@ nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
 {
 	const struct rte_vxlan_hdr *hdr;
 	struct nfp_flower_ipv4_udp_tun *tun4;
+	struct nfp_flower_ipv6_udp_tun *tun6;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_vxlan *spec;
 	const struct rte_flow_item_vxlan *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1109,11 +1152,21 @@ nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
 	mask = item->mask ? item->mask : proc->mask_default;
 	hdr = is_mask ? &mask->hdr : &spec->hdr;
 
-	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
-	tun4->tun_id = hdr->vx_vni;
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+		tun6->tun_id = hdr->vx_vni;
+	} else {
+		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+		tun4->tun_id = hdr->vx_vni;
+	}
 
 vxlan_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6))
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_udp_tun);
+	else
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 
 	return 0;
 }
@@ -1122,7 +1175,8 @@ nfp_flow_merge_vxlan(__rte_unused struct rte_flow *nfp_flow,
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH,
-			RTE_FLOW_ITEM_TYPE_IPV4),
+			RTE_FLOW_ITEM_TYPE_IPV4,
+			RTE_FLOW_ITEM_TYPE_IPV6),
 	},
 	[RTE_FLOW_ITEM_TYPE_ETH] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VLAN,
@@ -1395,6 +1449,7 @@ nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
 	char *mbuf_off_exact;
 	bool is_tun_flow = false;
 	bool is_outer_layer = true;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item *loop_item;
 
 	mbuf_off_exact = nfp_flow->payload.unmasked_data +
@@ -1404,6 +1459,12 @@ nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
 			sizeof(struct nfp_flower_meta_tci) +
 			sizeof(struct nfp_flower_in_port);
 
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META) {
+		mbuf_off_exact += sizeof(struct nfp_flower_ext_meta);
+		mbuf_off_mask += sizeof(struct nfp_flower_ext_meta);
+	}
+
 	/* Check if this is a tunnel flow and get the inner item*/
 	is_tun_flow = nfp_flow_inner_item_get(items, &loop_item);
 	if (is_tun_flow)
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 04/26] net/nfp: prepare for IPv4 tunnel encap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (2 preceding siblings ...)
  2022-10-25  7:58     ` [PATCH v3 03/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:58     ` Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 05/26] net/nfp: prepare for IPv6 " Chaoyong He
                       ` (22 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:58 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the encap action of IPv4 tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c | 29 ++++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 93 ++++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 88 ++++++++++++++++++++++
 drivers/net/nfp/nfp_flow.h               | 27 +++++++
 4 files changed, 237 insertions(+)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 15d838117a..7021d1fd43 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -246,3 +246,32 @@ nfp_flower_cmsg_flow_add(struct nfp_app_fw_flower *app_fw_flower,
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v4 *payload)
+{
+	uint16_t cnt;
+	size_t msg_len;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_neigh_v4 *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v4 tun neigh");
+		return -ENOMEM;
+	}
+
+	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v4);
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, msg_len);
+	memcpy(msg, payload, msg_len);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 996ba3b982..e44e311176 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -129,6 +129,36 @@ struct nfp_flower_cmsg_port_mod {
 	rte_be16_t mtu;
 };
 
+struct nfp_flower_tun_neigh {
+	uint8_t dst_mac[RTE_ETHER_ADDR_LEN];
+	uint8_t src_mac[RTE_ETHER_ADDR_LEN];
+	rte_be32_t port_id;
+};
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V4
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                           DST_IPV4                            |
+ *          +---------------------------------------------------------------+
+ *        1 |                           SRC_IPV4                            |
+ *          +---------------------------------------------------------------+
+ *        2 |                      DST_MAC_B5_B4_B3_B2                      |
+ *          +-------------------------------+-------------------------------+
+ *        3 |             DST_MAC_B1_B0     |        SRC_MAC_B5_B4          |
+ *          +-------------------------------+-------------------------------+
+ *        4 |                       SRC_MAC_B3_B2_B1_B0                     |
+ *          +---------------------------------------------------------------+
+ *        5 |                    Egress Port (NFP internal)                 |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_neigh_v4 {
+	rte_be32_t dst_ipv4;
+	rte_be32_t src_ipv4;
+	struct nfp_flower_tun_neigh common;
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -574,6 +604,67 @@ struct nfp_fl_act_set_tport {
 	rte_be16_t dst_port;
 };
 
+/*
+ * Pre-tunnel
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |  -  |  opcode |       |jump_id|              -      |M|   - |V|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |         ipv6_daddr_127_96     /     ipv4_daddr                |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_95_64                          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_63_32                          |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                     ipv6_daddr_31_0                           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_fl_act_pre_tun {
+	struct nfp_fl_act_head head;
+	rte_be16_t flags;
+	union {
+		rte_be32_t ipv4_dst;
+		uint8_t ipv6_dst[16];
+	};
+};
+
+/*
+ * Set tunnel
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | res |  opcode |  res  | len_lw|           reserved            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            tun_id0                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                            tun_id1                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                      reserved                 |  type |r| idx |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           ipv4_flags          |      ttl      |      tos      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         reserved_cvs1                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |          reserved_cvs2        |        reserved_cvs3          |
+ * |            var_flags          |            var_np             |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_fl_act_set_tun {
+	struct nfp_fl_act_head head;
+	rte_be16_t reserved;
+	rte_be64_t tun_id;
+	rte_be32_t tun_type_index;
+	rte_be16_t tun_flags;
+	uint8_t    ttl;
+	uint8_t    tos;
+	rte_be16_t outer_vlan_tpid;
+	rte_be16_t outer_vlan_tci;
+	uint8_t    tun_len;      /* Only valid for NFP_FL_TUNNEL_GENEVE */
+	uint8_t    reserved2;
+	rte_be16_t tun_proto;    /* Only valid for NFP_FL_TUNNEL_GENEVE */
+} __rte_packed;
+
 int nfp_flower_cmsg_mac_repr(struct nfp_app_fw_flower *app_fw_flower);
 int nfp_flower_cmsg_repr_reify(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_representor *repr);
@@ -583,5 +674,7 @@ int nfp_flower_cmsg_flow_delete(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
 int nfp_flower_cmsg_flow_add(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
+int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index bbd9dbabde..f71f8b1d5b 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1772,6 +1772,91 @@ nfp_flow_action_set_tc(char *act_data,
 	tc_hl->reserved = 0;
 }
 
+__rte_unused static void
+nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
+		rte_be32_t ipv4_dst)
+{
+	pre_tun->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
+	pre_tun->head.len_lw  = sizeof(struct nfp_fl_act_pre_tun) >> NFP_FL_LW_SIZ;
+	pre_tun->ipv4_dst     = ipv4_dst;
+}
+
+__rte_unused static void
+nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
+		enum nfp_flower_tun_type tun_type,
+		uint64_t tun_id,
+		uint8_t ttl,
+		uint8_t tos)
+{
+	/* Currently only support one pre-tunnel, so index is always 0. */
+	uint8_t pretun_idx = 0;
+	uint32_t tun_type_index;
+
+	tun_type_index = ((tun_type << 4) & 0xf0) | (pretun_idx & 0x07);
+
+	set_tun->head.jump_id   = NFP_FL_ACTION_OPCODE_SET_TUNNEL;
+	set_tun->head.len_lw    = sizeof(struct nfp_fl_act_set_tun) >> NFP_FL_LW_SIZ;
+	set_tun->tun_type_index = rte_cpu_to_be_32(tun_type_index);
+	set_tun->tun_id         = rte_cpu_to_be_64(tun_id);
+	set_tun->ttl            = ttl;
+	set_tun->tos            = tos;
+}
+
+__rte_unused static int
+nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun,
+		const struct rte_ether_hdr *eth,
+		const struct rte_flow_item_ipv4 *ipv4)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	tun->payload.v6_flag = 0;
+	tun->payload.dst.dst_ipv4 = ipv4->hdr.dst_addr;
+	tun->payload.src.src_ipv4 = ipv4->hdr.src_addr;
+	memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	port = (struct nfp_flower_in_port *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4->hdr.dst_addr;
+	payload.src_ipv4 = ipv4->hdr.src_addr;
+	memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
+__rte_unused static int
+nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
@@ -2487,6 +2572,9 @@ nfp_flow_priv_init(struct nfp_pf_dev *pf_dev)
 		goto free_mask_table;
 	}
 
+	/* neighbor next list */
+	LIST_INIT(&priv->nn_list);
+
 	return 0;
 
 free_mask_table:
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index 0ad89e51f4..892dbc08f1 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -90,6 +90,11 @@ enum nfp_flower_tun_type {
 	NFP_FL_TUN_GENEVE = 4,
 };
 
+enum nfp_flow_type {
+	NFP_FLOW_COMMON,
+	NFP_FLOW_ENCAP,
+};
+
 struct nfp_fl_key_ls {
 	uint32_t key_layer_two;
 	uint8_t key_layer;
@@ -118,6 +123,24 @@ struct nfp_fl_payload {
 	char *action_data;
 };
 
+struct nfp_fl_tun {
+	LIST_ENTRY(nfp_fl_tun) next;
+	uint8_t ref_cnt;
+	struct nfp_fl_tun_entry {
+		uint8_t v6_flag;
+		uint8_t dst_addr[RTE_ETHER_ADDR_LEN];
+		uint8_t src_addr[RTE_ETHER_ADDR_LEN];
+		union {
+			rte_be32_t dst_ipv4;
+			uint8_t dst_ipv6[16];
+		} dst;
+		union {
+			rte_be32_t src_ipv4;
+			uint8_t src_ipv6[16];
+		} src;
+	} payload;
+};
+
 #define CIRC_CNT(head, tail, size)     (((head) - (tail)) & ((size) - 1))
 #define CIRC_SPACE(head, tail, size)   CIRC_CNT((tail), ((head) + 1), (size))
 struct circ_buf {
@@ -161,13 +184,17 @@ struct nfp_flow_priv {
 	struct nfp_fl_stats_id stats_ids; /**< The stats id ring. */
 	struct nfp_fl_stats *stats; /**< Store stats of flow. */
 	rte_spinlock_t stats_lock; /** < Lock the update of 'stats' field. */
+	/* neighbor next */
+	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
 
 struct rte_flow {
 	struct nfp_fl_payload payload;
+	struct nfp_fl_tun tun;
 	size_t length;
 	uint32_t hash_key;
 	bool install_flag;
+	enum nfp_flow_type type;
 };
 
 int nfp_flow_priv_init(struct nfp_pf_dev *pf_dev);
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 05/26] net/nfp: prepare for IPv6 tunnel encap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (3 preceding siblings ...)
  2022-10-25  7:58     ` [PATCH v3 04/26] net/nfp: prepare for IPv4 tunnel encap flow action Chaoyong He
@ 2022-10-25  7:58     ` Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 06/26] net/nfp: support IPv4 VXLAN " Chaoyong He
                       ` (21 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:58 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the encap action of IPv6 tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  29 +++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  40 +++++++++
 drivers/net/nfp/nfp_flow.c               | 105 ++++++++++++++++++++++-
 3 files changed, 173 insertions(+), 1 deletion(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 7021d1fd43..8983178378 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -275,3 +275,32 @@ nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v6 *payload)
+{
+	uint16_t cnt;
+	size_t msg_len;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_neigh_v6 *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v6 tun neigh");
+		return -ENOMEM;
+	}
+
+	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v6);
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6, msg_len);
+	memcpy(msg, payload, msg_len);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index e44e311176..d1e0562cf9 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -159,6 +159,42 @@ struct nfp_flower_cmsg_tun_neigh_v4 {
 	struct nfp_flower_tun_neigh common;
 };
 
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                          DST_IPV6 [0]                         |
+ *          +---------------------------------------------------------------+
+ *        1 |                          DST_IPV6 [1]                         |
+ *          +---------------------------------------------------------------+
+ *        2 |                          DST_IPV6 [2]                         |
+ *          +---------------------------------------------------------------+
+ *        3 |                          DST_IPV6 [3]                         |
+ *          +---------------------------------------------------------------+
+ *        4 |                          SRC_IPV6 [0]                         |
+ *          +---------------------------------------------------------------+
+ *        5 |                          SRC_IPV6 [1]                         |
+ *          +---------------------------------------------------------------+
+ *        6 |                          SRC_IPV6 [2]                         |
+ *          +---------------------------------------------------------------+
+ *        7 |                          SRC_IPV6 [3]                         |
+ *          +---------------------------------------------------------------+
+ *        8 |                       DST_MAC_B5_B4_B3_B2                     |
+ *          +-------------------------------+-------------------------------+
+ *        9 |             DST_MAC_B1_B0     |        SRC_MAC_B5_B4          |
+ *          +-------------------------------+-------------------------------+
+ *       10 |                       SRC_MAC_B3_B2_B1_B0                     |
+ *          +---------------+---------------+---------------+---------------+
+ *       11 |                    Egress Port (NFP internal)                 |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_neigh_v6 {
+	uint8_t dst_ipv6[16];
+	uint8_t src_ipv6[16];
+	struct nfp_flower_tun_neigh common;
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -629,6 +665,8 @@ struct nfp_fl_act_pre_tun {
 	};
 };
 
+#define NFP_FL_PRE_TUN_IPV6    (1 << 0)
+
 /*
  * Set tunnel
  *    3                   2                   1
@@ -676,5 +714,7 @@ int nfp_flower_cmsg_flow_add(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *flow);
 int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
+int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index f71f8b1d5b..e1b892f303 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1781,6 +1781,16 @@ nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
 	pre_tun->ipv4_dst     = ipv4_dst;
 }
 
+__rte_unused static void
+nfp_flow_pre_tun_v6_process(struct nfp_fl_act_pre_tun *pre_tun,
+		const uint8_t ipv6_dst[])
+{
+	pre_tun->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
+	pre_tun->head.len_lw  = sizeof(struct nfp_fl_act_pre_tun) >> NFP_FL_LW_SIZ;
+	pre_tun->flags        = rte_cpu_to_be_16(NFP_FL_PRE_TUN_IPV6);
+	memcpy(pre_tun->ipv6_dst, ipv6_dst, sizeof(pre_tun->ipv6_dst));
+}
+
 __rte_unused static void
 nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
 		enum nfp_flower_tun_type tun_type,
@@ -1845,7 +1855,7 @@ nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
 {
@@ -1857,6 +1867,99 @@ nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun,
+		const struct rte_ether_hdr *eth,
+		const struct rte_flow_item_ipv6 *ipv6)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	tun->payload.v6_flag = 1;
+	memcpy(tun->payload.dst.dst_ipv6, ipv6->hdr.dst_addr, sizeof(tun->payload.dst.dst_ipv6));
+	memcpy(tun->payload.src.src_ipv6, ipv6->hdr.src_addr, sizeof(tun->payload.src.src_ipv6));
+	memcpy(tun->payload.dst_addr, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	port = (struct nfp_flower_in_port *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6->hdr.dst_addr, sizeof(payload.dst_ipv6));
+	memcpy(payload.src_ipv6, ipv6->hdr.src_addr, sizeof(payload.src_ipv6));
+	memcpy(payload.common.dst_mac, eth->dst_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->src_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
+static int
+nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t *ipv6)
+{
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6, sizeof(payload.dst_ipv6));
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
+__rte_unused static int
+nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	bool flag = false;
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+
+	tun = &nfp_flow->tun;
+	LIST_FOREACH(tmp, &app_fw_flower->flow_priv->nn_list, next) {
+		ret = memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry));
+		if (ret == 0) {
+			tmp->ref_cnt--;
+			flag = true;
+			break;
+		}
+	}
+
+	if (!flag) {
+		PMD_DRV_LOG(DEBUG, "Can't find nn entry in the nn list");
+		return -EINVAL;
+	}
+
+	if (tmp->ref_cnt == 0) {
+		LIST_REMOVE(tmp, next);
+		if (tmp->payload.v6_flag != 0) {
+			return nfp_flower_del_tun_neigh_v6(app_fw_flower,
+					tmp->payload.dst.dst_ipv6);
+		} else {
+			return nfp_flower_del_tun_neigh_v4(app_fw_flower,
+					tmp->payload.dst.dst_ipv4);
+		}
+	}
+
+	return 0;
+}
+
 static int
 nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 06/26] net/nfp: support IPv4 VXLAN encap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (4 preceding siblings ...)
  2022-10-25  7:58     ` [PATCH v3 05/26] net/nfp: prepare for IPv6 " Chaoyong He
@ 2022-10-25  7:58     ` Chaoyong He
  2022-10-25  7:58     ` [PATCH v3 07/26] net/nfp: support IPv6 " Chaoyong He
                       ` (20 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:58 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv4 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |   1 +
 drivers/net/nfp/nfp_flow.c       | 132 +++++++++++++++++++++++++++++--
 2 files changed, 128 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index faaa7da83c..ff97787bd9 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -56,3 +56,4 @@ set_mac_src          = Y
 set_tp_dst           = Y
 set_tp_src           = Y
 set_ttl              = Y
+vxlan_encap          = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index e1b892f303..d2e779ca96 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -10,8 +10,10 @@
 #include <rte_malloc.h>
 
 #include "nfp_common.h"
+#include "nfp_ctrl.h"
 #include "nfp_flow.h"
 #include "nfp_logs.h"
+#include "nfp_rxtx.h"
 #include "flower/nfp_flower.h"
 #include "flower/nfp_flower_cmsg.h"
 #include "flower/nfp_flower_ctrl.h"
@@ -19,6 +21,17 @@
 #include "nfpcore/nfp_mip.h"
 #include "nfpcore/nfp_rtsym.h"
 
+/*
+ * Maximum number of items in struct rte_flow_action_vxlan_encap.
+ * ETH / IPv4(6) / UDP / VXLAN / END
+ */
+#define ACTION_VXLAN_ENCAP_ITEMS_NUM 5
+
+struct vxlan_data {
+	struct rte_flow_action_vxlan_encap conf;
+	struct rte_flow_item items[ACTION_VXLAN_ENCAP_ITEMS_NUM];
+};
+
 /* Static initializer for a list of subsequent item types */
 #define NEXT_ITEM(...) \
 	((const enum rte_flow_item_type []){ \
@@ -724,6 +737,11 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[],
 				tc_hl_flag = true;
 			}
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP detected");
+			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
+			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1772,7 +1790,7 @@ nfp_flow_action_set_tc(char *act_data,
 	tc_hl->reserved = 0;
 }
 
-__rte_unused static void
+static void
 nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
 		rte_be32_t ipv4_dst)
 {
@@ -1791,7 +1809,7 @@ nfp_flow_pre_tun_v6_process(struct nfp_fl_act_pre_tun *pre_tun,
 	memcpy(pre_tun->ipv6_dst, ipv6_dst, sizeof(pre_tun->ipv6_dst));
 }
 
-__rte_unused static void
+static void
 nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
 		enum nfp_flower_tun_type tun_type,
 		uint64_t tun_id,
@@ -1812,7 +1830,7 @@ nfp_flow_set_tun_process(struct nfp_fl_act_set_tun *set_tun,
 	set_tun->tos            = tos;
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct nfp_fl_tun *tun,
@@ -1922,7 +1940,7 @@ nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -1961,7 +1979,81 @@ nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
 }
 
 static int
-nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
+nfp_flow_action_vxlan_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct vxlan_data *vxlan_data,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	const struct rte_flow_item_eth *eth;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_vxlan *vxlan;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth   = (const struct rte_flow_item_eth *)vxlan_data->items[0].spec;
+	ipv4  = (const struct rte_flow_item_ipv4 *)vxlan_data->items[1].spec;
+	vxlan = (const struct rte_flow_item_vxlan *)vxlan_data->items[3].spec;
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_VXLAN, vxlan->hdr.vx_vni,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_flags = vxlan->hdr.vx_flags;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, &eth->hdr, ipv4);
+}
+
+static int
+nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	size_t act_len;
+	size_t act_pre_size;
+	const struct vxlan_data *vxlan_data;
+
+	vxlan_data = action->conf;
+	if (vxlan_data->items[0].type != RTE_FLOW_ITEM_TYPE_ETH ||
+			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 ||
+			vxlan_data->items[2].type != RTE_FLOW_ITEM_TYPE_UDP ||
+			vxlan_data->items[3].type != RTE_FLOW_ITEM_TYPE_VXLAN ||
+			vxlan_data->items[4].type != RTE_FLOW_ITEM_TYPE_END) {
+		PMD_DRV_LOG(ERR, "Not an valid vxlan action conf.");
+		return -EINVAL;
+	}
+
+	/*
+	 * Pre_tunnel action must be the first on the action list.
+	 * If other actions already exist, they need to be pushed forward.
+	 */
+	act_len = act_data - actions;
+	if (act_len != 0) {
+		act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+		memmove(actions + act_pre_size, actions, act_len);
+	}
+
+	if (vxlan_data->items[1].type == RTE_FLOW_ITEM_TYPE_IPV4)
+		return nfp_flow_action_vxlan_encap_v4(app_fw_flower, act_data,
+				actions, vxlan_data, nfp_flow_meta, tun);
+
+	return 0;
+}
+
+static int
+nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
 		struct rte_flow *nfp_flow)
 {
@@ -2118,6 +2210,20 @@ nfp_flow_compile_action(__rte_unused struct nfp_flower_representor *representor,
 				tc_hl_flag = true;
 			}
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP");
+			ret = nfp_flow_action_vxlan_encap(representor->app_fw_flower,
+					position, action_data, action, nfp_flow_meta,
+					&nfp_flow->tun);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process"
+						" RTE_FLOW_ACTION_TYPE_VXLAN_ENCAP");
+				return ret;
+			}
+			position += sizeof(struct nfp_fl_act_pre_tun);
+			position += sizeof(struct nfp_fl_act_set_tun);
+			nfp_flow->type = NFP_FLOW_ENCAP;
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
 			return -ENOTSUP;
@@ -2410,6 +2516,22 @@ nfp_flow_destroy(struct rte_eth_dev *dev,
 		goto exit;
 	}
 
+	switch (nfp_flow->type) {
+	case NFP_FLOW_COMMON:
+		break;
+	case NFP_FLOW_ENCAP:
+		/* Delete the entry from nn table */
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Invalid nfp flow type %d.", nfp_flow->type);
+		ret = -EINVAL;
+		break;
+	}
+
+	if (ret != 0)
+		goto exit;
+
 	/* Delete the flow from hardware */
 	if (nfp_flow->install_flag) {
 		ret = nfp_flower_cmsg_flow_delete(app_fw_flower, nfp_flow);
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 07/26] net/nfp: support IPv6 VXLAN encap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (5 preceding siblings ...)
  2022-10-25  7:58     ` [PATCH v3 06/26] net/nfp: support IPv4 VXLAN " Chaoyong He
@ 2022-10-25  7:58     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 08/26] net/nfp: prepare for IPv4 UDP tunnel decap " Chaoyong He
                       ` (19 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:58 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv6 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 48 ++++++++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 5 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index d2e779ca96..9ee02b0fb9 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1799,7 +1799,7 @@ nfp_flow_pre_tun_v4_process(struct nfp_fl_act_pre_tun *pre_tun,
 	pre_tun->ipv4_dst     = ipv4_dst;
 }
 
-__rte_unused static void
+static void
 nfp_flow_pre_tun_v6_process(struct nfp_fl_act_pre_tun *pre_tun,
 		const uint8_t ipv6_dst[])
 {
@@ -1885,7 +1885,7 @@ nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct nfp_fl_tun *tun,
@@ -2013,6 +2013,42 @@ nfp_flow_action_vxlan_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
 			tun, &eth->hdr, ipv4);
 }
 
+static int
+nfp_flow_action_vxlan_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct vxlan_data *vxlan_data,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	const struct rte_flow_item_eth *eth;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_vxlan *vxlan;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth   = (const struct rte_flow_item_eth *)vxlan_data->items[0].spec;
+	ipv6  = (const struct rte_flow_item_ipv6 *)vxlan_data->items[1].spec;
+	vxlan = (const struct rte_flow_item_vxlan *)vxlan_data->items[3].spec;
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_VXLAN, vxlan->hdr.vx_vni,
+			ipv6->hdr.hop_limits,
+			(ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff);
+	set_tun->tun_flags = vxlan->hdr.vx_flags;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, &eth->hdr, ipv6);
+}
+
 static int
 nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
@@ -2027,7 +2063,8 @@ nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
 
 	vxlan_data = action->conf;
 	if (vxlan_data->items[0].type != RTE_FLOW_ITEM_TYPE_ETH ||
-			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 ||
+			(vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV4 &&
+			vxlan_data->items[1].type != RTE_FLOW_ITEM_TYPE_IPV6) ||
 			vxlan_data->items[2].type != RTE_FLOW_ITEM_TYPE_UDP ||
 			vxlan_data->items[3].type != RTE_FLOW_ITEM_TYPE_VXLAN ||
 			vxlan_data->items[4].type != RTE_FLOW_ITEM_TYPE_END) {
@@ -2048,8 +2085,9 @@ nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
 	if (vxlan_data->items[1].type == RTE_FLOW_ITEM_TYPE_IPV4)
 		return nfp_flow_action_vxlan_encap_v4(app_fw_flower, act_data,
 				actions, vxlan_data, nfp_flow_meta, tun);
-
-	return 0;
+	else
+		return nfp_flow_action_vxlan_encap_v6(app_fw_flower, act_data,
+				actions, vxlan_data, nfp_flow_meta, tun);
 }
 
 static int
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 08/26] net/nfp: prepare for IPv4 UDP tunnel decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (6 preceding siblings ...)
  2022-10-25  7:58     ` [PATCH v3 07/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 09/26] net/nfp: prepare for IPv6 " Chaoyong He
                       ` (18 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the decap action of IPv4 UDP tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini         |   1 +
 drivers/net/nfp/flower/nfp_flower_cmsg.c | 118 ++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  94 +++++
 drivers/net/nfp/nfp_flow.c               | 461 ++++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |  17 +
 5 files changed, 676 insertions(+), 15 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index ff97787bd9..5ccfd61336 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -40,6 +40,7 @@ vxlan                = Y
 [rte_flow actions]
 count                = Y
 drop                 = Y
+jump                 = Y
 of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 8983178378..f18f3de042 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -304,3 +304,121 @@ nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
 
 	return 0;
 }
+
+int
+nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower)
+{
+	uint16_t cnt;
+	uint32_t count = 0;
+	struct rte_mbuf *mbuf;
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+	struct nfp_flower_cmsg_tun_ipv4_addr *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v4 tun addr");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_IPS, sizeof(*msg));
+
+	priv = app_fw_flower->flow_priv;
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (count >= NFP_FL_IPV4_ADDRS_MAX) {
+			rte_spinlock_unlock(&priv->ipv4_off_lock);
+			PMD_DRV_LOG(ERR, "IPv4 offload exceeds limit.");
+			return -ERANGE;
+		}
+		msg->ipv4_addr[count] = entry->ipv4_addr;
+		count++;
+	}
+	msg->count = rte_cpu_to_be_32(count);
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		uint16_t mac_idx,
+		bool is_del)
+{
+	uint16_t cnt;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_pre_tun_rule *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for pre tunnel rule");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE, sizeof(*msg));
+
+	meta_tci = (struct nfp_flower_meta_tci *)((char *)nfp_flow_meta +
+			sizeof(struct nfp_fl_rule_metadata));
+	if (meta_tci->tci)
+		msg->vlan_tci = meta_tci->tci;
+	else
+		msg->vlan_tci = 0xffff;
+
+	if (is_del)
+		msg->flags = rte_cpu_to_be_32(NFP_TUN_PRE_TUN_RULE_DEL);
+
+	msg->port_idx = rte_cpu_to_be_16(mac_idx);
+	msg->host_ctx_id = nfp_flow_meta->host_ctx_id;
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+int
+nfp_flower_cmsg_tun_mac_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_ether_addr *mac,
+		uint16_t mac_idx,
+		bool is_del)
+{
+	uint16_t cnt;
+	struct rte_mbuf *mbuf;
+	struct nfp_flower_cmsg_tun_mac *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for tunnel mac");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_MAC, sizeof(*msg));
+
+	msg->count = rte_cpu_to_be_16(1);
+	msg->index = rte_cpu_to_be_16(mac_idx);
+	rte_ether_addr_copy(mac, &msg->addr);
+	if (is_del)
+		msg->flags = rte_cpu_to_be_16(NFP_TUN_MAC_OFFLOAD_DEL_FLAG);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index d1e0562cf9..0933dacfb1 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -195,6 +195,91 @@ struct nfp_flower_cmsg_tun_neigh_v6 {
 	struct nfp_flower_tun_neigh common;
 };
 
+#define NFP_TUN_PRE_TUN_RULE_DEL    (1 << 0)
+#define NFP_TUN_PRE_TUN_IDX_BIT     (1 << 3)
+#define NFP_TUN_PRE_TUN_IPV6_BIT    (1 << 7)
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_PRE_TUN_RULE
+ * Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ * -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *       +---------------------------------------------------------------+
+ *     0 |                             FLAGS                             |
+ *       +---------------------------------------------------------------+
+ *     1 |         MAC_IDX               |            VLAN_ID            |
+ *       +---------------------------------------------------------------+
+ *     2 |                           HOST_CTX                            |
+ *       +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_pre_tun_rule {
+	rte_be32_t flags;
+	rte_be16_t port_idx;
+	rte_be16_t vlan_tci;
+	rte_be32_t host_ctx_id;
+};
+
+#define NFP_TUN_MAC_OFFLOAD_DEL_FLAG  0x2
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_MAC
+ *     Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *    Word  +-----------------------+---+-+-+---------------+---------------+
+ *       0  |              spare    |NBI|D|F| Amount of MAC’s in this msg   |
+ *          +---------------+-------+---+-+-+---------------+---------------+
+ *       1  |            Index 0            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       2  |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       3  |            Index 1            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *       4  |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *                                        ...
+ *          +---------------+---------------+---------------+---------------+
+ *     2N-1 |            Index N            |     MAC[0]    |     MAC[1]    |
+ *          +---------------+---------------+---------------+---------------+
+ *     2N   |     MAC[2]    |     MAC[3]    |     MAC[4]    |     MAC[5]    |
+ *          +---------------+---------------+---------------+---------------+
+ *
+ *    F:   Flush bit. Set if entire table must be flushed. Rest of info in cmsg
+ *        will be ignored. Not implemented.
+ *    D:   Delete bit. Set if entry must be deleted instead of added
+ *    NBI: Network Block Interface. Set to 0
+ *    The amount of MAC’s per control message is limited only by the packet
+ *    buffer size. A 2048B buffer can fit 253 MAC address and a 10240B buffer
+ *    1277 MAC addresses.
+ */
+struct nfp_flower_cmsg_tun_mac {
+	rte_be16_t flags;
+	rte_be16_t count;           /**< Should always be 1 */
+	rte_be16_t index;
+	struct rte_ether_addr addr;
+};
+
+#define NFP_FL_IPV4_ADDRS_MAX        32
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_IPS
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                    Number of IP Addresses                     |
+ *          +---------------------------------------------------------------+
+ *        1 |                        IP Address #1                          |
+ *          +---------------------------------------------------------------+
+ *        2 |                        IP Address #2                          |
+ *          +---------------------------------------------------------------+
+ *          |                             ...                               |
+ *          +---------------------------------------------------------------+
+ *       32 |                        IP Address #32                         |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_ipv4_addr {
+	rte_be32_t count;
+	rte_be32_t ipv4_addr[NFP_FL_IPV4_ADDRS_MAX];
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -716,5 +801,14 @@ int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v4 *payload);
 int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
+int nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower);
+int nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		uint16_t mac_idx,
+		bool is_del);
+int nfp_flower_cmsg_tun_mac_rule(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_ether_addr *mac,
+		uint16_t mac_idx,
+		bool is_del);
 
 #endif /* _NFP_CMSG_H_ */
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 9ee02b0fb9..c088d24413 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -47,7 +47,8 @@ struct nfp_flow_item_proc {
 	/* Size in bytes for @p mask_support and @p mask_default. */
 	const unsigned int mask_sz;
 	/* Merge a pattern item into a flow rule handle. */
-	int (*merge)(struct rte_flow *nfp_flow,
+	int (*merge)(struct nfp_app_fw_flower *app_fw_flower,
+			struct rte_flow *nfp_flow,
 			char **mbuf_off,
 			const struct rte_flow_item *item,
 			const struct nfp_flow_item_proc *proc,
@@ -63,6 +64,12 @@ struct nfp_mask_id_entry {
 	uint8_t mask_id;
 };
 
+struct nfp_pre_tun_entry {
+	uint16_t mac_index;
+	uint16_t ref_cnt;
+	uint8_t mac_addr[RTE_ETHER_ADDR_LEN];
+} __rte_aligned(32);
+
 static inline struct nfp_flow_priv *
 nfp_flow_dev_to_priv(struct rte_eth_dev *dev)
 {
@@ -406,6 +413,83 @@ nfp_stats_id_free(struct nfp_flow_priv *priv, uint32_t ctx)
 	return 0;
 }
 
+__rte_unused static int
+nfp_tun_add_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+	struct nfp_ipv4_addr_entry *tmp_entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (entry->ipv4_addr == ipv4) {
+			entry->ref_count++;
+			rte_spinlock_unlock(&priv->ipv4_off_lock);
+			return 0;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	tmp_entry = rte_zmalloc("nfp_ipv4_off", sizeof(struct nfp_ipv4_addr_entry), 0);
+	if (tmp_entry == NULL) {
+		PMD_DRV_LOG(ERR, "Mem error when offloading IP address.");
+		return -ENOMEM;
+	}
+
+	tmp_entry->ipv4_addr = ipv4;
+	tmp_entry->ref_count = 1;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_INSERT_HEAD(&priv->ipv4_off_list, tmp_entry, next);
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	return nfp_flower_cmsg_tun_off_v4(app_fw_flower);
+}
+
+static int
+nfp_tun_del_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
+		rte_be32_t ipv4)
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv4_addr_entry *entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv4_off_lock);
+	LIST_FOREACH(entry, &priv->ipv4_off_list, next) {
+		if (entry->ipv4_addr == ipv4) {
+			entry->ref_count--;
+			if (entry->ref_count == 0) {
+				LIST_REMOVE(entry, next);
+				rte_free(entry);
+				rte_spinlock_unlock(&priv->ipv4_off_lock);
+				return nfp_flower_cmsg_tun_off_v4(app_fw_flower);
+			}
+			break;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv4_off_lock);
+
+	return 0;
+}
+
+static int
+nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	struct nfp_flower_ipv4_udp_tun *udp4;
+
+	udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+			sizeof(struct nfp_flower_ipv4_udp_tun));
+	ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+
+	return ret;
+}
+
 static void
 nfp_flower_compile_meta_tci(char *mbuf_off, struct nfp_fl_key_ls *key_layer)
 {
@@ -635,6 +719,9 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[],
 		case RTE_FLOW_ACTION_TYPE_COUNT:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_COUNT detected");
 			break;
+		case RTE_FLOW_ACTION_TYPE_JUMP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_JUMP detected");
+			break;
 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_PORT_ID detected");
 			key_ls->act_size += sizeof(struct nfp_fl_act_output);
@@ -786,7 +873,8 @@ nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
 }
 
 static int
-nfp_flow_merge_eth(__rte_unused struct rte_flow *nfp_flow,
+nfp_flow_merge_eth(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -823,7 +911,8 @@ nfp_flow_merge_eth(__rte_unused struct rte_flow *nfp_flow,
 }
 
 static int
-nfp_flow_merge_vlan(struct rte_flow *nfp_flow,
+nfp_flow_merge_vlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		__rte_unused char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -853,7 +942,8 @@ nfp_flow_merge_vlan(struct rte_flow *nfp_flow,
 }
 
 static int
-nfp_flow_merge_ipv4(struct rte_flow *nfp_flow,
+nfp_flow_merge_ipv4(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -914,7 +1004,8 @@ nfp_flow_merge_ipv4(struct rte_flow *nfp_flow,
 }
 
 static int
-nfp_flow_merge_ipv6(struct rte_flow *nfp_flow,
+nfp_flow_merge_ipv6(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -979,7 +1070,8 @@ nfp_flow_merge_ipv6(struct rte_flow *nfp_flow,
 }
 
 static int
-nfp_flow_merge_tcp(struct rte_flow *nfp_flow,
+nfp_flow_merge_tcp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1052,7 +1144,8 @@ nfp_flow_merge_tcp(struct rte_flow *nfp_flow,
 }
 
 static int
-nfp_flow_merge_udp(struct rte_flow *nfp_flow,
+nfp_flow_merge_udp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1100,7 +1193,8 @@ nfp_flow_merge_udp(struct rte_flow *nfp_flow,
 }
 
 static int
-nfp_flow_merge_sctp(struct rte_flow *nfp_flow,
+nfp_flow_merge_sctp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1142,7 +1236,8 @@ nfp_flow_merge_sctp(struct rte_flow *nfp_flow,
 }
 
 static int
-nfp_flow_merge_vxlan(struct rte_flow *nfp_flow,
+nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1391,7 +1486,8 @@ nfp_flow_inner_item_get(const struct rte_flow_item items[],
 }
 
 static int
-nfp_flow_compile_item_proc(const struct rte_flow_item items[],
+nfp_flow_compile_item_proc(struct nfp_flower_representor *repr,
+		const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow,
 		char **mbuf_off_exact,
 		char **mbuf_off_mask,
@@ -1402,6 +1498,7 @@ nfp_flow_compile_item_proc(const struct rte_flow_item items[],
 	bool continue_flag = true;
 	const struct rte_flow_item *item;
 	const struct nfp_flow_item_proc *proc_list;
+	struct nfp_app_fw_flower *app_fw_flower = repr->app_fw_flower;
 
 	proc_list = nfp_flow_item_proc_list;
 	for (item = items; item->type != RTE_FLOW_ITEM_TYPE_END && continue_flag; ++item) {
@@ -1437,14 +1534,14 @@ nfp_flow_compile_item_proc(const struct rte_flow_item items[],
 			break;
 		}
 
-		ret = proc->merge(nfp_flow, mbuf_off_exact, item,
+		ret = proc->merge(app_fw_flower, nfp_flow, mbuf_off_exact, item,
 				proc, false, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d exact merge failed", item->type);
 			break;
 		}
 
-		ret = proc->merge(nfp_flow, mbuf_off_mask, item,
+		ret = proc->merge(app_fw_flower, nfp_flow, mbuf_off_mask, item,
 				proc, true, is_outer_layer);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow item %d mask merge failed", item->type);
@@ -1458,7 +1555,7 @@ nfp_flow_compile_item_proc(const struct rte_flow_item items[],
 }
 
 static int
-nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
+nfp_flow_compile_items(struct nfp_flower_representor *representor,
 		const struct rte_flow_item items[],
 		struct rte_flow *nfp_flow)
 {
@@ -1489,7 +1586,7 @@ nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
 		is_outer_layer = false;
 
 	/* Go over items */
-	ret = nfp_flow_compile_item_proc(loop_item, nfp_flow,
+	ret = nfp_flow_compile_item_proc(representor, loop_item, nfp_flow,
 			&mbuf_off_exact, &mbuf_off_mask, is_outer_layer);
 	if (ret != 0) {
 		PMD_DRV_LOG(ERR, "nfp flow item compile failed.");
@@ -1498,7 +1595,7 @@ nfp_flow_compile_items(__rte_unused struct nfp_flower_representor *representor,
 
 	/* Go over inner items */
 	if (is_tun_flow) {
-		ret = nfp_flow_compile_item_proc(items, nfp_flow,
+		ret = nfp_flow_compile_item_proc(representor, items, nfp_flow,
 				&mbuf_off_exact, &mbuf_off_mask, true);
 		if (ret != 0) {
 			PMD_DRV_LOG(ERR, "nfp flow outer item compile failed.");
@@ -1873,6 +1970,59 @@ nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_ipv4 *ipv4;
+	struct nfp_flower_mac_mpls *eth;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_tun_neigh_v4 payload;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	port = (struct nfp_flower_in_port *)(meta_tci + 1);
+	eth = (struct nfp_flower_mac_mpls *)(port + 1);
+
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+		ipv4 = (struct nfp_flower_ipv4 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls) +
+				sizeof(struct nfp_flower_tp_ports));
+	else
+		ipv4 = (struct nfp_flower_ipv4 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls));
+
+	tun = &nfp_flow->tun;
+	tun->payload.v6_flag = 0;
+	tun->payload.dst.dst_ipv4 = ipv4->ipv4_src;
+	tun->payload.src.src_ipv4 = ipv4->ipv4_dst;
+	memcpy(tun->payload.dst_addr, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+	payload.dst_ipv4 = ipv4->ipv4_src;
+	payload.src_ipv4 = ipv4->ipv4_dst;
+	memcpy(payload.common.dst_mac, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flower_del_tun_neigh_v4(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
@@ -2090,6 +2240,200 @@ nfp_flow_action_vxlan_encap(struct nfp_app_fw_flower *app_fw_flower,
 				actions, vxlan_data, nfp_flow_meta, tun);
 }
 
+static struct nfp_pre_tun_entry *
+nfp_pre_tun_table_search(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int index;
+	uint32_t hash_key;
+	struct nfp_pre_tun_entry *mac_index;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	index = rte_hash_lookup_data(priv->pre_tun_table, &hash_key, (void **)&mac_index);
+	if (index < 0) {
+		PMD_DRV_LOG(DEBUG, "Data NOT found in the hash table");
+		return NULL;
+	}
+
+	return mac_index;
+}
+
+static bool
+nfp_pre_tun_table_add(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int ret;
+	uint32_t hash_key;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	ret = rte_hash_add_key_data(priv->pre_tun_table, &hash_key, hash_data);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Add to pre tunnel table failed");
+		return false;
+	}
+
+	return true;
+}
+
+static bool
+nfp_pre_tun_table_delete(struct nfp_flow_priv *priv,
+		char *hash_data,
+		uint32_t hash_len)
+{
+	int ret;
+	uint32_t hash_key;
+
+	hash_key = rte_jhash(hash_data, hash_len, priv->hash_seed);
+	ret = rte_hash_del_key(priv->pre_tun_table, &hash_key);
+	if (ret < 0) {
+		PMD_DRV_LOG(ERR, "Delete from pre tunnel table failed");
+		return false;
+	}
+
+	return true;
+}
+
+__rte_unused static int
+nfp_pre_tun_table_check_add(struct nfp_flower_representor *repr,
+		uint16_t *index)
+{
+	uint16_t i;
+	uint32_t entry_size;
+	uint16_t mac_index = 1;
+	struct nfp_flow_priv *priv;
+	struct nfp_pre_tun_entry *entry;
+	struct nfp_pre_tun_entry *find_entry;
+
+	priv = repr->app_fw_flower->flow_priv;
+	if (priv->pre_tun_cnt >= NFP_TUN_PRE_TUN_RULE_LIMIT) {
+		PMD_DRV_LOG(ERR, "Pre tunnel table has full");
+		return -EINVAL;
+	}
+
+	entry_size = sizeof(struct nfp_pre_tun_entry);
+	entry = rte_zmalloc("nfp_pre_tun", entry_size, 0);
+	if (entry == NULL) {
+		PMD_DRV_LOG(ERR, "Memory alloc failed for pre tunnel table");
+		return -ENOMEM;
+	}
+
+	entry->ref_cnt = 1U;
+	memcpy(entry->mac_addr, repr->mac_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	/* 0 is considered a failed match */
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0)
+			continue;
+		entry->mac_index = i;
+		find_entry = nfp_pre_tun_table_search(priv, (char *)entry, entry_size);
+		if (find_entry != NULL) {
+			find_entry->ref_cnt++;
+			*index = find_entry->mac_index;
+			rte_free(entry);
+			return 0;
+		}
+	}
+
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0) {
+			priv->pre_tun_bitmap[i] = 1U;
+			mac_index = i;
+			break;
+		}
+	}
+
+	entry->mac_index = mac_index;
+	if (!nfp_pre_tun_table_add(priv, (char *)entry, entry_size)) {
+		rte_free(entry);
+		return -EINVAL;
+	}
+
+	*index = entry->mac_index;
+	priv->pre_tun_cnt++;
+	return 0;
+}
+
+static int
+nfp_pre_tun_table_check_del(struct nfp_flower_representor *repr,
+		struct rte_flow *nfp_flow)
+{
+	uint16_t i;
+	int ret = 0;
+	uint32_t entry_size;
+	uint16_t nfp_mac_idx;
+	struct nfp_flow_priv *priv;
+	struct nfp_pre_tun_entry *entry;
+	struct nfp_pre_tun_entry *find_entry;
+	struct nfp_fl_rule_metadata *nfp_flow_meta;
+
+	priv = repr->app_fw_flower->flow_priv;
+	if (priv->pre_tun_cnt == 1)
+		return 0;
+
+	entry_size = sizeof(struct nfp_pre_tun_entry);
+	entry = rte_zmalloc("nfp_pre_tun", entry_size, 0);
+	if (entry == NULL) {
+		PMD_DRV_LOG(ERR, "Memory alloc failed for pre tunnel table");
+		return -ENOMEM;
+	}
+
+	entry->ref_cnt = 1U;
+	memcpy(entry->mac_addr, repr->mac_addr.addr_bytes, RTE_ETHER_ADDR_LEN);
+
+	/* 0 is considered a failed match */
+	for (i = 1; i < NFP_TUN_PRE_TUN_RULE_LIMIT; i++) {
+		if (priv->pre_tun_bitmap[i] == 0)
+			continue;
+		entry->mac_index = i;
+		find_entry = nfp_pre_tun_table_search(priv, (char *)entry, entry_size);
+		if (find_entry != NULL) {
+			find_entry->ref_cnt--;
+			if (find_entry->ref_cnt != 0)
+				goto free_entry;
+			priv->pre_tun_bitmap[i] = 0;
+			break;
+		}
+	}
+
+	nfp_flow_meta = nfp_flow->payload.meta;
+	nfp_mac_idx = (find_entry->mac_index << 8) |
+			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
+			NFP_TUN_PRE_TUN_IDX_BIT;
+	ret = nfp_flower_cmsg_tun_mac_rule(repr->app_fw_flower, &repr->mac_addr,
+			nfp_mac_idx, true);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send tunnel mac rule failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
+			nfp_mac_idx, true);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	find_entry->ref_cnt = 1U;
+	if (!nfp_pre_tun_table_delete(priv, (char *)find_entry, entry_size)) {
+		PMD_DRV_LOG(ERR, "Delete entry from pre tunnel table failed");
+		ret = -EINVAL;
+		goto free_entry;
+	}
+
+	rte_free(entry);
+	rte_free(find_entry);
+	priv->pre_tun_cnt--;
+
+free_entry:
+	rte_free(entry);
+
+	return ret;
+}
+
 static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
@@ -2125,6 +2469,9 @@ nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		case RTE_FLOW_ACTION_TYPE_COUNT:
 			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_COUNT");
 			break;
+		case RTE_FLOW_ACTION_TYPE_JUMP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_JUMP");
+			break;
 		case RTE_FLOW_ACTION_TYPE_PORT_ID:
 			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_PORT_ID");
 			ret = nfp_flow_action_output(position, action, nfp_flow_meta);
@@ -2561,6 +2908,15 @@ nfp_flow_destroy(struct rte_eth_dev *dev,
 		/* Delete the entry from nn table */
 		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
 		break;
+	case NFP_FLOW_DECAP:
+		/* Delete the entry from nn table */
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		if (ret != 0)
+			goto exit;
+
+		/* Delete the entry in pre tunnel table */
+		ret = nfp_pre_tun_table_check_del(representor, nfp_flow);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Invalid nfp flow type %d.", nfp_flow->type);
 		ret = -EINVAL;
@@ -2570,6 +2926,10 @@ nfp_flow_destroy(struct rte_eth_dev *dev,
 	if (ret != 0)
 		goto exit;
 
+	/* Delete the ip off */
+	if (nfp_flow_is_tunnel(nfp_flow))
+		nfp_tun_check_ip_off_del(representor, nfp_flow);
+
 	/* Delete the flow from hardware */
 	if (nfp_flow->install_flag) {
 		ret = nfp_flower_cmsg_flow_delete(app_fw_flower, nfp_flow);
@@ -2703,6 +3063,49 @@ nfp_flow_tunnel_item_release(__rte_unused struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int
+nfp_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
+		struct rte_flow_tunnel *tunnel,
+		struct rte_flow_action **pmd_actions,
+		uint32_t *num_of_actions,
+		__rte_unused struct rte_flow_error *err)
+{
+	struct rte_flow_action *nfp_action;
+
+	nfp_action = rte_zmalloc("nfp_tun_action", sizeof(struct rte_flow_action), 0);
+	if (nfp_action == NULL) {
+		PMD_DRV_LOG(ERR, "Alloc memory for nfp tunnel action failed.");
+		return -ENOMEM;
+	}
+
+	switch (tunnel->type) {
+	default:
+		*pmd_actions = NULL;
+		*num_of_actions = 0;
+		rte_free(nfp_action);
+		break;
+	}
+
+	return 0;
+}
+
+static int
+nfp_flow_tunnel_action_decap_release(__rte_unused struct rte_eth_dev *dev,
+		struct rte_flow_action *pmd_actions,
+		uint32_t num_of_actions,
+		__rte_unused struct rte_flow_error *err)
+{
+	uint32_t i;
+	struct rte_flow_action *nfp_action;
+
+	for (i = 0; i < num_of_actions; i++) {
+		nfp_action = &pmd_actions[i];
+		rte_free(nfp_action);
+	}
+
+	return 0;
+}
+
 static const struct rte_flow_ops nfp_flow_ops = {
 	.validate                    = nfp_flow_validate,
 	.create                      = nfp_flow_create,
@@ -2711,6 +3114,8 @@ static const struct rte_flow_ops nfp_flow_ops = {
 	.query                       = nfp_flow_query,
 	.tunnel_match                = nfp_flow_tunnel_match,
 	.tunnel_item_release         = nfp_flow_tunnel_item_release,
+	.tunnel_decap_set            = nfp_flow_tunnel_decap_set,
+	.tunnel_action_decap_release = nfp_flow_tunnel_action_decap_release,
 };
 
 int
@@ -2755,6 +3160,15 @@ nfp_flow_priv_init(struct nfp_pf_dev *pf_dev)
 		.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
 	};
 
+	struct rte_hash_parameters pre_tun_hash_params = {
+		.name       = "pre_tunnel_table",
+		.entries    = 32,
+		.hash_func  = rte_jhash,
+		.socket_id  = rte_socket_id(),
+		.key_len    = sizeof(uint32_t),
+		.extra_flag = RTE_HASH_EXTRA_FLAGS_RW_CONCURRENCY,
+	};
+
 	ctx_count = nfp_rtsym_read_le(pf_dev->sym_tbl,
 			"CONFIG_FC_HOST_CTX_COUNT", &ret);
 	if (ret < 0) {
@@ -2835,11 +3249,27 @@ nfp_flow_priv_init(struct nfp_pf_dev *pf_dev)
 		goto free_mask_table;
 	}
 
+	/* pre tunnel table */
+	priv->pre_tun_cnt = 1;
+	pre_tun_hash_params.hash_func_init_val = priv->hash_seed;
+	priv->pre_tun_table = rte_hash_create(&pre_tun_hash_params);
+	if (priv->pre_tun_table == NULL) {
+		PMD_INIT_LOG(ERR, "Pre tunnel table creation failed");
+		ret = -ENOMEM;
+		goto free_flow_table;
+	}
+
+	/* ipv4 off list */
+	rte_spinlock_init(&priv->ipv4_off_lock);
+	LIST_INIT(&priv->ipv4_off_list);
+
 	/* neighbor next list */
 	LIST_INIT(&priv->nn_list);
 
 	return 0;
 
+free_flow_table:
+	rte_hash_free(priv->flow_table);
 free_mask_table:
 	rte_free(priv->mask_table);
 free_stats:
@@ -2863,6 +3293,7 @@ nfp_flow_priv_uninit(struct nfp_pf_dev *pf_dev)
 	app_fw_flower = NFP_PRIV_TO_APP_FW_FLOWER(pf_dev->app_fw_priv);
 	priv = app_fw_flower->flow_priv;
 
+	rte_hash_free(priv->pre_tun_table);
 	rte_hash_free(priv->flow_table);
 	rte_hash_free(priv->mask_table);
 	rte_free(priv->stats);
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index 892dbc08f1..f536da2650 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -6,6 +6,7 @@
 #ifndef _NFP_FLOW_H_
 #define _NFP_FLOW_H_
 
+#include <sys/queue.h>
 #include <rte_bitops.h>
 #include <ethdev_driver.h>
 
@@ -93,6 +94,7 @@ enum nfp_flower_tun_type {
 enum nfp_flow_type {
 	NFP_FLOW_COMMON,
 	NFP_FLOW_ENCAP,
+	NFP_FLOW_DECAP,
 };
 
 struct nfp_fl_key_ls {
@@ -169,6 +171,14 @@ struct nfp_fl_stats {
 	uint64_t bytes;
 };
 
+struct nfp_ipv4_addr_entry {
+	LIST_ENTRY(nfp_ipv4_addr_entry) next;
+	rte_be32_t ipv4_addr;
+	int ref_count;
+};
+
+#define NFP_TUN_PRE_TUN_RULE_LIMIT  32
+
 struct nfp_flow_priv {
 	uint32_t hash_seed; /**< Hash seed for hash tables in this structure. */
 	uint64_t flower_version; /**< Flow version, always increase. */
@@ -184,6 +194,13 @@ struct nfp_flow_priv {
 	struct nfp_fl_stats_id stats_ids; /**< The stats id ring. */
 	struct nfp_fl_stats *stats; /**< Store stats of flow. */
 	rte_spinlock_t stats_lock; /** < Lock the update of 'stats' field. */
+	/* pre tunnel rule */
+	uint16_t pre_tun_cnt; /**< The size of pre tunnel rule */
+	uint8_t pre_tun_bitmap[NFP_TUN_PRE_TUN_RULE_LIMIT]; /**< Bitmap of pre tunnel rule */
+	struct rte_hash *pre_tun_table; /**< Hash table to store pre tunnel rule */
+	/* IPv4 off */
+	LIST_HEAD(, nfp_ipv4_addr_entry) ipv4_off_list; /**< Store ipv4 off */
+	rte_spinlock_t ipv4_off_lock; /**< Lock the ipv4 off list */
 	/* neighbor next */
 	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 09/26] net/nfp: prepare for IPv6 UDP tunnel decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (7 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 08/26] net/nfp: prepare for IPv4 UDP tunnel decap " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 10/26] net/nfp: support IPv4 VXLAN " Chaoyong He
                       ` (17 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and functions, prepare for
the decap action of IPv6 UDP tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.c |  42 +++++++
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  24 ++++
 drivers/net/nfp/nfp_flow.c               | 145 ++++++++++++++++++++++-
 drivers/net/nfp/nfp_flow.h               |   9 ++
 4 files changed, 217 insertions(+), 3 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index f18f3de042..76815cfe14 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -347,6 +347,48 @@ nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower)
 	return 0;
 }
 
+int
+nfp_flower_cmsg_tun_off_v6(struct nfp_app_fw_flower *app_fw_flower)
+{
+	uint16_t cnt;
+	uint32_t count = 0;
+	struct rte_mbuf *mbuf;
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+	struct nfp_flower_cmsg_tun_ipv6_addr *msg;
+
+	mbuf = rte_pktmbuf_alloc(app_fw_flower->ctrl_pktmbuf_pool);
+	if (mbuf == NULL) {
+		PMD_DRV_LOG(DEBUG, "Failed to alloc mbuf for v6 tun addr");
+		return -ENOMEM;
+	}
+
+	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_IPS_V6, sizeof(*msg));
+
+	priv = app_fw_flower->flow_priv;
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (count >= NFP_FL_IPV6_ADDRS_MAX) {
+			rte_spinlock_unlock(&priv->ipv6_off_lock);
+			PMD_DRV_LOG(ERR, "IPv6 offload exceeds limit.");
+			return -ERANGE;
+		}
+		memcpy(&msg->ipv6_addr[count * 16], entry->ipv6_addr, 16UL);
+		count++;
+	}
+	msg->count = rte_cpu_to_be_32(count);
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	cnt = nfp_flower_ctrl_vnic_xmit(app_fw_flower, mbuf);
+	if (cnt == 0) {
+		PMD_DRV_LOG(ERR, "Send cmsg through ctrl vnic failed.");
+		rte_pktmbuf_free(mbuf);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 int
 nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 0933dacfb1..61f2f83fc9 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -280,6 +280,29 @@ struct nfp_flower_cmsg_tun_ipv4_addr {
 	rte_be32_t ipv4_addr[NFP_FL_IPV4_ADDRS_MAX];
 };
 
+#define NFP_FL_IPV6_ADDRS_MAX        4
+
+/*
+ * NFP_FLOWER_CMSG_TYPE_TUN_IP_V6
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |                    Number of IP Addresses                     |
+ *          +---------------------------------------------------------------+
+ *        1 |                        IP Address1 #1                         |
+ *          +---------------------------------------------------------------+
+ *        2 |                        IP Address1 #2                         |
+ *          +---------------------------------------------------------------+
+ *          |                             ...                               |
+ *          +---------------------------------------------------------------+
+ *       16 |                        IP Address4 #4                         |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_cmsg_tun_ipv6_addr {
+	rte_be32_t count;
+	uint8_t ipv6_addr[NFP_FL_IPV6_ADDRS_MAX * 16];
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_FLOW_STATS
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -802,6 +825,7 @@ int nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 int nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_flower_cmsg_tun_neigh_v6 *payload);
 int nfp_flower_cmsg_tun_off_v4(struct nfp_app_fw_flower *app_fw_flower);
+int nfp_flower_cmsg_tun_off_v6(struct nfp_app_fw_flower *app_fw_flower);
 int nfp_flower_cmsg_pre_tunnel_rule(struct nfp_app_fw_flower *app_fw_flower,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		uint16_t mac_idx,
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index c088d24413..ad484b95b7 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -476,16 +476,95 @@ nfp_tun_del_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
 	return 0;
 }
 
+__rte_unused static int
+nfp_tun_add_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t ipv6[])
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+	struct nfp_ipv6_addr_entry *tmp_entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (!memcmp(entry->ipv6_addr, ipv6, sizeof(entry->ipv6_addr))) {
+			entry->ref_count++;
+			rte_spinlock_unlock(&priv->ipv6_off_lock);
+			return 0;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	tmp_entry = rte_zmalloc("nfp_ipv6_off", sizeof(struct nfp_ipv6_addr_entry), 0);
+	if (tmp_entry == NULL) {
+		PMD_DRV_LOG(ERR, "Mem error when offloading IP6 address.");
+		return -ENOMEM;
+	}
+	memcpy(tmp_entry->ipv6_addr, ipv6, sizeof(tmp_entry->ipv6_addr));
+	tmp_entry->ref_count = 1;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_INSERT_HEAD(&priv->ipv6_off_list, tmp_entry, next);
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	return nfp_flower_cmsg_tun_off_v6(app_fw_flower);
+}
+
+static int
+nfp_tun_del_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
+		uint8_t ipv6[])
+{
+	struct nfp_flow_priv *priv;
+	struct nfp_ipv6_addr_entry *entry;
+
+	priv = app_fw_flower->flow_priv;
+
+	rte_spinlock_lock(&priv->ipv6_off_lock);
+	LIST_FOREACH(entry, &priv->ipv6_off_list, next) {
+		if (!memcmp(entry->ipv6_addr, ipv6, sizeof(entry->ipv6_addr))) {
+			entry->ref_count--;
+			if (entry->ref_count == 0) {
+				LIST_REMOVE(entry, next);
+				rte_free(entry);
+				rte_spinlock_unlock(&priv->ipv6_off_lock);
+				return nfp_flower_cmsg_tun_off_v6(app_fw_flower);
+			}
+			break;
+		}
+	}
+	rte_spinlock_unlock(&priv->ipv6_off_lock);
+
+	return 0;
+}
+
 static int
 nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
 		struct rte_flow *nfp_flow)
 {
 	int ret;
+	uint32_t key_layer2 = 0;
 	struct nfp_flower_ipv4_udp_tun *udp4;
+	struct nfp_flower_ipv6_udp_tun *udp6;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 
-	udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
-			sizeof(struct nfp_flower_ipv4_udp_tun));
-	ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
+
+	if (ext_meta != NULL)
+		key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
+
+	if (key_layer2 & NFP_FLOWER_LAYER2_TUN_IPV6) {
+		udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
+				sizeof(struct nfp_flower_ipv6_udp_tun));
+		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+	} else {
+		udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+				sizeof(struct nfp_flower_ipv4_udp_tun));
+		ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+	}
 
 	return ret;
 }
@@ -2078,6 +2157,59 @@ nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
+__rte_unused static int
+nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct rte_flow *nfp_flow)
+{
+	struct nfp_fl_tun *tmp;
+	struct nfp_fl_tun *tun;
+	struct nfp_flow_priv *priv;
+	struct nfp_flower_ipv6 *ipv6;
+	struct nfp_flower_mac_mpls *eth;
+	struct nfp_flower_in_port *port;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_cmsg_tun_neigh_v6 payload;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	port = (struct nfp_flower_in_port *)(meta_tci + 1);
+	eth = (struct nfp_flower_mac_mpls *)(port + 1);
+
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_TP)
+		ipv6 = (struct nfp_flower_ipv6 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls) +
+				sizeof(struct nfp_flower_tp_ports));
+	else
+		ipv6 = (struct nfp_flower_ipv6 *)((char *)eth +
+				sizeof(struct nfp_flower_mac_mpls));
+
+	tun = &nfp_flow->tun;
+	tun->payload.v6_flag = 1;
+	memcpy(tun->payload.dst.dst_ipv6, ipv6->ipv6_src, sizeof(tun->payload.dst.dst_ipv6));
+	memcpy(tun->payload.src.src_ipv6, ipv6->ipv6_dst, sizeof(tun->payload.src.src_ipv6));
+	memcpy(tun->payload.dst_addr, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(tun->payload.src_addr, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+
+	tun->ref_cnt = 1;
+	priv = app_fw_flower->flow_priv;
+	LIST_FOREACH(tmp, &priv->nn_list, next) {
+		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
+			tmp->ref_cnt++;
+			return 0;
+		}
+	}
+
+	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+
+	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+	memcpy(payload.dst_ipv6, ipv6->ipv6_src, sizeof(payload.dst_ipv6));
+	memcpy(payload.src_ipv6, ipv6->ipv6_dst, sizeof(payload.src_ipv6));
+	memcpy(payload.common.dst_mac, eth->mac_src, RTE_ETHER_ADDR_LEN);
+	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
+	payload.common.port_id = port->in_port;
+
+	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
+}
+
 static int
 nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
 		uint8_t *ipv6)
@@ -2401,6 +2533,9 @@ nfp_pre_tun_table_check_del(struct nfp_flower_representor *repr,
 	nfp_mac_idx = (find_entry->mac_index << 8) |
 			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
 			NFP_TUN_PRE_TUN_IDX_BIT;
+	if (nfp_flow->tun.payload.v6_flag != 0)
+		nfp_mac_idx |= NFP_TUN_PRE_TUN_IPV6_BIT;
+
 	ret = nfp_flower_cmsg_tun_mac_rule(repr->app_fw_flower, &repr->mac_addr,
 			nfp_mac_idx, true);
 	if (ret != 0) {
@@ -3263,6 +3398,10 @@ nfp_flow_priv_init(struct nfp_pf_dev *pf_dev)
 	rte_spinlock_init(&priv->ipv4_off_lock);
 	LIST_INIT(&priv->ipv4_off_list);
 
+	/* ipv6 off list */
+	rte_spinlock_init(&priv->ipv6_off_lock);
+	LIST_INIT(&priv->ipv6_off_list);
+
 	/* neighbor next list */
 	LIST_INIT(&priv->nn_list);
 
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index f536da2650..a6994e08ee 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -177,6 +177,12 @@ struct nfp_ipv4_addr_entry {
 	int ref_count;
 };
 
+struct nfp_ipv6_addr_entry {
+	LIST_ENTRY(nfp_ipv6_addr_entry) next;
+	uint8_t ipv6_addr[16];
+	int ref_count;
+};
+
 #define NFP_TUN_PRE_TUN_RULE_LIMIT  32
 
 struct nfp_flow_priv {
@@ -201,6 +207,9 @@ struct nfp_flow_priv {
 	/* IPv4 off */
 	LIST_HEAD(, nfp_ipv4_addr_entry) ipv4_off_list; /**< Store ipv4 off */
 	rte_spinlock_t ipv4_off_lock; /**< Lock the ipv4 off list */
+	/* IPv6 off */
+	LIST_HEAD(, nfp_ipv6_addr_entry) ipv6_off_list; /**< Store ipv6 off */
+	rte_spinlock_t ipv6_off_lock; /**< Lock the ipv6 off list */
 	/* neighbor next */
 	LIST_HEAD(, nfp_fl_tun)nn_list; /**< Store nn entry */
 };
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 10/26] net/nfp: support IPv4 VXLAN decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (8 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 09/26] net/nfp: prepare for IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 11/26] net/nfp: support IPv6 " Chaoyong He
                       ` (16 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv4 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 75 +++++++++++++++++++++++++++++---
 2 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 5ccfd61336..9ab840c88b 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -57,4 +57,5 @@ set_mac_src          = Y
 set_tp_dst           = Y
 set_tp_src           = Y
 set_ttl              = Y
+vxlan_decap          = Y
 vxlan_encap          = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index ad484b95b7..e71292ff12 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -413,7 +413,7 @@ nfp_stats_id_free(struct nfp_flow_priv *priv, uint32_t ctx)
 	return 0;
 }
 
-__rte_unused static int
+static int
 nfp_tun_add_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
 		rte_be32_t ipv4)
 {
@@ -908,6 +908,9 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[],
 			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
 			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1315,7 +1318,7 @@ nfp_flow_merge_sctp(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 }
 
 static int
-nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_vxlan(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1323,6 +1326,7 @@ nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	const struct rte_vxlan_hdr *hdr;
 	struct nfp_flower_ipv4_udp_tun *tun4;
 	struct nfp_flower_ipv6_udp_tun *tun6;
@@ -1351,6 +1355,8 @@ nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = hdr->vx_vni;
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 vxlan_end:
@@ -1360,7 +1366,7 @@ nfp_flow_merge_vxlan(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 	else
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 
-	return 0;
+	return ret;
 }
 
 /* Graph of supported items and associated process function */
@@ -2049,7 +2055,7 @@ nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -2427,7 +2433,7 @@ nfp_pre_tun_table_delete(struct nfp_flow_priv *priv,
 	return true;
 }
 
-__rte_unused static int
+static int
 nfp_pre_tun_table_check_add(struct nfp_flower_representor *repr,
 		uint16_t *index)
 {
@@ -2569,6 +2575,49 @@ nfp_pre_tun_table_check_del(struct nfp_flower_representor *repr,
 	return ret;
 }
 
+static int
+nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
+		__rte_unused const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct rte_flow *nfp_flow)
+{
+	int ret;
+	uint16_t nfp_mac_idx = 0;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_app_fw_flower *app_fw_flower;
+
+	ret = nfp_pre_tun_table_check_add(repr, &nfp_mac_idx);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Pre tunnel table add failed");
+		return -EINVAL;
+	}
+
+	nfp_mac_idx = (nfp_mac_idx << 8) |
+			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
+			NFP_TUN_PRE_TUN_IDX_BIT;
+
+	app_fw_flower = repr->app_fw_flower;
+	ret = nfp_flower_cmsg_tun_mac_rule(app_fw_flower, &repr->mac_addr,
+			nfp_mac_idx, false);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send tunnel mac rule failed");
+		return -EINVAL;
+	}
+
+	ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
+			nfp_mac_idx, false);
+	if (ret != 0) {
+		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+		return -EINVAL;
+	}
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
+		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
+	else
+		return -ENOTSUP;
+}
+
 static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
@@ -2744,6 +2793,17 @@ nfp_flow_compile_action(struct nfp_flower_representor *representor,
 			position += sizeof(struct nfp_fl_act_set_tun);
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
+		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+			PMD_DRV_LOG(DEBUG, "process action tunnel decap");
+			ret = nfp_flow_action_tunnel_decap(representor, action,
+					nfp_flow_meta, nfp_flow);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process tunnel decap");
+				return ret;
+			}
+			nfp_flow->type = NFP_FLOW_DECAP;
+			nfp_flow->install_flag = false;
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
 			return -ENOTSUP;
@@ -3214,6 +3274,11 @@ nfp_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
 	}
 
 	switch (tunnel->type) {
+	case RTE_FLOW_ITEM_TYPE_VXLAN:
+		nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
+		*pmd_actions = nfp_action;
+		*num_of_actions = 1;
+		break;
 	default:
 		*pmd_actions = NULL;
 		*num_of_actions = 0;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 11/26] net/nfp: support IPv6 VXLAN decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (9 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 10/26] net/nfp: support IPv4 VXLAN " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 12/26] net/nfp: support IPv4 GENEVE encap " Chaoyong He
                       ` (15 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv6 VXLAN tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index e71292ff12..9e8073b0f8 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -476,7 +476,7 @@ nfp_tun_del_ipv4_off(struct nfp_app_fw_flower *app_fw_flower,
 	return 0;
 }
 
-__rte_unused static int
+static int
 nfp_tun_add_ipv6_off(struct nfp_app_fw_flower *app_fw_flower,
 		uint8_t ipv6[])
 {
@@ -1352,6 +1352,8 @@ nfp_flow_merge_vxlan(struct nfp_app_fw_flower *app_fw_flower,
 			NFP_FLOWER_LAYER2_TUN_IPV6)) {
 		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
 		tun6->tun_id = hdr->vx_vni;
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = hdr->vx_vni;
@@ -2163,7 +2165,7 @@ nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
-__rte_unused static int
+static int
 nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow)
 {
@@ -2577,7 +2579,7 @@ nfp_pre_tun_table_check_del(struct nfp_flower_representor *repr,
 
 static int
 nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
-		__rte_unused const struct rte_flow_action *action,
+		const struct rte_flow_action *action,
 		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
@@ -2595,6 +2597,8 @@ nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
 	nfp_mac_idx = (nfp_mac_idx << 8) |
 			NFP_FLOWER_CMSG_PORT_TYPE_OTHER_PORT |
 			NFP_TUN_PRE_TUN_IDX_BIT;
+	if (action->conf != NULL)
+		nfp_mac_idx |= NFP_TUN_PRE_TUN_IPV6_BIT;
 
 	app_fw_flower = repr->app_fw_flower;
 	ret = nfp_flower_cmsg_tun_mac_rule(app_fw_flower, &repr->mac_addr,
@@ -2615,7 +2619,7 @@ nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
 		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
 	else
-		return -ENOTSUP;
+		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow);
 }
 
 static int
@@ -2803,6 +2807,8 @@ nfp_flow_compile_action(struct nfp_flower_representor *representor,
 			}
 			nfp_flow->type = NFP_FLOW_DECAP;
 			nfp_flow->install_flag = false;
+			if (action->conf != NULL)
+				nfp_flow->tun.payload.v6_flag = 1;
 			break;
 		default:
 			PMD_DRV_LOG(ERR, "Unsupported action type: %d", action->type);
@@ -3273,6 +3279,9 @@ nfp_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
 		return -ENOMEM;
 	}
 
+	if (tunnel->is_ipv6)
+		nfp_action->conf = (void *)~0;
+
 	switch (tunnel->type) {
 	case RTE_FLOW_ITEM_TYPE_VXLAN:
 		nfp_action->type = RTE_FLOW_ACTION_TYPE_VXLAN_DECAP;
@@ -3300,6 +3309,7 @@ nfp_flow_tunnel_action_decap_release(__rte_unused struct rte_eth_dev *dev,
 
 	for (i = 0; i < num_of_actions; i++) {
 		nfp_action = &pmd_actions[i];
+		nfp_action->conf = NULL;
 		rte_free(nfp_action);
 	}
 
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 12/26] net/nfp: support IPv4 GENEVE encap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (10 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 11/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 13/26] net/nfp: support IPv6 " Chaoyong He
                       ` (14 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv4 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |   1 +
 drivers/net/nfp/nfp_flow.c       | 107 +++++++++++++++++++++++++++++++
 2 files changed, 108 insertions(+)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 9ab840c88b..deb27ee2d8 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -45,6 +45,7 @@ of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
 of_set_vlan_vid      = Y
+raw_encap            = Y
 port_id              = Y
 set_ipv4_dscp        = Y
 set_ipv4_dst         = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 9e8073b0f8..7d19781bd9 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -38,6 +38,12 @@ struct vxlan_data {
 		__VA_ARGS__, RTE_FLOW_ITEM_TYPE_END, \
 	})
 
+/* Data length of various conf of raw encap action */
+#define GENEVE_V4_LEN    (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv4_hdr) + \
+				sizeof(struct rte_udp_hdr) + \
+				sizeof(struct rte_flow_item_geneve))
+
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
 	/* Bit-mask for fields supported by this PMD. */
@@ -908,6 +914,11 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[],
 			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
 			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_ENCAP detected");
+			key_ls->act_size += sizeof(struct nfp_fl_act_pre_tun);
+			key_ls->act_size += sizeof(struct nfp_fl_act_set_tun);
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
 			break;
@@ -2622,6 +2633,88 @@ nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
 		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow);
 }
 
+static int
+nfp_flow_action_geneve_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint64_t tun_id;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_udp *udp;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_geneve *geneve;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv4   = (const struct rte_flow_item_ipv4 *)(eth + 1);
+	udp    = (const struct rte_flow_item_udp *)(ipv4 + 1);
+	geneve = (const struct rte_flow_item_geneve *)(udp + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tun_id = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GENEVE, tun_id,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_proto = geneve->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv4);
+}
+
+static int
+nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action *action,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	int ret;
+	size_t act_len;
+	size_t act_pre_size;
+	const struct rte_flow_action_raw_encap *raw_encap;
+
+	raw_encap = action->conf;
+	if (raw_encap->data == NULL) {
+		PMD_DRV_LOG(ERR, "The raw encap action conf is NULL.");
+		return -EINVAL;
+	}
+
+	/* Pre_tunnel action must be the first on action list.
+	 * If other actions already exist, they need to be
+	 * pushed forward.
+	 */
+	act_len = act_data - actions;
+	if (act_len != 0) {
+		act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+		memmove(actions + act_pre_size, actions, act_len);
+	}
+
+	switch (raw_encap->size) {
+	case GENEVE_V4_LEN:
+		ret = nfp_flow_action_geneve_encap_v4(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
+	default:
+		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
 static int
 nfp_flow_compile_action(struct nfp_flower_representor *representor,
 		const struct rte_flow_action actions[],
@@ -2797,6 +2890,20 @@ nfp_flow_compile_action(struct nfp_flower_representor *representor,
 			position += sizeof(struct nfp_fl_act_set_tun);
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_ENCAP:
+			PMD_DRV_LOG(DEBUG, "Process RTE_FLOW_ACTION_TYPE_RAW_ENCAP");
+			ret = nfp_flow_action_raw_encap(representor->app_fw_flower,
+					position, action_data, action, nfp_flow_meta,
+					&nfp_flow->tun);
+			if (ret != 0) {
+				PMD_DRV_LOG(ERR, "Failed when process"
+						" RTE_FLOW_ACTION_TYPE_RAW_ENCAP");
+				return ret;
+			}
+			position += sizeof(struct nfp_fl_act_pre_tun);
+			position += sizeof(struct nfp_fl_act_set_tun);
+			nfp_flow->type = NFP_FLOW_ENCAP;
+			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "process action tunnel decap");
 			ret = nfp_flow_action_tunnel_decap(representor, action,
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 13/26] net/nfp: support IPv6 GENEVE encap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (11 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 12/26] net/nfp: support IPv4 GENEVE encap " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 14/26] net/nfp: support IPv4 GENEVE flow item Chaoyong He
                       ` (13 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action for IPv6 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 49 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 7d19781bd9..8416229f20 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -43,6 +43,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv4_hdr) + \
 				sizeof(struct rte_udp_hdr) + \
 				sizeof(struct rte_flow_item_geneve))
+#define GENEVE_V6_LEN    (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv6_hdr) + \
+				sizeof(struct rte_udp_hdr) + \
+				sizeof(struct rte_flow_item_geneve))
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2672,6 +2676,47 @@ nfp_flow_action_geneve_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
 			tun, eth, ipv4);
 }
 
+static int
+nfp_flow_action_geneve_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint8_t tos;
+	uint64_t tun_id;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_udp *udp;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_geneve *geneve;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv6   = (const struct rte_flow_item_ipv6 *)(eth + 1);
+	udp    = (const struct rte_flow_item_udp *)(ipv6 + 1);
+	geneve = (const struct rte_flow_item_geneve *)(udp + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tos = (ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff;
+	tun_id = (geneve->vni[0] << 16) | (geneve->vni[1] << 8) | geneve->vni[2];
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GENEVE, tun_id,
+			ipv6->hdr.hop_limits, tos);
+	set_tun->tun_proto = geneve->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv6);
+}
+
 static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
@@ -2706,6 +2751,10 @@ nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		ret = nfp_flow_action_geneve_encap_v4(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case GENEVE_V6_LEN:
+		ret = nfp_flow_action_geneve_encap_v6(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 14/26] net/nfp: support IPv4 GENEVE flow item
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (12 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 13/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 15/26] net/nfp: support IPv6 " Chaoyong He
                       ` (12 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv4 GENEVE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 75 +++++++++++++++++++++++++++++++-
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index deb27ee2d8..2e215bb324 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -28,6 +28,7 @@ Usage doc            = Y
 
 [rte_flow items]
 eth                  = Y
+geneve               = Y
 ipv4                 = Y
 ipv6                 = Y
 port_id              = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 8416229f20..39ed279778 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -769,6 +769,23 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 				return -EINVAL;
 			}
 			break;
+		case RTE_FLOW_ITEM_TYPE_GENEVE:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GENEVE detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_GENEVE;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;
+			key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -960,12 +977,22 @@ nfp_flow_key_layers_calculate(const struct rte_flow_item items[],
 static bool
 nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
 {
+	uint32_t key_layer2;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_meta_tci *meta_tci;
 
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_VXLAN)
 		return true;
 
+	if (!(meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META))
+		return false;
+
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
+	key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
+	if (key_layer2 & NFP_FLOWER_LAYER2_GENEVE)
+		return true;
+
 	return false;
 }
 
@@ -1386,6 +1413,39 @@ nfp_flow_merge_vxlan(struct nfp_app_fw_flower *app_fw_flower,
 	return ret;
 }
 
+static int
+nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	struct nfp_flower_ipv4_udp_tun *tun4;
+	const struct rte_flow_item_geneve *spec;
+	const struct rte_flow_item_geneve *mask;
+	const struct rte_flow_item_geneve *geneve;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge geneve: no item->spec!");
+		goto geneve_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	geneve = is_mask ? mask : spec;
+
+	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+	tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+			(geneve->vni[1] << 8) | (geneve->vni[2]));
+
+geneve_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+
+	return 0;
+}
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
@@ -1474,7 +1534,8 @@ static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 		.merge = nfp_flow_merge_tcp,
 	},
 	[RTE_FLOW_ITEM_TYPE_UDP] = {
-		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN),
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_VXLAN,
+			RTE_FLOW_ITEM_TYPE_GENEVE),
 		.mask_support = &(const struct rte_flow_item_udp){
 			.hdr = {
 				.src_port = RTE_BE16(0xffff),
@@ -1507,6 +1568,15 @@ static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 		.mask_sz = sizeof(struct rte_flow_item_vxlan),
 		.merge = nfp_flow_merge_vxlan,
 	},
+	[RTE_FLOW_ITEM_TYPE_GENEVE] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &(const struct rte_flow_item_geneve){
+			.vni = "\xff\xff\xff",
+		},
+		.mask_default = &rte_flow_item_geneve_mask,
+		.mask_sz = sizeof(struct rte_flow_item_geneve),
+		.merge = nfp_flow_merge_geneve,
+	},
 };
 
 static int
@@ -1563,7 +1633,8 @@ nfp_flow_item_check(const struct rte_flow_item *item,
 static bool
 nfp_flow_is_tun_item(const struct rte_flow_item *item)
 {
-	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN)
+	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
+			item->type == RTE_FLOW_ITEM_TYPE_GENEVE)
 		return true;
 
 	return false;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 15/26] net/nfp: support IPv6 GENEVE flow item
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (13 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 14/26] net/nfp: support IPv4 GENEVE flow item Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 16/26] net/nfp: support IPv4 GENEVE decap flow action Chaoyong He
                       ` (11 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv6 GENEVE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 43 ++++++++++++++++++++++++++++++++------
 1 file changed, 37 insertions(+), 6 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 39ed279778..50e5131f54 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -771,8 +771,9 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 			break;
 		case RTE_FLOW_ITEM_TYPE_GENEVE:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GENEVE detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_GENEVE;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
 			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GENEVE;
@@ -784,6 +785,17 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 				 * in `struct nfp_flower_ipv4_udp_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_udp_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_udp_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for GENEVE tunnel.");
+				return -EINVAL;
 			}
 			break;
 		default:
@@ -1415,7 +1427,7 @@ nfp_flow_merge_vxlan(struct nfp_app_fw_flower *app_fw_flower,
 
 static int
 nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
 		const struct nfp_flow_item_proc *proc,
@@ -1423,9 +1435,16 @@ nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		__rte_unused bool is_outer_layer)
 {
 	struct nfp_flower_ipv4_udp_tun *tun4;
+	struct nfp_flower_ipv6_udp_tun *tun6;
+	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_geneve *spec;
 	const struct rte_flow_item_geneve *mask;
 	const struct rte_flow_item_geneve *geneve;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1436,12 +1455,24 @@ nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 	mask = item->mask ? item->mask : proc->mask_default;
 	geneve = is_mask ? mask : spec;
 
-	tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
-	tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
-			(geneve->vni[1] << 8) | (geneve->vni[2]));
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+		tun6->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+				(geneve->vni[1] << 8) | (geneve->vni[2]));
+	} else {
+		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
+				(geneve->vni[1] << 8) | (geneve->vni[2]));
+	}
 
 geneve_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)) {
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_udp_tun);
+	} else {
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
+	}
 
 	return 0;
 }
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 16/26] net/nfp: support IPv4 GENEVE decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (14 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 15/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 17/26] net/nfp: support IPv6 " Chaoyong He
                       ` (10 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv4 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  1 +
 drivers/net/nfp/nfp_flow.c       | 16 ++++++++++++++--
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index 2e215bb324..fe1cb971f1 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -46,6 +46,7 @@ of_pop_vlan          = Y
 of_push_vlan         = Y
 of_set_vlan_pcp      = Y
 of_set_vlan_vid      = Y
+raw_decap            = Y
 raw_encap            = Y
 port_id              = Y
 set_ipv4_dscp        = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 50e5131f54..46a047cd7b 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -955,6 +955,9 @@ nfp_flow_key_layers_calculate_actions(const struct rte_flow_action actions[],
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_VXLAN_DECAP detected");
 			break;
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ACTION_TYPE_RAW_DECAP detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Action type %d not supported.", action->type);
 			return -ENOTSUP;
@@ -1426,7 +1429,7 @@ nfp_flow_merge_vxlan(struct nfp_app_fw_flower *app_fw_flower,
 }
 
 static int
-nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_geneve(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1434,6 +1437,7 @@ nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	struct nfp_flower_ipv4_udp_tun *tun4;
 	struct nfp_flower_ipv6_udp_tun *tun6;
 	struct nfp_flower_meta_tci *meta_tci;
@@ -1464,6 +1468,8 @@ nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
 				(geneve->vni[1] << 8) | (geneve->vni[2]));
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 geneve_end:
@@ -1474,7 +1480,7 @@ nfp_flow_merge_geneve(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_udp_tun);
 	}
 
-	return 0;
+	return ret;
 }
 
 /* Graph of supported items and associated process function */
@@ -3056,6 +3062,7 @@ nfp_flow_compile_action(struct nfp_flower_representor *representor,
 			nfp_flow->type = NFP_FLOW_ENCAP;
 			break;
 		case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP:
+		case RTE_FLOW_ACTION_TYPE_RAW_DECAP:
 			PMD_DRV_LOG(DEBUG, "process action tunnel decap");
 			ret = nfp_flow_action_tunnel_decap(representor, action,
 					nfp_flow_meta, nfp_flow);
@@ -3546,6 +3553,11 @@ nfp_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
 		*pmd_actions = nfp_action;
 		*num_of_actions = 1;
 		break;
+	case RTE_FLOW_ITEM_TYPE_GENEVE:
+		nfp_action->type = RTE_FLOW_ACTION_TYPE_RAW_DECAP;
+		*pmd_actions = nfp_action;
+		*num_of_actions = 1;
+		break;
 	default:
 		*pmd_actions = NULL;
 		*num_of_actions = 0;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 17/26] net/nfp: support IPv6 GENEVE decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (15 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 16/26] net/nfp: support IPv4 GENEVE decap flow action Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 18/26] net/nfp: support IPv4 NVGRE encap " Chaoyong He
                       ` (9 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action for IPv6 GENEVE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 46a047cd7b..ee9c2a36e0 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1464,6 +1464,8 @@ nfp_flow_merge_geneve(struct nfp_app_fw_flower *app_fw_flower,
 		tun6 = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
 		tun6->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
 				(geneve->vni[1] << 8) | (geneve->vni[2]));
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 		tun4->tun_id = rte_cpu_to_be_32((geneve->vni[0] << 16) |
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 18/26] net/nfp: support IPv4 NVGRE encap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (16 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 17/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 19/26] net/nfp: support IPv6 " Chaoyong He
                       ` (8 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action of IPv4 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 43 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index ee9c2a36e0..cc09ba45e2 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -47,6 +47,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv6_hdr) + \
 				sizeof(struct rte_udp_hdr) + \
 				sizeof(struct rte_flow_item_geneve))
+#define NVGRE_V4_LEN     (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv4_hdr) + \
+				sizeof(struct rte_flow_item_gre) + \
+				sizeof(rte_be32_t))    /* gre key */
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2827,6 +2831,41 @@ nfp_flow_action_geneve_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
 			tun, eth, ipv6);
 }
 
+static int
+nfp_flow_action_nvgre_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_ipv4 *ipv4;
+	const struct rte_flow_item_gre *gre;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth  = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv4 = (const struct rte_flow_item_ipv4 *)(eth + 1);
+	gre  = (const struct rte_flow_item_gre *)(ipv4 + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v4_process(pre_tun, ipv4->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GRE, 0,
+			ipv4->hdr.time_to_live, ipv4->hdr.type_of_service);
+	set_tun->tun_proto = gre->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v4_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv4);
+}
+
 static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
@@ -2865,6 +2904,10 @@ nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		ret = nfp_flow_action_geneve_encap_v6(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case NVGRE_V4_LEN:
+		ret = nfp_flow_action_nvgre_encap_v4(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 19/26] net/nfp: support IPv6 NVGRE encap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (17 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 18/26] net/nfp: support IPv4 NVGRE encap " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 20/26] net/nfp: prepare for IPv4 GRE tunnel decap " Chaoyong He
                       ` (7 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of encap action of IPv6 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 45 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index cc09ba45e2..06115cc954 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -51,6 +51,10 @@ struct vxlan_data {
 				sizeof(struct rte_ipv4_hdr) + \
 				sizeof(struct rte_flow_item_gre) + \
 				sizeof(rte_be32_t))    /* gre key */
+#define NVGRE_V6_LEN     (sizeof(struct rte_ether_hdr) + \
+				sizeof(struct rte_ipv6_hdr) + \
+				sizeof(struct rte_flow_item_gre) + \
+				sizeof(rte_be32_t))    /* gre key */
 
 /* Process structure associated with a flow item */
 struct nfp_flow_item_proc {
@@ -2866,6 +2870,43 @@ nfp_flow_action_nvgre_encap_v4(struct nfp_app_fw_flower *app_fw_flower,
 			tun, eth, ipv4);
 }
 
+static int
+nfp_flow_action_nvgre_encap_v6(struct nfp_app_fw_flower *app_fw_flower,
+		char *act_data,
+		char *actions,
+		const struct rte_flow_action_raw_encap *raw_encap,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
+		struct nfp_fl_tun *tun)
+{
+	uint8_t tos;
+	const struct rte_ether_hdr *eth;
+	const struct rte_flow_item_ipv6 *ipv6;
+	const struct rte_flow_item_gre *gre;
+	struct nfp_fl_act_pre_tun *pre_tun;
+	struct nfp_fl_act_set_tun *set_tun;
+	size_t act_pre_size = sizeof(struct nfp_fl_act_pre_tun);
+	size_t act_set_size = sizeof(struct nfp_fl_act_set_tun);
+
+	eth    = (const struct rte_ether_hdr *)raw_encap->data;
+	ipv6   = (const struct rte_flow_item_ipv6 *)(eth + 1);
+	gre    = (const struct rte_flow_item_gre *)(ipv6 + 1);
+
+	pre_tun = (struct nfp_fl_act_pre_tun *)actions;
+	memset(pre_tun, 0, act_pre_size);
+	nfp_flow_pre_tun_v6_process(pre_tun, ipv6->hdr.dst_addr);
+
+	set_tun = (struct nfp_fl_act_set_tun *)(act_data + act_pre_size);
+	memset(set_tun, 0, act_set_size);
+	tos = (ipv6->hdr.vtc_flow >> RTE_IPV6_HDR_TC_SHIFT) & 0xff;
+	nfp_flow_set_tun_process(set_tun, NFP_FL_TUN_GRE, 0,
+			ipv6->hdr.hop_limits, tos);
+	set_tun->tun_proto = gre->protocol;
+
+	/* Send the tunnel neighbor cmsg to fw */
+	return nfp_flower_add_tun_neigh_v6_encap(app_fw_flower, nfp_flow_meta,
+			tun, eth, ipv6);
+}
+
 static int
 nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		char *act_data,
@@ -2908,6 +2949,10 @@ nfp_flow_action_raw_encap(struct nfp_app_fw_flower *app_fw_flower,
 		ret = nfp_flow_action_nvgre_encap_v4(app_fw_flower, act_data,
 				actions, raw_encap, nfp_flow_meta, tun);
 		break;
+	case NVGRE_V6_LEN:
+		ret = nfp_flow_action_nvgre_encap_v6(app_fw_flower, act_data,
+				actions, raw_encap, nfp_flow_meta, tun);
+		break;
 	default:
 		PMD_DRV_LOG(ERR, "Not an valid raw encap action conf.");
 		ret = -EINVAL;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 20/26] net/nfp: prepare for IPv4 GRE tunnel decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (18 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 19/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 21/26] net/nfp: prepare for IPv6 " Chaoyong He
                       ` (6 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and logics, prepare for
the decap action of IPv4 GRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 29 +++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 40 ++++++++++++++++++------
 drivers/net/nfp/nfp_flow.h               |  3 ++
 3 files changed, 63 insertions(+), 9 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 61f2f83fc9..8bca7c2fa2 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -575,6 +575,35 @@ struct nfp_flower_ipv6_udp_tun {
 	rte_be32_t tun_id;
 };
 
+/*
+ * Flow Frame GRE TUNNEL --> Tunnel details (6W/24B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_src                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                         ipv4_addr_dst                         |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           tun_flags           |       tos     |       ttl     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |            Reserved           |           Ethertype           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                              Key                              |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                           Reserved                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv4_gre_tun {
+	struct nfp_flower_tun_ipv4 ipv4;
+	rte_be16_t tun_flags;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be16_t reserved1;
+	rte_be16_t ethertype;
+	rte_be32_t tun_key;
+	rte_be32_t reserved2;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 06115cc954..115b9cbb92 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -564,6 +564,7 @@ nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
 	uint32_t key_layer2 = 0;
 	struct nfp_flower_ipv4_udp_tun *udp4;
 	struct nfp_flower_ipv6_udp_tun *udp6;
+	struct nfp_flower_ipv4_gre_tun *gre4;
 	struct nfp_flower_meta_tci *meta_tci;
 	struct nfp_flower_ext_meta *ext_meta = NULL;
 
@@ -579,9 +580,15 @@ nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
 				sizeof(struct nfp_flower_ipv6_udp_tun));
 		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
 	} else {
-		udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
-				sizeof(struct nfp_flower_ipv4_udp_tun));
-		ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
+			gre4 = (struct nfp_flower_ipv4_gre_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv4_gre_tun));
+			ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, gre4->ipv4.dst);
+		} else {
+			udp4 = (struct nfp_flower_ipv4_udp_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv4_udp_tun));
+			ret = nfp_tun_del_ipv4_off(repr->app_fw_flower, udp4->ipv4.dst);
+		}
 	}
 
 	return ret;
@@ -1013,7 +1020,7 @@ nfp_flow_is_tunnel(struct rte_flow *nfp_flow)
 
 	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 	key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
-	if (key_layer2 & NFP_FLOWER_LAYER2_GENEVE)
+	if (key_layer2 & (NFP_FLOWER_LAYER2_GENEVE | NFP_FLOWER_LAYER2_GRE))
 		return true;
 
 	return false;
@@ -1102,11 +1109,15 @@ nfp_flow_merge_ipv4(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv4 *spec;
 	const struct rte_flow_item_ipv4 *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 	struct nfp_flower_ipv4_udp_tun *ipv4_udp_tun;
+	struct nfp_flower_ipv4_gre_tun *ipv4_gre_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
 		if (spec == NULL) {
@@ -1115,12 +1126,23 @@ nfp_flow_merge_ipv4(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		}
 
 		hdr = is_mask ? &mask->hdr : &spec->hdr;
-		ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
 
-		ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
-		ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
-		ipv4_udp_tun->ipv4.src   = hdr->src_addr;
-		ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+		if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+				NFP_FLOWER_LAYER2_GRE)) {
+			ipv4_gre_tun = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+
+			ipv4_gre_tun->ip_ext.tos = hdr->type_of_service;
+			ipv4_gre_tun->ip_ext.ttl = hdr->time_to_live;
+			ipv4_gre_tun->ipv4.src   = hdr->src_addr;
+			ipv4_gre_tun->ipv4.dst   = hdr->dst_addr;
+		} else {
+			ipv4_udp_tun = (struct nfp_flower_ipv4_udp_tun *)*mbuf_off;
+
+			ipv4_udp_tun->ip_ext.tos = hdr->type_of_service;
+			ipv4_udp_tun->ip_ext.ttl = hdr->time_to_live;
+			ipv4_udp_tun->ipv4.src   = hdr->src_addr;
+			ipv4_udp_tun->ipv4.dst   = hdr->dst_addr;
+		}
 	} else {
 		if (spec == NULL) {
 			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv4: no item->spec!");
diff --git a/drivers/net/nfp/nfp_flow.h b/drivers/net/nfp/nfp_flow.h
index a6994e08ee..b0c2aaf6d8 100644
--- a/drivers/net/nfp/nfp_flow.h
+++ b/drivers/net/nfp/nfp_flow.h
@@ -49,6 +49,9 @@
 #define NFP_FL_SC_ACT_POPV      0x6A000000
 #define NFP_FL_SC_ACT_NULL      0x00000000
 
+/* GRE Tunnel flags */
+#define NFP_FL_GRE_FLAG_KEY         (1 << 2)
+
 /* Action opcodes */
 #define NFP_FL_ACTION_OPCODE_OUTPUT             0
 #define NFP_FL_ACTION_OPCODE_PUSH_VLAN          1
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 21/26] net/nfp: prepare for IPv6 GRE tunnel decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (19 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 20/26] net/nfp: prepare for IPv4 GRE tunnel decap " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 22/26] net/nfp: support IPv4 NVGRE flow item Chaoyong He
                       ` (5 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the related data structure and logics, prepare for
the decap action of IPv6 GRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower_cmsg.h | 41 ++++++++++++++++++++
 drivers/net/nfp/nfp_flow.c               | 49 ++++++++++++++++++------
 2 files changed, 78 insertions(+), 12 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index 8bca7c2fa2..a48da67222 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -604,6 +604,47 @@ struct nfp_flower_ipv4_gre_tun {
 	rte_be32_t reserved2;
 };
 
+/*
+ * Flow Frame GRE TUNNEL V6 --> Tunnel details (12W/48B)
+ * -----------------------------------------------------------------
+ *    3                   2                   1
+ *  1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_src, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,   31 - 0                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  63 - 32                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst,  95 - 64                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                  ipv6_addr_dst, 127 - 96                      |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |           tun_flags           |       tos     |       ttl     |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |            Reserved           |           Ethertype           |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                              Key                              |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                           Reserved                            |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+struct nfp_flower_ipv6_gre_tun {
+	struct nfp_flower_tun_ipv6 ipv6;
+	rte_be16_t tun_flags;
+	struct nfp_flower_tun_ip_ext ip_ext;
+	rte_be16_t reserved1;
+	rte_be16_t ethertype;
+	rte_be32_t tun_key;
+	rte_be32_t reserved2;
+};
+
 struct nfp_fl_act_head {
 	uint8_t jump_id;
 	uint8_t len_lw;
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 115b9cbb92..0353eed499 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -565,6 +565,7 @@ nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
 	struct nfp_flower_ipv4_udp_tun *udp4;
 	struct nfp_flower_ipv6_udp_tun *udp6;
 	struct nfp_flower_ipv4_gre_tun *gre4;
+	struct nfp_flower_ipv6_gre_tun *gre6;
 	struct nfp_flower_meta_tci *meta_tci;
 	struct nfp_flower_ext_meta *ext_meta = NULL;
 
@@ -576,9 +577,15 @@ nfp_tun_check_ip_off_del(struct nfp_flower_representor *repr,
 		key_layer2 = rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2);
 
 	if (key_layer2 & NFP_FLOWER_LAYER2_TUN_IPV6) {
-		udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
-				sizeof(struct nfp_flower_ipv6_udp_tun));
-		ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
+			gre6 = (struct nfp_flower_ipv6_gre_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv6_gre_tun));
+			ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, gre6->ipv6.ipv6_dst);
+		} else {
+			udp6 = (struct nfp_flower_ipv6_udp_tun *)(nfp_flow->payload.mask_data -
+					sizeof(struct nfp_flower_ipv6_udp_tun));
+			ret = nfp_tun_del_ipv6_off(repr->app_fw_flower, udp6->ipv6.ipv6_dst);
+		}
 	} else {
 		if (key_layer2 & NFP_FLOWER_LAYER2_GRE) {
 			gre4 = (struct nfp_flower_ipv4_gre_tun *)(nfp_flow->payload.mask_data -
@@ -1186,11 +1193,15 @@ nfp_flow_merge_ipv6(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 	struct nfp_flower_meta_tci *meta_tci;
 	const struct rte_flow_item_ipv6 *spec;
 	const struct rte_flow_item_ipv6 *mask;
+	struct nfp_flower_ext_meta *ext_meta = NULL;
 	struct nfp_flower_ipv6_udp_tun *ipv6_udp_tun;
+	struct nfp_flower_ipv6_gre_tun *ipv6_gre_tun;
 
 	spec = item->spec;
 	mask = item->mask ? item->mask : proc->mask_default;
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_EXT_META)
+		ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	if (is_outer_layer && nfp_flow_is_tunnel(nfp_flow)) {
 		if (spec == NULL) {
@@ -1199,15 +1210,29 @@ nfp_flow_merge_ipv6(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		}
 
 		hdr = is_mask ? &mask->hdr : &spec->hdr;
-		ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
-
-		ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
-				RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
-		ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
-		memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
-				sizeof(ipv6_udp_tun->ipv6.ipv6_src));
-		memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
-				sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+
+		if (ext_meta && (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+				NFP_FLOWER_LAYER2_GRE)) {
+			ipv6_gre_tun = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+
+			ipv6_gre_tun->ip_ext.tos = (hdr->vtc_flow &
+					RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+			ipv6_gre_tun->ip_ext.ttl = hdr->hop_limits;
+			memcpy(ipv6_gre_tun->ipv6.ipv6_src, hdr->src_addr,
+					sizeof(ipv6_gre_tun->ipv6.ipv6_src));
+			memcpy(ipv6_gre_tun->ipv6.ipv6_dst, hdr->dst_addr,
+					sizeof(ipv6_gre_tun->ipv6.ipv6_dst));
+		} else {
+			ipv6_udp_tun = (struct nfp_flower_ipv6_udp_tun *)*mbuf_off;
+
+			ipv6_udp_tun->ip_ext.tos = (hdr->vtc_flow &
+					RTE_IPV6_HDR_TC_MASK) >> RTE_IPV6_HDR_TC_SHIFT;
+			ipv6_udp_tun->ip_ext.ttl = hdr->hop_limits;
+			memcpy(ipv6_udp_tun->ipv6.ipv6_src, hdr->src_addr,
+					sizeof(ipv6_udp_tun->ipv6.ipv6_src));
+			memcpy(ipv6_udp_tun->ipv6.ipv6_dst, hdr->dst_addr,
+					sizeof(ipv6_udp_tun->ipv6.ipv6_dst));
+		}
 	} else {
 		if (spec == NULL) {
 			PMD_DRV_LOG(DEBUG, "nfp flow merge ipv6: no item->spec!");
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 22/26] net/nfp: support IPv4 NVGRE flow item
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (20 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 21/26] net/nfp: prepare for IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 23/26] net/nfp: support IPv6 " Chaoyong He
                       ` (4 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv4 NVGRE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 doc/guides/nics/features/nfp.ini |  2 +
 drivers/net/nfp/nfp_flow.c       | 99 +++++++++++++++++++++++++++++++-
 2 files changed, 99 insertions(+), 2 deletions(-)

diff --git a/doc/guides/nics/features/nfp.ini b/doc/guides/nics/features/nfp.ini
index fe1cb971f1..9e075a680b 100644
--- a/doc/guides/nics/features/nfp.ini
+++ b/doc/guides/nics/features/nfp.ini
@@ -29,6 +29,8 @@ Usage doc            = Y
 [rte_flow items]
 eth                  = Y
 geneve               = Y
+gre                  = Y
+gre_key              = Y
 ipv4                 = Y
 ipv6                 = Y
 port_id              = Y
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 0353eed499..226fc7d590 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -820,6 +820,26 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 				return -EINVAL;
 			}
 			break;
+		case RTE_FLOW_ITEM_TYPE_GRE:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE detected");
+			/* Clear IPv4 bits */
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->tun_type = NFP_FL_TUN_GRE;
+			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
+			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GRE;
+			key_ls->key_size += sizeof(struct nfp_flower_ext_meta);
+			if (outer_ip4_flag) {
+				key_ls->key_size += sizeof(struct nfp_flower_ipv4_gre_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv4_gre_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			}
+			break;
+		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
+			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE_KEY detected");
+			break;
 		default:
 			PMD_DRV_LOG(ERR, "Item type %d not supported.", item->type);
 			return -ENOTSUP;
@@ -1540,6 +1560,62 @@ nfp_flow_merge_geneve(struct nfp_app_fw_flower *app_fw_flower,
 	return ret;
 }
 
+static int
+nfp_flow_merge_gre(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		__rte_unused const struct rte_flow_item *item,
+		__rte_unused const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	struct nfp_flower_ipv4_gre_tun *tun4;
+
+	/* NVGRE is the only supported GRE tunnel type */
+	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+	if (is_mask)
+		tun4->ethertype = rte_cpu_to_be_16(~0);
+	else
+		tun4->ethertype = rte_cpu_to_be_16(0x6558);
+
+	return 0;
+}
+
+static int
+nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+		__rte_unused struct rte_flow *nfp_flow,
+		char **mbuf_off,
+		const struct rte_flow_item *item,
+		__rte_unused const struct nfp_flow_item_proc *proc,
+		bool is_mask,
+		__rte_unused bool is_outer_layer)
+{
+	rte_be32_t tun_key;
+	const rte_be32_t *spec;
+	const rte_be32_t *mask;
+	struct nfp_flower_ipv4_gre_tun *tun4;
+
+	spec = item->spec;
+	if (spec == NULL) {
+		PMD_DRV_LOG(DEBUG, "nfp flow merge gre key: no item->spec!");
+		goto gre_key_end;
+	}
+
+	mask = item->mask ? item->mask : proc->mask_default;
+	tun_key = is_mask ? *mask : *spec;
+
+	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+	tun4->tun_key = tun_key;
+	tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+
+gre_key_end:
+	*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
+
+	return 0;
+}
+
+const rte_be32_t nfp_flow_item_gre_key = 0xffffffff;
+
 /* Graph of supported items and associated process function */
 static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_END] = {
@@ -1580,7 +1656,8 @@ static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_IPV4] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_TCP,
 			RTE_FLOW_ITEM_TYPE_UDP,
-			RTE_FLOW_ITEM_TYPE_SCTP),
+			RTE_FLOW_ITEM_TYPE_SCTP,
+			RTE_FLOW_ITEM_TYPE_GRE),
 		.mask_support = &(const struct rte_flow_item_ipv4){
 			.hdr = {
 				.type_of_service = 0xff,
@@ -1671,6 +1748,23 @@ static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 		.mask_sz = sizeof(struct rte_flow_item_geneve),
 		.merge = nfp_flow_merge_geneve,
 	},
+	[RTE_FLOW_ITEM_TYPE_GRE] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_GRE_KEY),
+		.mask_support = &(const struct rte_flow_item_gre){
+			.c_rsvd0_ver = RTE_BE16(0xa000),
+			.protocol = RTE_BE16(0xffff),
+		},
+		.mask_default = &rte_flow_item_gre_mask,
+		.mask_sz = sizeof(struct rte_flow_item_gre),
+		.merge = nfp_flow_merge_gre,
+	},
+	[RTE_FLOW_ITEM_TYPE_GRE_KEY] = {
+		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_ETH),
+		.mask_support = &nfp_flow_item_gre_key,
+		.mask_default = &nfp_flow_item_gre_key,
+		.mask_sz = sizeof(rte_be32_t),
+		.merge = nfp_flow_merge_gre_key,
+	},
 };
 
 static int
@@ -1728,7 +1822,8 @@ static bool
 nfp_flow_is_tun_item(const struct rte_flow_item *item)
 {
 	if (item->type == RTE_FLOW_ITEM_TYPE_VXLAN ||
-			item->type == RTE_FLOW_ITEM_TYPE_GENEVE)
+			item->type == RTE_FLOW_ITEM_TYPE_GENEVE ||
+			item->type == RTE_FLOW_ITEM_TYPE_GRE_KEY)
 		return true;
 
 	return false;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 23/26] net/nfp: support IPv6 NVGRE flow item
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (21 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 22/26] net/nfp: support IPv4 NVGRE flow item Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 24/26] net/nfp: support IPv4 NVGRE decap flow action Chaoyong He
                       ` (3 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the corresponding logics to support the offload of
IPv6 NVGRE item.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 73 ++++++++++++++++++++++++++++++--------
 1 file changed, 59 insertions(+), 14 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 226fc7d590..78af7bcf0c 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -822,8 +822,9 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 			break;
 		case RTE_FLOW_ITEM_TYPE_GRE:
 			PMD_DRV_LOG(DEBUG, "RTE_FLOW_ITEM_TYPE_GRE detected");
-			/* Clear IPv4 bits */
+			/* Clear IPv4 and IPv6 bits */
 			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV4;
+			key_ls->key_layer &= ~NFP_FLOWER_LAYER_IPV6;
 			key_ls->tun_type = NFP_FL_TUN_GRE;
 			key_ls->key_layer |= NFP_FLOWER_LAYER_EXT_META;
 			key_ls->key_layer_two |= NFP_FLOWER_LAYER2_GRE;
@@ -835,6 +836,17 @@ nfp_flow_key_layers_calculate_items(const struct rte_flow_item items[],
 				 * in `struct nfp_flower_ipv4_gre_tun`
 				 */
 				key_ls->key_size -= sizeof(struct nfp_flower_ipv4);
+			} else if (outer_ip6_flag) {
+				key_ls->key_layer_two |= NFP_FLOWER_LAYER2_TUN_IPV6;
+				key_ls->key_size += sizeof(struct nfp_flower_ipv6_gre_tun);
+				/*
+				 * The outer l3 layer information is
+				 * in `struct nfp_flower_ipv6_gre_tun`
+				 */
+				key_ls->key_size -= sizeof(struct nfp_flower_ipv6);
+			} else {
+				PMD_DRV_LOG(ERR, "No outer IP layer for GRE tunnel.");
+				return -1;
 			}
 			break;
 		case RTE_FLOW_ITEM_TYPE_GRE_KEY:
@@ -1562,38 +1574,59 @@ nfp_flow_merge_geneve(struct nfp_app_fw_flower *app_fw_flower,
 
 static int
 nfp_flow_merge_gre(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		__rte_unused const struct rte_flow_item *item,
 		__rte_unused const struct nfp_flow_item_proc *proc,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_ipv4_gre_tun *tun4;
+	struct nfp_flower_ipv6_gre_tun *tun6;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	/* NVGRE is the only supported GRE tunnel type */
-	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
-	if (is_mask)
-		tun4->ethertype = rte_cpu_to_be_16(~0);
-	else
-		tun4->ethertype = rte_cpu_to_be_16(0x6558);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6) {
+		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+		if (is_mask)
+			tun6->ethertype = rte_cpu_to_be_16(~0);
+		else
+			tun6->ethertype = rte_cpu_to_be_16(0x6558);
+	} else {
+		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+		if (is_mask)
+			tun4->ethertype = rte_cpu_to_be_16(~0);
+		else
+			tun4->ethertype = rte_cpu_to_be_16(0x6558);
+	}
 
 	return 0;
 }
 
 static int
 nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
-		__rte_unused struct rte_flow *nfp_flow,
+		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
-		__rte_unused const struct nfp_flow_item_proc *proc,
+		const struct nfp_flow_item_proc *proc,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
 	rte_be32_t tun_key;
 	const rte_be32_t *spec;
 	const rte_be32_t *mask;
+	struct nfp_flower_meta_tci *meta_tci;
+	struct nfp_flower_ext_meta *ext_meta;
 	struct nfp_flower_ipv4_gre_tun *tun4;
+	struct nfp_flower_ipv6_gre_tun *tun6;
+
+	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
+	ext_meta = (struct nfp_flower_ext_meta *)(meta_tci + 1);
 
 	spec = item->spec;
 	if (spec == NULL) {
@@ -1604,12 +1637,23 @@ nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 	mask = item->mask ? item->mask : proc->mask_default;
 	tun_key = is_mask ? *mask : *spec;
 
-	tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
-	tun4->tun_key = tun_key;
-	tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6) {
+		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
+		tun6->tun_key = tun_key;
+		tun6->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	} else {
+		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
+		tun4->tun_key = tun_key;
+		tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+	}
 
 gre_key_end:
-	*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
+	if (rte_be_to_cpu_32(ext_meta->nfp_flow_key_layer2) &
+			NFP_FLOWER_LAYER2_TUN_IPV6)
+		*mbuf_off += sizeof(struct nfp_flower_ipv6_gre_tun);
+	else
+		*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
 
 	return 0;
 }
@@ -1675,7 +1719,8 @@ static const struct nfp_flow_item_proc nfp_flow_item_proc_list[] = {
 	[RTE_FLOW_ITEM_TYPE_IPV6] = {
 		.next_item = NEXT_ITEM(RTE_FLOW_ITEM_TYPE_TCP,
 			RTE_FLOW_ITEM_TYPE_UDP,
-			RTE_FLOW_ITEM_TYPE_SCTP),
+			RTE_FLOW_ITEM_TYPE_SCTP,
+			RTE_FLOW_ITEM_TYPE_GRE),
 		.mask_support = &(const struct rte_flow_item_ipv6){
 			.hdr = {
 				.vtc_flow   = RTE_BE32(0x0ff00000),
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 24/26] net/nfp: support IPv4 NVGRE decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (22 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 23/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 25/26] net/nfp: support IPv6 " Chaoyong He
                       ` (2 subsequent siblings)
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action of IPv4 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 78af7bcf0c..d666446edf 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1609,7 +1609,7 @@ nfp_flow_merge_gre(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 }
 
 static int
-nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
+nfp_flow_merge_gre_key(struct nfp_app_fw_flower *app_fw_flower,
 		struct rte_flow *nfp_flow,
 		char **mbuf_off,
 		const struct rte_flow_item *item,
@@ -1617,6 +1617,7 @@ nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		bool is_mask,
 		__rte_unused bool is_outer_layer)
 {
+	int ret = 0;
 	rte_be32_t tun_key;
 	const rte_be32_t *spec;
 	const rte_be32_t *mask;
@@ -1646,6 +1647,8 @@ nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
 		tun4->tun_key = tun_key;
 		tun4->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+		if (!is_mask)
+			ret = nfp_tun_add_ipv4_off(app_fw_flower, tun4->ipv4.dst);
 	}
 
 gre_key_end:
@@ -1655,7 +1658,7 @@ nfp_flow_merge_gre_key(__rte_unused struct nfp_app_fw_flower *app_fw_flower,
 	else
 		*mbuf_off += sizeof(struct nfp_flower_ipv4_gre_tun);
 
-	return 0;
+	return ret;
 }
 
 const rte_be32_t nfp_flow_item_gre_key = 0xffffffff;
@@ -3831,6 +3834,7 @@ nfp_flow_tunnel_decap_set(__rte_unused struct rte_eth_dev *dev,
 		*num_of_actions = 1;
 		break;
 	case RTE_FLOW_ITEM_TYPE_GENEVE:
+	case RTE_FLOW_ITEM_TYPE_GRE:
 		nfp_action->type = RTE_FLOW_ACTION_TYPE_RAW_DECAP;
 		*pmd_actions = nfp_action;
 		*num_of_actions = 1;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 25/26] net/nfp: support IPv6 NVGRE decap flow action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (23 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 24/26] net/nfp: support IPv4 NVGRE decap flow action Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25  7:59     ` [PATCH v3 26/26] net/nfp: support new solution for tunnel decap action Chaoyong He
  2022-10-25 11:42     ` [PATCH v3 00/26] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

Add the offload support of decap action of IPv6 NVGRE tunnel.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/nfp_flow.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index d666446edf..93a9233b8b 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -1643,6 +1643,8 @@ nfp_flow_merge_gre_key(struct nfp_app_fw_flower *app_fw_flower,
 		tun6 = (struct nfp_flower_ipv6_gre_tun *)*mbuf_off;
 		tun6->tun_key = tun_key;
 		tun6->tun_flags = rte_cpu_to_be_16(NFP_FL_GRE_FLAG_KEY);
+		if (!is_mask)
+			ret = nfp_tun_add_ipv6_off(app_fw_flower, tun6->ipv6.ipv6_dst);
 	} else {
 		tun4 = (struct nfp_flower_ipv4_gre_tun *)*mbuf_off;
 		tun4->tun_key = tun_key;
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* [PATCH v3 26/26] net/nfp: support new solution for tunnel decap action
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (24 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 25/26] net/nfp: support IPv6 " Chaoyong He
@ 2022-10-25  7:59     ` Chaoyong He
  2022-10-25 11:42     ` [PATCH v3 00/26] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
  26 siblings, 0 replies; 88+ messages in thread
From: Chaoyong He @ 2022-10-25  7:59 UTC (permalink / raw)
  To: dev; +Cc: oss-drivers, niklas.soderlund, Chaoyong He

The new version of flower firmware application add the support of
a new tunnel decap action solution.

It changes the structure of tunnel neighbor, and use a feature flag
to indicate which tunnel decap action solution is used.

Add the logic of read extra features from firmware, and store it in
the app private structure.

Adjust the data structure and related logic to make the PMD support
both version of tunnel decap action solutions.

Signed-off-by: Chaoyong He <chaoyong.he@corigine.com>
Reviewed-by: Niklas Söderlund <niklas.soderlund@corigine.com>
---
 drivers/net/nfp/flower/nfp_flower.c      |  14 +++
 drivers/net/nfp/flower/nfp_flower.h      |  24 +++++
 drivers/net/nfp/flower/nfp_flower_cmsg.c |   4 +
 drivers/net/nfp/flower/nfp_flower_cmsg.h |  17 ++++
 drivers/net/nfp/nfp_flow.c               | 118 +++++++++++++++++++----
 5 files changed, 157 insertions(+), 20 deletions(-)

diff --git a/drivers/net/nfp/flower/nfp_flower.c b/drivers/net/nfp/flower/nfp_flower.c
index 41b0fe2337..aa8199dde2 100644
--- a/drivers/net/nfp/flower/nfp_flower.c
+++ b/drivers/net/nfp/flower/nfp_flower.c
@@ -1074,6 +1074,8 @@ int
 nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
 {
 	int ret;
+	int err;
+	uint64_t ext_features;
 	unsigned int numa_node;
 	struct nfp_net_hw *pf_hw;
 	struct nfp_net_hw *ctrl_hw;
@@ -1115,6 +1117,18 @@ nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
 		goto vnic_cleanup;
 	}
 
+	/* Read the extra features */
+	ext_features = nfp_rtsym_read_le(pf_dev->sym_tbl, "_abi_flower_extra_features",
+			&err);
+	if (err != 0) {
+		PMD_INIT_LOG(ERR, "Couldn't read extra features from fw");
+		ret = -EIO;
+		goto pf_cpp_area_cleanup;
+	}
+
+	/* Store the extra features */
+	app_fw_flower->ext_features = ext_features;
+
 	/* Fill in the PF vNIC and populate app struct */
 	app_fw_flower->pf_hw = pf_hw;
 	pf_hw->ctrl_bar = pf_dev->ctrl_bar;
diff --git a/drivers/net/nfp/flower/nfp_flower.h b/drivers/net/nfp/flower/nfp_flower.h
index f199741190..c05a761a95 100644
--- a/drivers/net/nfp/flower/nfp_flower.h
+++ b/drivers/net/nfp/flower/nfp_flower.h
@@ -8,6 +8,21 @@
 
 #include "../nfp_common.h"
 
+/* Extra features bitmap. */
+#define NFP_FL_FEATS_GENEVE             RTE_BIT64(0)
+#define NFP_FL_NBI_MTU_SETTING          RTE_BIT64(1)
+#define NFP_FL_FEATS_GENEVE_OPT         RTE_BIT64(2)
+#define NFP_FL_FEATS_VLAN_PCP           RTE_BIT64(3)
+#define NFP_FL_FEATS_VF_RLIM            RTE_BIT64(4)
+#define NFP_FL_FEATS_FLOW_MOD           RTE_BIT64(5)
+#define NFP_FL_FEATS_PRE_TUN_RULES      RTE_BIT64(6)
+#define NFP_FL_FEATS_IPV6_TUN           RTE_BIT64(7)
+#define NFP_FL_FEATS_VLAN_QINQ          RTE_BIT64(8)
+#define NFP_FL_FEATS_QOS_PPS            RTE_BIT64(9)
+#define NFP_FL_FEATS_QOS_METER          RTE_BIT64(10)
+#define NFP_FL_FEATS_DECAP_V2           RTE_BIT64(11)
+#define NFP_FL_FEATS_HOST_ACK           RTE_BIT64(31)
+
 /*
  * Flower fallback and ctrl path always adds and removes
  * 8 bytes of prepended data. Tx descriptors must point
@@ -57,9 +72,18 @@ struct nfp_app_fw_flower {
 	/* service id of ctrl vnic service */
 	uint32_t ctrl_vnic_id;
 
+	/* Flower extra features */
+	uint64_t ext_features;
+
 	struct nfp_flow_priv *flow_priv;
 };
 
+static inline bool
+nfp_flower_support_decap_v2(const struct nfp_app_fw_flower *app_fw_flower)
+{
+	return app_fw_flower->ext_features & NFP_FL_FEATS_DECAP_V2;
+}
+
 int nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev);
 int nfp_secondary_init_app_fw_flower(struct nfp_cpp *cpp);
 uint16_t nfp_flower_pf_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.c b/drivers/net/nfp/flower/nfp_flower_cmsg.c
index 76815cfe14..babdd8e36b 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.c
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.c
@@ -263,6 +263,8 @@ nfp_flower_cmsg_tun_neigh_v4_rule(struct nfp_app_fw_flower *app_fw_flower,
 	}
 
 	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v4);
+	if (!nfp_flower_support_decap_v2(app_fw_flower))
+		msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
 	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH, msg_len);
 	memcpy(msg, payload, msg_len);
 
@@ -292,6 +294,8 @@ nfp_flower_cmsg_tun_neigh_v6_rule(struct nfp_app_fw_flower *app_fw_flower,
 	}
 
 	msg_len = sizeof(struct nfp_flower_cmsg_tun_neigh_v6);
+	if (!nfp_flower_support_decap_v2(app_fw_flower))
+		msg_len -= sizeof(struct nfp_flower_tun_neigh_ext);
 	msg = nfp_flower_cmsg_init(mbuf, NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V6, msg_len);
 	memcpy(msg, payload, msg_len);
 
diff --git a/drivers/net/nfp/flower/nfp_flower_cmsg.h b/drivers/net/nfp/flower/nfp_flower_cmsg.h
index a48da67222..04601cb0bd 100644
--- a/drivers/net/nfp/flower/nfp_flower_cmsg.h
+++ b/drivers/net/nfp/flower/nfp_flower_cmsg.h
@@ -135,6 +135,21 @@ struct nfp_flower_tun_neigh {
 	rte_be32_t port_id;
 };
 
+/*
+ *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
+ *    -----\ 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+ *          +---------------------------------------------------------------+
+ *        0 |         VLAN_TPID             |            VLAN_ID            |
+ *          +---------------------------------------------------------------+
+ *        1 |                           HOST_CTX                            |
+ *          +---------------------------------------------------------------+
+ */
+struct nfp_flower_tun_neigh_ext {
+	rte_be16_t vlan_tpid;
+	rte_be16_t vlan_tci;
+	rte_be32_t host_ctx;
+};
+
 /*
  * NFP_FLOWER_CMSG_TYPE_TUN_NEIGH_V4
  *    Bit    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0
@@ -157,6 +172,7 @@ struct nfp_flower_cmsg_tun_neigh_v4 {
 	rte_be32_t dst_ipv4;
 	rte_be32_t src_ipv4;
 	struct nfp_flower_tun_neigh common;
+	struct nfp_flower_tun_neigh_ext ext;
 };
 
 /*
@@ -193,6 +209,7 @@ struct nfp_flower_cmsg_tun_neigh_v6 {
 	uint8_t dst_ipv6[16];
 	uint8_t src_ipv6[16];
 	struct nfp_flower_tun_neigh common;
+	struct nfp_flower_tun_neigh_ext ext;
 };
 
 #define NFP_TUN_PRE_TUN_RULE_DEL    (1 << 0)
diff --git a/drivers/net/nfp/nfp_flow.c b/drivers/net/nfp/nfp_flow.c
index 93a9233b8b..af56e7bef2 100644
--- a/drivers/net/nfp/nfp_flow.c
+++ b/drivers/net/nfp/nfp_flow.c
@@ -2384,8 +2384,10 @@ nfp_flower_add_tun_neigh_v4_encap(struct nfp_app_fw_flower *app_fw_flower,
 
 static int
 nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
+	bool exists = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
 	struct nfp_flow_priv *priv;
@@ -2419,11 +2421,17 @@ nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
 	LIST_FOREACH(tmp, &priv->nn_list, next) {
 		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
 			tmp->ref_cnt++;
-			return 0;
+			exists = true;
+			break;
 		}
 	}
 
-	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	if (exists) {
+		if (!nfp_flower_support_decap_v2(app_fw_flower))
+			return 0;
+	} else {
+		LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	}
 
 	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
 	payload.dst_ipv4 = ipv4->ipv4_src;
@@ -2432,6 +2440,17 @@ nfp_flower_add_tun_neigh_v4_decap(struct nfp_app_fw_flower *app_fw_flower,
 	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
 	payload.common.port_id = port->in_port;
 
+	if (nfp_flower_support_decap_v2(app_fw_flower)) {
+		if (meta_tci->tci != 0) {
+			payload.ext.vlan_tci = meta_tci->tci;
+			payload.ext.vlan_tpid = 0x88a8;
+		} else {
+			payload.ext.vlan_tci = 0xffff;
+			payload.ext.vlan_tpid = 0xffff;
+		}
+		payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
+	}
+
 	return nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &payload);
 }
 
@@ -2492,8 +2511,10 @@ nfp_flower_add_tun_neigh_v6_encap(struct nfp_app_fw_flower *app_fw_flower,
 
 static int
 nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
+		struct nfp_fl_rule_metadata *nfp_flow_meta,
 		struct rte_flow *nfp_flow)
 {
+	bool exists = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
 	struct nfp_flow_priv *priv;
@@ -2527,11 +2548,17 @@ nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
 	LIST_FOREACH(tmp, &priv->nn_list, next) {
 		if (memcmp(&tmp->payload, &tun->payload, sizeof(struct nfp_fl_tun_entry)) == 0) {
 			tmp->ref_cnt++;
-			return 0;
+			exists = true;
+			break;
 		}
 	}
 
-	LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	if (exists) {
+		if (!nfp_flower_support_decap_v2(app_fw_flower))
+			return 0;
+	} else {
+		LIST_INSERT_HEAD(&priv->nn_list, tun, next);
+	}
 
 	memset(&payload, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
 	memcpy(payload.dst_ipv6, ipv6->ipv6_src, sizeof(payload.dst_ipv6));
@@ -2540,6 +2567,17 @@ nfp_flower_add_tun_neigh_v6_decap(struct nfp_app_fw_flower *app_fw_flower,
 	memcpy(payload.common.src_mac, eth->mac_dst, RTE_ETHER_ADDR_LEN);
 	payload.common.port_id = port->in_port;
 
+	if (nfp_flower_support_decap_v2(app_fw_flower)) {
+		if (meta_tci->tci != 0) {
+			payload.ext.vlan_tci = meta_tci->tci;
+			payload.ext.vlan_tpid = 0x88a8;
+		} else {
+			payload.ext.vlan_tci = 0xffff;
+			payload.ext.vlan_tpid = 0xffff;
+		}
+		payload.ext.host_ctx = nfp_flow_meta->host_ctx_id;
+	}
+
 	return nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &payload);
 }
 
@@ -2557,12 +2595,14 @@ nfp_flower_del_tun_neigh_v6(struct nfp_app_fw_flower *app_fw_flower,
 
 static int
 nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
-		struct rte_flow *nfp_flow)
+		struct rte_flow *nfp_flow,
+		bool decap_flag)
 {
 	int ret;
 	bool flag = false;
 	struct nfp_fl_tun *tmp;
 	struct nfp_fl_tun *tun;
+	struct nfp_flower_in_port *port;
 
 	tun = &nfp_flow->tun;
 	LIST_FOREACH(tmp, &app_fw_flower->flow_priv->nn_list, next) {
@@ -2590,6 +2630,40 @@ nfp_flower_del_tun_neigh(struct nfp_app_fw_flower *app_fw_flower,
 		}
 	}
 
+	if (!decap_flag)
+		return 0;
+
+	port = (struct nfp_flower_in_port *)(nfp_flow->payload.unmasked_data +
+			sizeof(struct nfp_fl_rule_metadata) +
+			sizeof(struct nfp_flower_meta_tci));
+
+	if (tmp->payload.v6_flag != 0) {
+		struct nfp_flower_cmsg_tun_neigh_v6 nn_v6;
+		memset(&nn_v6, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v6));
+		memcpy(nn_v6.dst_ipv6, tmp->payload.dst.dst_ipv6, sizeof(nn_v6.dst_ipv6));
+		memcpy(nn_v6.src_ipv6, tmp->payload.src.src_ipv6, sizeof(nn_v6.src_ipv6));
+		memcpy(nn_v6.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
+		memcpy(nn_v6.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
+		nn_v6.common.port_id = port->in_port;
+
+		ret = nfp_flower_cmsg_tun_neigh_v6_rule(app_fw_flower, &nn_v6);
+	} else {
+		struct nfp_flower_cmsg_tun_neigh_v4 nn_v4;
+		memset(&nn_v4, 0, sizeof(struct nfp_flower_cmsg_tun_neigh_v4));
+		nn_v4.dst_ipv4 = tmp->payload.dst.dst_ipv4;
+		nn_v4.src_ipv4 = tmp->payload.src.src_ipv4;
+		memcpy(nn_v4.common.dst_mac, tmp->payload.dst_addr, RTE_ETHER_ADDR_LEN);
+		memcpy(nn_v4.common.src_mac, tmp->payload.src_addr, RTE_ETHER_ADDR_LEN);
+		nn_v4.common.port_id = port->in_port;
+
+		ret = nfp_flower_cmsg_tun_neigh_v4_rule(app_fw_flower, &nn_v4);
+	}
+
+	if (ret != 0) {
+		PMD_DRV_LOG(DEBUG, "Failed to send the nn entry");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -2877,12 +2951,14 @@ nfp_pre_tun_table_check_del(struct nfp_flower_representor *repr,
 		goto free_entry;
 	}
 
-	ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
-			nfp_mac_idx, true);
-	if (ret != 0) {
-		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
-		ret = -EINVAL;
-		goto free_entry;
+	if (!nfp_flower_support_decap_v2(repr->app_fw_flower)) {
+		ret = nfp_flower_cmsg_pre_tunnel_rule(repr->app_fw_flower, nfp_flow_meta,
+				nfp_mac_idx, true);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+			ret = -EINVAL;
+			goto free_entry;
+		}
 	}
 
 	find_entry->ref_cnt = 1U;
@@ -2933,18 +3009,20 @@ nfp_flow_action_tunnel_decap(struct nfp_flower_representor *repr,
 		return -EINVAL;
 	}
 
-	ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
-			nfp_mac_idx, false);
-	if (ret != 0) {
-		PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
-		return -EINVAL;
+	if (!nfp_flower_support_decap_v2(app_fw_flower)) {
+		ret = nfp_flower_cmsg_pre_tunnel_rule(app_fw_flower, nfp_flow_meta,
+				nfp_mac_idx, false);
+		if (ret != 0) {
+			PMD_DRV_LOG(ERR, "Send pre tunnel rule failed");
+			return -EINVAL;
+		}
 	}
 
 	meta_tci = (struct nfp_flower_meta_tci *)nfp_flow->payload.unmasked_data;
 	if (meta_tci->nfp_flow_key_layer & NFP_FLOWER_LAYER_IPV4)
-		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow);
+		return nfp_flower_add_tun_neigh_v4_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
 	else
-		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow);
+		return nfp_flower_add_tun_neigh_v6_decap(app_fw_flower, nfp_flow_meta, nfp_flow);
 }
 
 static int
@@ -3654,11 +3732,11 @@ nfp_flow_destroy(struct rte_eth_dev *dev,
 		break;
 	case NFP_FLOW_ENCAP:
 		/* Delete the entry from nn table */
-		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, false);
 		break;
 	case NFP_FLOW_DECAP:
 		/* Delete the entry from nn table */
-		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow);
+		ret = nfp_flower_del_tun_neigh(app_fw_flower, nfp_flow, true);
 		if (ret != 0)
 			goto exit;
 
-- 
2.29.3


^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v2 25/25] net/nfp: support new tunnel solution
  2022-10-25  1:44       ` Chaoyong He
@ 2022-10-25  8:18         ` Ferruh Yigit
  0 siblings, 0 replies; 88+ messages in thread
From: Ferruh Yigit @ 2022-10-25  8:18 UTC (permalink / raw)
  To: Chaoyong He; +Cc: oss-drivers, Niklas Soderlund, dev

On 10/25/2022 2:44 AM, Chaoyong He wrote:
>> On 10/22/2022 9:24 AM, Chaoyong He wrote:
>>> The new version of flower firmware application add the support of a
>>> new tunnel solution.
>>>
>>> It changes the structure of tunnel neighbor, and use a feature flag to
>>> indicate which tunnel solution is used.
>>>
>>> Add the logic of read extra features from firmware, and store it in
>>> the app private structure.
>>>
>>> Adjust the data structure and related logic to make the PMD support
>>> both version of tunnel solutions.
>>>
>>> Signed-off-by: Chaoyong He<chaoyong.he@corigine.com>
>>> Reviewed-by: Niklas Söderlund<niklas.soderlund@corigine.com>
>>> ---
>>>    drivers/net/nfp/flower/nfp_flower.c      |  14 ++++
>>>    drivers/net/nfp/flower/nfp_flower.h      |  24 +++++++
>>>    drivers/net/nfp/flower/nfp_flower_cmsg.c |   4 ++
>>>    drivers/net/nfp/flower/nfp_flower_cmsg.h |  17 +++++
>>>    drivers/net/nfp/nfp_flow.c               | 118 +++++++++++++++++++++++++-
>> -----
>>>    5 files changed, 157 insertions(+), 20 deletions(-)
>>>
>>> diff --git a/drivers/net/nfp/flower/nfp_flower.c
>>> b/drivers/net/nfp/flower/nfp_flower.c
>>> index 41b0fe2..aa8199d 100644
>>> --- a/drivers/net/nfp/flower/nfp_flower.c
>>> +++ b/drivers/net/nfp/flower/nfp_flower.c
>>> @@ -1074,6 +1074,8 @@
>>>    nfp_init_app_fw_flower(struct nfp_pf_dev *pf_dev)
>>>    {
>>>    	int ret;
>>> +	int err;
>>> +	uint64_t ext_features;
>>>    	unsigned int numa_node;
>>>    	struct nfp_net_hw *pf_hw;
>>>    	struct nfp_net_hw *ctrl_hw;
>>> @@ -1115,6 +1117,18 @@
>>>    		goto vnic_cleanup;
>>>    	}
>>>
>>> +	/* Read the extra features */
>>> +	ext_features = nfp_rtsym_read_le(pf_dev->sym_tbl,
>> "_abi_flower_extra_features",
>>> +			&err);
>>> +	if (err != 0) {
>>> +		PMD_INIT_LOG(ERR, "Couldn't read extra features from fw");
>>> +		ret = -EIO;
>>> +		goto pf_cpp_area_cleanup;
>>> +	}
>>
>> Hi Chaoyong,
>>
>> It looks like there are two flavor of the flower firmware application, one with
>> 'extra_features' other without it.
>> Does this worth documenting in the driver documentation and the release
>> notes?
> 
> Actually, it's just two different methods to process the tunnel decap action in the flower
> firmware application.
> 
> The old version flower firmware application needs 'tunnel neighbor' and 'pre-tunnel' table
> to get needed information to decap the tunnel packet.
> While the new version flower firmware application extends the 'tunnel neighbor' table and
> does not need 'pre-tunnel' table anymore when decap the tunnel packet.
> 
> The app which use the rte_flow know nothing about this difference.
> So, should we still explain this in the documentation and the release notes? I'm not quite sure
> about how details should we expose in these documents.

Thanks for clarification, if this is transparent to user/app may not 
need to document.

^ permalink raw reply	[flat|nested] 88+ messages in thread

* Re: [PATCH v3 00/26] add the extend rte_flow offload support of nfp PMD
  2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
                       ` (25 preceding siblings ...)
  2022-10-25  7:59     ` [PATCH v3 26/26] net/nfp: support new solution for tunnel decap action Chaoyong He
@ 2022-10-25 11:42     ` Ferruh Yigit
  26 siblings, 0 replies; 88+ messages in thread
From: Ferruh Yigit @ 2022-10-25 11:42 UTC (permalink / raw)
  To: Chaoyong He, dev; +Cc: oss-drivers, niklas.soderlund

On 10/25/2022 8:58 AM, Chaoyong He wrote:
> This is the third patch series to add the support of rte_flow offload for
> nfp PMD, includes:
> Add the offload support of decap/encap of VXLAN
> Add the offload support of decap/encap of GENEVE
> Add the offload support of decap/encap of NVGRE
> 
> Changes since v2
> - Fix the inconsistency in 'nfp.ini' file.
> - Modify the commit message about the new solution of tunnel decap action.
> - Add a commit which fix the CPP bridge service stuck the DPDK app.
> 
> Changes since v1
> - Delete the modificaiton of release note.
> - Modify the commit title.
> - Rebase to the lastest logic.
> 
> Chaoyong He (26):
>    net/nfp: fix the app stuck by CPP bridge service
>    net/nfp: support IPv4 VXLAN flow item
>    net/nfp: support IPv6 VXLAN flow item
>    net/nfp: prepare for IPv4 tunnel encap flow action
>    net/nfp: prepare for IPv6 tunnel encap flow action
>    net/nfp: support IPv4 VXLAN encap flow action
>    net/nfp: support IPv6 VXLAN encap flow action
>    net/nfp: prepare for IPv4 UDP tunnel decap flow action
>    net/nfp: prepare for IPv6 UDP tunnel decap flow action
>    net/nfp: support IPv4 VXLAN decap flow action
>    net/nfp: support IPv6 VXLAN decap flow action
>    net/nfp: support IPv4 GENEVE encap flow action
>    net/nfp: support IPv6 GENEVE encap flow action
>    net/nfp: support IPv4 GENEVE flow item
>    net/nfp: support IPv6 GENEVE flow item
>    net/nfp: support IPv4 GENEVE decap flow action
>    net/nfp: support IPv6 GENEVE decap flow action
>    net/nfp: support IPv4 NVGRE encap flow action
>    net/nfp: support IPv6 NVGRE encap flow action
>    net/nfp: prepare for IPv4 GRE tunnel decap flow action
>    net/nfp: prepare for IPv6 GRE tunnel decap flow action
>    net/nfp: support IPv4 NVGRE flow item
>    net/nfp: support IPv6 NVGRE flow item
>    net/nfp: support IPv4 NVGRE decap flow action
>    net/nfp: support IPv6 NVGRE decap flow action
>    net/nfp: support new solution for tunnel decap action

Series applied to dpdk-next-net/main, thanks.

^ permalink raw reply	[flat|nested] 88+ messages in thread

end of thread, other threads:[~2022-10-25 11:42 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-18  3:22 [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Chaoyong He
2022-10-18  3:22 ` [PATCH 01/25] net/nfp: add the offload support of IPv4 VXLAN item Chaoyong He
2022-10-18  3:22 ` [PATCH 02/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 03/25] net/nfp: prepare for the encap action of IPv4 tunnel Chaoyong He
2022-10-18  3:22 ` [PATCH 04/25] net/nfp: prepare for the encap action of IPv6 tunnel Chaoyong He
2022-10-18  3:22 ` [PATCH 05/25] net/nfp: add the offload support of IPv4 VXLAN encap action Chaoyong He
2022-10-18  3:22 ` [PATCH 06/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 07/25] net/nfp: prepare for the decap action of IPv4 UDP tunnel Chaoyong He
2022-10-18  3:22 ` [PATCH 08/25] net/nfp: prepare for the decap action of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 09/25] net/nfp: add the offload support of IPv4 VXLAN decap action Chaoyong He
2022-10-18  3:22 ` [PATCH 10/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 11/25] net/nfp: add the offload support of IPv4 GENEVE encap action Chaoyong He
2022-10-18  3:22 ` [PATCH 12/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 13/25] net/nfp: add the offload support of IPv4 GENEVE item Chaoyong He
2022-10-18  3:22 ` [PATCH 14/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 15/25] net/nfp: add the offload support of IPv4 GENEVE decap action Chaoyong He
2022-10-18  3:22 ` [PATCH 16/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 17/25] net/nfp: add the offload support of IPv4 NVGRE encap action Chaoyong He
2022-10-18  3:22 ` [PATCH 18/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 19/25] net/nfp: prepare for the decap action of IPv4 GRE tunnel Chaoyong He
2022-10-18  3:22 ` [PATCH 20/25] net/nfp: prepare for the decap action of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 21/25] net/nfp: add the offload support of IPv4 NVGRE item Chaoyong He
2022-10-18  3:22 ` [PATCH 22/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 23/25] net/nfp: add the offload support of IPv4 NVGRE decap action Chaoyong He
2022-10-18  3:22 ` [PATCH 24/25] net/nfp: add the offload support of IPv6 " Chaoyong He
2022-10-18  3:22 ` [PATCH 25/25] net/nfp: add the support of new tunnel solution Chaoyong He
2022-10-21 13:37 ` [PATCH 00/25] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
2022-10-21 13:39   ` Ferruh Yigit
2022-10-22  8:24 ` [PATCH v2 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 01/25] net/nfp: support IPv4 VXLAN flow item Chaoyong He
2022-10-22  8:24   ` [PATCH v2 02/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 03/25] net/nfp: prepare for IPv4 tunnel encap flow action Chaoyong He
2022-10-22  8:24   ` [PATCH v2 04/25] net/nfp: prepare for IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 05/25] net/nfp: support IPv4 VXLAN " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 06/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 07/25] net/nfp: prepare for IPv4 UDP tunnel decap " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 08/25] net/nfp: prepare for IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 09/25] net/nfp: support IPv4 VXLAN " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 10/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 11/25] net/nfp: support IPv4 GENEVE encap " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 12/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 13/25] net/nfp: support IPv4 GENEVE flow item Chaoyong He
2022-10-22  8:24   ` [PATCH v2 14/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 15/25] net/nfp: support IPv4 GENEVE decap flow action Chaoyong He
2022-10-22  8:24   ` [PATCH v2 16/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 17/25] net/nfp: support IPv4 NVGRE encap " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 18/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 19/25] net/nfp: prepare for IPv4 GRE tunnel decap " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 20/25] net/nfp: prepare for IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 21/25] net/nfp: support IPv4 NVGRE flow item Chaoyong He
2022-10-22  8:24   ` [PATCH v2 22/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 23/25] net/nfp: support IPv4 NVGRE decap flow action Chaoyong He
2022-10-22  8:24   ` [PATCH v2 24/25] net/nfp: support IPv6 " Chaoyong He
2022-10-22  8:24   ` [PATCH v2 25/25] net/nfp: support new tunnel solution Chaoyong He
2022-10-24 15:09     ` Ferruh Yigit
2022-10-25  1:44       ` Chaoyong He
2022-10-25  8:18         ` Ferruh Yigit
2022-10-24 15:07   ` [PATCH v2 00/25] add the extend rte_flow offload support of nfp PMD Ferruh Yigit
2022-10-25  3:17     ` Chaoyong He
2022-10-25  3:29       ` Chaoyong He
2022-10-25  7:58   ` [PATCH v3 00/26] " Chaoyong He
2022-10-25  7:58     ` [PATCH v3 01/26] net/nfp: fix the app stuck by CPP bridge service Chaoyong He
2022-10-25  7:58     ` [PATCH v3 02/26] net/nfp: support IPv4 VXLAN flow item Chaoyong He
2022-10-25  7:58     ` [PATCH v3 03/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:58     ` [PATCH v3 04/26] net/nfp: prepare for IPv4 tunnel encap flow action Chaoyong He
2022-10-25  7:58     ` [PATCH v3 05/26] net/nfp: prepare for IPv6 " Chaoyong He
2022-10-25  7:58     ` [PATCH v3 06/26] net/nfp: support IPv4 VXLAN " Chaoyong He
2022-10-25  7:58     ` [PATCH v3 07/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 08/26] net/nfp: prepare for IPv4 UDP tunnel decap " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 09/26] net/nfp: prepare for IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 10/26] net/nfp: support IPv4 VXLAN " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 11/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 12/26] net/nfp: support IPv4 GENEVE encap " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 13/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 14/26] net/nfp: support IPv4 GENEVE flow item Chaoyong He
2022-10-25  7:59     ` [PATCH v3 15/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 16/26] net/nfp: support IPv4 GENEVE decap flow action Chaoyong He
2022-10-25  7:59     ` [PATCH v3 17/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 18/26] net/nfp: support IPv4 NVGRE encap " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 19/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 20/26] net/nfp: prepare for IPv4 GRE tunnel decap " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 21/26] net/nfp: prepare for IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 22/26] net/nfp: support IPv4 NVGRE flow item Chaoyong He
2022-10-25  7:59     ` [PATCH v3 23/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 24/26] net/nfp: support IPv4 NVGRE decap flow action Chaoyong He
2022-10-25  7:59     ` [PATCH v3 25/26] net/nfp: support IPv6 " Chaoyong He
2022-10-25  7:59     ` [PATCH v3 26/26] net/nfp: support new solution for tunnel decap action Chaoyong He
2022-10-25 11:42     ` [PATCH v3 00/26] add the extend rte_flow offload support of nfp PMD Ferruh Yigit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).