From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id E9411A04BA; Wed, 7 Oct 2020 22:01:55 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 716B12BC7; Wed, 7 Oct 2020 22:01:54 +0200 (CEST) Received: from mail-ot1-f67.google.com (mail-ot1-f67.google.com [209.85.210.67]) by dpdk.org (Postfix) with ESMTP id BB2752B8C for ; Wed, 7 Oct 2020 22:01:52 +0200 (CEST) Received: by mail-ot1-f67.google.com with SMTP id e20so2945373otj.11 for ; Wed, 07 Oct 2020 13:01:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=DOMgruN8pxP2OscgmpxJRQ9tNmvWFCrSiy23pvKWxhU=; b=KGLtCi86axwvWZnMsQtWR8swwwC/8Xxwma6PbX9gWrRyObiUlX6nI42N3pVUOoSVX1 z4wdujm/OvroqiI6o3zxDZpK1cDV04doDI+dMKDC7S/Hona+e/hKpg6e6ebAQqTh9LGo t3y3p/R4zYdKC+P3nF5tMIrGNffrluVyiXZcY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=DOMgruN8pxP2OscgmpxJRQ9tNmvWFCrSiy23pvKWxhU=; b=OkFk6/HtE+i3+pKmf7151b9JW63oTRicRSd/S89I/TLVNLzluCZ0ZdABh+sLI2Fn73 ghqOZmtnQ9lKoTkAyKaIv4oKHSVwp7Hb38gTTocKCdDLbA1B0inTE7ag3Wt+wYKiNBuI E6xoMvm0ijWAM3sVCW+jqD4Zt51WYBiRFauPdR2E9PBMxDvnmA925LL8G63SjQKgGjnw qaLEpnEQJ/n1KcXvIyO5MieACA99W5ADmehzGSFJCb5dmAMzjsmFfMccRZKRAyRoObW+ Vf7REwiPPS3Sm4WPuZJiOS/yOgN/8wbMa9R/TBQHLSqPWr6aMfNJ60LRTAsRuMM4uY82 4u4Q== X-Gm-Message-State: AOAM533Mi2pUyeM2fWl5RpXNE8YETOZntjVzRj9gryAnHous5L1Vqr++ 3H8o3JeNuhQum+t4bmeLH4rCPgNmAtCO7eHTri3F1g== X-Google-Smtp-Source: ABdhPJx5T3dD2XcgSmzAwhZrLMXinqlwwfo4QgRpG5cczix2nJMvSqs6L1fUJkHz7dSMxlz3xcF71Xl5P3oX5hryzas= X-Received: by 2002:a9d:6acc:: with SMTP id m12mr2640540otq.95.1602100910437; Wed, 07 Oct 2020 13:01:50 -0700 (PDT) MIME-Version: 1.0 References: <20200702120511.16315-1-andreyv@mellanox.com> <20201007183607.5130-1-andreyv@nvidia.com> <20201007183607.5130-3-andreyv@nvidia.com> In-Reply-To: <20201007183607.5130-3-andreyv@nvidia.com> From: Ajit Khaparde Date: Wed, 7 Oct 2020 13:01:34 -0700 Message-ID: To: Andrey Vesnovaty Cc: dpdk-dev , jer@marvell.com, Jerin Jacob , Thomas Monjalon , Ferruh Yigit , Stephen Hemminger , Bruce Richardson , Ori Kam , Slava Ovsiienko , andrey.vesnovaty@gmail.com, Ray Kinsella , Neil Horman , Samik Gupta , Wenzhuo Lu , Beilei Xing , Bernard Iremonger Content-Type: text/plain; charset="UTF-8" X-Content-Filtered-By: Mailman/MimeDel 2.1.15 Subject: Re: [dpdk-dev] [PATCH v6 2/2] app/testpmd: support shared action X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" On Wed, Oct 7, 2020 at 11:36 AM Andrey Vesnovaty 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 > Acked-by: Ori Kam > Signed-off-by: Andrey Vesnovaty > --- > 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? > + 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? > + 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. > + 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. > + > +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 >