* [PATCH 10/10] app/testpmd: implement rte flow queue indirect action
@ 2022-01-18 5:09 Alexander Kozyrev
0 siblings, 0 replies; only message in thread
From: Alexander Kozyrev @ 2022-01-18 5:09 UTC (permalink / raw)
To: dev
Cc: orika, thomas, ivan.malov, andrew.rybchenko, ferruh.yigit,
mohammad.abdul.awal, qi.z.zhang, jerinj, ajit.khaparde
Add testpmd support for the rte_flow_q_action_handle API.
Provide the command line interface for operations dequeue.
Usage example:
flow queue 0 indirect_action 0 create action_id 9
ingress drain yes action rss / end
flow queue 0 indirect_action 0 update action_id 9
action queue index 0 / end
flow queue 0 indirect_action 0 destroy action_id 9
Signed-off-by: Alexander Kozyrev <akozyrev@nvidia.com>
---
app/test-pmd/cmdline_flow.c | 276 ++++++++++++++++++++
app/test-pmd/config.c | 131 ++++++++++
app/test-pmd/testpmd.h | 10 +
doc/guides/testpmd_app_ug/testpmd_funcs.rst | 65 +++++
4 files changed, 482 insertions(+)
diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index 507eb87984..50b6424933 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -120,6 +120,7 @@ enum index {
/* Queue arguments. */
QUEUE_CREATE,
QUEUE_DESTROY,
+ QUEUE_INDIRECT_ACTION,
/* Queue create arguments. */
QUEUE_CREATE_ID,
@@ -133,6 +134,26 @@ enum index {
QUEUE_DESTROY_ID,
QUEUE_DESTROY_DRAIN,
+ /* Queue indirect action arguments */
+ QUEUE_INDIRECT_ACTION_CREATE,
+ QUEUE_INDIRECT_ACTION_UPDATE,
+ QUEUE_INDIRECT_ACTION_DESTROY,
+
+ /* Queue indirect action create arguments */
+ QUEUE_INDIRECT_ACTION_CREATE_ID,
+ QUEUE_INDIRECT_ACTION_INGRESS,
+ QUEUE_INDIRECT_ACTION_EGRESS,
+ QUEUE_INDIRECT_ACTION_TRANSFER,
+ QUEUE_INDIRECT_ACTION_CREATE_DRAIN,
+ QUEUE_INDIRECT_ACTION_SPEC,
+
+ /* Queue indirect action update arguments */
+ QUEUE_INDIRECT_ACTION_UPDATE_DRAIN,
+
+ /* Queue indirect action destroy arguments */
+ QUEUE_INDIRECT_ACTION_DESTROY_ID,
+ QUEUE_INDIRECT_ACTION_DESTROY_DRAIN,
+
/* Dequeue arguments. */
DEQUEUE_QUEUE,
@@ -1099,6 +1120,7 @@ static const enum index next_table_destroy_attr[] = {
static const enum index next_queue_subcmd[] = {
QUEUE_CREATE,
QUEUE_DESTROY,
+ QUEUE_INDIRECT_ACTION,
ZERO,
};
@@ -1108,6 +1130,36 @@ static const enum index next_queue_destroy_attr[] = {
ZERO,
};
+static const enum index next_qia_subcmd[] = {
+ QUEUE_INDIRECT_ACTION_CREATE,
+ QUEUE_INDIRECT_ACTION_UPDATE,
+ QUEUE_INDIRECT_ACTION_DESTROY,
+ ZERO,
+};
+
+static const enum index next_qia_create_attr[] = {
+ QUEUE_INDIRECT_ACTION_CREATE_ID,
+ QUEUE_INDIRECT_ACTION_INGRESS,
+ QUEUE_INDIRECT_ACTION_EGRESS,
+ QUEUE_INDIRECT_ACTION_TRANSFER,
+ QUEUE_INDIRECT_ACTION_CREATE_DRAIN,
+ QUEUE_INDIRECT_ACTION_SPEC,
+ ZERO,
+};
+
+static const enum index next_qia_update_attr[] = {
+ QUEUE_INDIRECT_ACTION_UPDATE_DRAIN,
+ QUEUE_INDIRECT_ACTION_SPEC,
+ ZERO,
+};
+
+static const enum index next_qia_destroy_attr[] = {
+ QUEUE_INDIRECT_ACTION_DESTROY_DRAIN,
+ QUEUE_INDIRECT_ACTION_DESTROY_ID,
+ END,
+ ZERO,
+};
+
static const enum index next_ia_create_attr[] = {
INDIRECT_ACTION_CREATE_ID,
INDIRECT_ACTION_INGRESS,
@@ -2163,6 +2215,12 @@ static int parse_qo(struct context *, const struct token *,
static int parse_qo_destroy(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
+static int parse_qia(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
+static int parse_qia_destroy(struct context *, const struct token *,
+ const char *, unsigned int,
+ void *, unsigned int);
static int parse_dequeue(struct context *, const struct token *,
const char *, unsigned int,
void *, unsigned int);
@@ -2729,6 +2787,13 @@ static const struct token token_list[] = {
.args = ARGS(ARGS_ENTRY(struct buffer, queue)),
.call = parse_qo_destroy,
},
+ [QUEUE_INDIRECT_ACTION] = {
+ .name = "indirect_action",
+ .help = "queue indirect actions",
+ .next = NEXT(next_qia_subcmd, NEXT_ENTRY(COMMON_QUEUE_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, queue)),
+ .call = parse_qia,
+ },
/* Queue arguments. */
[QUEUE_TABLE] = {
.name = "table",
@@ -2782,6 +2847,90 @@ static const struct token token_list[] = {
args.destroy.rule)),
.call = parse_qo_destroy,
},
+ /* Queue indirect action arguments */
+ [QUEUE_INDIRECT_ACTION_CREATE] = {
+ .name = "create",
+ .help = "create indirect action",
+ .next = NEXT(next_qia_create_attr),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_UPDATE] = {
+ .name = "update",
+ .help = "update indirect action",
+ .next = NEXT(next_qia_update_attr,
+ NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_DESTROY] = {
+ .name = "destroy",
+ .help = "destroy indirect action",
+ .next = NEXT(next_qia_destroy_attr),
+ .call = parse_qia_destroy,
+ },
+ /* Indirect action destroy arguments. */
+ [QUEUE_INDIRECT_ACTION_DESTROY_DRAIN] = {
+ .name = "drain",
+ .help = "drain operation immediately",
+ .next = NEXT(next_qia_destroy_attr,
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, drain)),
+ },
+ [QUEUE_INDIRECT_ACTION_DESTROY_ID] = {
+ .name = "action_id",
+ .help = "specify a indirect action id to destroy",
+ .next = NEXT(next_qia_destroy_attr,
+ NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
+ args.ia_destroy.action_id)),
+ .call = parse_qia_destroy,
+ },
+ /* Indirect action update arguments. */
+ [QUEUE_INDIRECT_ACTION_UPDATE_DRAIN] = {
+ .name = "drain",
+ .help = "drain operation immediately",
+ .next = NEXT(next_qia_update_attr,
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, drain)),
+ },
+ /* Indirect action create arguments. */
+ [QUEUE_INDIRECT_ACTION_CREATE_ID] = {
+ .name = "action_id",
+ .help = "specify a indirect action id to create",
+ .next = NEXT(next_qia_create_attr,
+ NEXT_ENTRY(COMMON_INDIRECT_ACTION_ID)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
+ },
+ [QUEUE_INDIRECT_ACTION_INGRESS] = {
+ .name = "ingress",
+ .help = "affect rule to ingress",
+ .next = NEXT(next_qia_create_attr),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_EGRESS] = {
+ .name = "egress",
+ .help = "affect rule to egress",
+ .next = NEXT(next_qia_create_attr),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_TRANSFER] = {
+ .name = "transfer",
+ .help = "affect rule to transfer",
+ .next = NEXT(next_qia_create_attr),
+ .call = parse_qia,
+ },
+ [QUEUE_INDIRECT_ACTION_CREATE_DRAIN] = {
+ .name = "drain",
+ .help = "drain operation immediately",
+ .next = NEXT(next_qia_create_attr,
+ NEXT_ENTRY(COMMON_BOOLEAN)),
+ .args = ARGS(ARGS_ENTRY(struct buffer, drain)),
+ },
+ [QUEUE_INDIRECT_ACTION_SPEC] = {
+ .name = "action",
+ .help = "specify action to create indirect handle",
+ .next = NEXT(next_action),
+ },
/* Top-level command. */
[DEQUEUE] = {
.name = "dequeue",
@@ -6181,6 +6330,110 @@ parse_ia_destroy(struct context *ctx, const struct token *token,
return len;
}
+/** Parse tokens for indirect action commands. */
+static int
+parse_qia(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command) {
+ if (ctx->curr != QUEUE)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->args.vc.data = (uint8_t *)out + size;
+ return len;
+ }
+ switch (ctx->curr) {
+ case QUEUE_INDIRECT_ACTION:
+ return len;
+ case QUEUE_INDIRECT_ACTION_CREATE:
+ case QUEUE_INDIRECT_ACTION_UPDATE:
+ out->args.vc.actions =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ out->args.vc.attr.group = UINT32_MAX;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case QUEUE_INDIRECT_ACTION_EGRESS:
+ out->args.vc.attr.egress = 1;
+ return len;
+ case QUEUE_INDIRECT_ACTION_INGRESS:
+ out->args.vc.attr.ingress = 1;
+ return len;
+ case QUEUE_INDIRECT_ACTION_TRANSFER:
+ out->args.vc.attr.transfer = 1;
+ return len;
+ case QUEUE_INDIRECT_ACTION_CREATE_DRAIN:
+ return len;
+ default:
+ return -1;
+ }
+}
+
+/** Parse tokens for indirect action destroy command. */
+static int
+parse_qia_destroy(struct context *ctx, const struct token *token,
+ const char *str, unsigned int len,
+ void *buf, unsigned int size)
+{
+ struct buffer *out = buf;
+ uint32_t *action_id;
+
+ /* Token name must match. */
+ if (parse_default(ctx, token, str, len, NULL, 0) < 0)
+ return -1;
+ /* Nothing else to do if there is no buffer. */
+ if (!out)
+ return len;
+ if (!out->command || out->command == QUEUE) {
+ if (ctx->curr != QUEUE_INDIRECT_ACTION_DESTROY)
+ return -1;
+ if (sizeof(*out) > size)
+ return -1;
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ out->args.ia_destroy.action_id =
+ (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+ sizeof(double));
+ return len;
+ }
+ switch (ctx->curr) {
+ case QUEUE_INDIRECT_ACTION:
+ out->command = ctx->curr;
+ ctx->objdata = 0;
+ ctx->object = out;
+ ctx->objmask = NULL;
+ return len;
+ case QUEUE_INDIRECT_ACTION_DESTROY_ID:
+ action_id = out->args.ia_destroy.action_id
+ + out->args.ia_destroy.action_id_n++;
+ if ((uint8_t *)action_id > (uint8_t *)out + size)
+ return -1;
+ ctx->objdata = 0;
+ ctx->object = action_id;
+ ctx->objmask = NULL;
+ return len;
+ case QUEUE_INDIRECT_ACTION_DESTROY_DRAIN:
+ return len;
+ default:
+ return -1;
+ }
+}
+
/** Parse tokens for meter policy action commands. */
static int
parse_mp(struct context *ctx, const struct token *token,
@@ -9857,6 +10110,29 @@ cmd_flow_parsed(const struct buffer *in)
case DRAIN:
port_queue_flow_drain(in->port, in->queue);
break;
+ case QUEUE_INDIRECT_ACTION_CREATE:
+ port_queue_action_handle_create(
+ in->port, in->queue, in->drain,
+ in->args.vc.attr.group,
+ &((const struct rte_flow_indir_action_conf) {
+ .ingress = in->args.vc.attr.ingress,
+ .egress = in->args.vc.attr.egress,
+ .transfer = in->args.vc.attr.transfer,
+ }),
+ in->args.vc.actions);
+ break;
+ case QUEUE_INDIRECT_ACTION_DESTROY:
+ port_queue_action_handle_destroy(in->port,
+ in->queue, in->drain,
+ in->args.ia_destroy.action_id_n,
+ in->args.ia_destroy.action_id);
+ break;
+ case QUEUE_INDIRECT_ACTION_UPDATE:
+ port_queue_action_handle_update(in->port,
+ in->queue, in->drain,
+ in->args.vc.attr.group,
+ in->args.vc.actions);
+ 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 5d23edf562..634174eec6 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -2536,6 +2536,137 @@ port_queue_flow_destroy(portid_t port_id, queueid_t queue_id,
return ret;
}
+/** Enqueue indirect action create operation*/
+int
+port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
+ bool drain, uint32_t id,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *action)
+{
+ const struct rte_flow_q_ops_attr attr = { .drain = drain};
+ struct rte_port *port;
+ struct port_indirect_action *pia;
+ int ret;
+ struct rte_flow_error error;
+
+ ret = action_alloc(port_id, id, &pia);
+ if (ret)
+ return ret;
+
+ port = &ports[port_id];
+ if (queue_id >= port->queue_nb) {
+ printf("Queue #%u is invalid\n", queue_id);
+ return -EINVAL;
+ }
+
+ 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_q_action_handle_create(port_id, queue_id, &attr,
+ conf, action, &error);
+ if (!pia->handle) {
+ uint32_t destroy_id = pia->id;
+ port_queue_action_handle_destroy(port_id, queue_id,
+ drain, 1, &destroy_id);
+ return port_flow_complain(&error);
+ }
+ pia->type = action->type;
+ printf("Indirect action #%u creation queued\n", pia->id);
+ return 0;
+}
+
+/** Enqueue indirect action destroy operation*/
+int
+port_queue_action_handle_destroy(portid_t port_id,
+ uint32_t queue_id, bool drain,
+ uint32_t n, const uint32_t *actions)
+{
+ const struct rte_flow_q_ops_attr attr = { .drain = drain};
+ struct rte_port *port;
+ struct port_indirect_action **tmp;
+ uint32_t c = 0;
+ int ret = 0;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+ port_id == (portid_t)RTE_PORT_ALL)
+ return -EINVAL;
+ port = &ports[port_id];
+
+ if (queue_id >= port->queue_nb) {
+ printf("Queue #%u is invalid\n", queue_id);
+ return -EINVAL;
+ }
+
+ tmp = &port->actions_list;
+ while (*tmp) {
+ uint32_t i;
+
+ for (i = 0; i != n; ++i) {
+ struct rte_flow_error error;
+ struct port_indirect_action *pia = *tmp;
+
+ if (actions[i] != pia->id)
+ continue;
+ /*
+ * Poisoning to make sure PMDs update it in case
+ * of error.
+ */
+ memset(&error, 0x99, sizeof(error));
+
+ if (pia->handle &&
+ rte_flow_q_action_handle_destroy(port_id, queue_id,
+ &attr, pia->handle, &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)
+ tmp = &(*tmp)->next;
+ ++c;
+ }
+ return ret;
+}
+
+/** Enqueue indirect action update operation*/
+int
+port_queue_action_handle_update(portid_t port_id,
+ uint32_t queue_id, bool drain, uint32_t id,
+ const struct rte_flow_action *action)
+{
+ const struct rte_flow_q_ops_attr attr = { .drain = drain};
+ struct rte_port *port;
+ struct rte_flow_error error;
+ struct rte_flow_action_handle *action_handle;
+
+ action_handle = port_action_handle_get_by_id(port_id, id);
+ 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;
+ }
+
+ if (rte_flow_q_action_handle_update(port_id, queue_id, &attr,
+ action_handle, action, &error)) {
+ return port_flow_complain(&error);
+ }
+ printf("Indirect action #%u update queued\n", id);
+ return 0;
+}
+
/** Drain all the queue operations down the queue. */
int
port_queue_flow_drain(portid_t port_id, queueid_t queue_id)
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 3cf336dbae..eeaf1864cd 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -934,6 +934,16 @@ int port_queue_flow_create(portid_t port_id, queueid_t queue_id,
const struct rte_flow_action *actions);
int port_queue_flow_destroy(portid_t port_id, queueid_t queue_id,
bool drain, uint32_t n, const uint32_t *rule);
+int port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
+ bool drain, uint32_t id,
+ const struct rte_flow_indir_action_conf *conf,
+ const struct rte_flow_action *action);
+int port_queue_action_handle_destroy(portid_t port_id,
+ uint32_t queue_id, bool drain,
+ uint32_t n, const uint32_t *action);
+int port_queue_action_handle_update(portid_t port_id, uint32_t queue_id,
+ bool drain, uint32_t id,
+ const struct rte_flow_action *action);
int port_queue_flow_drain(portid_t port_id, queueid_t queue_id);
int port_queue_flow_dequeue(portid_t port_id, queueid_t queue_id);
int port_flow_validate(portid_t port_id,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index fff4de8f00..dfb81d56d8 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -4728,6 +4728,31 @@ port 0::
testpmd> flow indirect_action 0 create action_id \
ingress action rss queues 0 1 end / end
+Enqueueing creation of indirect actions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``flow queue indirect_action create`` adds creation operation of an indirect
+action to a queue. It is bound to ``rte_flow_q_action_handle_create()``::
+
+ flow queue {port_id} create {queue_id} [drain {boolean}]
+ table {table_id} item_template {item_template_id}
+ action_template {action_template_id}
+ pattern {item} [/ {item} [...]] / end
+ actions {action} [/ {action} [...]] / end
+
+If successful, it will show::
+
+ Indirect action #[...] creation queued
+
+Otherwise it will show an error message of the form::
+
+ Caught error type [...] ([...]): [...]
+
+This command uses the same parameters as ``flow indirect_action create``,
+described in `Creating indirect actions`_.
+
+``flow queue dequeue`` must be called to retrieve the operation status.
+
Updating indirect actions
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4757,6 +4782,25 @@ Update indirect rss action having id 100 on port 0 with rss to queues 0 and 3
testpmd> flow indirect_action 0 update 100 action rss queues 0 3 end / end
+Enqueueing update of indirect actions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``flow queue indirect_action update`` adds update operation for an indirect
+action to a queue. It is bound to ``rte_flow_q_action_handle_update()``::
+
+ flow queue {port_id} indirect_action {queue_id} update
+ {indirect_action_id} [drain {boolean}] action {action} / end
+
+If successful, it will return a flow rule ID usable with other commands::
+
+ Indirect action #[...] update queued
+
+Otherwise it will show an error message of the form::
+
+ Caught error type [...] ([...]): [...]
+
+``flow queue dequeue`` must be called to retrieve the operation status.
+
Destroying indirect actions
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -4780,6 +4824,27 @@ Destroy indirect actions having id 100 & 101::
testpmd> flow indirect_action 0 destroy action_id 100 action_id 101
+Enqueueing destruction of indirect actions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``flow queue indirect_action destroy`` adds destruction operation to destroy
+one or more indirect actions from their indirect action IDs (as returned by
+``flow queue {port_id} indirect_action {queue_id} create``) to a queue.
+It is bound to ``rte_flow_q_action_handle_destroy()``::
+
+ flow queue {port_id} indirect_action {queue_id} destroy
+ [drain {boolean}] action_id {indirect_action_id} [...]
+
+If successful, it will return a flow rule ID usable with other commands::
+
+ Indirect action #[...] destruction queued
+
+Otherwise it will show an error message of the form::
+
+ Caught error type [...] ([...]): [...]
+
+``flow queue dequeue`` must be called to retrieve the operation status.
+
Query indirect actions
~~~~~~~~~~~~~~~~~~~~~~
--
2.18.2
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-01-18 5:10 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-18 5:09 [PATCH 10/10] app/testpmd: implement rte flow queue indirect action Alexander Kozyrev
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).