From patchwork Wed Nov 16 16:23:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Adrien Mazarguil X-Patchwork-Id: 17031 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id CDD955936; Wed, 16 Nov 2016 17:25:16 +0100 (CET) Received: from mail-wm0-f50.google.com (mail-wm0-f50.google.com [74.125.82.50]) by dpdk.org (Postfix) with ESMTP id 442E7567E for ; Wed, 16 Nov 2016 17:24:21 +0100 (CET) Received: by mail-wm0-f50.google.com with SMTP id t79so83413223wmt.0 for ; Wed, 16 Nov 2016 08:24:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=6wind-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=purWCtq1zgttvxvSYNS9twM2tB2WSfPK/mRn7ZIa4iU=; b=VZiNGNkMNEy40Ess9GeMRlmLWs0tgFYNX0zppPyvvw/AtrPfVqbzE6h3k0q7DJ2PoR ST/U53bGtj6v0qsR4PWQy2oY+1eeD54RxtP0UQKzNeeBCwdOmdL7esvg1IViwaNBqEnJ hJ87z1G225WlQ0ivKtMSCo3rMosJwU5Mke3IuBI+6Ai+r36FECNGaRU4tgOkkJJuQwlD J8tBYHUb8GcSN4QP28EBjXYjDmkCQ1041EsZjWW1SZcFeWw3ork/W6X79XSFxUcFY2Nf pG+uvsZFhh03YQfuHAOct/l0w4TGp1aoQaG96l+8SGlxFBNtaWdQrdqS6Z67+bTkzDKy mHcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=purWCtq1zgttvxvSYNS9twM2tB2WSfPK/mRn7ZIa4iU=; b=UEaBV9UP+iz4dI0l/hQ2Q9dRo4aye+TV7p2rmW0NhrJlUcc3TDzdLBpAf7nRbkoY6c ylfcRzL887DabEFHv1v7WCZdRgCEWA5hh/NJeC1mS3mtTP/HmxdkTb1zkY8SPX9iWVUO ULiM01swPhcx3Op1OLV6euQcwvm7JhNoSLVBLjIaO0gsBjIxQ/WAj2RjkJO1E4gR4L7w aaSJEZXttji8xyGJKdgugFqQez7JXTIWO6JtmYGIXVpsQPf4sECWGLFO2HZnbh6IyOhz nyen1jN/nIm7SIyAma0NocpxmWxaUCjGxD390H1W0/Odl6Zv4gJWnyF1/u0CvJ2teDSn kvUw== X-Gm-Message-State: ABUngvf5egl9BH7drA8U9t0HnoVX90L39O2ouedwVaWF5ew/AUdwIvI1RtEsP3FqQPZZAbP5 X-Received: by 10.194.85.137 with SMTP id h9mr2438378wjz.23.1479313460674; Wed, 16 Nov 2016 08:24:20 -0800 (PST) Received: from 6wind.com (guy78-3-82-239-227-177.fbx.proxad.net. [82.239.227.177]) by smtp.gmail.com with ESMTPSA id x188sm10950106wmx.4.2016.11.16.08.24.18 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Wed, 16 Nov 2016 08:24:19 -0800 (PST) From: Adrien Mazarguil To: dev@dpdk.org Cc: Thomas Monjalon , Pablo de Lara , Olivier Matz Date: Wed, 16 Nov 2016 17:23:33 +0100 Message-Id: <83203ed6d586efc26dd293bda5f4d06a6d12f969.1479309720.git.adrien.mazarguil@6wind.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: References: Subject: [dpdk-dev] [PATCH 07/22] app/testpmd: add flow list command X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Syntax: flow list {port_id} [group {group_id}] [...] List configured flow rules on a port. Output can optionally be limited to a given set of group identifiers. Signed-off-by: Adrien Mazarguil --- app/test-pmd/cmdline.c | 4 ++ app/test-pmd/cmdline_flow.c | 141 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index b7d10b3..09357c0 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -810,6 +810,10 @@ static void cmd_help_long_parsed(void *parsed_result, "sctp-src-port|sctp-dst-port|sctp-veri-tag|none)" " (select|add)\n" " Set the input set for FDir.\n\n" + + "flow list {port_id} [group {group_id}] [...]\n" + " List existing flow rules sorted by priority," + " filtered by group identifiers.\n\n" ); } } diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c index 7078f80..727fe78 100644 --- a/app/test-pmd/cmdline_flow.c +++ b/app/test-pmd/cmdline_flow.c @@ -56,9 +56,17 @@ enum index { /* Common tokens. */ INTEGER, UNSIGNED, + PORT_ID, + GROUP_ID, /* Top-level command. */ FLOW, + + /* Sub-level commands. */ + LIST, + + /* List arguments. */ + LIST_GROUP, }; /** Maximum number of subsequent tokens and arguments on the stack. */ @@ -77,6 +85,7 @@ struct context { uint32_t reparse:1; /**< Start over from the beginning. */ uint32_t eol:1; /**< EOL has been detected. */ uint32_t last:1; /**< No more arguments. */ + uint16_t port; /**< Current port ID (for completions). */ void *object; /**< Address of current object for relative offsets. */ }; @@ -153,16 +162,36 @@ struct token { struct buffer { enum index command; /**< Flow command. */ uint16_t port; /**< Affected port ID. */ + union { + struct { + uint32_t *group; + uint32_t group_n; + } list; /**< List arguments. */ + } args; /**< Command arguments. */ +}; + +static const enum index next_list_attr[] = { + LIST_GROUP, + END, + 0, }; static int parse_init(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_list(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int parse_int(struct context *, const struct token *, const char *, unsigned int, void *, unsigned int); +static int parse_port(struct context *, const struct token *, + const char *, unsigned int, + void *, unsigned int); static int comp_none(struct context *, const struct token *, unsigned int, char *, unsigned int); +static int comp_port(struct context *, const struct token *, + unsigned int, char *, unsigned int); /** Token definitions. */ static const struct token token_list[] = { @@ -192,13 +221,44 @@ static const struct token token_list[] = { .call = parse_int, .comp = comp_none, }, + [PORT_ID] = { + .name = "{port_id}", + .type = "PORT ID", + .help = "port identifier", + .call = parse_port, + .comp = comp_port, + }, + [GROUP_ID] = { + .name = "{group_id}", + .type = "GROUP ID", + .help = "group identifier", + .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(LIST)), .call = parse_init, }, + /* Sub-level commands. */ + [LIST] = { + .name = "list", + .help = "list existing flow rules", + .next = NEXT(next_list_attr, NEXT_ENTRY(PORT_ID)), + .args = ARGS(ARGS_ENTRY(struct buffer, port)), + .call = parse_list, + }, + /* List arguments. */ + [LIST_GROUP] = { + .name = "group", + .help = "specify a group", + .next = NEXT(next_list_attr, NEXT_ENTRY(GROUP_ID)), + .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.list.group)), + .call = parse_list, + }, }; /** Remove and return last entry from argument stack. */ @@ -256,6 +316,39 @@ parse_init(struct context *ctx, const struct token *token, return len; } +/** Parse tokens for list command. */ +static int +parse_list(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 != LIST) + return -1; + if (sizeof(*out) > size) + return -1; + out->command = ctx->curr; + ctx->object = out; + out->args.list.group = + (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1), + sizeof(double)); + return len; + } + if (((uint8_t *)(out->args.list.group + out->args.list.group_n) + + sizeof(*out->args.list.group)) > (uint8_t *)out + size) + return -1; + ctx->object = out->args.list.group + out->args.list.group_n++; + return len; +} + /** * Parse signed/unsigned integers 8 to 64-bit long. * @@ -307,6 +400,29 @@ parse_int(struct context *ctx, const struct token *token, return -1; } +/** Parse port and update context. */ +static int +parse_port(struct context *ctx, const struct token *token, + const char *str, unsigned int len, + void *buf, unsigned int size) +{ + struct buffer *out = &(struct buffer){ .port = 0 }; + int ret; + + if (buf) + out = buf; + else { + ctx->object = out; + size = sizeof(*out); + } + ret = parse_int(ctx, token, str, len, out, size); + if (ret >= 0) + ctx->port = out->port; + if (!buf) + ctx->object = NULL; + return ret; +} + /** No completion. */ static int comp_none(struct context *ctx, const struct token *token, @@ -320,6 +436,26 @@ comp_none(struct context *ctx, const struct token *token, return 0; } +/** Complete available ports. */ +static int +comp_port(struct context *ctx, const struct token *token, + unsigned int ent, char *buf, unsigned int size) +{ + unsigned int i = 0; + portid_t p; + + (void)ctx; + (void)token; + FOREACH_PORT(p, ports) { + if (buf && i == ent) + return snprintf(buf, size, "%u", p); + ++i; + } + if (buf) + return -1; + return i; +} + /** Internal context. */ static struct context cmd_flow_context; @@ -338,6 +474,7 @@ cmd_flow_context_init(struct context *ctx) ctx->reparse = 0; ctx->eol = 0; ctx->last = 0; + ctx->port = 0; ctx->object = NULL; } @@ -561,6 +698,10 @@ static void cmd_flow_parsed(const struct buffer *in) { switch (in->command) { + case LIST: + port_flow_list(in->port, in->args.list.group_n, + in->args.list.group); + break; default: break; }