DPDK patches and discussions
 help / color / mirror / Atom feed
From: Andrey Vesnovaty <andreyv@nvidia.com>
To: Ajit Khaparde <ajit.khaparde@broadcom.com>
Cc: dpdk-dev <dev@dpdk.org>, "jer@marvell.com" <jer@marvell.com>,
	Jerin Jacob <jerinjacobk@gmail.com>,
	NBU-Contact-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" <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 v6 2/2] app/testpmd: support shared action
Date: Thu, 8 Oct 2020 10:58:47 +0000
Message-ID: <MWHPR1201MB2525B3409D2B7D746843BEA9DB0B0@MWHPR1201MB2525.namprd12.prod.outlook.com> (raw)
In-Reply-To: <CACZ4nhv8T1UC3imL4otsLG_wnfv6CaNQgEtRuSO6nuQWThFByw@mail.gmail.com>

Hi Ajit.

I completely agree that action direction was overlooked by me
just because RSS has implicit ingress direction.

v7 patch is about to be sent in an hour with following changes:
* Added handling of direction arguments for create CLI.
* Both create & update CLI can receive all RTE flow action types now.

PSB my suggestion regarding improving update CLI.

Thanks,
Andrey

> -----Original Message-----
> From: Ajit Khaparde <ajit.khaparde@broadcom.com>
> Sent: Wednesday, October 7, 2020 11:02 PM
> To: Andrey Vesnovaty <andreyv@nvidia.com>
> Cc: dpdk-dev <dev@dpdk.org>; jer@marvell.com; Jerin Jacob
> <jerinjacobk@gmail.com>; NBU-Contact-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: [PATCH v6 2/2] app/testpmd: support shared action
> 
> On Wed, Oct 7, 2020 at 11:36 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) create {action_id (shared_action_id)} \
> >         (action) / end
> >
> > Create shared action examples:
> >         flow shared_action 0 create action_id 100 \
> >                 rss queues 1 2 end / end
> I don't see the direction being specified.
> 
> >         This creates shared rss action with id 100 on port 0.
> >
> >         flow shared_action 0 create action_id \
> >                 rss queues 0 1 end / end
> Same here.
> 
> >         This creates shared rss action with id assigned by tetspmd
> >         on port 0.
> >
> > Update shared action syntax:
> > flow shared_action (port) update (shared_action_id) (action) / end
> The syntax will be incomplete without parsing the direction which
> a part of the shared action configuration.
> 
> >
> > Update shared action example:
> >         flow shared_action 0 update 100 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) destroy action_id (shared_action_id) \
> >         { action_id (shared_action_id) [...]}
> >
> > Update 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) ... / 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>
> > Signed-off-by: Andrey Vesnovaty <andreyv@nvidia.com>
> > ---
> >  app/test-pmd/cmdline_flow.c                 | 262 +++++++++++++++++++-
> >  app/test-pmd/config.c                       | 215 ++++++++++++++++
> >  app/test-pmd/testpmd.h                      |  19 ++
> >  doc/guides/testpmd_app_ug/testpmd_funcs.rst | 111 +++++++++
> >  4 files changed, 606 insertions(+), 1 deletion(-)
> >
> > diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> > index 6e04d538ea..402ce69aa3 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,18 @@ 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 destroy arguments */
> > +       SHARED_ACTION_DESTROY_ID,
> > +
> >         /* Validate/create pattern. */
> >         PATTERN,
> >         ITEM_PARAM_IS,
> > @@ -360,6 +374,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 +669,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 +732,19 @@ struct parse_action_priv {
> >                 .size = s, \
> >         })
> >
> > +static const enum index next_sa_create_attr[] = {
> > +       SHARED_ACTION_CREATE_ID,
> > +       ACTION_RSS,
> This is only for RSS.
> What if we want to do it for another resource?
> 

Fixed, now it accepts all RTE flow actions.
Unimplemented/unsupported actions rejected by RTE flow layer/PMD.

> > +       ZERO,
> > +};
> > +
> > +static const enum index next_sa_subcmd[] = {
> > +       SHARED_ACTION_CREATE,
> > +       SHARED_ACTION_UPDATE,
> > +       SHARED_ACTION_DESTROY,
> > +       SHARED_ACTION_QUERY,
> > +};
> > +
> [snip]
> 
> > +       /* 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),
> > +               .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.attr.group)),
> > +               .call = parse_sa,
> > +       },
> > +       [SHARED_ACTION_UPDATE] = {
> > +               .name = "update",
> > +               .help = "update shared action",
> > +               .next = NEXT(NEXT_ENTRY(ACTION_RSS),
> 
> Can't we fill this action based on the input of the flow shared_action
> create command?
> 
Do you mean tab completion improvement for shared action ID?
If yes, please let me to keep this improvement for post RC1 phase.
BW, now update receives all RTE flow action types similar to create.
> 
> > +                            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 +3957,40 @@ 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_ENTRY(ACTION_RSS),
> Same here. This is assuming RSS action only.
> 
Fixed, all RTE flow action types supported.
> 
> > +                            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,
> > +       },
> >  };
> >
> >  /** Remove and return last entry from argument stack. */
> > @@ -4043,6 +4175,91 @@ 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;
> > +       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 +6327,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 +6802,23 @@ 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,
> > +                                         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..cee3f908ef 100644
> > --- a/app/test-pmd/config.c
> > +++ b/app/test-pmd/config.c
> > @@ -1580,6 +1580,221 @@ 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_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, NULL, 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..a78fc9f3f0 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,14 @@ 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_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 +774,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..f4b26ed307 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,112 @@ 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}] \
> > +      {action} / end
> Need to allow passing the direction attribute.
> 

Fixed.

> > +
> > +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 \
> > +      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 \
> > +               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} / 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 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 10:59 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 [this message]
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
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=MWHPR1201MB2525B3409D2B7D746843BEA9DB0B0@MWHPR1201MB2525.namprd12.prod.outlook.com \
    --to=andreyv@nvidia.com \
    --cc=ajit.khaparde@broadcom.com \
    --cc=andrey.vesnovaty@gmail.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