DPDK patches and discussions
 help / color / mirror / Atom feed
From: Ori Kam <orika@nvidia.com>
To: Suanming Mou <suanmingm@nvidia.com>,
	Xiaoyun Li <xiaoyun.li@intel.com>,
	Aman Singh <aman.deep.singh@intel.com>,
	Yuying Zhang <yuying.zhang@intel.com>,
	"NBU-Contact-Thomas Monjalon (EXTERNAL)" <thomas@monjalon.net>,
	Ferruh Yigit <ferruh.yigit@xilinx.com>,
	Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>,
	Ray Kinsella <mdr@ashroe.eu>
Cc: "dev@dpdk.org" <dev@dpdk.org>
Subject: RE: [RFC] ethdev: add indirect action async query
Date: Mon, 15 Aug 2022 12:01:43 +0000	[thread overview]
Message-ID: <MW2PR12MB4666F34C01FCCFCBD65497FFD6689@MW2PR12MB4666.namprd12.prod.outlook.com> (raw)
In-Reply-To: <20220809132824.25890-1-suanmingm@nvidia.com>



> -----Original Message-----
> From: Suanming Mou <suanmingm@nvidia.com>
> Sent: Tuesday, 9 August 2022 16:28
> Subject: [RFC] ethdev: add indirect action async query
> 
> As rte_flow_action_handle_create/destroy/update() have their own
> asynchronous rte_flow_async_action_handle_create/destroy/update()
> version functions to accelerate the indirect action operations in
> queue based flow engine. Currently, the asynchronous version query
> function for indirect action was missing.
> 
> This patch adds the rte_flow_async_action_handle_query() function
> corresponds to rte_flow_action_handle_query(). The new asynchronous
> version function enables enqueue the query to the hardware similar
> as asynchronous flow management does and returns immediately to free
> the CPU for other tasks. Application can get the query results from
> rte_flow_pull() when the hardware completes its work.
> 
> Signed-off-by: Suanming Mou <suanmingm@nvidia.com>
> ---
>  app/test-pmd/cmdline_flow.c                 |  34 +++
>  app/test-pmd/config.c                       | 240 ++++++++++++++------
>  app/test-pmd/testpmd.h                      |  28 +++
>  doc/guides/prog_guide/rte_flow.rst          |  16 ++
>  doc/guides/rel_notes/release_22_11.rst      |   5 +
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst |  19 ++
>  lib/ethdev/rte_flow.c                       |  18 ++
>  lib/ethdev/rte_flow.h                       |  44 ++++
>  lib/ethdev/rte_flow_driver.h                |   9 +
>  lib/ethdev/version.map                      |   3 +
>  10 files changed, 345 insertions(+), 71 deletions(-)
> 
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index 7f50028eb7..0223286c1a 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -145,6 +145,7 @@ enum index {
>  	QUEUE_INDIRECT_ACTION_CREATE,
>  	QUEUE_INDIRECT_ACTION_UPDATE,
>  	QUEUE_INDIRECT_ACTION_DESTROY,
> +	QUEUE_INDIRECT_ACTION_QUERY,
> 
>  	/* Queue indirect action create arguments */
>  	QUEUE_INDIRECT_ACTION_CREATE_ID,
> @@ -161,6 +162,9 @@ enum index {
>  	QUEUE_INDIRECT_ACTION_DESTROY_ID,
>  	QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
> 
> +	/* Queue indirect action query arguments */
> +	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
> +
>  	/* Push arguments. */
>  	PUSH_QUEUE,
> 
> @@ -1171,6 +1175,7 @@ static const enum index next_qia_subcmd[] = {
>  	QUEUE_INDIRECT_ACTION_CREATE,
>  	QUEUE_INDIRECT_ACTION_UPDATE,
>  	QUEUE_INDIRECT_ACTION_DESTROY,
> +	QUEUE_INDIRECT_ACTION_QUERY,
>  	ZERO,
>  };
> 
> @@ -1197,6 +1202,12 @@ static const enum index next_qia_destroy_attr[] =
> {
>  	ZERO,
>  };
> 
> +static const enum index next_qia_query_attr[] = {
> +	QUEUE_INDIRECT_ACTION_QUERY_POSTPONE,
> +	END,
> +	ZERO,
> +};
> +
>  static const enum index next_ia_create_attr[] = {
>  	INDIRECT_ACTION_CREATE_ID,
>  	INDIRECT_ACTION_INGRESS,
> @@ -3013,6 +3024,14 @@ static const struct token token_list[] = {
>  		.next = NEXT(next_qia_destroy_attr),
>  		.call = parse_qia_destroy,
>  	},
> +	[QUEUE_INDIRECT_ACTION_QUERY] = {
> +		.name = "query",
> +		.help = "query indirect action",
> +		.next = NEXT(next_qia_query_attr,
> +			     NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
> +		.args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
> +		.call = parse_qia,
> +	},
>  	/* Indirect action destroy arguments. */
>  	[QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE] = {
>  		.name = "postpone",
> @@ -3038,6 +3057,14 @@ static const struct token token_list[] = {
>  			     NEXT_ENTRY(COMMON_BOOLEAN)),
>  		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
>  	},
> +	/* Indirect action update arguments. */
> +	[QUEUE_INDIRECT_ACTION_QUERY_POSTPONE] = {
> +		.name = "postpone",
> +		.help = "postpone query operation",
> +		.next = NEXT(next_qia_query_attr,
> +			     NEXT_ENTRY(COMMON_BOOLEAN)),
> +		.args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
> +	},
>  	/* Indirect action create arguments. */
>  	[QUEUE_INDIRECT_ACTION_CREATE_ID] = {
>  		.name = "action_id",
> @@ -6682,6 +6709,8 @@ parse_qia(struct context *ctx, const struct token
> *token,
>  			(void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
>  					       sizeof(double));
>  		out->args.vc.attr.group = UINT32_MAX;
> +		/* fallthrough */
> +	case QUEUE_INDIRECT_ACTION_QUERY:
>  		out->command = ctx->curr;
>  		ctx->objdata = 0;
>  		ctx->object = out;
> @@ -10509,6 +10538,11 @@ cmd_flow_parsed(const struct buffer *in)
>  						in->args.vc.attr.group,
>  						in->args.vc.actions);
>  		break;
> +	case QUEUE_INDIRECT_ACTION_QUERY:
> +		port_queue_action_handle_query(in->port,
> +					       in->queue, in->postpone,
> +					       in->args.vc.attr.group);
> +		break;
>  	case INDIRECT_ACTION_CREATE:
>  		port_action_handle_create(
>  				in->port, in->args.vc.attr.group,
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index a2939867c4..4c51ed03a8 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -2080,44 +2080,18 @@ port_action_handle_update(portid_t port_id,
> uint32_t id,
>  	return 0;
>  }
> 
> -int
> -port_action_handle_query(portid_t port_id, uint32_t id)
> +static void
> +port_action_handle_query_dump(uint32_t type, union port_action_query
> *query)
>  {
> -	struct rte_flow_error error;
> -	struct port_indirect_action *pia;
> -	union {
> -		struct rte_flow_query_count count;
> -		struct rte_flow_query_age age;
> -		struct rte_flow_action_conntrack ct;
> -	} query;
> -
> -	pia = action_get_by_id(port_id, id);
> -	if (!pia)
> -		return -EINVAL;
> -	switch (pia->type) {
> -	case RTE_FLOW_ACTION_TYPE_AGE:
> -	case RTE_FLOW_ACTION_TYPE_COUNT:
> -		break;
> -	default:
> -		fprintf(stderr,
> -			"Indirect action %u (type: %d) on port %u doesn't
> support query\n",
> -			id, pia->type, port_id);
> -		return -ENOTSUP;
> -	}
> -	/* Poisoning to make sure PMDs update it in case of error. */
> -	memset(&error, 0x55, sizeof(error));
> -	memset(&query, 0, sizeof(query));
> -	if (rte_flow_action_handle_query(port_id, pia->handle, &query,
> &error))
> -		return port_flow_complain(&error);
> -	switch (pia->type) {
> +	switch (type) {
>  	case RTE_FLOW_ACTION_TYPE_AGE:
>  		printf("Indirect AGE action:\n"
>  		       " aged: %u\n"
>  		       " sec_since_last_hit_valid: %u\n"
>  		       " sec_since_last_hit: %" PRIu32 "\n",
> -		       query.age.aged,
> -		       query.age.sec_since_last_hit_valid,
> -		       query.age.sec_since_last_hit);
> +		       query->age.aged,
> +		       query->age.sec_since_last_hit_valid,
> +		       query->age.sec_since_last_hit);
>  		break;
>  	case RTE_FLOW_ACTION_TYPE_COUNT:
>  		printf("Indirect COUNT action:\n"
> @@ -2125,10 +2099,10 @@ port_action_handle_query(portid_t port_id,
> uint32_t id)
>  		       " bytes_set: %u\n"
>  		       " hits: %" PRIu64 "\n"
>  		       " bytes: %" PRIu64 "\n",
> -		       query.count.hits_set,
> -		       query.count.bytes_set,
> -		       query.count.hits,
> -		       query.count.bytes);
> +		       query->count.hits_set,
> +		       query->count.bytes_set,
> +		       query->count.hits,
> +		       query->count.bytes);
>  		break;
>  	case RTE_FLOW_ACTION_TYPE_CONNTRACK:
>  		printf("Conntrack Context:\n"
> @@ -2138,47 +2112,76 @@ port_action_handle_query(portid_t port_id,
> uint32_t id)
>  		       "  Factor: %u, Retrans: %u, TCP flags: %u\n"
>  		       "  Last Seq: %u, Last ACK: %u\n"
>  		       "  Last Win: %u, Last End: %u\n",
> -		       query.ct.peer_port,
> -		       query.ct.is_original_dir ? "Original" : "Reply",
> -		       query.ct.enable, query.ct.live_connection,
> -		       query.ct.selective_ack, query.ct.challenge_ack_passed,
> -		       query.ct.last_direction ? "Original" : "Reply",
> -		       query.ct.liberal_mode, query.ct.state,
> -		       query.ct.max_ack_window,
> query.ct.retransmission_limit,
> -		       query.ct.last_index, query.ct.last_seq,
> -		       query.ct.last_ack, query.ct.last_window,
> -		       query.ct.last_end);
> +		       query->ct.peer_port,
> +		       query->ct.is_original_dir ? "Original" : "Reply",
> +		       query->ct.enable, query->ct.live_connection,
> +		       query->ct.selective_ack, query-
> >ct.challenge_ack_passed,
> +		       query->ct.last_direction ? "Original" : "Reply",
> +		       query->ct.liberal_mode, query->ct.state,
> +		       query->ct.max_ack_window, query-
> >ct.retransmission_limit,
> +		       query->ct.last_index, query->ct.last_seq,
> +		       query->ct.last_ack, query->ct.last_window,
> +		       query->ct.last_end);
>  		printf("  Original Dir:\n"
>  		       "    scale: %u, fin: %u, ack seen: %u\n"
>  		       " unacked data: %u\n    Sent end: %u,"
>  		       "    Reply end: %u, Max win: %u, Max ACK: %u\n",
> -		       query.ct.original_dir.scale,
> -		       query.ct.original_dir.close_initiated,
> -		       query.ct.original_dir.last_ack_seen,
> -		       query.ct.original_dir.data_unacked,
> -		       query.ct.original_dir.sent_end,
> -		       query.ct.original_dir.reply_end,
> -		       query.ct.original_dir.max_win,
> -		       query.ct.original_dir.max_ack);
> +		       query->ct.original_dir.scale,
> +		       query->ct.original_dir.close_initiated,
> +		       query->ct.original_dir.last_ack_seen,
> +		       query->ct.original_dir.data_unacked,
> +		       query->ct.original_dir.sent_end,
> +		       query->ct.original_dir.reply_end,
> +		       query->ct.original_dir.max_win,
> +		       query->ct.original_dir.max_ack);
>  		printf("  Reply Dir:\n"
>  		       "    scale: %u, fin: %u, ack seen: %u\n"
>  		       " unacked data: %u\n    Sent end: %u,"
>  		       "    Reply end: %u, Max win: %u, Max ACK: %u\n",
> -		       query.ct.reply_dir.scale,
> -		       query.ct.reply_dir.close_initiated,
> -		       query.ct.reply_dir.last_ack_seen,
> -		       query.ct.reply_dir.data_unacked,
> -		       query.ct.reply_dir.sent_end,
> -		       query.ct.reply_dir.reply_end,
> -		       query.ct.reply_dir.max_win,
> -		       query.ct.reply_dir.max_ack);
> +		       query->ct.reply_dir.scale,
> +		       query->ct.reply_dir.close_initiated,
> +		       query->ct.reply_dir.last_ack_seen,
> +		       query->ct.reply_dir.data_unacked,
> +		       query->ct.reply_dir.sent_end,
> +		       query->ct.reply_dir.reply_end,
> +		       query->ct.reply_dir.max_win,
> +		       query->ct.reply_dir.max_ack);
> +		break;
> +	default:
> +		fprintf(stderr,
> +			"Indirect action (type: %d) doesn't support query\n",
> +			type);
> +		break;
> +	}
> +
> +}
> +
> +int
> +port_action_handle_query(portid_t port_id, uint32_t id)
> +{
> +	struct rte_flow_error error;
> +	struct port_indirect_action *pia;
> +	union port_action_query query;
> +
> +	pia = action_get_by_id(port_id, id);
> +	if (!pia)
> +		return -EINVAL;
> +	switch (pia->type) {
> +	case RTE_FLOW_ACTION_TYPE_AGE:
> +	case RTE_FLOW_ACTION_TYPE_COUNT:
>  		break;
>  	default:
>  		fprintf(stderr,
>  			"Indirect action %u (type: %d) on port %u doesn't
> support query\n",
>  			id, pia->type, port_id);
> -		break;
> +		return -ENOTSUP;
>  	}
> +	/* Poisoning to make sure PMDs update it in case of error. */
> +	memset(&error, 0x55, sizeof(error));
> +	memset(&query, 0, sizeof(query));
> +	if (rte_flow_action_handle_query(port_id, pia->handle, &query,
> &error))
> +		return port_flow_complain(&error);
> +	port_action_handle_query_dump(pia->type, &query);
>  	return 0;
>  }
> 
> @@ -2670,6 +2673,7 @@ port_queue_flow_create(portid_t port_id,
> queueid_t queue_id,
>  	bool found;
>  	struct rte_flow_error error = { RTE_FLOW_ERROR_TYPE_NONE,
> NULL, NULL };
>  	struct rte_flow_action_age *age = age_action_get(actions);
> +	struct queue_job *job;
> 
>  	port = &ports[port_id];
>  	if (port->flow_list) {
> @@ -2713,9 +2717,18 @@ port_queue_flow_create(portid_t port_id,
> queueid_t queue_id,
>  		return -EINVAL;
>  	}
> 
> +	job = calloc(1, sizeof(*job));
> +	if (!job) {
> +		printf("Queue flow create job allocate failed\n");
> +		return -ENOMEM;
> +	}
> +	job->type = QUEUE_JOB_TYPE_FLOW_CREATE;
> +
>  	pf = port_flow_new(NULL, pattern, actions, &error);
> -	if (!pf)
> +	if (!pf) {
> +		free(job);
>  		return port_flow_complain(&error);
> +	}
>  	if (age) {
>  		pf->age_type = ACTION_AGE_CONTEXT_TYPE_FLOW;
>  		age->context = &pf->age_type;
> @@ -2723,16 +2736,18 @@ port_queue_flow_create(portid_t port_id,
> queueid_t queue_id,
>  	/* Poisoning to make sure PMDs update it in case of error. */
>  	memset(&error, 0x11, sizeof(error));
>  	flow = rte_flow_async_create(port_id, queue_id, &op_attr, pt-
> >table,
> -		pattern, pattern_idx, actions, actions_idx, NULL, &error);
> +		pattern, pattern_idx, actions, actions_idx, job, &error);
>  	if (!flow) {
>  		uint32_t flow_id = pf->id;
>  		port_queue_flow_destroy(port_id, queue_id, true, 1,
> &flow_id);
> +		free(job);
>  		return port_flow_complain(&error);
>  	}
> 
>  	pf->next = port->flow_list;
>  	pf->id = id;
>  	pf->flow = flow;
> +	job->pf = pf;
>  	port->flow_list = pf;
>  	printf("Flow rule #%u creation enqueued\n", pf->id);
>  	return 0;
> @@ -2748,6 +2763,7 @@ port_queue_flow_destroy(portid_t port_id,
> queueid_t queue_id,
>  	struct port_flow **tmp;
>  	uint32_t c = 0;
>  	int ret = 0;
> +	struct queue_job *job;
> 
>  	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
>  	    port_id == (portid_t)RTE_PORT_ALL)
> @@ -2774,14 +2790,22 @@ port_queue_flow_destroy(portid_t port_id,
> queueid_t queue_id,
>  			 * update it in case of error.
>  			 */
>  			memset(&error, 0x33, sizeof(error));
> +			job = calloc(1, sizeof(*job));
> +			if (!job) {
> +				printf("Queue flow destroy job allocate
> failed\n");
> +				return -ENOMEM;
> +			}
> +			job->type = QUEUE_JOB_TYPE_FLOW_DESTROY;
> +			job->pf = pf;
> +
>  			if (rte_flow_async_destroy(port_id, queue_id,
> &op_attr,
> -						   pf->flow, NULL, &error)) {
> +						   pf->flow, job, &error)) {
> +				free(job);
>  				ret = port_flow_complain(&error);
>  				continue;
>  			}
>  			printf("Flow rule #%u destruction enqueued\n", pf-
> >id);
>  			*tmp = pf->next;
> -			free(pf);
>  			break;
>  		}
>  		if (i == n)
> @@ -2803,6 +2827,7 @@ port_queue_action_handle_create(portid_t
> port_id, uint32_t queue_id,
>  	struct port_indirect_action *pia;
>  	int ret;
>  	struct rte_flow_error error;
> +	struct queue_job *job;
> 
>  	ret = action_alloc(port_id, id, &pia);
>  	if (ret)
> @@ -2813,6 +2838,13 @@ port_queue_action_handle_create(portid_t
> port_id, uint32_t queue_id,
>  		printf("Queue #%u is invalid\n", queue_id);
>  		return -EINVAL;
>  	}
> +	job = calloc(1, sizeof(*job));
> +	if (!job) {
> +		printf("Queue action create job allocate failed\n");
> +		return -ENOMEM;
> +	}
> +	job->type = QUEUE_JOB_TYPE_ACTION_CREATE;
> +	job->pia = pia;
> 
>  	if (action->type == RTE_FLOW_ACTION_TYPE_AGE) {
>  		struct rte_flow_action_age *age =
> @@ -2824,11 +2856,12 @@ port_queue_action_handle_create(portid_t
> port_id, uint32_t queue_id,
>  	/* 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, NULL, &error);
> +					&attr, conf, action, job, &error);
>  	if (!pia->handle) {
>  		uint32_t destroy_id = pia->id;
>  		port_queue_action_handle_destroy(port_id, queue_id,
>  						 postpone, 1, &destroy_id);
> +		free(job);
>  		return port_flow_complain(&error);
>  	}
>  	pia->type = action->type;
> @@ -2847,6 +2880,7 @@ port_queue_action_handle_destroy(portid_t
> port_id,
>  	struct port_indirect_action **tmp;
>  	uint32_t c = 0;
>  	int ret = 0;
> +	struct queue_job *job;
> 
>  	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
>  	    port_id == (portid_t)RTE_PORT_ALL)
> @@ -2873,17 +2907,23 @@ port_queue_action_handle_destroy(portid_t
> port_id,
>  			 * of error.
>  			 */
>  			memset(&error, 0x99, sizeof(error));
> +			job = calloc(1, sizeof(*job));
> +			if (!job) {
> +				printf("Queue action destroy job allocate
> failed\n");
> +				return -ENOMEM;
> +			}
> +			job->type = QUEUE_JOB_TYPE_ACTION_DESTROY;
> +			job->pia = pia;
> 
>  			if (pia->handle &&
>  			    rte_flow_async_action_handle_destroy(port_id,
> -				queue_id, &attr, pia->handle, NULL, &error))
> {
> +				queue_id, &attr, pia->handle, job, &error)) {
>  				ret = port_flow_complain(&error);
>  				continue;
>  			}
>  			*tmp = pia->next;
>  			printf("Indirect action #%u destruction queued\n",
>  			       pia->id);
> -			free(pia);
>  			break;
>  		}
>  		if (i == n)
> @@ -2903,6 +2943,7 @@ port_queue_action_handle_update(portid_t
> port_id,
>  	struct rte_port *port;
>  	struct rte_flow_error error;
>  	struct rte_flow_action_handle *action_handle;
> +	struct queue_job *job;
> 
>  	action_handle = port_action_handle_get_by_id(port_id, id);
>  	if (!action_handle)
> @@ -2914,8 +2955,56 @@ port_queue_action_handle_update(portid_t
> port_id,
>  		return -EINVAL;
>  	}
> 
> +	job = calloc(1, sizeof(*job));
> +	if (!job) {
> +		printf("Queue action update job allocate failed\n");
> +		return -ENOMEM;
> +	}
> +	job->type = QUEUE_JOB_TYPE_ACTION_UPDATE;
> +
>  	if (rte_flow_async_action_handle_update(port_id, queue_id, &attr,
> -				    action_handle, action, NULL, &error)) {
> +				    action_handle, action, job, &error)) {
> +		free(job);
> +		return port_flow_complain(&error);
> +	}
> +	printf("Indirect action #%u update queued\n", id);
> +	return 0;
> +}
> +
> +/** Enqueue indirect action query operation. */
> +int
> +port_queue_action_handle_query(portid_t port_id,
> +			       uint32_t queue_id, bool postpone, uint32_t id)
> +{
> +	const struct rte_flow_op_attr attr = { .postpone = postpone};
> +	struct rte_port *port;
> +	struct rte_flow_error error;
> +	struct rte_flow_action_handle *action_handle;
> +	struct port_indirect_action *pia;
> +	struct queue_job *job;
> +
> +	pia = action_get_by_id(port_id, id);
> +	action_handle = pia ? pia->handle : NULL;
> +	if (!action_handle)
> +		return -EINVAL;
> +
> +	port = &ports[port_id];
> +	if (queue_id >= port->queue_nb) {
> +		printf("Queue #%u is invalid\n", queue_id);
> +		return -EINVAL;
> +	}
> +
> +	job = calloc(1, sizeof(*job));
> +	if (!job) {
> +		printf("Queue action update job allocate failed\n");
> +		return -ENOMEM;
> +	}
> +	job->type = QUEUE_JOB_TYPE_ACTION_QUERY;
> +	job->pia = pia;
> +
> +	if (rte_flow_async_action_handle_query(port_id, queue_id, &attr,
> +				    action_handle, &job->query, job, &error)) {
> +		free(job);
>  		return port_flow_complain(&error);
>  	}
>  	printf("Indirect action #%u update queued\n", id);
> @@ -2960,6 +3049,7 @@ port_queue_flow_pull(portid_t port_id, queueid_t
> queue_id)
>  	int ret = 0;
>  	int success = 0;
>  	int i;
> +	struct queue_job *job;
> 
>  	if (port_id_is_invalid(port_id, ENABLED_WARN) ||
>  	    port_id == (portid_t)RTE_PORT_ALL)
> @@ -2989,6 +3079,14 @@ port_queue_flow_pull(portid_t port_id,
> queueid_t queue_id)
>  	for (i = 0; i < ret; i++) {
>  		if (res[i].status == RTE_FLOW_OP_SUCCESS)
>  			success++;
> +		job = (struct queue_job *)res[i].user_data;
> +		if (job->type == QUEUE_JOB_TYPE_FLOW_DESTROY)
> +			free(job->pf);
> +		else if (job->type == QUEUE_JOB_TYPE_ACTION_DESTROY)
> +			free(job->pia);
> +		else if (job->type == QUEUE_JOB_TYPE_ACTION_QUERY)
> +			port_action_handle_query_dump(job->pia->type,
> &job->query);
> +		free(job);
>  	}
>  	printf("Queue #%u pulled %u operations (%u failed, %u
> succeeded)\n",
>  	       queue_id, ret, ret - success, success);
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> index fb2f5195d3..c7a96d062c 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -105,6 +105,15 @@ enum {
>  	/**< allocate mempool natively, use
> rte_pktmbuf_pool_create_extbuf */
>  };
> 
> +enum {
> +	QUEUE_JOB_TYPE_FLOW_CREATE,
> +	QUEUE_JOB_TYPE_FLOW_DESTROY,
> +	QUEUE_JOB_TYPE_ACTION_CREATE,
> +	QUEUE_JOB_TYPE_ACTION_DESTROY,
> +	QUEUE_JOB_TYPE_ACTION_UPDATE,
> +	QUEUE_JOB_TYPE_ACTION_QUERY,
> +};
> +
>  /**
>   * The data structure associated with RX and TX packet burst statistics
>   * that are recorded for each forwarding stream.
> @@ -220,6 +229,23 @@ struct port_indirect_action {
>  	enum age_action_context_type age_type; /**< Age action context
> type. */
>  };
> 
> +/* Descriptor for action query data. */
> +union port_action_query {
> +	struct rte_flow_query_count count;
> +	struct rte_flow_query_age age;
> +	struct rte_flow_action_conntrack ct;
> +};
> +
> +/* Descriptor for queue job. */
> +struct queue_job {
> +	uint32_t type; /**< Job type. */
> +	union {
> +		struct port_flow *pf;
> +		struct port_indirect_action *pia;
> +	};
> +	union port_action_query query;
> +};
> +
>  struct port_flow_tunnel {
>  	LIST_ENTRY(port_flow_tunnel) chain;
>  	struct rte_flow_action *pmd_actions;
> @@ -980,6 +1006,8 @@ int port_queue_action_handle_destroy(portid_t
> port_id,
>  int port_queue_action_handle_update(portid_t port_id, uint32_t queue_id,
>  				    bool postpone, uint32_t id,
>  				    const struct rte_flow_action *action);
> +int port_queue_action_handle_query(portid_t port_id, uint32_t queue_id,
> +				   bool postpone, uint32_t id);
>  int port_queue_flow_push(portid_t port_id, queueid_t queue_id);
>  int port_queue_flow_pull(portid_t port_id, queueid_t queue_id);
>  int port_flow_validate(portid_t port_id,
> diff --git a/doc/guides/prog_guide/rte_flow.rst
> b/doc/guides/prog_guide/rte_flow.rst
> index 588914b231..9e6aadf954 100644
> --- a/doc/guides/prog_guide/rte_flow.rst
> +++ b/doc/guides/prog_guide/rte_flow.rst
> @@ -3911,6 +3911,22 @@ Asynchronous version of indirect action update
> API.
>             void *user_data,
>             struct rte_flow_error *error);
> 
> +Enqueue indirect action query operation
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +Asynchronous version of indirect action query API.
> +
> +.. code-block:: c
> +
> +   int
> +   rte_flow_async_action_handle_query(uint16_t port_id,
> +           uint32_t queue_id,
> +           const struct rte_flow_op_attr *q_ops_attr,
> +           struct rte_flow_action_handle *action_handle,
> +           void *data,
> +           void *user_data,
> +           struct rte_flow_error *error);
> +
>  Push enqueued operations
>  ~~~~~~~~~~~~~~~~~~~~~~~~
> 
> diff --git a/doc/guides/rel_notes/release_22_11.rst
> b/doc/guides/rel_notes/release_22_11.rst
> index 8c021cf050..597b28ede1 100644
> --- a/doc/guides/rel_notes/release_22_11.rst
> +++ b/doc/guides/rel_notes/release_22_11.rst
> @@ -55,6 +55,11 @@ New Features
>       Also, make sure to start the actual text at the margin.
>       =======================================================
> 
> +* **Added support for queue based async query in rte_flow.**
> +
> +  Added new API ``rte_flow_async_action_handle_query()``, to query the
> +  action asynchronously.
> +
> 
>  Removed Items
>  -------------
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 330e34427d..d2c6e385db 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -4676,6 +4676,25 @@ Query indirect action having id 100::
> 
>     testpmd> flow indirect_action 0 query 100
> 
> +Enqueueing query of indirect actions
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> +
> +``flow queue indirect_action query`` adds query operation for an indirect
> +action to a queue. It is bound to
> ``rte_flow_async_action_handle_query()``::
> +
> +   flow queue {port_id} indirect_action {queue_id} query
> +      {indirect_action_id} [postpone {boolean}]
> +
> +If successful, it will show::
> +
> +   Indirect action #[...] query queued
> +
> +Otherwise it will show an error message of the form::
> +
> +   Caught error type [...] ([...]): [...]
> +
> +``flow queue pull`` must be called to retrieve the operation status.
> +
>  Sample QinQ flow rules
>  ~~~~~~~~~~~~~~~~~~~~~~
> 
> diff --git a/lib/ethdev/rte_flow.c b/lib/ethdev/rte_flow.c
> index 501be9d602..eb6a6b737e 100644
> --- a/lib/ethdev/rte_flow.c
> +++ b/lib/ethdev/rte_flow.c
> @@ -1844,3 +1844,21 @@ rte_flow_async_action_handle_update(uint16_t
> port_id,
>  					  action_handle, update, user_data,
> error);
>  	return flow_err(port_id, ret, error);
>  }
> +
> +int
> +rte_flow_async_action_handle_query(uint16_t port_id,
> +		uint32_t queue_id,
> +		const struct rte_flow_op_attr *op_attr,
> +		const struct rte_flow_action_handle *action_handle,
> +		void *data,
> +		void *user_data,
> +		struct rte_flow_error *error)
> +{
> +	struct rte_eth_dev *dev = &rte_eth_devices[port_id];
> +	const struct rte_flow_ops *ops = rte_flow_ops_get(port_id, error);
> +	int ret;
> +
> +	ret = ops->async_action_handle_query(dev, queue_id, op_attr,
> +					  action_handle, data, 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 a79f1e7ef0..a5e84bd85e 100644
> --- a/lib/ethdev/rte_flow.h
> +++ b/lib/ethdev/rte_flow.h
> @@ -5612,6 +5612,50 @@ rte_flow_async_action_handle_update(uint16_t
> port_id,
>  		const void *update,
>  		void *user_data,
>  		struct rte_flow_error *error);
> +
> +/**
> + * @warning
> + * @b EXPERIMENTAL: this API may change without prior notice.
> + *
> + * Enqueue indirect action query operation.
> + *
> + * Retrieve action-specific data such as counters.
> + * Data is gathered by special action which may be present/referenced in
> + * more than one flow rule definition.
> + * Data will be available only when completion event returns.
> + *
> + * @see RTE_FLOW_ACTION_TYPE_CONNTRACK
> + *
> + * @param port_id
> + *   Port identifier of Ethernet device.
> + * @param[in] queue_id
> + *   Flow queue which is used to query the action.
> + * @param[in] op_attr
> + *   Indirect action update operation attributes.
> + * @param[in] action_handle
> + *   Handle for the action object to query.
> + * @param[in, out] data
> + *   Pointer to storage for the associated query data type.
> + *   The out data will be available only when completion event returns
> + *   from rte_flow_pull.
> + * @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_handle_query(uint16_t port_id,
> +		uint32_t queue_id,
> +		const struct rte_flow_op_attr *op_attr,
> +		const struct rte_flow_action_handle *action_handle,
> +		void *data,
> +		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 2bff732d6a..7289deb538 100644
> --- a/lib/ethdev/rte_flow_driver.h
> +++ b/lib/ethdev/rte_flow_driver.h
> @@ -260,6 +260,15 @@ struct rte_flow_ops {
>  		 const void *update,
>  		 void *user_data,
>  		 struct rte_flow_error *error);
> +	/** See rte_flow_async_action_handle_query() */
> +	int (*async_action_handle_query)
> +		(struct rte_eth_dev *dev,
> +		 uint32_t queue_id,
> +		 const struct rte_flow_op_attr *op_attr,
> +		 const struct rte_flow_action_handle *action_handle,
> +		 void *data,
> +		 void *user_data,
> +		 struct rte_flow_error *error);
>  };
> 
>  /**
> diff --git a/lib/ethdev/version.map b/lib/ethdev/version.map
> index 03f52fee91..722081a8c7 100644
> --- a/lib/ethdev/version.map
> +++ b/lib/ethdev/version.map
> @@ -285,6 +285,9 @@ EXPERIMENTAL {
>  	rte_mtr_color_in_protocol_priority_get;
>  	rte_mtr_color_in_protocol_set;
>  	rte_mtr_meter_vlan_table_update;
> +
> +	# added in 22.11
> +	rte_flow_async_action_handle_query;
>  };
> 
>  INTERNAL {
> --
> 2.25.1

Acked-by: Ori Kam <orika@nvidia.com>
Best,
Ori

  reply	other threads:[~2022-08-15 12:01 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-09 13:28 Suanming Mou
2022-08-15 12:01 ` Ori Kam [this message]
2022-09-20  7:11 ` [PATCH v1] " Suanming Mou
2022-09-28  8:50   ` Andrew Rybchenko
2022-11-17  8:06   ` David Marchand
2022-11-17  8:18     ` Suanming Mou
2022-11-17  8:31       ` David Marchand
2022-11-17  8:40         ` Suanming Mou

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=MW2PR12MB4666F34C01FCCFCBD65497FFD6689@MW2PR12MB4666.namprd12.prod.outlook.com \
    --to=orika@nvidia.com \
    --cc=aman.deep.singh@intel.com \
    --cc=andrew.rybchenko@oktetlabs.ru \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@xilinx.com \
    --cc=mdr@ashroe.eu \
    --cc=suanmingm@nvidia.com \
    --cc=thomas@monjalon.net \
    --cc=xiaoyun.li@intel.com \
    --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).