app/testpmd: add flow destroy command
authorAdrien Mazarguil <adrien.mazarguil@6wind.com>
Wed, 21 Dec 2016 14:51:27 +0000 (15:51 +0100)
committerThomas Monjalon <thomas.monjalon@6wind.com>
Fri, 23 Dec 2016 09:24:13 +0000 (10:24 +0100)
Syntax:

 flow destroy {port_id} rule {rule_id} [...]

Destroy a given set of flow rules associated with a port.

Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Acked-by: Olga Shern <olgas@mellanox.com>
app/test-pmd/cmdline.c
app/test-pmd/cmdline_flow.c

index 6e2b289..80ddda2 100644 (file)
@@ -811,6 +811,9 @@ static void cmd_help_long_parsed(void *parsed_result,
                        " (select|add)\n"
                        "    Set the input set for FDir.\n\n"
 
+                       "flow destroy {port_id} rule {rule_id} [...]\n"
+                       "    Destroy specific flow rules.\n\n"
+
                        "flow flush {port_id}\n"
                        "    Destroy all flow rules.\n\n"
 
index 5972b80..5c45b3a 100644 (file)
@@ -56,6 +56,7 @@ enum index {
        /* Common tokens. */
        INTEGER,
        UNSIGNED,
+       RULE_ID,
        PORT_ID,
        GROUP_ID,
 
@@ -63,9 +64,13 @@ enum index {
        FLOW,
 
        /* Sub-level commands. */
+       DESTROY,
        FLUSH,
        LIST,
 
+       /* Destroy arguments. */
+       DESTROY_RULE,
+
        /* List arguments. */
        LIST_GROUP,
 };
@@ -164,6 +169,10 @@ struct buffer {
        enum index command; /**< Flow command. */
        uint16_t port; /**< Affected port ID. */
        union {
+               struct {
+                       uint32_t *rule;
+                       uint32_t rule_n;
+               } destroy; /**< Destroy arguments. */
                struct {
                        uint32_t *group;
                        uint32_t group_n;
@@ -171,6 +180,12 @@ struct buffer {
        } args; /**< Command arguments. */
 };
 
+static const enum index next_destroy_attr[] = {
+       DESTROY_RULE,
+       END,
+       ZERO,
+};
+
 static const enum index next_list_attr[] = {
        LIST_GROUP,
        END,
@@ -180,6 +195,9 @@ static const enum index next_list_attr[] = {
 static int parse_init(struct context *, const struct token *,
                      const char *, unsigned int,
                      void *, unsigned int);
+static int parse_destroy(struct context *, const struct token *,
+                        const char *, unsigned int,
+                        void *, unsigned int);
 static int parse_flush(struct context *, const struct token *,
                       const char *, unsigned int,
                       void *, unsigned int);
@@ -196,6 +214,8 @@ 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);
+static int comp_rule_id(struct context *, const struct token *,
+                       unsigned int, char *, unsigned int);
 
 /** Token definitions. */
 static const struct token token_list[] = {
@@ -225,6 +245,13 @@ static const struct token token_list[] = {
                .call = parse_int,
                .comp = comp_none,
        },
+       [RULE_ID] = {
+               .name = "{rule id}",
+               .type = "RULE ID",
+               .help = "rule identifier",
+               .call = parse_int,
+               .comp = comp_rule_id,
+       },
        [PORT_ID] = {
                .name = "{port_id}",
                .type = "PORT ID",
@@ -245,11 +272,19 @@ static const struct token token_list[] = {
                .type = "{command} {port_id} [{arg} [...]]",
                .help = "manage ingress/egress flow rules",
                .next = NEXT(NEXT_ENTRY
-                            (FLUSH,
+                            (DESTROY,
+                             FLUSH,
                              LIST)),
                .call = parse_init,
        },
        /* Sub-level commands. */
+       [DESTROY] = {
+               .name = "destroy",
+               .help = "destroy specific flow rules",
+               .next = NEXT(NEXT_ENTRY(DESTROY_RULE), NEXT_ENTRY(PORT_ID)),
+               .args = ARGS(ARGS_ENTRY(struct buffer, port)),
+               .call = parse_destroy,
+       },
        [FLUSH] = {
                .name = "flush",
                .help = "destroy all flow rules",
@@ -264,6 +299,14 @@ static const struct token token_list[] = {
                .args = ARGS(ARGS_ENTRY(struct buffer, port)),
                .call = parse_list,
        },
+       /* Destroy arguments. */
+       [DESTROY_RULE] = {
+               .name = "rule",
+               .help = "specify a rule identifier",
+               .next = NEXT(next_destroy_attr, NEXT_ENTRY(RULE_ID)),
+               .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
+               .call = parse_destroy,
+       },
        /* List arguments. */
        [LIST_GROUP] = {
                .name = "group",
@@ -329,6 +372,39 @@ parse_init(struct context *ctx, const struct token *token,
        return len;
 }
 
+/** Parse tokens for destroy command. */
+static int
+parse_destroy(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 != DESTROY)
+                       return -1;
+               if (sizeof(*out) > size)
+                       return -1;
+               out->command = ctx->curr;
+               ctx->object = out;
+               out->args.destroy.rule =
+                       (void *)RTE_ALIGN_CEIL((uintptr_t)(out + 1),
+                                              sizeof(double));
+               return len;
+       }
+       if (((uint8_t *)(out->args.destroy.rule + out->args.destroy.rule_n) +
+            sizeof(*out->args.destroy.rule)) > (uint8_t *)out + size)
+               return -1;
+       ctx->object = out->args.destroy.rule + out->args.destroy.rule_n++;
+       return len;
+}
+
 /** Parse tokens for flush command. */
 static int
 parse_flush(struct context *ctx, const struct token *token,
@@ -494,6 +570,30 @@ comp_port(struct context *ctx, const struct token *token,
        return i;
 }
 
+/** Complete available rule IDs. */
+static int
+comp_rule_id(struct context *ctx, const struct token *token,
+            unsigned int ent, char *buf, unsigned int size)
+{
+       unsigned int i = 0;
+       struct rte_port *port;
+       struct port_flow *pf;
+
+       (void)token;
+       if (port_id_is_invalid(ctx->port, DISABLED_WARN) ||
+           ctx->port == (uint16_t)RTE_PORT_ALL)
+               return -1;
+       port = &ports[ctx->port];
+       for (pf = port->flow_list; pf != NULL; pf = pf->next) {
+               if (buf && i == ent)
+                       return snprintf(buf, size, "%u", pf->id);
+               ++i;
+       }
+       if (buf)
+               return -1;
+       return i;
+}
+
 /** Internal context. */
 static struct context cmd_flow_context;
 
@@ -736,6 +836,10 @@ static void
 cmd_flow_parsed(const struct buffer *in)
 {
        switch (in->command) {
+       case DESTROY:
+               port_flow_destroy(in->port, in->args.destroy.rule_n,
+                                 in->args.destroy.rule);
+               break;
        case FLUSH:
                port_flow_flush(in->port);
                break;