diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 72b54952ab..8417e3fd27 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -146,6 +146,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, @@ -162,6 +163,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, @@ -1168,6 +1172,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, }; @@ -1194,6 +1199,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, @@ -2995,6 +3006,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", @@ -3020,6 +3039,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", @@ -6605,6 +6632,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; @@ -10432,6 +10461,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 568b0881d4..b57fb97f2e 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -1886,16 +1886,88 @@ port_action_handle_update(portid_t port_id, uint32_t id, return 0; } +static void +port_action_handle_query_dump(uint32_t type, union port_action_query *query) +{ + 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); + break; + case RTE_FLOW_ACTION_TYPE_COUNT: + printf("Indirect COUNT action:\n" + " hits_set: %u\n" + " bytes_set: %u\n" + " hits: %" PRIu64 "\n" + " bytes: %" PRIu64 "\n", + 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" + " Peer: %u, Flow dir: %s, Enable: %u\n" + " Live: %u, SACK: %u, CACK: %u\n" + " Packet dir: %s, Liberal: %u, State: %u\n" + " 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); + 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); + 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); + 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 { - struct rte_flow_query_count count; - struct rte_flow_query_age age; - struct rte_flow_action_conntrack ct; - } query; + union port_action_query query; pia = action_get_by_id(port_id, id); if (!pia) @@ -1915,76 +1987,7 @@ port_action_handle_query(portid_t port_id, uint32_t id) 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) { - 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); - break; - case RTE_FLOW_ACTION_TYPE_COUNT: - printf("Indirect COUNT action:\n" - " hits_set: %u\n" - " bytes_set: %u\n" - " hits: %" PRIu64 "\n" - " bytes: %" PRIu64 "\n", - 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" - " Peer: %u, Flow dir: %s, Enable: %u\n" - " Live: %u, SACK: %u, CACK: %u\n" - " Packet dir: %s, Liberal: %u, State: %u\n" - " 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); - 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); - 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); - break; - default: - fprintf(stderr, - "Indirect action %u (type: %d) on port %u doesn't support query\n", - id, pia->type, port_id); - break; - } + port_action_handle_query_dump(pia->type, &query); return 0; } @@ -2476,6 +2479,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) { @@ -2519,9 +2523,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; @@ -2529,16 +2542,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; @@ -2554,6 +2569,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) @@ -2580,14 +2596,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) @@ -2609,6 +2633,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) @@ -2619,6 +2644,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 = @@ -2630,11 +2662,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; @@ -2653,6 +2686,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) @@ -2679,17 +2713,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) @@ -2709,6 +2749,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) @@ -2720,8 +2761,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); @@ -2766,6 +2855,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) @@ -2795,6 +2885,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 21c5632aec..a7b8565a6d 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -103,6 +103,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. @@ -218,6 +227,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; @@ -905,6 +931,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 becf7c29c9..ca763ab5fe 100644 --- a/doc/guides/prog_guide/rte_flow.rst +++ b/doc/guides/prog_guide/rte_flow.rst @@ -3774,6 +3774,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 ee64ee75cc..cec4a81882 100644 --- a/doc/guides/rel_notes/release_22_11.rst +++ b/doc/guides/rel_notes/release_22_11.rst @@ -61,6 +61,11 @@ New Features and ``rte_flow_info_get``. PMD can prepare the connection tracking resources according to the hint. +* **Added support for queue-based async query in flow API.** + + Added new function ``rte_flow_async_action_handle_query()``, + to query the action asynchronously. + * **Updated Intel iavf driver.** * Added flow subscription support. diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst index d38b0104bc..1e17e04ba7 100644 --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst @@ -4454,6 +4454,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 eeb9398e77..af0eb9619c 100644 --- a/lib/ethdev/rte_flow.c +++ b/lib/ethdev/rte_flow.c @@ -1840,3 +1840,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 d058e54b7b..be8a35588d 100644 --- a/lib/ethdev/rte_flow.h +++ b/lib/ethdev/rte_flow.h @@ -5481,6 +5481,51 @@ 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_async_action_handle_query + * + * @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 25e54f9d3e..3def7bfd24 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 {