> -----Original Message----- > From: Suanming Mou <suanmi...@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 <suanmi...@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 <or...@nvidia.com> Best, Ori