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 C590AA04BC; Fri, 9 Oct 2020 01:55:11 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id E7C131BCE5; Fri, 9 Oct 2020 01:55:09 +0200 (CEST) Received: from mail-ot1-f65.google.com (mail-ot1-f65.google.com [209.85.210.65]) by dpdk.org (Postfix) with ESMTP id 23E401BCD7 for ; Fri, 9 Oct 2020 01:55:08 +0200 (CEST) Received: by mail-ot1-f65.google.com with SMTP id e20so6890293otj.11 for ; Thu, 08 Oct 2020 16:55:08 -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=b/df1M5qihKW57OJWqa3hfgbB9sBR4Cs6pnsRZpUcAw=; b=HA9Th13P3xZf0C7p61IKEhMKNJHoc2dcB6kzQDyV7MkhFwrftzt2GH6WpNbbT4Byub R91VO91dEstc4CTTyca6YZ3cAiqxX+plfqnBD589JMfWGbIVu9wfn5Ey8jeUrDQGxuQr OrAjbEznNSZvLu4Z3/AyXQZrdU+NhYVkzNAzY= 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=b/df1M5qihKW57OJWqa3hfgbB9sBR4Cs6pnsRZpUcAw=; b=HISKemm571WUpH50Gyjdd06dEqFTUl9MtDsQo1xMwG8CSeike6u9DNFg3Jf+QKSEB0 qzH+f0MIDVvTBLEg0w2ygOJr6zkPwGYf5l4Yu3R8KuOaB/yaHTLdaXxnz3V60vNNBBCh /FYRqJIW4Tu1QHOqiwr28KcYpkeNmNTnJeXoMwr+prZyrCRv5I3+IRCV+fZnx1gWVuWh Zg9mkcI70/6Zhbgv+AVqjzPunw7qZbgqAYyWVqef/3iOrkGeih6+czHJNZfPAcLcnydh Z7J62ZeJkKEPp3dShIiF2l5iwq+6cbg7YQmFwfpM96ATH7o0OuaS8joQXQr2R23gX2Rp PSyw== X-Gm-Message-State: AOAM530MBQtMziooCeq/rTqDmr5Hi41inCP/oNwQhAiC15RzgDjRdzkz 8/gre7UYbMedW9A3gUCH7q6YnsokQDRMKm2psGLGsw== X-Google-Smtp-Source: ABdhPJyO6YDQ2ctJSPJZjMsNrS2MV53Fxk3HL93Nc+mWLlKl+FhZWpR9hE+kBuLTt+1zRK7Eu/5VcaVV7oOus084HLI= X-Received: by 2002:a9d:f67:: with SMTP id 94mr4627958ott.154.1602201305895; Thu, 08 Oct 2020 16:55:05 -0700 (PDT) MIME-Version: 1.0 References: <20200702120511.16315-1-andreyv@mellanox.com> <20201008115143.13208-1-andreyv@nvidia.com> <20201008115143.13208-3-andreyv@nvidia.com> In-Reply-To: <20201008115143.13208-3-andreyv@nvidia.com> From: Ajit Khaparde Date: Thu, 8 Oct 2020 16:54:49 -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 v7 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 Thu, Oct 8, 2020 at 4:51 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_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 > Acked-by: Ori Kam Acked-by: Ajit Khaparde > --- > 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 >