DPDK patches and discussions
 help / color / mirror / Atom feed
From: Gregory Etelson <getelson@nvidia.com>
To: <dev@dpdk.org>
Cc: <mkashani@nvidia.com>, Ori Kam <orika@nvidia.com>,
	Aman Singh <aman.deep.singh@intel.com>,
	Yuying Zhang <yuying.zhang@intel.com>,
	"Ferruh Yigit" <ferruh.yigit@amd.com>,
	Thomas Monjalon <thomas@monjalon.net>,
	"Andrew Rybchenko" <andrew.rybchenko@oktetlabs.ru>
Subject: [PATCH] ethdev: add indirect list flow action
Date: Tue, 18 Apr 2023 20:21:44 +0300	[thread overview]
Message-ID: <20230418172144.24365-1-getelson@nvidia.com> (raw)

Indirect flow action provides a handler to hardware
flow action object. The handler is  used in flow rules for sharing
hardware action object state.

Current  INDIRECT flow handler can reference a single
flow action type.

New INDIRECT_LIST extends existing functionality.
INDIRECT_LIST flow handler can reference one or many flow actions.

testpmd example:

set raw_encap 0 \
eth src is 11:00:00:00:00:11 dst is aa:00:00:00:00:aa / \
ipv4 src is 1.1.1.1 dst is 2.2.2.2 ttl is 64 proto is 17 / \
udp src is 0x1234 dst is 4789 / vxlan vni is 0xabcd / end_set
set raw_encap 1 \
eth src is 22:00:00:00:00:22 dst is bb:00:00:00:00:bb / \
ipv6 src is 2001::1111 dst is 2001::2222 proto is 17 / \
udp src is 0x1234 dst is 4789 / vxlan vni is 0xabcd / end_set

set sample_actions 0 \
raw_encap index 0 / represented_port ethdev_port_id 0 / end
set sample_actions 1 \
raw_encap index 1 / represented_port ethdev_port_id 0 / end

flow indirect_action 0 create transfer list actions \
sample ratio 1 index 0 / \
sample ratio 1 index 1 / \
jump group 0xcaca / end

flow actions_template 0 create transfer actions_template_id 10 \
template indirect_list 0 / end mask indirect_list / end

Signed-off-by: Gregory Etelson <getelson@nvidia.com>
---
 app/test-pmd/cmdline_flow.c            |  41 ++++++-
 app/test-pmd/config.c                  | 162 +++++++++++++++++++------
 app/test-pmd/testpmd.h                 |   7 +-
 doc/guides/nics/features/default.ini   |   1 +
 doc/guides/prog_guide/rte_flow.rst     |   6 +
 doc/guides/rel_notes/release_23_07.rst |   4 +
 lib/ethdev/rte_flow.c                  |  92 ++++++++++++++
 lib/ethdev/rte_flow.h                  | 149 +++++++++++++++++++++++
 lib/ethdev/rte_flow_driver.h           |  27 ++++-
 lib/ethdev/version.map                 |   4 +
 10 files changed, 452 insertions(+), 41 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 58939ec321..956a39d167 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -145,6 +145,7 @@ enum index {
 
 	/* Queue indirect action arguments */
 	QUEUE_INDIRECT_ACTION_CREATE,
+	QUEUE_INDIRECT_ACTION_LIST_CREATE,
 	QUEUE_INDIRECT_ACTION_UPDATE,
 	QUEUE_INDIRECT_ACTION_DESTROY,
 	QUEUE_INDIRECT_ACTION_QUERY,
@@ -157,6 +158,7 @@ enum index {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 
 	/* Queue indirect action update arguments */
 	QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
@@ -242,6 +244,7 @@ enum index {
 
 	/* Indirect action arguments */
 	INDIRECT_ACTION_CREATE,
+	INDIRECT_ACTION_LIST_CREATE,
 	INDIRECT_ACTION_UPDATE,
 	INDIRECT_ACTION_DESTROY,
 	INDIRECT_ACTION_QUERY,
@@ -253,6 +256,7 @@ enum index {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
 
 	/* Indirect action destroy arguments */
 	INDIRECT_ACTION_DESTROY_ID,
@@ -626,6 +630,7 @@ enum index {
 	ACTION_SAMPLE_INDEX,
 	ACTION_SAMPLE_INDEX_VALUE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
 	ACTION_SHARED_INDIRECT,
 	INDIRECT_ACTION_PORT,
 	INDIRECT_ACTION_ID2PTR,
@@ -1266,6 +1271,7 @@ static const enum index next_qia_create_attr[] = {
 	QUEUE_INDIRECT_ACTION_TRANSFER,
 	QUEUE_INDIRECT_ACTION_CREATE_POSTPONE,
 	QUEUE_INDIRECT_ACTION_SPEC,
+	QUEUE_INDIRECT_ACTION_LIST,
 	ZERO,
 };
 
@@ -1294,6 +1300,7 @@ static const enum index next_ia_create_attr[] = {
 	INDIRECT_ACTION_EGRESS,
 	INDIRECT_ACTION_TRANSFER,
 	INDIRECT_ACTION_SPEC,
+	INDIRECT_ACTION_LIST,
 	ZERO,
 };
 
@@ -2013,6 +2020,7 @@ static const enum index next_action[] = {
 	ACTION_AGE_UPDATE,
 	ACTION_SAMPLE,
 	ACTION_INDIRECT,
+	ACTION_INDIRECT_LIST,
 	ACTION_SHARED_INDIRECT,
 	ACTION_MODIFY_FIELD,
 	ACTION_CONNTRACK,
@@ -2289,6 +2297,7 @@ static const enum index next_action_sample[] = {
 	ACTION_RAW_ENCAP,
 	ACTION_VXLAN_ENCAP,
 	ACTION_NVGRE_ENCAP,
+	ACTION_REPRESENTED_PORT,
 	ACTION_NEXT,
 	ZERO,
 };
@@ -3426,6 +3435,12 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[QUEUE_INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_qia,
+	},
 	/* Top-level command. */
 	[PUSH] = {
 		.name = "push",
@@ -6775,6 +6790,14 @@ static const struct token token_list[] = {
 		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
 		.call = parse_vc,
 	},
+	[ACTION_INDIRECT_LIST] = {
+		.name = "indirect_list",
+		.help = "apply indirect list action by id",
+		.priv = PRIV_ACTION(INDIRECT_LIST, 0),
+		.next = NEXT(next_ia),
+		.args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
+		.call = parse_vc,
+	},
 	[ACTION_SHARED_INDIRECT] = {
 		.name = "shared_indirect",
 		.help = "apply indirect action by id and port",
@@ -6823,6 +6846,12 @@ static const struct token token_list[] = {
 		.help = "specify action to create indirect handle",
 		.next = NEXT(next_action),
 	},
+	[INDIRECT_ACTION_LIST] = {
+		.name = "list",
+		.help = "specify actions for indirect handle list",
+		.next = NEXT(NEXT_ENTRY(ACTIONS, END)),
+		.call = parse_ia,
+	},
 	[ACTION_POL_G] = {
 		.name = "g_actions",
 		.help = "submit a list of associated actions for green",
@@ -7181,6 +7210,9 @@ parse_ia(struct context *ctx, const struct token *token,
 		return len;
 	case INDIRECT_ACTION_QU_MODE:
 		return len;
+	case INDIRECT_ACTION_LIST:
+		out->command = INDIRECT_ACTION_LIST_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7278,6 +7310,9 @@ parse_qia(struct context *ctx, const struct token *token,
 		return len;
 	case QUEUE_INDIRECT_ACTION_QU_MODE:
 		return len;
+	case QUEUE_INDIRECT_ACTION_LIST:
+		out->command = QUEUE_INDIRECT_ACTION_LIST_CREATE;
+		return len;
 	default:
 		return -1;
 	}
@@ -7454,10 +7489,12 @@ parse_vc(struct context *ctx, const struct token *token,
 			return -1;
 		break;
 	case ACTIONS:
-		out->args.vc.actions =
+		out->args.vc.actions = out->args.vc.pattern ?
 			(void *)RTE_ALIGN_CEIL((uintptr_t)
 					       (out->args.vc.pattern +
 						out->args.vc.pattern_n),
+					       sizeof(double)) :
+			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
 					       sizeof(double));
 		ctx->object = out->args.vc.actions;
 		ctx->objmask = NULL;
@@ -11532,6 +11569,7 @@ cmd_flow_parsed(const struct buffer *in)
 				     in->args.aged.destroy);
 		break;
 	case QUEUE_INDIRECT_ACTION_CREATE:
+	case QUEUE_INDIRECT_ACTION_LIST_CREATE:
 		port_queue_action_handle_create(
 				in->port, in->queue, in->postpone,
 				in->args.vc.attr.group,
@@ -11567,6 +11605,7 @@ cmd_flow_parsed(const struct buffer *in)
 						      in->args.vc.actions);
 		break;
 	case INDIRECT_ACTION_CREATE:
+	case INDIRECT_ACTION_LIST_CREATE:
 		port_action_handle_create(
 				in->port, in->args.vc.attr.group,
 				&((const struct rte_flow_indir_action_conf) {
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 096c218c12..c220682ff9 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1764,6 +1764,44 @@ port_flow_configure(portid_t port_id,
 	return 0;
 }
 
+static int
+action_handle_create(portid_t port_id,
+		     struct port_indirect_action *pia,
+		     const struct rte_flow_indir_action_conf *conf,
+		     const struct rte_flow_action *action,
+		     struct rte_flow_error *error)
+{
+	if (action->type == RTE_FLOW_ACTION_TYPE_AGE) {
+		struct rte_flow_action_age *age =
+			(struct rte_flow_action_age *)(uintptr_t)(action->conf);
+
+		pia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;
+		age->context = &pia->age_type;
+	} else if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK) {
+		struct rte_flow_action_conntrack *ct =
+			(struct rte_flow_action_conntrack *)(uintptr_t)(action->conf);
+
+		memcpy(ct, &conntrack_context, sizeof(*ct));
+	}
+	pia->type = action->type;
+	pia->handle = rte_flow_action_handle_create(port_id, conf, action,
+						    error);
+	return pia->handle ? 0 : -1;
+}
+
+static int
+action_list_handle_create(portid_t port_id,
+			  struct port_indirect_action *pia,
+			  const struct rte_flow_indir_action_conf *conf,
+			  const struct rte_flow_action *actions,
+			  struct rte_flow_error *error)
+{
+	pia->type = RTE_FLOW_ACTION_TYPE_INDIRECT_LIST;
+	pia->list_handle =
+		rte_flow_action_list_handle_create(port_id, conf,
+						   actions, error);
+	return pia->list_handle ? 0 : -1;
+}
 /** Create indirect action */
 int
 port_action_handle_create(portid_t port_id, uint32_t id,
@@ -1773,32 +1811,21 @@ port_action_handle_create(portid_t port_id, uint32_t id,
 	struct port_indirect_action *pia;
 	int ret;
 	struct rte_flow_error error;
+	bool is_indirect_list = action[1].type != RTE_FLOW_ACTION_TYPE_END;
 
 	ret = action_alloc(port_id, id, &pia);
 	if (ret)
 		return ret;
-	if (action->type == RTE_FLOW_ACTION_TYPE_AGE) {
-		struct rte_flow_action_age *age =
-			(struct rte_flow_action_age *)(uintptr_t)(action->conf);
-
-		pia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;
-		age->context = &pia->age_type;
-	} else if (action->type == RTE_FLOW_ACTION_TYPE_CONNTRACK) {
-		struct rte_flow_action_conntrack *ct =
-		(struct rte_flow_action_conntrack *)(uintptr_t)(action->conf);
-
-		memcpy(ct, &conntrack_context, sizeof(*ct));
-	}
 	/* Poisoning to make sure PMDs update it in case of error. */
 	memset(&error, 0x22, sizeof(error));
-	pia->handle = rte_flow_action_handle_create(port_id, conf, action,
-						    &error);
-	if (!pia->handle) {
+	ret = is_indirect_list ?
+	       action_list_handle_create(port_id, pia, conf, action, &error) :
+	       action_handle_create(port_id, pia, conf, action, &error);
+	if (ret) {
 		uint32_t destroy_id = pia->id;
 		port_action_handle_destroy(port_id, 1, &destroy_id);
 		return port_flow_complain(&error);
 	}
-	pia->type = action->type;
 	printf("Indirect action #%u created\n", pia->id);
 	return 0;
 }
@@ -1833,10 +1860,17 @@ port_action_handle_destroy(portid_t port_id,
 			 */
 			memset(&error, 0x33, sizeof(error));
 
-			if (pia->handle && rte_flow_action_handle_destroy(
-					port_id, pia->handle, &error)) {
-				ret = port_flow_complain(&error);
-				continue;
+			if (pia->handle) {
+				ret = pia->type ==
+				      RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?
+					rte_flow_action_list_handle_destroy
+					(port_id, pia->list_handle, &error) :
+					rte_flow_action_handle_destroy
+					(port_id, pia->handle, &error);
+				if (ret) {
+					ret = port_flow_complain(&error);
+					continue;
+				}
 			}
 			*tmp = pia->next;
 			printf("Indirect action #%u destroyed\n", pia->id);
@@ -1867,11 +1901,18 @@ port_action_handle_flush(portid_t port_id)
 
 		/* Poisoning to make sure PMDs update it in case of error. */
 		memset(&error, 0x44, sizeof(error));
-		if (pia->handle != NULL &&
-		    rte_flow_action_handle_destroy
-					(port_id, pia->handle, &error) != 0) {
-			printf("Indirect action #%u not destroyed\n", pia->id);
-			ret = port_flow_complain(&error);
+		if (pia->handle != NULL) {
+			ret = pia->type ==
+			      RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?
+			      rte_flow_action_list_handle_destroy
+				      (port_id, pia->list_handle, &error) :
+			      rte_flow_action_handle_destroy
+				      (port_id, pia->handle, &error);
+			if (ret) {
+				printf("Indirect action #%u not destroyed\n",
+				       pia->id);
+				ret = port_flow_complain(&error);
+			}
 			tmp = &pia->next;
 		} else {
 			*tmp = pia->next;
@@ -2822,6 +2863,45 @@ port_queue_flow_destroy(portid_t port_id, queueid_t queue_id,
 	return ret;
 }
 
+static void
+queue_action_handle_create(portid_t port_id, uint32_t queue_id,
+			   struct port_indirect_action *pia,
+			   struct queue_job *job,
+			   const struct rte_flow_op_attr *attr,
+			   const struct rte_flow_indir_action_conf *conf,
+			   const struct rte_flow_action *action,
+			   struct rte_flow_error *error)
+{
+	if (action->type == RTE_FLOW_ACTION_TYPE_AGE) {
+		struct rte_flow_action_age *age =
+			(struct rte_flow_action_age *)(uintptr_t)(action->conf);
+
+		pia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;
+		age->context = &pia->age_type;
+	}
+	/* Poisoning to make sure PMDs update it in case of error. */
+	pia->handle = rte_flow_async_action_handle_create(port_id, queue_id,
+							  attr, conf, action,
+							  job, error);
+	pia->type = action->type;
+}
+
+static void
+queue_action_list_handle_create(portid_t port_id, uint32_t queue_id,
+				struct port_indirect_action *pia,
+				struct queue_job *job,
+				const struct rte_flow_op_attr *attr,
+				const struct rte_flow_indir_action_conf *conf,
+				const struct rte_flow_action *action,
+				struct rte_flow_error *error)
+{
+	/* Poisoning to make sure PMDs update it in case of error. */
+	pia->type = RTE_FLOW_ACTION_TYPE_INDIRECT_LIST;
+	pia->list_handle = rte_flow_async_action_list_handle_create
+				(port_id, queue_id, attr, conf, action,
+				 job, error);
+}
+
 /** Enqueue indirect action create operation. */
 int
 port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
@@ -2835,6 +2915,8 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
 	int ret;
 	struct rte_flow_error error;
 	struct queue_job *job;
+	bool is_indirect_list = action[1].type != RTE_FLOW_ACTION_TYPE_END;
+
 
 	ret = action_alloc(port_id, id, &pia);
 	if (ret)
@@ -2853,17 +2935,16 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
 	job->type = QUEUE_JOB_TYPE_ACTION_CREATE;
 	job->pia = pia;
 
-	if (action->type == RTE_FLOW_ACTION_TYPE_AGE) {
-		struct rte_flow_action_age *age =
-			(struct rte_flow_action_age *)(uintptr_t)(action->conf);
-
-		pia->age_type = ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION;
-		age->context = &pia->age_type;
-	}
 	/* Poisoning to make sure PMDs update it in case of error. */
 	memset(&error, 0x88, sizeof(error));
-	pia->handle = rte_flow_async_action_handle_create(port_id, queue_id,
-					&attr, conf, action, job, &error);
+
+	if (is_indirect_list)
+		queue_action_list_handle_create(port_id, queue_id, pia, job,
+						&attr, conf, action, &error);
+	else
+		queue_action_handle_create(port_id, queue_id, pia, job, &attr,
+					   conf, action, &error);
+
 	if (!pia->handle) {
 		uint32_t destroy_id = pia->id;
 		port_queue_action_handle_destroy(port_id, queue_id,
@@ -2871,7 +2952,6 @@ port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
 		free(job);
 		return port_flow_complain(&error);
 	}
-	pia->type = action->type;
 	printf("Indirect action #%u creation queued\n", pia->id);
 	return 0;
 }
@@ -2920,9 +3000,15 @@ port_queue_action_handle_destroy(portid_t port_id,
 			}
 			job->type = QUEUE_JOB_TYPE_ACTION_DESTROY;
 			job->pia = pia;
-
-			if (rte_flow_async_action_handle_destroy(port_id,
-				queue_id, &attr, pia->handle, job, &error)) {
+			ret = pia->type == RTE_FLOW_ACTION_TYPE_INDIRECT_LIST ?
+			      rte_flow_async_action_list_handle_destroy
+				      (port_id, queue_id,
+				       &attr, pia->list_handle,
+				       job, &error) :
+			      rte_flow_async_action_handle_destroy
+				      (port_id, queue_id, &attr, pia->handle,
+				       job, &error);
+			if (ret) {
 				free(job);
 				ret = port_flow_complain(&error);
 				continue;
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index bdfbfd36d3..9786e62d28 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -228,7 +228,12 @@ struct port_indirect_action {
 	struct port_indirect_action *next; /**< Next flow in list. */
 	uint32_t id; /**< Indirect action ID. */
 	enum rte_flow_action_type type; /**< Action type. */
-	struct rte_flow_action_handle *handle;	/**< Indirect action handle. */
+	union {
+		struct rte_flow_action_handle *handle;
+		/**< Indirect action handle. */
+		struct rte_flow_action_list_handle *list_handle;
+		/**< Indirect action list handle*/
+	};
 	enum age_action_context_type age_type; /**< Age action context type. */
 };
 
diff --git a/doc/guides/nics/features/default.ini b/doc/guides/nics/features/default.ini
index 1a5087abad..10a1c1af77 100644
--- a/doc/guides/nics/features/default.ini
+++ b/doc/guides/nics/features/default.ini
@@ -158,6 +158,7 @@ drop                 =
 flag                 =
 inc_tcp_ack          =
 inc_tcp_seq          =
+indirect_list        =
 jump                 =
 mac_swap             =
 mark                 =
diff --git a/doc/guides/prog_guide/rte_flow.rst b/doc/guides/prog_guide/rte_flow.rst
index 32fc45516a..ed67e86c58 100644
--- a/doc/guides/prog_guide/rte_flow.rst
+++ b/doc/guides/prog_guide/rte_flow.rst
@@ -3300,6 +3300,12 @@ The ``quota`` value is reduced according to ``mode`` setting.
    | ``RTE_FLOW_QUOTA_MODE_L3``      | Count packet bytes starting from L3 |
    +------------------+----------------------------------------------------+
 
+Action: ``INDIRECT_LIST``
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The new ``INDIRECT_LIST`` flow action references one or many flow actions.
+Extends the ``INDIRECT`` flow action.
+
 Negative types
 ~~~~~~~~~~~~~~
 
diff --git a/doc/guides/rel_notes/release_23_07.rst b/doc/guides/rel_notes/release_23_07.rst
index a9b1293689..955493e445 100644
--- a/doc/guides/rel_notes/release_23_07.rst
+++ b/doc/guides/rel_notes/release_23_07.rst
@@ -55,6 +55,10 @@ New Features
      Also, make sure to start the actual text at the margin.
      =======================================================
 
+   * **Added indirect list flow action.**
+
+     * ``RTE_FLOW_ACTION_TYPE_INDIRECT_LIST``
+
 
 Removed Items
 -------------
diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
index 69e6e749f7..73b31fc69f 100644
--- a/lib/ethdev/rte_flow.c
+++ b/lib/ethdev/rte_flow.c
@@ -259,6 +259,7 @@ static const struct rte_flow_desc_data rte_flow_desc_action[] = {
 	MK_FLOW_ACTION(METER_MARK, sizeof(struct rte_flow_action_meter_mark)),
 	MK_FLOW_ACTION(SEND_TO_KERNEL, 0),
 	MK_FLOW_ACTION(QUOTA, sizeof(struct rte_flow_action_quota)),
+	MK_FLOW_ACTION(INDIRECT_LIST, 0),
 };
 
 int
@@ -2171,3 +2172,94 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,
 						    user_data, error);
 	return flow_err(port_id, ret, error);
 }
+
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+				   const
+				   struct rte_flow_indir_action_conf *conf,
+				   const struct rte_flow_action *actions,
+				   struct rte_flow_error *error)
+{
+	struct rte_eth_dev *dev;
+	const struct rte_flow_ops *ops;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, NULL);
+	ops = rte_flow_ops_get(port_id, error);
+	if (!ops || !ops->action_list_handle_create) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "action_list handle not supported");
+		return NULL;
+	}
+	dev = &rte_eth_devices[port_id];
+	return ops->action_list_handle_create(dev, conf, actions, error);
+}
+
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+				    struct rte_flow_action_list_handle *handle,
+				    struct rte_flow_error *error)
+{
+	struct rte_eth_dev *dev;
+	const struct rte_flow_ops *ops;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	ops = rte_flow_ops_get(port_id, error);
+	if (!ops || !ops->action_list_handle_destroy)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "action_list handle not supported");
+	dev = &rte_eth_devices[port_id];
+	return ops->action_list_handle_destroy(dev, handle, error);
+}
+
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,
+					 const struct rte_flow_op_attr *attr,
+					 const struct
+					 rte_flow_indir_action_conf *conf,
+					 const struct rte_flow_action *actions,
+					 void *user_data,
+					 struct rte_flow_error *error)
+{
+	struct rte_eth_dev *dev;
+	const struct rte_flow_ops *ops;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, NULL);
+	ops = rte_flow_ops_get(port_id, error);
+	if (!ops || !ops->async_action_list_handle_create) {
+		rte_flow_error_set(error, ENOTSUP,
+				   RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+				   "action_list handle not supported");
+		return NULL;
+	}
+	dev = &rte_eth_devices[port_id];
+	return ops->async_action_list_handle_create(dev, queue_id, attr, conf,
+						    actions, user_data, error);
+}
+
+int
+rte_flow_async_action_list_handle_destroy(uint16_t port_id, uint32_t queue_id,
+					  const
+					  struct rte_flow_op_attr *op_attr,
+					  struct
+					  rte_flow_action_list_handle *handle,
+					  void *user_data,
+					  struct rte_flow_error *error)
+{
+	int ret;
+	struct rte_eth_dev *dev;
+	const struct rte_flow_ops *ops;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV);
+	ops = rte_flow_ops_get(port_id, error);
+	if (!ops || !ops->async_action_list_handle_destroy)
+		return rte_flow_error_set(error, ENOTSUP,
+					  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+					  "async action_list handle not supported");
+	dev = &rte_eth_devices[port_id];
+	ret = ops->async_action_list_handle_destroy(dev, queue_id, op_attr,
+						    handle, user_data, error);
+	return flow_err(port_id, ret, error);
+}
+
diff --git a/lib/ethdev/rte_flow.h b/lib/ethdev/rte_flow.h
index 713ba8b65c..deb5dc2f9d 100644
--- a/lib/ethdev/rte_flow.h
+++ b/lib/ethdev/rte_flow.h
@@ -2912,6 +2912,11 @@ enum rte_flow_action_type {
 	 * applied to the given ethdev Rx queue.
 	 */
 	RTE_FLOW_ACTION_TYPE_SKIP_CMAN,
+
+	/**
+	 * RTE_FLOW_ACTION_TYPE_INDIRECT_LIST
+	 */
+	RTE_FLOW_ACTION_TYPE_INDIRECT_LIST,
 };
 
 /**
@@ -6118,6 +6123,150 @@ rte_flow_async_action_handle_query_update(uint16_t port_id, uint32_t queue_id,
 					  void *user_data,
 					  struct rte_flow_error *error);
 
+struct rte_flow_action_list_handle;
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Create an indirect flow action object from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action lists.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_action_list_handle_create(uint16_t port_id,
+				   const
+				   struct rte_flow_indir_action_conf *conf,
+				   const struct rte_flow_action *actions,
+				   struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Async function call to create an indirect flow action object
+ * from flow actions list.
+ * The object is identified by a unique handle.
+ * The handle has single state and configuration
+ * across all the flow rules using it.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to update the rule.
+ * @param[in] attr
+ *   Indirect action update operation attributes.
+ * @param[in] conf
+ *   Action configuration for the indirect action list creation.
+ * @param[in] actions
+ *   Specific configuration of the indirect action list.
+ * @param[in] user_data
+ *   The user data that will be returned on async completion event.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   A valid handle in case of success, NULL otherwise and rte_errno is set
+ *   to one of the error codes defined:
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-EINVAL) if *actions* list invalid.
+ *   - (-ENOTSUP) if *action* list element valid but unsupported.
+ *   - (-E2BIG) to many elements in *actions*
+ */
+__rte_experimental
+struct rte_flow_action_list_handle *
+rte_flow_async_action_list_handle_create(uint16_t port_id, uint32_t queue_id,
+					 const struct rte_flow_op_attr *attr,
+					 const struct
+					 rte_flow_indir_action_conf *conf,
+					 const struct rte_flow_action *actions,
+					 void *user_data,
+					 struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Destroy indirect actions list by handle.
+ *
+ * @param[in] port_id
+ *    The port identifier of the Ethernet device.
+ * @param[in] handle
+ *   Handle for the indirect actions list to be destroyed.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL. PMDs initialize this
+ *   structure in case of error only.
+ * @return
+ *   - (0) if success.
+ *   - (-ENODEV) if *port_id* invalid.
+ *   - (-ENOSYS) if underlying device does not support this functionality.
+ *   - (-EIO) if underlying device is removed.
+ *   - (-ENOENT) if actions list pointed by *action* handle was not found.
+ *   - (-EBUSY) if actions list pointed by *action* handle still used
+ *   rte_errno is also set.
+ */
+__rte_experimental
+int
+rte_flow_action_list_handle_destroy(uint16_t port_id,
+				    struct rte_flow_action_list_handle *handle,
+				    struct rte_flow_error *error);
+
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Enqueue indirect action list destruction operation.
+ * The destroy queue must be the same
+ * as the queue on which the action was created.
+ *
+ * @param[in] port_id
+ *   Port identifier of Ethernet device.
+ * @param[in] queue_id
+ *   Flow queue which is used to destroy the rule.
+ * @param[in] op_attr
+ *   Indirect action destruction operation attributes.
+ * @param[in] handle
+ *   Handle for the indirect action object to be destroyed.
+ * @param[in] user_data
+ *   The user data that will be returned on the completion events.
+ * @param[out] error
+ *   Perform verbose error reporting if not NULL.
+ *   PMDs initialize this structure in case of error only.
+ *
+ * @return
+ *   0 on success, a negative errno value otherwise and rte_errno is set.
+ */
+__rte_experimental
+int
+rte_flow_async_action_list_handle_destroy
+		(uint16_t port_id, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *handle,
+		 void *user_data, struct rte_flow_error *error);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/ethdev/rte_flow_driver.h b/lib/ethdev/rte_flow_driver.h
index a129a4605d..71d9b4b0a7 100644
--- a/lib/ethdev/rte_flow_driver.h
+++ b/lib/ethdev/rte_flow_driver.h
@@ -121,6 +121,17 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_create() */
+	struct rte_flow_action_list_handle *(*action_list_handle_create)
+		(struct rte_eth_dev *dev,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action actions[],
+		 struct rte_flow_error *error);
+	/** @see rte_flow_action_list_handle_destroy() */
+	int (*action_list_handle_destroy)
+		(struct rte_eth_dev *dev,
+		 struct rte_flow_action_list_handle *handle,
+		 struct rte_flow_error *error);
 	/** See rte_flow_tunnel_decap_set() */
 	int (*tunnel_decap_set)
 		(struct rte_eth_dev *dev,
@@ -294,7 +305,7 @@ struct rte_flow_ops {
 		 void *data,
 		 void *user_data,
 		 struct rte_flow_error *error);
-	/** See rte_flow_async_action_handle_query_update */
+	/** @see rte_flow_async_action_handle_query_update */
 	int (*async_action_handle_query_update)
 		(struct rte_eth_dev *dev, uint32_t queue_id,
 		 const struct rte_flow_op_attr *op_attr,
@@ -302,6 +313,20 @@ struct rte_flow_ops {
 		 const void *update, void *query,
 		 enum rte_flow_query_update_mode qu_mode,
 		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_create() */
+	struct rte_flow_action_list_handle *
+	(*async_action_list_handle_create)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *attr,
+		 const struct rte_flow_indir_action_conf *conf,
+		 const struct rte_flow_action *actions,
+		 void *user_data, struct rte_flow_error *error);
+	/** @see rte_flow_async_action_list_handle_destroy() */
+	int (*async_action_list_handle_destroy)
+		(struct rte_eth_dev *dev, uint32_t queue_id,
+		 const struct rte_flow_op_attr *op_attr,
+		 struct rte_flow_action_list_handle *action_handle,
+		 void *user_data, struct rte_flow_error *error);
 };
 
 /**
diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
index 357d1a88c0..d6c0b927f1 100644
--- a/lib/ethdev/version.map
+++ b/lib/ethdev/version.map
@@ -299,6 +299,10 @@ EXPERIMENTAL {
 	rte_flow_action_handle_query_update;
 	rte_flow_async_action_handle_query_update;
 	rte_flow_async_create_by_index;
+	rte_flow_action_list_handle_create;
+	rte_flow_action_list_handle_destroy;
+	rte_flow_async_action_list_handle_create;
+	rte_flow_async_action_list_handle_destroy;
 };
 
 INTERNAL {
-- 
2.34.1


             reply	other threads:[~2023-04-18 17:22 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-18 17:21 Gregory Etelson [this message]
2023-05-02 15:09 ` [RFC PATCH v2] " Gregory Etelson
2023-05-02 16:00   ` Ivan Malov
2023-05-03  7:05     ` Gregory Etelson
2023-05-07  9:50 ` [RFC PATCH v3] " Gregory Etelson
2023-05-17 16:57   ` Ori Kam
2023-05-18 18:18     ` Gregory Etelson
2023-05-19 11:59 ` [PATCH v4] " Gregory Etelson
2023-05-24 17:46   ` Ori Kam
2023-05-25  8:14     ` Gregory Etelson
2023-05-25  8:12 ` [PATCH v5 1/2] " Gregory Etelson
2023-05-25  8:12   ` [PATCH v5 2/2] ethdev: add indirect list METER_MARK update structures Gregory Etelson
2023-05-28 14:07     ` Ori Kam
2023-05-29  4:03       ` Gregory Etelson
2023-05-28 15:43 ` [PATCH v6] ethdev: add indirect list flow action Gregory Etelson
2023-05-29  6:14   ` Ori Kam
2023-05-31 11:24     ` Ferruh Yigit

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230418172144.24365-1-getelson@nvidia.com \
    --to=getelson@nvidia.com \
    --cc=aman.deep.singh@intel.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@amd.com \
    --cc=mkashani@nvidia.com \
    --cc=orika@nvidia.com \
    --cc=thomas@monjalon.net \
    --cc=yuying.zhang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).