DPDK patches and discussions
 help / color / mirror / Atom feed
From: Ajit Khaparde <ajit.khaparde@broadcom.com>
To: Andrey Vesnovaty <andreyv@nvidia.com>
Cc: dpdk-dev <dev@dpdk.org>,
	jer@marvell.com, Jerin Jacob <jerinjacobk@gmail.com>,
	 Thomas Monjalon <thomas@monjalon.net>,
	Ferruh Yigit <ferruh.yigit@intel.com>,
	 Stephen Hemminger <stephen@networkplumber.org>,
	Bruce Richardson <bruce.richardson@intel.com>,
	 Ori Kam <orika@nvidia.com>,
	Slava Ovsiienko <viacheslavo@nvidia.com>,
	andrey.vesnovaty@gmail.com,  Ray Kinsella <mdr@ashroe.eu>,
	Neil Horman <nhorman@tuxdriver.com>,
	 Samik Gupta <samik.gupta@broadcom.com>,
	Wenzhuo Lu <wenzhuo.lu@intel.com>,
	 Beilei Xing <beilei.xing@intel.com>,
	Bernard Iremonger <bernard.iremonger@intel.com>
Subject: Re: [dpdk-dev] [PATCH v7 2/2] app/testpmd: support shared action
Date: Thu, 8 Oct 2020 16:54:49 -0700
Message-ID: <CACZ4nhu87e3YDn4C0aC0AWybYT4ORVjDnPOH=qYMo=48qkdoCA@mail.gmail.com> (raw)
In-Reply-To: <20201008115143.13208-3-andreyv@nvidia.com>

On Thu, Oct 8, 2020 at 4:51 AM Andrey Vesnovaty <andreyv@nvidia.com> wrote:
>
> This patch adds shared action support to testpmd CLI.
>
> All shared actions created via testpmd CLI assigned ID for further
> reference in other CLI commands. Shared action ID supplied as CLI
> argument or assigned by testpmd is similar to flow ID & limited to
> scope of testpdm CLI.
>
> Create shared action syntax:
> flow shared_action {port_id} create [action_id {shared_action_id}]
>         [ingress] [egress] action {action} / end
>
> Create shared action examples:
>         flow shared_action 0 create action_id 100 \
>                 ingress action rss queues 1 2 end / end
>         This creates shared rss action with id 100 on port 0.
>
>         flow shared_action 0 create action_id \
>                 ingress action rss queues 0 1 end / end
>         This creates shared rss action with id assigned by testpmd
>         on port 0.
>
> Update shared action syntax:
> flow shared_action {port_id} update {shared_action_id}
>         action {action} / end
>
> Update shared action example:
>         flow shared_action 0 update 100 \
>                 action rss queues 0 3 end / end
>         This updates shared rss action having id 100 on port 0
>         with rss to queues 0 3 (in create example rss queues were
>         1 & 2).
>
> Destroy shared action syntax:
> flow shared_action {port_id} destroy action_id {shared_action_id} [...]
>
> Destroy shared action example:
>         flow shared_action 0 destroy action_id 100 action_id 101
>         This destroys shared actions having id 100 & 101
>
> Query shared action syntax:
> flow shared_action {port} query {shared_action_id}
>
> Query shared action example:
>         flow shared_action 0 query 100
>         This queries shared actions having id 100
>
> Use shared action as flow action syntax:
> flow create {port_id} ... / end actions [action / [...]]
>         shared {action_id} / [action / [...]] end
>
> Use shared action as flow action example:
>         flow create 0 ingress pattern ... / end \
>                 actions shared 100 / end
>         This creates flow rule where rss action is shared rss action
>         having id 100.
>
> All shared action CLIs report status of the command.
> Shared action query CLI output depends on action type.
>
> Signed-off-by: Andrey Vesnovaty <andreyv@nvidia.com>
> Acked-by: Ori Kam <orika@nvidia.com>
Acked-by: Ajit Khaparde <ajit.khaparde@broadcom.com>

> ---
>  app/test-pmd/cmdline.c                      |  18 ++
>  app/test-pmd/cmdline_flow.c                 | 294 +++++++++++++++++++-
>  app/test-pmd/config.c                       | 216 ++++++++++++++
>  app/test-pmd/testpmd.h                      |  20 ++
>  doc/guides/testpmd_app_ug/testpmd_funcs.rst | 112 ++++++++
>  5 files changed, 659 insertions(+), 1 deletion(-)
>
> diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c
> index 524c75b267..32ba08a590 100644
> --- a/app/test-pmd/cmdline.c
> +++ b/app/test-pmd/cmdline.c
> @@ -1143,6 +1143,24 @@ static void cmd_help_long_parsed(void *parsed_result,
>                         "    List and destroy aged flows"
>                         " flow rules\n\n"
>
> +                       "flow shared_action {port_id} create"
> +                       " [action_id {shared_action_id}]"
> +                       " [ingress] [egress]"
> +                       " action {action} / end\n"
> +                       "    Create shared action.\n\n"
> +
> +                       "flow shared_action {port_id} update"
> +                       " {shared_action_id} action {action} / end\n"
> +                       "    Update shared action.\n\n"
> +
> +                       "flow shared_action {port_id} destroy"
> +                       " action_id {shared_action_id} [...]\n"
> +                       "    Destroy specific shared actions.\n\n"
> +
> +                       "flow shared_action {port_id} query"
> +                       " {shared_action_id}\n"
> +                       "    Query an existing shared action.\n\n"
> +
>                         "set vxlan ip-version (ipv4|ipv6) vni (vni) udp-src"
>                         " (udp-src) udp-dst (udp-dst) ip-src (ip-src) ip-dst"
>                         " (ip-dst) eth-src (eth-src) eth-dst (eth-dst)\n"
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index 6e04d538ea..ff6b188a6d 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -49,6 +49,7 @@ enum index {
>         PORT_ID,
>         GROUP_ID,
>         PRIORITY_LEVEL,
> +       SHARED_ACTION_ID,
>
>         /* Top-level command. */
>         SET,
> @@ -60,6 +61,7 @@ enum index {
>         /* Top-level command. */
>         FLOW,
>         /* Sub-level commands. */
> +       SHARED_ACTION,
>         VALIDATE,
>         CREATE,
>         DESTROY,
> @@ -89,6 +91,21 @@ enum index {
>         EGRESS,
>         TRANSFER,
>
> +       /* Shared action arguments */
> +       SHARED_ACTION_CREATE,
> +       SHARED_ACTION_UPDATE,
> +       SHARED_ACTION_DESTROY,
> +       SHARED_ACTION_QUERY,
> +
> +       /* Shared action create arguments */
> +       SHARED_ACTION_CREATE_ID,
> +       SHARED_ACTION_INGRESS,
> +       SHARED_ACTION_EGRESS,
> +       SHARED_ACTION_SPEC,
> +
> +       /* Shared action destroy arguments */
> +       SHARED_ACTION_DESTROY_ID,
> +
>         /* Validate/create pattern. */
>         PATTERN,
>         ITEM_PARAM_IS,
> @@ -360,6 +377,8 @@ enum index {
>         ACTION_SET_IPV6_DSCP_VALUE,
>         ACTION_AGE,
>         ACTION_AGE_TIMEOUT,
> +       ACTION_SHARED,
> +       SHARED_ACTION_ID2PTR,
>  };
>
>  /** Maximum size for pattern in struct rte_flow_item_raw. */
> @@ -653,6 +672,13 @@ struct buffer {
>         enum index command; /**< Flow command. */
>         portid_t port; /**< Affected port ID. */
>         union {
> +               struct {
> +                       uint32_t *action_id;
> +                       uint32_t action_id_n;
> +               } sa_destroy; /**< Shared action destroy arguments. */
> +               struct {
> +                       uint32_t action_id;
> +               } sa; /* Shared action query arguments */
>                 struct {
>                         struct rte_flow_attr attr;
>                         struct rte_flow_item *pattern;
> @@ -709,6 +735,22 @@ struct parse_action_priv {
>                 .size = s, \
>         })
>
> +static const enum index next_sa_create_attr[] = {
> +       SHARED_ACTION_CREATE_ID,
> +       SHARED_ACTION_INGRESS,
> +       SHARED_ACTION_EGRESS,
> +       SHARED_ACTION_SPEC,
> +       ZERO,
> +};
> +
> +static const enum index next_sa_subcmd[] = {
> +       SHARED_ACTION_CREATE,
> +       SHARED_ACTION_UPDATE,
> +       SHARED_ACTION_DESTROY,
> +       SHARED_ACTION_QUERY,
> +       ZERO,
> +};
> +
>  static const enum index next_vc_attr[] = {
>         GROUP,
>         PRIORITY,
> @@ -743,6 +785,12 @@ static const enum index next_aged_attr[] = {
>         ZERO,
>  };
>
> +static const enum index next_sa_destroy_attr[] = {
> +       SHARED_ACTION_DESTROY_ID,
> +       END,
> +       ZERO,
> +};
> +
>  static const enum index item_param[] = {
>         ITEM_PARAM_IS,
>         ITEM_PARAM_SPEC,
> @@ -1193,6 +1241,7 @@ static const enum index next_action[] = {
>         ACTION_SET_IPV4_DSCP,
>         ACTION_SET_IPV6_DSCP,
>         ACTION_AGE,
> +       ACTION_SHARED,
>         ZERO,
>  };
>
> @@ -1550,6 +1599,15 @@ static int parse_ipv6_addr(struct context *, const struct token *,
>  static int parse_port(struct context *, const struct token *,
>                       const char *, unsigned int,
>                       void *, unsigned int);
> +static int parse_sa(struct context *, const struct token *,
> +                   const char *, unsigned int,
> +                   void *, unsigned int);
> +static int parse_sa_destroy(struct context *ctx, const struct token *token,
> +                           const char *str, unsigned int len,
> +                           void *buf, unsigned int size);
> +static int parse_sa_id2ptr(struct context *ctx, const struct token *token,
> +                          const char *str, unsigned int len, void *buf,
> +                          unsigned int size);
>  static int comp_none(struct context *, const struct token *,
>                      unsigned int, char *, unsigned int);
>  static int comp_boolean(struct context *, const struct token *,
> @@ -1688,13 +1746,21 @@ static const struct token token_list[] = {
>                 .call = parse_int,
>                 .comp = comp_none,
>         },
> +       [SHARED_ACTION_ID] = {
> +               .name = "{shared_action_id}",
> +               .type = "SHARED_ACTION_ID",
> +               .help = "shared action id",
> +               .call = parse_int,
> +               .comp = comp_none,
> +       },
>         /* Top-level command. */
>         [FLOW] = {
>                 .name = "flow",
>                 .type = "{command} {port_id} [{arg} [...]]",
>                 .help = "manage ingress/egress flow rules",
>                 .next = NEXT(NEXT_ENTRY
> -                            (VALIDATE,
> +                            (SHARED_ACTION,
> +                             VALIDATE,
>                               CREATE,
>                               DESTROY,
>                               FLUSH,
> @@ -1705,7 +1771,44 @@ static const struct token token_list[] = {
>                               ISOLATE)),
>                 .call = parse_init,
>         },
> +       /* Top-level command. */
> +       [SHARED_ACTION] = {
> +               .name = "shared_action",
> +               .type = "{command} {port_id} [{arg} [...]]",
> +               .help = "manage shared actions",
> +               .next = NEXT(next_sa_subcmd, NEXT_ENTRY(PORT_ID)),
> +               .args = ARGS(ARGS_ENTRY(struct buffer, port)),
> +               .call = parse_sa,
> +       },
>         /* Sub-level commands. */
> +       [SHARED_ACTION_CREATE] = {
> +               .name = "create",
> +               .help = "create shared action",
> +               .next = NEXT(next_sa_create_attr),
> +               .call = parse_sa,
> +       },
> +       [SHARED_ACTION_UPDATE] = {
> +               .name = "update",
> +               .help = "update shared action",
> +               .next = NEXT(NEXT_ENTRY(SHARED_ACTION_SPEC),
> +                            NEXT_ENTRY(SHARED_ACTION_ID)),
> +               .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
> +               .call = parse_sa,
> +       },
> +       [SHARED_ACTION_DESTROY] = {
> +               .name = "destroy",
> +               .help = "destroy shared action",
> +               .next = NEXT(NEXT_ENTRY(SHARED_ACTION_DESTROY_ID)),
> +               .args = ARGS(ARGS_ENTRY(struct buffer, port)),
> +               .call = parse_sa_destroy,
> +       },
> +       [SHARED_ACTION_QUERY] = {
> +               .name = "query",
> +               .help = "query shared action",
> +               .next = NEXT(NEXT_ENTRY(END), NEXT_ENTRY(SHARED_ACTION_ID)),
> +               .args = ARGS(ARGS_ENTRY(struct buffer, args.sa.action_id)),
> +               .call = parse_sa,
> +       },
>         [VALIDATE] = {
>                 .name = "validate",
>                 .help = "check whether a flow rule can be created",
> @@ -3859,6 +3962,57 @@ static const struct token token_list[] = {
>                 .next = NEXT(action_age, NEXT_ENTRY(UNSIGNED)),
>                 .call = parse_vc_conf,
>         },
> +       /* Shared action destroy arguments. */
> +       [SHARED_ACTION_DESTROY_ID] = {
> +               .name = "action_id",
> +               .help = "specify a shared action id to destroy",
> +               .next = NEXT(next_sa_destroy_attr,
> +                            NEXT_ENTRY(SHARED_ACTION_ID)),
> +               .args = ARGS(ARGS_ENTRY_PTR(struct buffer,
> +                                           args.sa_destroy.action_id)),
> +               .call = parse_sa_destroy,
> +       },
> +       /* Shared action create arguments. */
> +       [SHARED_ACTION_CREATE_ID] = {
> +               .name = "action_id",
> +               .help = "specify a shared action id to create",
> +               .next = NEXT(next_sa_create_attr,
> +                            NEXT_ENTRY(SHARED_ACTION_ID)),
> +               .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
> +       },
> +       [ACTION_SHARED] = {
> +               .name = "shared",
> +               .help = "apply shared action by id",
> +               .priv = PRIV_ACTION(SHARED, 0),
> +               .next = NEXT(NEXT_ENTRY(SHARED_ACTION_ID2PTR)),
> +               .args = ARGS(ARGS_ENTRY_ARB(0, sizeof(uint32_t))),
> +               .call = parse_vc,
> +       },
> +       [SHARED_ACTION_ID2PTR] = {
> +               .name = "{action_id}",
> +               .type = "SHARED_ACTION_ID",
> +               .help = "shared action id",
> +               .next = NEXT(NEXT_ENTRY(ACTION_NEXT)),
> +               .call = parse_sa_id2ptr,
> +               .comp = comp_none,
> +       },
> +       [SHARED_ACTION_INGRESS] = {
> +               .name = "ingress",
> +               .help = "affect rule to ingress",
> +               .next = NEXT(next_sa_create_attr),
> +               .call = parse_sa,
> +       },
> +       [SHARED_ACTION_EGRESS] = {
> +               .name = "egress",
> +               .help = "affect rule to egress",
> +               .next = NEXT(next_sa_create_attr),
> +               .call = parse_sa,
> +       },
> +       [SHARED_ACTION_SPEC] = {
> +               .name = "action",
> +               .help = "specify action to share",
> +               .next = NEXT(next_action),
> +       },
>  };
>
>  /** Remove and return last entry from argument stack. */
> @@ -4043,6 +4197,97 @@ parse_init(struct context *ctx, const struct token *token,
>         return len;
>  }
>
> +/** Parse tokens for shared action commands. */
> +static int
> +parse_sa(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 != SHARED_ACTION)
> +                       return -1;
> +               if (sizeof(*out) > size)
> +                       return -1;
> +               out->command = ctx->curr;
> +               ctx->objdata = 0;
> +               ctx->object = out;
> +               ctx->objmask = NULL;
> +               out->args.vc.data = (uint8_t *)out + size;
> +               return len;
> +       }
> +       switch (ctx->curr) {
> +       case SHARED_ACTION_CREATE:
> +       case SHARED_ACTION_UPDATE:
> +               out->args.vc.actions =
> +                       (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
> +                                              sizeof(double));
> +               out->args.vc.attr.group = UINT32_MAX;
> +               /* fallthrough */
> +       case SHARED_ACTION_QUERY:
> +               out->command = ctx->curr;
> +               ctx->objdata = 0;
> +               ctx->object = out;
> +               ctx->objmask = NULL;
> +               return len;
> +       case SHARED_ACTION_EGRESS:
> +               out->args.vc.attr.egress = 1;
> +               return len;
> +       case SHARED_ACTION_INGRESS:
> +               out->args.vc.attr.ingress = 1;
> +               return len;
> +       default:
> +               return -1;
> +       }
> +}
> +
> +
> +/** Parse tokens for shared action destroy command. */
> +static int
> +parse_sa_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 == SHARED_ACTION) {
> +               if (ctx->curr != SHARED_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.sa_destroy.action_id =
> +                       (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
> +                                              sizeof(double));
> +               return len;
> +       }
> +       action_id = out->args.sa_destroy.action_id
> +                   + out->args.sa_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;
> +}
> +
>  /** Parse tokens for validate/create commands. */
>  static int
>  parse_vc(struct context *ctx, const struct token *token,
> @@ -6110,6 +6355,32 @@ parse_port(struct context *ctx, const struct token *token,
>         return ret;
>  }
>
> +static int
> +parse_sa_id2ptr(struct context *ctx, const struct token *token,
> +               const char *str, unsigned int len,
> +               void *buf, unsigned int size)
> +{
> +       struct rte_flow_action *action = ctx->object;
> +       uint32_t id;
> +       int ret;
> +
> +       (void)buf;
> +       (void)size;
> +       ctx->objdata = 0;
> +       ctx->object = &id;
> +       ctx->objmask = NULL;
> +       ret = parse_int(ctx, token, str, len, ctx->object, sizeof(id));
> +       ctx->object = action;
> +       if (ret != (int)len)
> +               return ret;
> +       /* set shared action */
> +       if (action) {
> +               action->conf = port_shared_action_get_by_id(ctx->port, id);
> +               ret = (action->conf) ? ret : -1;
> +       }
> +       return ret;
> +}
> +
>  /** Parse set command, initialize output buffer for subsequent tokens. */
>  static int
>  parse_set_raw_encap_decap(struct context *ctx, const struct token *token,
> @@ -6559,6 +6830,27 @@ static void
>  cmd_flow_parsed(const struct buffer *in)
>  {
>         switch (in->command) {
> +       case SHARED_ACTION_CREATE:
> +               port_shared_action_create(
> +                               in->port, in->args.vc.attr.group,
> +                               &((const struct rte_flow_shared_action_conf) {
> +                                       .ingress = in->args.vc.attr.ingress,
> +                                       .egress = in->args.vc.attr.egress,
> +                               }),
> +                               in->args.vc.actions);
> +               break;
> +       case SHARED_ACTION_DESTROY:
> +               port_shared_action_destroy(in->port,
> +                                          in->args.sa_destroy.action_id_n,
> +                                          in->args.sa_destroy.action_id);
> +               break;
> +       case SHARED_ACTION_UPDATE:
> +               port_shared_action_update(in->port, in->args.vc.attr.group,
> +                                         in->args.vc.actions);
> +               break;
> +       case SHARED_ACTION_QUERY:
> +               port_shared_action_query(in->port, in->args.sa.action_id);
> +               break;
>         case VALIDATE:
>                 port_flow_validate(in->port, &in->args.vc.attr,
>                                    in->args.vc.pattern, in->args.vc.actions);
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
> index 418ea6dda4..89b5721d6f 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -1580,6 +1580,222 @@ rss_config_display(struct rte_flow_action_rss *rss_conf)
>         }
>  }
>
> +static struct port_shared_action *
> +action_get_by_id(portid_t port_id, uint32_t id)
> +{
> +       struct rte_port *port;
> +       struct port_shared_action **ppsa;
> +       struct port_shared_action *psa = NULL;
> +
> +       if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +           port_id == (portid_t)RTE_PORT_ALL)
> +               return NULL;
> +       port = &ports[port_id];
> +       ppsa = &port->actions_list;
> +       while (*ppsa) {
> +               if ((*ppsa)->id == id) {
> +                       psa = *ppsa;
> +                       break;
> +               }
> +               ppsa = &(*ppsa)->next;
> +       }
> +       if (!psa)
> +               printf("Failed to find shared action #%u on port %u\n",
> +                      id, port_id);
> +       return psa;
> +}
> +
> +static int
> +action_alloc(portid_t port_id, uint32_t id,
> +            struct port_shared_action **action)
> +{
> +       struct rte_port *port;
> +       struct port_shared_action **ppsa;
> +       struct port_shared_action *psa = NULL;
> +
> +       *action = NULL;
> +       if (port_id_is_invalid(port_id, ENABLED_WARN) ||
> +           port_id == (portid_t)RTE_PORT_ALL)
> +               return -EINVAL;
> +       port = &ports[port_id];
> +       if (id == UINT32_MAX) {
> +               /* taking first available ID */
> +               if (port->actions_list) {
> +                       if (port->actions_list->id == UINT32_MAX - 1) {
> +                               printf("Highest shared action ID is already"
> +                               " assigned, delete it first\n");
> +                               return -ENOMEM;
> +                       }
> +                       id = port->actions_list->id + 1;
> +               } else {
> +                       id = 0;
> +               }
> +       }
> +       psa = calloc(1, sizeof(*psa));
> +       if (!psa) {
> +               printf("Allocation of port %u shared action failed\n",
> +                      port_id);
> +               return -ENOMEM;
> +       }
> +       ppsa = &port->actions_list;
> +       while (*ppsa && (*ppsa)->id > id)
> +               ppsa = &(*ppsa)->next;
> +       if (*ppsa && (*ppsa)->id == id) {
> +               printf("Shared action #%u is already assigned,"
> +                       " delete it first\n", id);
> +               free(psa);
> +               return -EINVAL;
> +       }
> +       psa->next = *ppsa;
> +       psa->id = id;
> +       *ppsa = psa;
> +       *action = psa;
> +       return 0;
> +}
> +
> +/** Create shared action */
> +int
> +port_shared_action_create(portid_t port_id, uint32_t id,
> +                         const struct rte_flow_shared_action_conf *conf,
> +                         const struct rte_flow_action *action)
> +{
> +       struct port_shared_action *psa;
> +       int ret;
> +       struct rte_flow_error error;
> +
> +       ret = action_alloc(port_id, id, &psa);
> +       if (ret)
> +               return ret;
> +       /* Poisoning to make sure PMDs update it in case of error. */
> +       memset(&error, 0x22, sizeof(error));
> +       psa->action = rte_flow_shared_action_create(port_id, conf, action,
> +                                                   &error);
> +       if (!psa->action) {
> +               uint32_t destroy_id = psa->id;
> +               port_shared_action_destroy(port_id, 1, &destroy_id);
> +               return port_flow_complain(&error);
> +       }
> +       psa->type = action->type;
> +       printf("Shared action #%u created\n", psa->id);
> +       return 0;
> +}
> +
> +/** Destroy shared action */
> +int
> +port_shared_action_destroy(portid_t port_id,
> +                          uint32_t n,
> +                          const uint32_t *actions)
> +{
> +       struct rte_port *port;
> +       struct port_shared_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];
> +       tmp = &port->actions_list;
> +       while (*tmp) {
> +               uint32_t i;
> +
> +               for (i = 0; i != n; ++i) {
> +                       struct rte_flow_error error;
> +                       struct port_shared_action *psa = *tmp;
> +
> +                       if (actions[i] != psa->id)
> +                               continue;
> +                       /*
> +                        * Poisoning to make sure PMDs update it in case
> +                        * of error.
> +                        */
> +                       memset(&error, 0x33, sizeof(error));
> +
> +                       if (psa->action && rte_flow_shared_action_destroy(
> +                                       port_id, psa->action, &error)) {
> +                               ret = port_flow_complain(&error);
> +                               continue;
> +                       }
> +                       *tmp = psa->next;
> +                       free(psa);
> +                       printf("Shared action #%u destroyed\n", psa->id);
> +                       break;
> +               }
> +               if (i == n)
> +                       tmp = &(*tmp)->next;
> +               ++c;
> +       }
> +       return ret;
> +}
> +
> +
> +/** Get shared action by port + id */
> +struct rte_flow_shared_action *
> +port_shared_action_get_by_id(portid_t port_id, uint32_t id)
> +{
> +
> +       struct port_shared_action *psa = action_get_by_id(port_id, id);
> +
> +       return (psa) ? psa->action : NULL;
> +}
> +
> +/** Update shared action */
> +int
> +port_shared_action_update(portid_t port_id, uint32_t id,
> +                         const struct rte_flow_action *action)
> +{
> +       struct rte_flow_error error;
> +       struct rte_flow_shared_action *shared_action;
> +
> +       shared_action = port_shared_action_get_by_id(port_id, id);
> +       if (!shared_action)
> +               return -EINVAL;
> +       if (rte_flow_shared_action_update(port_id, shared_action, action,
> +                                         &error)) {
> +               return port_flow_complain(&error);
> +       }
> +       printf("Shared action #%u updated\n", id);
> +       return 0;
> +}
> +
> +int
> +port_shared_action_query(portid_t port_id, uint32_t id)
> +{
> +       struct rte_flow_error error;
> +       struct port_shared_action *psa;
> +       uint64_t default_data;
> +       void *data = NULL;
> +       int ret = 0;
> +
> +       psa = action_get_by_id(port_id, id);
> +       if (!psa)
> +               return -EINVAL;
> +       switch (psa->type) {
> +       case RTE_FLOW_ACTION_TYPE_RSS:
> +               data = &default_data;
> +               break;
> +       default:
> +               printf("Shared action %u (type: %d) on port %u doesn't support"
> +                      " query\n", id, psa->type, port_id);
> +               return -1;
> +       }
> +       if (rte_flow_shared_action_query(port_id, psa->action, data, &error))
> +               ret = port_flow_complain(&error);
> +       switch (psa->type) {
> +       case RTE_FLOW_ACTION_TYPE_RSS:
> +               if (!ret)
> +                       printf("Shared RSS action:\n\trefs:%u\n",
> +                              *((uint32_t *)data));
> +               data = NULL;
> +               break;
> +       default:
> +               printf("Shared action %u (type: %d) on port %u doesn't support"
> +                      " query\n", id, psa->type, port_id);
> +               ret = -1;
> +       }
> +       return ret;
> +}
> +
>  /** Validate flow rule. */
>  int
>  port_flow_validate(portid_t port_id,
> diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
> index c7e7e41a97..f26e0aad03 100644
> --- a/app/test-pmd/testpmd.h
> +++ b/app/test-pmd/testpmd.h
> @@ -142,6 +142,14 @@ struct port_flow {
>         uint8_t data[]; /**< Storage for flow rule description */
>  };
>
> +/* Descriptor for shared action */
> +struct port_shared_action {
> +       struct port_shared_action *next; /**< Next flow in list. */
> +       uint32_t id; /**< Shared action ID. */
> +       enum rte_flow_action_type type; /**< Action type. */
> +       struct rte_flow_shared_action *action;  /**< Shared action handle. */
> +};
> +
>  /**
>   * The data structure associated with each port.
>   */
> @@ -172,6 +180,8 @@ struct rte_port {
>         uint32_t                mc_addr_nb; /**< nb. of addr. in mc_addr_pool */
>         uint8_t                 slave_flag; /**< bonding slave port */
>         struct port_flow        *flow_list; /**< Associated flows. */
> +       struct port_shared_action *actions_list;
> +       /**< Associated shared actions. */
>         const struct rte_eth_rxtx_callback *rx_dump_cb[RTE_MAX_QUEUES_PER_PORT+1];
>         const struct rte_eth_rxtx_callback *tx_dump_cb[RTE_MAX_QUEUES_PER_PORT+1];
>         /**< metadata value to insert in Tx packets. */
> @@ -748,6 +758,15 @@ void port_reg_bit_field_set(portid_t port_id, uint32_t reg_off,
>                             uint8_t bit1_pos, uint8_t bit2_pos, uint32_t value);
>  void port_reg_display(portid_t port_id, uint32_t reg_off);
>  void port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t value);
> +int port_shared_action_create(portid_t port_id, uint32_t id,
> +                             const struct rte_flow_shared_action_conf *conf,
> +                             const struct rte_flow_action *action);
> +int port_shared_action_destroy(portid_t port_id,
> +                              uint32_t n, const uint32_t *action);
> +struct rte_flow_shared_action *port_shared_action_get_by_id(portid_t port_id,
> +                                                           uint32_t id);
> +int port_shared_action_update(portid_t port_id, uint32_t id,
> +                             const struct rte_flow_action *action);
>  int port_flow_validate(portid_t port_id,
>                        const struct rte_flow_attr *attr,
>                        const struct rte_flow_item *pattern,
> @@ -756,6 +775,7 @@ int port_flow_create(portid_t port_id,
>                      const struct rte_flow_attr *attr,
>                      const struct rte_flow_item *pattern,
>                      const struct rte_flow_action *actions);
> +int port_shared_action_query(portid_t port_id, uint32_t id);
>  void update_age_action_context(const struct rte_flow_action *actions,
>                      struct port_flow *pf);
>  int port_flow_destroy(portid_t port_id, uint32_t n, const uint32_t *rule);
> diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> index 72bdb1be43..e912c5b54b 100644
> --- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> +++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
> @@ -4382,6 +4382,11 @@ This section lists supported actions and their attributes, if any.
>
>    - ``dscp_value {unsigned}``: The new DSCP value to be set
>
> +- ``shared``: Use shared action created via
> +  ``flow shared_action {port_id} create``
> +
> +  - ``shared_action_id {unsigned}``: Shared action ID to use
> +
>  Destroying flow rules
>  ~~~~~~~~~~~~~~~~~~~~~
>
> @@ -4671,6 +4676,113 @@ If attach ``destroy`` parameter, the command will destroy all the list aged flow
>     testpmd> flow aged 0
>     Port 0 total aged flows: 0
>
> +Creating shared actions
> +~~~~~~~~~~~~~~~~~~~~~~~
> +``flow shared_action {port_id} create`` creates shared action with optional
> +shared action ID. It is bound to ``rte_flow_shared_action_create()``::
> +
> +   flow shared_action {port_id} create [action_id {shared_action_id}]
> +      [ingress] [egress] action {action} / end
> +
> +If successful, it will show::
> +
> +   Shared action #[...] created
> +
> +Otherwise, it will complain either that shared action already exists or that
> +some error occurred::
> +
> +   Shared action #[...] is already assigned, delete it first
> +
> +::
> +
> +   Caught error type [...] ([...]): [...]
> +
> +Create shared rss action with id 100 to queues 1 and 2 on port 0::
> +
> +   testpmd> flow shared_action 0 create action_id 100 \
> +      ingress action rss queues 1 2 end / end
> +
> +Create shared rss action with id assigned by testpmd to queues 1 and 2 on
> +port 0::
> +
> +       testpmd> flow shared_action 0 create action_id \
> +               ingress action rss queues 0 1 end / end
> +
> +Updating shared actions
> +~~~~~~~~~~~~~~~~~~~~~~~
> +``flow shared_action {port_id} update`` updates configuration of the shared
> +action from its shared action ID (as returned by
> +``flow shared_action {port_id} create``). It is bound to
> +``rte_flow_shared_action_update()``::
> +
> +   flow shared_action {port_id} update {shared_action_id}
> +      action {action} / end
> +
> +If successful, it will show::
> +
> +   Shared action #[...] updated
> +
> +Otherwise, it will complain either that shared action not found or that some
> +error occurred::
> +
> +   Failed to find shared action #[...] on port [...]
> +
> +::
> +
> +   Caught error type [...] ([...]): [...]
> +
> +Update shared rss action having id 100 on port 0 with rss to queues 0 and 3
> +(in create example above rss queues were 1 and 2)::
> +
> +   testpmd> flow shared_action 0 update 100 action rss queues 0 3 end / end
> +
> +Destroying shared actions
> +~~~~~~~~~~~~~~~~~~~~~~~~~
> +``flow shared_action {port_id} update`` destroys one or more shared actions
> +from their shared action IDs (as returned by
> +``flow shared_action {port_id} create``). It is bound to
> +``rte_flow_shared_action_destroy()``::
> +
> +   flow shared_action {port_id} destroy action_id {shared_action_id} [...]
> +
> +If successful, it will show::
> +
> +   Shared action #[...] destroyed
> +
> +It does not report anything for shared action IDs that do not exist.
> +The usual error message is shown when a shared action cannot be destroyed::
> +
> +   Caught error type [...] ([...]): [...]
> +
> +Destroy shared actions having id 100 & 101::
> +
> +   testpmd> flow shared_action 0 destroy action_id 100 action_id 101
> +
> +Query shared actions
> +~~~~~~~~~~~~~~~~~~~~
> +``flow shared_action {port_id} query`` queries the shared action from its
> +shared action ID (as returned by ``flow shared_action {port_id} create``).
> +It is bound to ``rte_flow_shared_action_query()``::
> +
> +  flow shared_action {port_id} query {shared_action_id}
> +
> +Currently only rss shared action supported. If successful, it will show::
> +
> +   Shared RSS action:
> +      refs:[...]
> +
> +Otherwise, it will complain either that shared action not found or that some
> +error occurred::
> +
> +   Failed to find shared action #[...] on port [...]
> +
> +::
> +
> +   Caught error type [...] ([...]): [...]
> +
> +Query shared action having id 100::
> +
> +   testpmd> flow shared_action 0 query 100
>
>  Sample QinQ flow rules
>  ~~~~~~~~~~~~~~~~~~~~~~
> --
> 2.26.2
>

  reply	other threads:[~2020-10-08 23:55 UTC|newest]

Thread overview: 106+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-02 12:05 [dpdk-dev] [PATCH] add flow shared action API Andrey Vesnovaty
2020-07-03 15:02 ` Jerin Jacob
2020-07-03 15:21   ` Thomas Monjalon
2020-07-04  9:54     ` Andrey Vesnovaty
2020-07-04 10:10   ` Andrey Vesnovaty
2020-07-04 12:33     ` Jerin Jacob
2020-07-05 10:26       ` Ori Kam
2020-07-06  9:00         ` Jerin Jacob
2020-07-06 12:28           ` Ori Kam
2020-07-06 13:32             ` Andrey Vesnovaty
2020-07-07  2:30               ` Jerin Jacob
2020-07-07  6:21                 ` Ori Kam
2020-07-07 15:21                   ` Ferruh Yigit
2020-07-07 17:24                     ` Ori Kam
2020-07-07 17:52                       ` Ferruh Yigit
2020-07-07 19:38                   ` Jerin Jacob
2020-07-07 21:03                     ` Ori Kam
2020-07-08  9:25                       ` Jerin Jacob
2020-07-08  9:47                         ` Ori Kam
2020-07-08 11:00                           ` Jerin Jacob
2020-07-08 11:50                             ` Thomas Monjalon
2020-07-08 12:18                             ` Ori Kam
     [not found]                               ` <20200708204015.24429-2-andreyv@mellanox.com>
2020-07-13  8:04                                 ` [dpdk-dev] [PATCH v2 1/6] ethdev: " Kinsella, Ray
2020-07-13 10:16                                   ` Andrew Rybchenko
2020-07-15  8:54                                   ` Andrew Rybchenko
2020-07-15  9:00                                     ` Andrew Rybchenko
2020-09-15 11:30                                     ` Andrey Vesnovaty
     [not found]                               ` <20200708204015.24429-3-andreyv@mellanox.com>
2020-07-13  8:06                                 ` [dpdk-dev] [PATCH v2 2/6] common/mlx5: modify advanced Rx object via DevX Kinsella, Ray
2020-07-08 21:39 ` [dpdk-dev] [PATCH v2 0/6] add flow shared action API + PMD Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 1/6] ethdev: add flow shared action API Andrey Vesnovaty
2020-09-12  2:18     ` Ajit Khaparde
2020-09-15 11:50       ` Andrey Vesnovaty
2020-09-15 15:49         ` Ajit Khaparde
2020-09-16 15:52           ` Andrey Vesnovaty
2020-09-16 19:20             ` Ajit Khaparde
2020-09-17 15:33               ` Andrew Rybchenko
2020-09-17 16:02                 ` Ori Kam
2020-09-24 19:25                   ` Ajit Khaparde
2020-09-26 11:09                     ` Andrey Vesnovaty
2020-10-03 22:06                       ` [dpdk-dev] [PATCH v3 00/10] RTE flow shared action Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 01/10] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-04 11:10                           ` Ori Kam
2020-10-06 10:22                             ` Andrey Vesnovaty
2020-10-04 17:00                           ` Stephen Hemminger
2020-10-04 17:01                             ` Stephen Hemminger
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 02/10] ethdev: add conf arg to shared action icreate API Andrey Vesnovaty
2020-10-04 11:11                           ` Ori Kam
2020-10-06 10:28                             ` Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 03/10] common/mlx5: modify advanced Rx object via DevX Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 04/10] net/mlx5: modify hash Rx queue objects Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 05/10] net/mlx5: shared action PMD Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 06/10] net/mlx5: shared action PMD create conf arg Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 07/10] net/mlx5: driver support for shared action Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 08/10] net/mlx5: shared action create conf drv support Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 09/10] examples/flow_filtering: utilize shared RSS action Andrey Vesnovaty
2020-10-04 11:21                           ` Ori Kam
2020-10-06 10:34                             ` Andrey Vesnovaty
2020-10-03 22:06                         ` [dpdk-dev] [PATCH v3 10/10] app/testpmd: support shared action Andrey Vesnovaty
2020-10-04 11:28                           ` Ori Kam
2020-10-04 12:04                             ` Ori Kam
2020-10-06 10:36                               ` Andrey Vesnovaty
2020-10-04 11:14                         ` [dpdk-dev] [PATCH v3 00/10] RTE flow " Ori Kam
2020-10-06 10:28                           ` Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 2/6] common/mlx5: modify advanced Rx object via DevX Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 3/6] net/mlx5: modify hash Rx queue objects Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 4/6] net/mlx5: shared action PMD Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 5/6] net/mlx5: driver support for shared action Andrey Vesnovaty
2020-07-08 21:39   ` [dpdk-dev] [PATCH v2 6/6] examples/flow_filtering: utilize shared RSS action Andrey Vesnovaty
2020-07-09  4:44     ` Jerin Jacob
2020-07-09  6:08       ` Ori Kam
2020-07-09 12:25         ` Andrey Vesnovaty
2020-07-09 12:39           ` Thomas Monjalon
2020-07-09  4:39   ` [dpdk-dev] [PATCH v2 0/6] add flow shared action API + PMD Jerin Jacob
2020-10-06 20:08 ` [dpdk-dev] [PATCH v4 0/2] RTE flow shared action Andrey Vesnovaty
2020-10-06 20:08   ` [dpdk-dev] [PATCH v4 1/2] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-07  6:27     ` Ori Kam
2020-10-06 20:08   ` [dpdk-dev] [PATCH v4 2/2] app/testpmd: support shared action Andrey Vesnovaty
2020-10-07  6:30     ` Ori Kam
2020-10-07 12:56 ` [dpdk-dev] [PATCH v5 0/2] RTE flow " Andrey Vesnovaty
2020-10-07 12:56   ` [dpdk-dev] [PATCH v5 1/2] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-07 13:01     ` Ori Kam
2020-10-07 21:23     ` Ajit Khaparde
2020-10-08  7:28       ` Andrey Vesnovaty
2020-10-07 12:56   ` [dpdk-dev] [PATCH v5 2/2] app/testpmd: support shared action Andrey Vesnovaty
2020-10-07 18:36 ` [dpdk-dev] [PATCH v6 0/2] RTE flow " Andrey Vesnovaty
2020-10-07 18:36   ` [dpdk-dev] [PATCH v6 1/2] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-07 18:36   ` [dpdk-dev] [PATCH v6 2/2] app/testpmd: support shared action Andrey Vesnovaty
2020-10-07 20:01     ` Ajit Khaparde
2020-10-08 10:58       ` Andrey Vesnovaty
2020-10-08 11:51 ` [dpdk-dev] [PATCH v7 0/2] RTE flow " Andrey Vesnovaty
2020-10-08 11:51   ` [dpdk-dev] [PATCH v7 1/2] ethdev: add flow shared action API Andrey Vesnovaty
2020-10-08 22:30     ` Ajit Khaparde
2020-10-14 11:47       ` Andrey Vesnovaty
2020-10-12 14:19     ` Andrew Rybchenko
2020-10-13 20:06       ` Andrey Vesnovaty
2020-10-14  6:49         ` Andrew Rybchenko
2020-10-14  7:22           ` Thomas Monjalon
2020-10-14 11:43             ` Andrey Vesnovaty
2020-10-14 11:42           ` Andrey Vesnovaty
2020-10-08 11:51   ` [dpdk-dev] [PATCH v7 2/2] app/testpmd: support shared action Andrey Vesnovaty
2020-10-08 23:54     ` Ajit Khaparde [this message]
2020-10-14 11:40 ` [dpdk-dev] [PATCH v8 0/2] RTE flow " Andrey Vesnovaty
2020-10-14 11:40   ` [dpdk-dev] [PATCH v8 1/2] ethdev: add shared actions to flow API Andrey Vesnovaty
2020-10-14 11:44     ` Andrew Rybchenko
2020-10-14 16:17       ` Ferruh Yigit
2020-10-14 11:40   ` [dpdk-dev] [PATCH v8 2/2] app/testpmd: support shared action Andrey Vesnovaty

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='CACZ4nhu87e3YDn4C0aC0AWybYT4ORVjDnPOH=qYMo=48qkdoCA@mail.gmail.com' \
    --to=ajit.khaparde@broadcom.com \
    --cc=andrey.vesnovaty@gmail.com \
    --cc=andreyv@nvidia.com \
    --cc=beilei.xing@intel.com \
    --cc=bernard.iremonger@intel.com \
    --cc=bruce.richardson@intel.com \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@intel.com \
    --cc=jer@marvell.com \
    --cc=jerinjacobk@gmail.com \
    --cc=mdr@ashroe.eu \
    --cc=nhorman@tuxdriver.com \
    --cc=orika@nvidia.com \
    --cc=samik.gupta@broadcom.com \
    --cc=stephen@networkplumber.org \
    --cc=thomas@monjalon.net \
    --cc=viacheslavo@nvidia.com \
    --cc=wenzhuo.lu@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

DPDK patches and discussions

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://inbox.dpdk.org/dev/0 dev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dev dev/ https://inbox.dpdk.org/dev \
		dev@dpdk.org
	public-inbox-index dev

Example config snippet for mirrors.
Newsgroup available over NNTP:
	nntp://inbox.dpdk.org/inbox.dpdk.dev


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git