patch 'net/iavf: fix null engine for egress security flows' has been queued to stable release 24.11.9

luca.boccassi at gmail.com luca.boccassi at gmail.com
Thu Nov 5 17:42:20 CET 2026


Hi,

FYI, your patch has been queued to stable release 24.11.9

Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet.
It will be pushed if I get no objections before 11/07/26. So please
shout if anyone has objections.

Also note that after the patch there's a diff of the upstream commit vs the
patch applied to the branch. This will indicate if there was any rebasing
needed to apply to the stable branch. If there were code changes for rebasing
(ie: not only metadata diffs), please double check that the rebase was
correctly done.

Queued patches are on a temporary branch at:
https://github.com/bluca/dpdk-stable

This queued commit can be viewed at:
https://github.com/bluca/dpdk-stable/commit/fe77017493758256fc0545dc5885cf81d5cb8116

Thanks.

Luca Boccassi

---
>From fe77017493758256fc0545dc5885cf81d5cb8116 Mon Sep 17 00:00:00 2001
From: Anatoly Burakov <anatoly.burakov at intel.com>
Date: Fri, 23 Oct 2026 10:32:29 +0100
Subject: [PATCH] net/iavf: fix null engine for egress security flows

[ upstream commit 99f371f25bfb55bd1268769320f4629cf28a0b9d ]

Egress security flows bypass the flow parsers and are inserted with a
NULL `engine` pointer. The create path then dereferences that pointer
when logging the new flow, and other engine-based operations cannot
handle the flow consistently.

Register an egress security engine and route these flows through the
normal parser and lifecycle callbacks. Egress flows own no rule and
require no hardware teardown.

Fixes: e783da175250 ("net/iavf: fix memory leak on egress IPsec flows")

Signed-off-by: Anatoly Burakov <anatoly.burakov at intel.com>
Acked-by: Radu Nicolau <radu.nicolau at intel.com>
---
 drivers/net/iavf/iavf_generic_flow.c |  79 ++++++++---------
 drivers/net/iavf/iavf_generic_flow.h |   2 +-
 drivers/net/iavf/iavf_ipsec_crypto.c | 125 +++++++++++++++++++++++++--
 3 files changed, 152 insertions(+), 54 deletions(-)

diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c
index cd9a88010be..5c791762886 100644
--- a/drivers/net/iavf/iavf_generic_flow.c
+++ b/drivers/net/iavf/iavf_generic_flow.c
@@ -1785,7 +1785,7 @@ enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
 typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad,
 		struct rte_flow *flow,
 		struct iavf_parser_list *parser_list,
-		uint32_t priority,
+		const struct rte_flow_attr *attr,
 		const struct rte_flow_item pattern[],
 		const struct rte_flow_action actions[],
 		struct rte_flow_error *error);
@@ -1902,7 +1902,8 @@ iavf_register_parser(struct iavf_flow_parser *parser,
 			}
 		}
 		TAILQ_INSERT_HEAD(list, parser_node, node);
-	} else if (parser->engine->type == IAVF_FLOW_ENGINE_IPSEC_CRYPTO) {
+	} else if (parser->engine->type == IAVF_FLOW_ENGINE_IPSEC_CRYPTO ||
+		   parser->engine->type == IAVF_FLOW_ENGINE_IPSEC_EGRESS) {
 		list = &vf->ipsec_crypto_parser_list;
 		TAILQ_INSERT_HEAD(list, parser_node, node);
 	} else if (parser->engine->type == IAVF_FLOW_ENGINE_FSUB) {
@@ -1931,7 +1932,8 @@ iavf_unregister_parser(struct iavf_flow_parser *parser,
 	else if ((parser->engine->type == IAVF_FLOW_ENGINE_FDIR) ||
 		 (parser->engine->type == IAVF_FLOW_ENGINE_FSUB))
 		list = &vf->dist_parser_list;
-	else if (parser->engine->type == IAVF_FLOW_ENGINE_IPSEC_CRYPTO)
+	else if (parser->engine->type == IAVF_FLOW_ENGINE_IPSEC_CRYPTO ||
+		 parser->engine->type == IAVF_FLOW_ENGINE_IPSEC_EGRESS)
 		list = &vf->ipsec_crypto_parser_list;
 
 	if (list == NULL)
@@ -1949,19 +1951,24 @@ static int
 iavf_flow_valid_attr(const struct rte_flow_attr *attr,
 		     struct rte_flow_error *error)
 {
-	/* Must be input direction */
-	if (!attr->ingress) {
+	if (!attr->ingress && !attr->egress) {
 		rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
-				attr, "Only support ingress.");
+				attr, "Only support ingress or egress.");
 		return -rte_errno;
 	}
 
-	/* Not supported */
-	if (attr->egress) {
+	if (attr->ingress && attr->egress) {
 		rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
-				attr, "Not support egress.");
+				attr, "Cannot combine ingress and egress.");
+		return -rte_errno;
+	}
+
+	if (attr->egress && attr->transfer) {
+		rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
+				attr, "Not support transfer.");
 		return -rte_errno;
 	}
 
@@ -2113,7 +2120,7 @@ static struct iavf_flow_engine *
 iavf_parse_engine_create(struct iavf_adapter *ad,
 		struct rte_flow *flow,
 		struct iavf_parser_list *parser_list,
-		uint32_t priority,
+		const struct rte_flow_attr *attr,
 		const struct rte_flow_item pattern[],
 		const struct rte_flow_action actions[],
 		struct rte_flow_error *error)
@@ -2124,14 +2131,16 @@ iavf_parse_engine_create(struct iavf_adapter *ad,
 	void *meta = NULL;
 
 	RTE_TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
+		engine = parser_node->parser->engine;
+		if (attr->egress != (engine->type == IAVF_FLOW_ENGINE_IPSEC_EGRESS))
+			continue;
+
 		if (parser_node->parser->parse_pattern_action(ad,
 				parser_node->parser->array,
 				parser_node->parser->array_len,
-				pattern, actions, priority, &meta, error) < 0)
+				pattern, actions, attr->priority, &meta, error) < 0)
 			continue;
 
-		engine = parser_node->parser->engine;
-
 		RTE_ASSERT(engine->create != NULL);
 		if (!(engine->create(ad, flow, meta, error)))
 			return engine;
@@ -2143,7 +2152,7 @@ static struct iavf_flow_engine *
 iavf_parse_engine_validate(struct iavf_adapter *ad,
 		struct rte_flow *flow,
 		struct iavf_parser_list *parser_list,
-		uint32_t priority,
+		const struct rte_flow_attr *attr,
 		const struct rte_flow_item pattern[],
 		const struct rte_flow_action actions[],
 		struct rte_flow_error *error)
@@ -2154,13 +2163,16 @@ iavf_parse_engine_validate(struct iavf_adapter *ad,
 	void *meta = NULL;
 
 	RTE_TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
+		engine = parser_node->parser->engine;
+		if (attr->egress != (engine->type == IAVF_FLOW_ENGINE_IPSEC_EGRESS))
+			continue;
+
 		if (parser_node->parser->parse_pattern_action(ad,
 				parser_node->parser->array,
 				parser_node->parser->array_len,
-				pattern, actions, priority, &meta, error) < 0)
+				pattern, actions, attr->priority, &meta, error) < 0)
 			continue;
 
-		engine = parser_node->parser->engine;
 		if (engine->validation == NULL) {
 			rte_flow_error_set(error, EINVAL,
 				RTE_FLOW_ERROR_TYPE_HANDLE,
@@ -2220,17 +2232,17 @@ iavf_flow_process_filter(struct rte_eth_dev *dev,
 		return ret;
 
 	*engine = iavf_parse_engine(ad, flow, &vf->rss_parser_list,
-				    attr->priority, pattern, actions, error);
+				    attr, pattern, actions, error);
 	if (*engine)
 		return 0;
 
 	*engine = iavf_parse_engine(ad, flow, &vf->dist_parser_list,
-				    attr->priority, pattern, actions, error);
+				    attr, pattern, actions, error);
 	if (*engine)
 		return 0;
 
 	*engine = iavf_parse_engine(ad, flow, &vf->ipsec_crypto_parser_list,
-				    attr->priority, pattern, actions, error);
+				    attr, pattern, actions, error);
 	if (*engine)
 		return 0;
 
@@ -2279,12 +2291,6 @@ iavf_flow_create(struct rte_eth_dev *dev,
 		return flow;
 	}
 
-	/* Special case for inline crypto egress flows */
-	if (attr->egress && actions[0].type == RTE_FLOW_ACTION_TYPE_SECURITY) {
-		flow->is_ipsec_egress_flow = true;
-		goto tailq_insert;
-	}
-
 	ret = iavf_flow_process_filter(dev, flow, attr, pattern, actions,
 			&engine, iavf_parse_engine_create, error);
 	if (ret < 0) {
@@ -2295,7 +2301,6 @@ iavf_flow_create(struct rte_eth_dev *dev,
 	}
 
 	flow->engine = engine;
-tailq_insert:
 	rte_spinlock_lock(&vf->flow_ops_lock);
 	TAILQ_INSERT_TAIL(&vf->flow_list, flow, node);
 	rte_spinlock_unlock(&vf->flow_ops_lock);
@@ -2311,14 +2316,7 @@ iavf_flow_is_valid(struct rte_flow *flow)
 	struct iavf_flow_engine *engine;
 	void *temp;
 
-	if (flow == NULL)
-		return false;
-
-	/* these flows don't use engines */
-	if (flow->is_ipsec_egress_flow)
-		return true;
-
-	if (flow->engine) {
+	if (flow != NULL && flow->engine != NULL) {
 		RTE_TAILQ_FOREACH_SAFE(engine, &engine_list, node, temp) {
 			if (engine == flow->engine)
 				return true;
@@ -2336,26 +2334,17 @@ iavf_flow_destroy(struct rte_eth_dev *dev,
 	struct iavf_adapter *ad =
 		IAVF_DEV_PRIVATE_TO_ADAPTER(dev->data->dev_private);
 	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
-	bool need_destroy;
 	int ret = 0;
 
-	if (!iavf_flow_is_valid(flow)) {
+	if (!iavf_flow_is_valid(flow) || flow->engine->destroy == NULL) {
 		rte_flow_error_set(error, EINVAL,
 				   RTE_FLOW_ERROR_TYPE_HANDLE,
 				   NULL, "Invalid flow destroy");
 		return -rte_errno;
 	}
-	need_destroy = !flow->is_ipsec_egress_flow;
-
-	if (need_destroy && flow->engine->destroy == NULL) {
-		return rte_flow_error_set(error, EINVAL,
-				RTE_FLOW_ERROR_TYPE_HANDLE, NULL,
-				"Invalid flow destroy");
-	}
 
 	rte_spinlock_lock(&vf->flow_ops_lock);
-	if (need_destroy)
-		ret = flow->engine->destroy(ad, flow, error);
+	ret = flow->engine->destroy(ad, flow, error);
 
 	if (!ret) {
 		TAILQ_REMOVE(&vf->flow_list, flow, node);
diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
index b11bb4cf2bc..00792a525c1 100644
--- a/drivers/net/iavf/iavf_generic_flow.h
+++ b/drivers/net/iavf/iavf_generic_flow.h
@@ -482,6 +482,7 @@ enum iavf_flow_engine_type {
 	IAVF_FLOW_ENGINE_FDIR,
 	IAVF_FLOW_ENGINE_HASH,
 	IAVF_FLOW_ENGINE_FSUB,
+	IAVF_FLOW_ENGINE_IPSEC_EGRESS,
 	IAVF_FLOW_ENGINE_MAX,
 };
 
@@ -517,7 +518,6 @@ TAILQ_HEAD(iavf_engine_list, iavf_flow_engine);
 /* Struct to store flow created. */
 struct rte_flow {
 	TAILQ_ENTRY(rte_flow) node;
-	bool is_ipsec_egress_flow;
 	struct iavf_flow_engine *engine;
 	void *rule;
 };
diff --git a/drivers/net/iavf/iavf_ipsec_crypto.c b/drivers/net/iavf/iavf_ipsec_crypto.c
index 42814604951..6d551a23f6f 100644
--- a/drivers/net/iavf/iavf_ipsec_crypto.c
+++ b/drivers/net/iavf/iavf_ipsec_crypto.c
@@ -1852,6 +1852,7 @@ flow_cleanup:
 
 
 static struct iavf_flow_parser iavf_ipsec_flow_parser;
+static struct iavf_flow_parser iavf_ipsec_egress_flow_parser;
 
 static int
 iavf_ipsec_flow_init(struct iavf_adapter *ad)
@@ -1943,14 +1944,6 @@ iavf_ipsec_flow_destroy(struct iavf_adapter *ad,
 	return 0;
 }
 
-static struct iavf_flow_engine iavf_ipsec_flow_engine = {
-	.init = iavf_ipsec_flow_init,
-	.uninit = iavf_ipsec_flow_uninit,
-	.create = iavf_ipsec_flow_create,
-	.destroy = iavf_ipsec_flow_destroy,
-	.type = IAVF_FLOW_ENGINE_IPSEC_CRYPTO,
-};
-
 static int
 iavf_ipsec_flow_parse(struct iavf_adapter *ad,
 		      struct iavf_pattern_match_item *array,
@@ -1981,6 +1974,111 @@ iavf_ipsec_flow_parse(struct iavf_adapter *ad,
 	return ret;
 }
 
+/*
+ * Inline crypto egress flows only associate Tx traffic with a security
+ * session; nothing is programmed in hardware, so the engine owns no rule.
+ */
+static int
+iavf_ipsec_egress_flow_init(struct iavf_adapter *ad)
+{
+	struct iavf_info *vf = IAVF_DEV_PRIVATE_TO_VF(ad);
+
+	if (!vf->vf_res)
+		return -EINVAL;
+
+	if (!(vf->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_INLINE_IPSEC_CRYPTO))
+		return -ENOTSUP;
+
+	return iavf_register_parser(&iavf_ipsec_egress_flow_parser, ad);
+}
+
+static void
+iavf_ipsec_egress_flow_uninit(struct iavf_adapter *ad)
+{
+	iavf_unregister_parser(&iavf_ipsec_egress_flow_parser, ad);
+}
+
+static int
+iavf_ipsec_egress_flow_create(__rte_unused struct iavf_adapter *ad,
+		struct rte_flow *flow,
+		__rte_unused void *meta,
+		__rte_unused struct rte_flow_error *error)
+{
+	flow->rule = NULL;
+	return 0;
+}
+
+static int
+iavf_ipsec_egress_flow_destroy(__rte_unused struct iavf_adapter *ad,
+		__rte_unused struct rte_flow *flow,
+		__rte_unused struct rte_flow_error *error)
+{
+	return 0;
+}
+
+/* The pattern is not used, as there is nothing to match in hardware. */
+static int
+iavf_ipsec_egress_flow_parse(__rte_unused struct iavf_adapter *ad,
+		__rte_unused struct iavf_pattern_match_item *array,
+		__rte_unused uint32_t array_len,
+		__rte_unused const struct rte_flow_item pattern[],
+		const struct rte_flow_action actions[],
+		uint32_t priority,
+		void **meta,
+		struct rte_flow_error *error)
+{
+	const struct rte_flow_action *action;
+	bool has_security = false;
+
+	if (priority != 0)
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
+				"Egress security flows do not support priority.");
+
+	for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
+		if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
+			continue;
+
+		if (action->type != RTE_FLOW_ACTION_TYPE_SECURITY || has_security)
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION, action,
+					"Only one security action is supported.");
+
+		if (action->conf == NULL)
+			return rte_flow_error_set(error, EINVAL,
+					RTE_FLOW_ERROR_TYPE_ACTION_CONF, action,
+					"Security action requires configuration.");
+
+		has_security = true;
+	}
+
+	if (!has_security)
+		return rte_flow_error_set(error, EINVAL,
+				RTE_FLOW_ERROR_TYPE_ACTION, actions,
+				"Security action is required.");
+
+	if (meta != NULL)
+		*meta = NULL;
+
+	return 0;
+}
+
+static struct iavf_flow_engine iavf_ipsec_flow_engine = {
+	.init = iavf_ipsec_flow_init,
+	.uninit = iavf_ipsec_flow_uninit,
+	.create = iavf_ipsec_flow_create,
+	.destroy = iavf_ipsec_flow_destroy,
+	.type = IAVF_FLOW_ENGINE_IPSEC_CRYPTO,
+};
+
+static struct iavf_flow_engine iavf_ipsec_egress_flow_engine = {
+	.init = iavf_ipsec_egress_flow_init,
+	.uninit = iavf_ipsec_egress_flow_uninit,
+	.create = iavf_ipsec_egress_flow_create,
+	.destroy = iavf_ipsec_egress_flow_destroy,
+	.type = IAVF_FLOW_ENGINE_IPSEC_EGRESS,
+};
+
 static struct iavf_flow_parser iavf_ipsec_flow_parser = {
 	.engine = &iavf_ipsec_flow_engine,
 	.array = iavf_ipsec_flow_pattern,
@@ -1989,7 +2087,18 @@ static struct iavf_flow_parser iavf_ipsec_flow_parser = {
 	.stage = IAVF_FLOW_STAGE_IPSEC_CRYPTO,
 };
 
+static struct iavf_flow_parser iavf_ipsec_egress_flow_parser = {
+	.engine = &iavf_ipsec_egress_flow_engine,
+	.parse_pattern_action = iavf_ipsec_egress_flow_parse,
+	.stage = IAVF_FLOW_STAGE_IPSEC_CRYPTO,
+};
+
 RTE_INIT(iavf_ipsec_flow_engine_register)
 {
 	iavf_register_flow_engine(&iavf_ipsec_flow_engine);
 }
+
+RTE_INIT(iavf_ipsec_egress_flow_engine_register)
+{
+	iavf_register_flow_engine(&iavf_ipsec_egress_flow_engine);
+}
-- 
2.47.3

---
  Diff of the applied patch vs upstream commit (please double-check if non-empty:
---
--- -	2026-11-05 16:42:47.018744310 +0000
+++ 0053-net-iavf-fix-null-engine-for-egress-security-flows.patch	2026-11-05 16:42:44.965062101 +0000
@@ -1 +1 @@
-From 99f371f25bfb55bd1268769320f4629cf28a0b9d Mon Sep 17 00:00:00 2001
+From fe77017493758256fc0545dc5885cf81d5cb8116 Mon Sep 17 00:00:00 2001
@@ -5,0 +6,2 @@
+[ upstream commit 99f371f25bfb55bd1268769320f4629cf28a0b9d ]
+
@@ -16 +17,0 @@
-Cc: stable at dpdk.org
@@ -21,4 +22,4 @@
- drivers/net/intel/iavf/iavf_generic_flow.c |  44 +++-----
- drivers/net/intel/iavf/iavf_generic_flow.h |   2 +-
- drivers/net/intel/iavf/iavf_ipsec_crypto.c | 120 +++++++++++++++++++--
- 3 files changed, 123 insertions(+), 43 deletions(-)
+ drivers/net/iavf/iavf_generic_flow.c |  79 ++++++++---------
+ drivers/net/iavf/iavf_generic_flow.h |   2 +-
+ drivers/net/iavf/iavf_ipsec_crypto.c | 125 +++++++++++++++++++++++++--
+ 3 files changed, 152 insertions(+), 54 deletions(-)
@@ -26,5 +27,14 @@
-diff --git a/drivers/net/intel/iavf/iavf_generic_flow.c b/drivers/net/intel/iavf/iavf_generic_flow.c
-index 1593ea297c..be7ddf5db6 100644
---- a/drivers/net/intel/iavf/iavf_generic_flow.c
-+++ b/drivers/net/intel/iavf/iavf_generic_flow.c
-@@ -1914,7 +1914,8 @@ iavf_register_parser(struct iavf_flow_parser *parser,
+diff --git a/drivers/net/iavf/iavf_generic_flow.c b/drivers/net/iavf/iavf_generic_flow.c
+index cd9a88010be..5c791762886 100644
+--- a/drivers/net/iavf/iavf_generic_flow.c
++++ b/drivers/net/iavf/iavf_generic_flow.c
+@@ -1785,7 +1785,7 @@ enum rte_flow_item_type iavf_pattern_eth_ipv6_udp_l2tpv2_ppp_ipv6_tcp[] = {
+ typedef struct iavf_flow_engine * (*parse_engine_t)(struct iavf_adapter *ad,
+ 		struct rte_flow *flow,
+ 		struct iavf_parser_list *parser_list,
+-		uint32_t priority,
++		const struct rte_flow_attr *attr,
+ 		const struct rte_flow_item pattern[],
+ 		const struct rte_flow_action actions[],
+ 		struct rte_flow_error *error);
+@@ -1902,7 +1902,8 @@ iavf_register_parser(struct iavf_flow_parser *parser,
@@ -40 +50 @@
-@@ -1943,7 +1944,8 @@ iavf_unregister_parser(struct iavf_flow_parser *parser,
+@@ -1931,7 +1932,8 @@ iavf_unregister_parser(struct iavf_flow_parser *parser,
@@ -50 +60,110 @@
-@@ -2250,12 +2252,6 @@ iavf_flow_create(struct rte_eth_dev *dev,
+@@ -1949,19 +1951,24 @@ static int
+ iavf_flow_valid_attr(const struct rte_flow_attr *attr,
+ 		     struct rte_flow_error *error)
+ {
+-	/* Must be input direction */
+-	if (!attr->ingress) {
++	if (!attr->ingress && !attr->egress) {
+ 		rte_flow_error_set(error, EINVAL,
+ 				RTE_FLOW_ERROR_TYPE_ATTR_INGRESS,
+-				attr, "Only support ingress.");
++				attr, "Only support ingress or egress.");
+ 		return -rte_errno;
+ 	}
+ 
+-	/* Not supported */
+-	if (attr->egress) {
++	if (attr->ingress && attr->egress) {
+ 		rte_flow_error_set(error, EINVAL,
+ 				RTE_FLOW_ERROR_TYPE_ATTR_EGRESS,
+-				attr, "Not support egress.");
++				attr, "Cannot combine ingress and egress.");
++		return -rte_errno;
++	}
++
++	if (attr->egress && attr->transfer) {
++		rte_flow_error_set(error, EINVAL,
++				RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER,
++				attr, "Not support transfer.");
+ 		return -rte_errno;
+ 	}
+ 
+@@ -2113,7 +2120,7 @@ static struct iavf_flow_engine *
+ iavf_parse_engine_create(struct iavf_adapter *ad,
+ 		struct rte_flow *flow,
+ 		struct iavf_parser_list *parser_list,
+-		uint32_t priority,
++		const struct rte_flow_attr *attr,
+ 		const struct rte_flow_item pattern[],
+ 		const struct rte_flow_action actions[],
+ 		struct rte_flow_error *error)
+@@ -2124,14 +2131,16 @@ iavf_parse_engine_create(struct iavf_adapter *ad,
+ 	void *meta = NULL;
+ 
+ 	RTE_TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
++		engine = parser_node->parser->engine;
++		if (attr->egress != (engine->type == IAVF_FLOW_ENGINE_IPSEC_EGRESS))
++			continue;
++
+ 		if (parser_node->parser->parse_pattern_action(ad,
+ 				parser_node->parser->array,
+ 				parser_node->parser->array_len,
+-				pattern, actions, priority, &meta, error) < 0)
++				pattern, actions, attr->priority, &meta, error) < 0)
+ 			continue;
+ 
+-		engine = parser_node->parser->engine;
+-
+ 		RTE_ASSERT(engine->create != NULL);
+ 		if (!(engine->create(ad, flow, meta, error)))
+ 			return engine;
+@@ -2143,7 +2152,7 @@ static struct iavf_flow_engine *
+ iavf_parse_engine_validate(struct iavf_adapter *ad,
+ 		struct rte_flow *flow,
+ 		struct iavf_parser_list *parser_list,
+-		uint32_t priority,
++		const struct rte_flow_attr *attr,
+ 		const struct rte_flow_item pattern[],
+ 		const struct rte_flow_action actions[],
+ 		struct rte_flow_error *error)
+@@ -2154,13 +2163,16 @@ iavf_parse_engine_validate(struct iavf_adapter *ad,
+ 	void *meta = NULL;
+ 
+ 	RTE_TAILQ_FOREACH_SAFE(parser_node, parser_list, node, temp) {
++		engine = parser_node->parser->engine;
++		if (attr->egress != (engine->type == IAVF_FLOW_ENGINE_IPSEC_EGRESS))
++			continue;
++
+ 		if (parser_node->parser->parse_pattern_action(ad,
+ 				parser_node->parser->array,
+ 				parser_node->parser->array_len,
+-				pattern, actions, priority, &meta, error) < 0)
++				pattern, actions, attr->priority, &meta, error) < 0)
+ 			continue;
+ 
+-		engine = parser_node->parser->engine;
+ 		if (engine->validation == NULL) {
+ 			rte_flow_error_set(error, EINVAL,
+ 				RTE_FLOW_ERROR_TYPE_HANDLE,
+@@ -2220,17 +2232,17 @@ iavf_flow_process_filter(struct rte_eth_dev *dev,
+ 		return ret;
+ 
+ 	*engine = iavf_parse_engine(ad, flow, &vf->rss_parser_list,
+-				    attr->priority, pattern, actions, error);
++				    attr, pattern, actions, error);
+ 	if (*engine)
+ 		return 0;
+ 
+ 	*engine = iavf_parse_engine(ad, flow, &vf->dist_parser_list,
+-				    attr->priority, pattern, actions, error);
++				    attr, pattern, actions, error);
+ 	if (*engine)
+ 		return 0;
+ 
+ 	*engine = iavf_parse_engine(ad, flow, &vf->ipsec_crypto_parser_list,
+-				    attr->priority, pattern, actions, error);
++				    attr, pattern, actions, error);
+ 	if (*engine)
+ 		return 0;
+ 
+@@ -2279,12 +2291,6 @@ iavf_flow_create(struct rte_eth_dev *dev,
@@ -63 +182 @@
-@@ -2266,7 +2262,6 @@ iavf_flow_create(struct rte_eth_dev *dev,
+@@ -2295,7 +2301,6 @@ iavf_flow_create(struct rte_eth_dev *dev,
@@ -71 +190 @@
-@@ -2282,14 +2277,7 @@ iavf_flow_is_valid(struct rte_flow *flow)
+@@ -2311,14 +2316,7 @@ iavf_flow_is_valid(struct rte_flow *flow)
@@ -87 +206 @@
-@@ -2307,26 +2295,17 @@ iavf_flow_destroy(struct rte_eth_dev *dev,
+@@ -2336,26 +2334,17 @@ iavf_flow_destroy(struct rte_eth_dev *dev,
@@ -116,27 +235,5 @@
-@@ -2444,16 +2423,17 @@ iavf_flow_dev_dump(struct rte_eth_dev *dev,
- 		if (flow != NULL && f != flow)
- 			continue;
- 
--		/* this should not happen */
--		if (f->engine == NULL || f->rule == NULL) {
-+		if (!iavf_flow_is_valid(f)) {
- 			PMD_DRV_LOG(DEBUG, "Invalid flow");
- 			continue;
- 		}
- 
- 		found = true;
- 
--		rule_size = f->engine->rule_size;
--		rule_data = f->rule;
-+		if (f->rule != NULL) {
-+			rule_size = f->engine->rule_size;
-+			rule_data = f->rule;
-+		}
- 
- 		iavf_flow_dump_blob(file,
- 			f->engine->name != NULL ?
-diff --git a/drivers/net/intel/iavf/iavf_generic_flow.h b/drivers/net/intel/iavf/iavf_generic_flow.h
-index 3a8f5f92e8..75bb92900b 100644
---- a/drivers/net/intel/iavf/iavf_generic_flow.h
-+++ b/drivers/net/intel/iavf/iavf_generic_flow.h
-@@ -481,6 +481,7 @@ enum iavf_flow_engine_type {
+diff --git a/drivers/net/iavf/iavf_generic_flow.h b/drivers/net/iavf/iavf_generic_flow.h
+index b11bb4cf2bc..00792a525c1 100644
+--- a/drivers/net/iavf/iavf_generic_flow.h
++++ b/drivers/net/iavf/iavf_generic_flow.h
+@@ -482,6 +482,7 @@ enum iavf_flow_engine_type {
@@ -150 +247 @@
-@@ -503,7 +504,6 @@ TAILQ_HEAD(iavf_engine_list, iavf_flow_engine);
+@@ -517,7 +518,6 @@ TAILQ_HEAD(iavf_engine_list, iavf_flow_engine);
@@ -158,5 +255,5 @@
-diff --git a/drivers/net/intel/iavf/iavf_ipsec_crypto.c b/drivers/net/intel/iavf/iavf_ipsec_crypto.c
-index e9acd1bb1d..f7e391a74a 100644
---- a/drivers/net/intel/iavf/iavf_ipsec_crypto.c
-+++ b/drivers/net/intel/iavf/iavf_ipsec_crypto.c
-@@ -1832,6 +1832,7 @@ flow_cleanup:
+diff --git a/drivers/net/iavf/iavf_ipsec_crypto.c b/drivers/net/iavf/iavf_ipsec_crypto.c
+index 42814604951..6d551a23f6f 100644
+--- a/drivers/net/iavf/iavf_ipsec_crypto.c
++++ b/drivers/net/iavf/iavf_ipsec_crypto.c
+@@ -1852,6 +1852,7 @@ flow_cleanup:
@@ -170 +267 @@
-@@ -1922,16 +1923,6 @@ iavf_ipsec_flow_destroy(struct iavf_adapter *ad,
+@@ -1943,14 +1944,6 @@ iavf_ipsec_flow_destroy(struct iavf_adapter *ad,
@@ -179 +275,0 @@
--	.name = "ipsec_crypto",
@@ -181 +276,0 @@
--	.rule_size = sizeof(struct iavf_ipsec_flow_item),
@@ -187 +282 @@
-@@ -1975,6 +1966,105 @@ iavf_ipsec_flow_parse(struct iavf_adapter *ad,
+@@ -1981,6 +1974,111 @@ iavf_ipsec_flow_parse(struct iavf_adapter *ad,
@@ -240 +335 @@
-+		const struct rte_flow_attr *attr,
++		uint32_t priority,
@@ -244,20 +339,29 @@
-+	struct ci_flow_actions parsed_actions = {0};
-+	struct ci_flow_actions_check_param param = {
-+		.allowed_types = (enum rte_flow_action_type[]){
-+			RTE_FLOW_ACTION_TYPE_SECURITY,
-+			RTE_FLOW_ACTION_TYPE_END,
-+		},
-+		.max_actions = 1,
-+	};
-+	struct ci_flow_attr_check_param attr_param = {
-+		.require_egress = true,
-+	};
-+	int ret;
-+
-+	ret = ci_flow_check_attr(attr, &attr_param, error);
-+	if (ret)
-+		return ret;
-+
-+	ret = ci_flow_check_actions(actions, &param, &parsed_actions, error);
-+	if (ret < 0)
-+		return ret;
++	const struct rte_flow_action *action;
++	bool has_security = false;
++
++	if (priority != 0)
++		return rte_flow_error_set(error, EINVAL,
++				RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
++				"Egress security flows do not support priority.");
++
++	for (action = actions; action->type != RTE_FLOW_ACTION_TYPE_END; action++) {
++		if (action->type == RTE_FLOW_ACTION_TYPE_VOID)
++			continue;
++
++		if (action->type != RTE_FLOW_ACTION_TYPE_SECURITY || has_security)
++			return rte_flow_error_set(error, EINVAL,
++					RTE_FLOW_ERROR_TYPE_ACTION, action,
++					"Only one security action is supported.");
++
++		if (action->conf == NULL)
++			return rte_flow_error_set(error, EINVAL,
++					RTE_FLOW_ERROR_TYPE_ACTION_CONF, action,
++					"Security action requires configuration.");
++
++		has_security = true;
++	}
++
++	if (!has_security)
++		return rte_flow_error_set(error, EINVAL,
++				RTE_FLOW_ERROR_TYPE_ACTION, actions,
++				"Security action is required.");
@@ -276 +379,0 @@
-+	.name = "ipsec_crypto",
@@ -278 +380,0 @@
-+	.rule_size = sizeof(struct iavf_ipsec_flow_item),
@@ -286 +387,0 @@
-+	.name = "ipsec_egress",
@@ -293,2 +394,2 @@
-@@ -1982,7 +2072,17 @@ static struct iavf_flow_parser iavf_ipsec_flow_parser = {
- 	.parse_pattern_action = iavf_ipsec_flow_parse,
+@@ -1989,7 +2087,18 @@ static struct iavf_flow_parser iavf_ipsec_flow_parser = {
+ 	.stage = IAVF_FLOW_STAGE_IPSEC_CRYPTO,
@@ -299,0 +401 @@
++	.stage = IAVF_FLOW_STAGE_IPSEC_CRYPTO,


More information about the stable mailing list