]> git.droids-corp.org - dpdk.git/commitdiff
app/testpmd: add async indirect actions operations
authorAlexander Kozyrev <akozyrev@nvidia.com>
Wed, 23 Feb 2022 03:02:40 +0000 (05:02 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 24 Feb 2022 13:04:48 +0000 (14:04 +0100)
Add testpmd support for the rte_flow_async_action_handle API.
Provide the command line interface for operations dequeue.
Usage example:
  flow queue 0 indirect_action 0 create action_id 9
    ingress postpone 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>
Acked-by: Ori Kam <orika@nvidia.com>
app/test-pmd/cmdline_flow.c
app/test-pmd/config.c
app/test-pmd/testpmd.h
doc/guides/testpmd_app_ug/testpmd_funcs.rst

index d4b72724e671c3d7555bae06391e9498b8ad5273..b5f1191e55cb40e5353de6ef146a754a196d348c 100644 (file)
@@ -127,6 +127,7 @@ enum index {
        /* Queue arguments. */
        QUEUE_CREATE,
        QUEUE_DESTROY,
+       QUEUE_INDIRECT_ACTION,
 
        /* Queue create arguments. */
        QUEUE_CREATE_ID,
@@ -140,6 +141,26 @@ enum index {
        QUEUE_DESTROY_ID,
        QUEUE_DESTROY_POSTPONE,
 
+       /* 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_POSTPONE,
+       QUEUE_INDIRECT_ACTION_SPEC,
+
+       /* Queue indirect action update arguments */
+       QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
+
+       /* Queue indirect action destroy arguments */
+       QUEUE_INDIRECT_ACTION_DESTROY_ID,
+       QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
+
        /* Push arguments. */
        PUSH_QUEUE,
 
@@ -1135,6 +1156,7 @@ static const enum index next_table_destroy_attr[] = {
 static const enum index next_queue_subcmd[] = {
        QUEUE_CREATE,
        QUEUE_DESTROY,
+       QUEUE_INDIRECT_ACTION,
        ZERO,
 };
 
@@ -1144,6 +1166,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_POSTPONE,
+       QUEUE_INDIRECT_ACTION_SPEC,
+       ZERO,
+};
+
+static const enum index next_qia_update_attr[] = {
+       QUEUE_INDIRECT_ACTION_UPDATE_POSTPONE,
+       QUEUE_INDIRECT_ACTION_SPEC,
+       ZERO,
+};
+
+static const enum index next_qia_destroy_attr[] = {
+       QUEUE_INDIRECT_ACTION_DESTROY_POSTPONE,
+       QUEUE_INDIRECT_ACTION_DESTROY_ID,
+       END,
+       ZERO,
+};
+
 static const enum index next_ia_create_attr[] = {
        INDIRECT_ACTION_CREATE_ID,
        INDIRECT_ACTION_INGRESS,
@@ -2260,6 +2312,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_push(struct context *, const struct token *,
                      const char *, unsigned int,
                      void *, unsigned int);
@@ -2873,6 +2931,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_TEMPLATE_TABLE] = {
                .name = "template table",
@@ -2926,6 +2991,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_POSTPONE] = {
+               .name = "postpone",
+               .help = "postpone destroy operation",
+               .next = NEXT(next_qia_destroy_attr,
+                            NEXT_ENTRY(COMMON_BOOLEAN)),
+               .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
+       },
+       [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_POSTPONE] = {
+               .name = "postpone",
+               .help = "postpone update operation",
+               .next = NEXT(next_qia_update_attr,
+                            NEXT_ENTRY(COMMON_BOOLEAN)),
+               .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
+       },
+       /* 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_POSTPONE] = {
+               .name = "postpone",
+               .help = "postpone create operation",
+               .next = NEXT(next_qia_create_attr,
+                            NEXT_ENTRY(COMMON_BOOLEAN)),
+               .args = ARGS(ARGS_ENTRY(struct buffer, postpone)),
+       },
+       [QUEUE_INDIRECT_ACTION_SPEC] = {
+               .name = "action",
+               .help = "specify action to create indirect handle",
+               .next = NEXT(next_action),
+       },
        /* Top-level command. */
        [PUSH] = {
                .name = "push",
@@ -6501,6 +6650,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_POSTPONE:
+               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_POSTPONE:
+               return len;
+       default:
+               return -1;
+       }
+}
+
 /** Parse tokens for meter policy action commands. */
 static int
 parse_mp(struct context *ctx, const struct token *token,
@@ -10228,6 +10481,29 @@ cmd_flow_parsed(const struct buffer *in)
        case PULL:
                port_queue_flow_pull(in->port, in->queue);
                break;
+       case QUEUE_INDIRECT_ACTION_CREATE:
+               port_queue_action_handle_create(
+                               in->port, in->queue, in->postpone,
+                               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->postpone,
+                                          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->postpone,
+                                               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,
index 158d1b38a831fb5249ffea49768edc6db678635f..cc8e7aa13822efbdb66856fa7c41e1c6ee3909f8 100644 (file)
@@ -2598,6 +2598,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 postpone, uint32_t id,
+                               const struct rte_flow_indir_action_conf *conf,
+                               const struct rte_flow_action *action)
+{
+       const struct rte_flow_op_attr attr = { .postpone = postpone};
+       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_async_action_handle_create(port_id, queue_id,
+                                       &attr, conf, action, NULL, &error);
+       if (!pia->handle) {
+               uint32_t destroy_id = pia->id;
+               port_queue_action_handle_destroy(port_id, queue_id,
+                                                postpone, 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 postpone,
+                                uint32_t n, const uint32_t *actions)
+{
+       const struct rte_flow_op_attr attr = { .postpone = postpone};
+       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_async_action_handle_destroy(port_id,
+                               queue_id, &attr, pia->handle, NULL, &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 postpone, uint32_t id,
+                               const struct rte_flow_action *action)
+{
+       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;
+
+       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_async_action_handle_update(port_id, queue_id, &attr,
+                                   action_handle, action, NULL, &error)) {
+               return port_flow_complain(&error);
+       }
+       printf("Indirect action #%u update queued\n", id);
+       return 0;
+}
+
 /** Push all the queue operations in the queue to the NIC. */
 int
 port_queue_flow_push(portid_t port_id, queueid_t queue_id)
index 5ea2408a0b238b4ec0bcf0c195c1f3d4819b5d55..31f766c96557fcbb0da142fbafbfb64d859b964a 100644 (file)
@@ -940,6 +940,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 postpone, uint32_t n, const uint32_t *rule);
+int port_queue_action_handle_create(portid_t port_id, uint32_t queue_id,
+                       bool postpone, 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 postpone,
+                                    uint32_t n, const uint32_t *action);
+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_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,
index 5080ddb256fec6019540b90c639c5bff24f01262..1083c6d5381d90a9b318447992fd4ec82e8c568b 100644 (file)
@@ -4792,6 +4792,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_async_action_handle_create()``::
+
+   flow queue {port_id} create {queue_id} [postpone {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 pull`` must be called to retrieve the operation status.
+
 Updating indirect actions
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -4821,6 +4846,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_async_action_handle_update()``::
+
+   flow queue {port_id} indirect_action {queue_id} update
+      {indirect_action_id} [postpone {boolean}] action {action} / end
+
+If successful, it will show::
+
+   Indirect action #[...] update 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.
+
 Destroying indirect actions
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -4844,6 +4888,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_async_action_handle_destroy()``::
+
+   flow queue {port_id} indirect_action {queue_id} destroy
+      [postpone {boolean}] action_id {indirect_action_id} [...]
+
+If successful, it will show::
+
+   Indirect action #[...] destruction 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.
+
 Query indirect actions
 ~~~~~~~~~~~~~~~~~~~~~~