Currently, testpmd assigns its own IDs, as indices, to created flows.
Later, the flow index is used as the ID for flow operations (query,
destroy, dump).

Allow the user to assign a user-id, to be later used as an alternative
to the flow index testpmd assigns.

Example:

testpmd> flow create 0 ingress user_id 0x1234 pattern eth / end actions
count / drop / end
Flow rule #0 created, user-id 0x1234

testpmd> flow query 0 0x1234 count user_id

testpmd> flow dump 0 user_id rule 0x1234

testpmd> flow destroy 0 rule 0x1234 user_id
Flow rule user_id 0x1234 destroyed

testpmd> flow destroy 0 rule 0x1234 user_id
Flow rule #0 destroyed, user-id 0x1234

Signed-off-by: Eli Britstein <el...@nvidia.com>
---
 app/test-pmd/cmdline_flow.c                 | 72 +++++++++++++++++++--
 app/test-pmd/config.c                       | 34 +++++++---
 app/test-pmd/testpmd.h                      | 12 ++--
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 14 ++--
 4 files changed, 108 insertions(+), 24 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index a2709e8aa9..758ca03966 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -206,9 +206,11 @@ enum index {
 
        /* Destroy arguments. */
        DESTROY_RULE,
+       DESTROY_IS_USER_ID,
 
        /* Query arguments. */
        QUERY_ACTION,
+       QUERY_IS_USER_ID,
 
        /* List arguments. */
        LIST_GROUP,
@@ -224,10 +226,12 @@ enum index {
        VC_TRANSFER,
        VC_TUNNEL_SET,
        VC_TUNNEL_MATCH,
+       VC_USER_ID,
 
        /* Dump arguments */
        DUMP_ALL,
        DUMP_ONE,
+       DUMP_IS_USER_ID,
 
        /* Configure arguments */
        CONFIG_QUEUES_NUMBER,
@@ -1077,6 +1081,7 @@ struct buffer {
                        uint32_t act_templ_id;
                        struct rte_flow_attr attr;
                        struct tunnel_ops tunnel_ops;
+                       uintptr_t user_id;
                        struct rte_flow_item *pattern;
                        struct rte_flow_action *actions;
                        struct rte_flow_action *masks;
@@ -1087,15 +1092,18 @@ struct buffer {
                struct {
                        uintptr_t *rule;
                        uintptr_t rule_n;
+                       bool is_user_id;
                } destroy; /**< Destroy arguments. */
                struct {
                        char file[128];
                        bool mode;
                        uintptr_t rule;
+                       bool is_user_id;
                } dump; /**< Dump arguments. */
                struct {
                        uintptr_t rule;
                        struct rte_flow_action action;
+                       bool is_user_id;
                } query; /**< Query arguments. */
                struct {
                        uint32_t *group;
@@ -1319,6 +1327,7 @@ static const enum index next_ia_qu_attr[] = {
 static const enum index next_dump_subcmd[] = {
        DUMP_ALL,
        DUMP_ONE,
+       DUMP_IS_USER_ID,
        ZERO,
 };
 
@@ -1339,12 +1348,14 @@ static const enum index next_vc_attr[] = {
        VC_TRANSFER,
        VC_TUNNEL_SET,
        VC_TUNNEL_MATCH,
+       VC_USER_ID,
        ITEM_PATTERN,
        ZERO,
 };
 
 static const enum index next_destroy_attr[] = {
        DESTROY_RULE,
+       DESTROY_IS_USER_ID,
        END,
        ZERO,
 };
@@ -1355,6 +1366,12 @@ static const enum index next_dump_attr[] = {
        ZERO,
 };
 
+static const enum index next_query_attr[] = {
+       QUERY_IS_USER_ID,
+       END,
+       ZERO,
+};
+
 static const enum index next_list_attr[] = {
        LIST_GROUP,
        END,
@@ -3533,7 +3550,7 @@ static const struct token token_list[] = {
        [DESTROY] = {
                .name = "destroy",
                .help = "destroy specific flow rules",
-               .next = NEXT(NEXT_ENTRY(DESTROY_RULE),
+               .next = NEXT(next_destroy_attr,
                             NEXT_ENTRY(COMMON_PORT_ID)),
                .args = ARGS(ARGS_ENTRY(struct buffer, port)),
                .call = parse_destroy,
@@ -3555,7 +3572,7 @@ static const struct token token_list[] = {
        [QUERY] = {
                .name = "query",
                .help = "query an existing flow rule",
-               .next = NEXT(NEXT_ENTRY(QUERY_ACTION),
+               .next = NEXT(next_query_attr, NEXT_ENTRY(QUERY_ACTION),
                             NEXT_ENTRY(COMMON_RULE_ID),
                             NEXT_ENTRY(COMMON_PORT_ID)),
                .args = ARGS(ARGS_ENTRY(struct buffer, args.query.action.type),
@@ -3674,6 +3691,12 @@ static const struct token token_list[] = {
                .args = ARGS(ARGS_ENTRY_PTR(struct buffer, args.destroy.rule)),
                .call = parse_destroy,
        },
+       [DESTROY_IS_USER_ID] = {
+               .name = "user_id",
+               .help = "rule identifier is user-id",
+               .next = NEXT(next_destroy_attr),
+               .call = parse_destroy,
+       },
        /* Dump arguments. */
        [DUMP_ALL] = {
                .name = "all",
@@ -3690,6 +3713,12 @@ static const struct token token_list[] = {
                                ARGS_ENTRY(struct buffer, args.dump.rule)),
                .call = parse_dump,
        },
+       [DUMP_IS_USER_ID] = {
+               .name = "user_id",
+               .help = "rule identifier is user-id",
+               .next = NEXT(next_dump_subcmd),
+               .call = parse_dump,
+       },
        /* Query arguments. */
        [QUERY_ACTION] = {
                .name = "{action}",
@@ -3698,6 +3727,12 @@ static const struct token token_list[] = {
                .call = parse_action,
                .comp = comp_action,
        },
+       [QUERY_IS_USER_ID] = {
+               .name = "user_id",
+               .help = "rule identifier is user-id",
+               .next = NEXT(next_query_attr),
+               .call = parse_query,
+       },
        /* List arguments. */
        [LIST_GROUP] = {
                .name = "group",
@@ -3759,6 +3794,13 @@ static const struct token token_list[] = {
                .args = ARGS(ARGS_ENTRY(struct tunnel_ops, id)),
                .call = parse_vc,
        },
+       [VC_USER_ID] = {
+               .name = "user_id",
+               .help = "specify a user id to create",
+               .next = NEXT(next_vc_attr, NEXT_ENTRY(COMMON_UNSIGNED)),
+               .args = ARGS(ARGS_ENTRY(struct buffer, args.vc.user_id)),
+               .call = parse_vc,
+       },
        /* Validate/create pattern. */
        [ITEM_PATTERN] = {
                .name = "pattern",
@@ -7415,11 +7457,15 @@ parse_vc(struct context *ctx, const struct token *token,
        case VC_TUNNEL_MATCH:
                ctx->object = &out->args.vc.tunnel_ops;
                break;
+       case VC_USER_ID:
+               ctx->object = out;
+               break;
        }
        ctx->objmask = NULL;
        switch (ctx->curr) {
        case VC_GROUP:
        case VC_PRIORITY:
+       case VC_USER_ID:
                return len;
        case VC_TUNNEL_SET:
                out->args.vc.tunnel_ops.enabled = 1;
@@ -9109,6 +9155,10 @@ parse_destroy(struct context *ctx, const struct token 
*token,
                                               sizeof(double));
                return len;
        }
+       if (ctx->curr == DESTROY_IS_USER_ID) {
+               out->args.destroy.is_user_id = true;
+               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;
@@ -9179,6 +9229,9 @@ parse_dump(struct context *ctx, const struct token *token,
                ctx->object = out;
                ctx->objmask = NULL;
                return len;
+       case DUMP_IS_USER_ID:
+               out->args.dump.is_user_id = true;
+               return len;
        default:
                return -1;
        }
@@ -9208,6 +9261,10 @@ parse_query(struct context *ctx, const struct token 
*token,
                ctx->object = out;
                ctx->objmask = NULL;
        }
+       if (ctx->curr == QUERY_IS_USER_ID) {
+               out->args.query.is_user_id = true;
+               return len;
+       }
        return len;
 }
 
@@ -11602,11 +11659,12 @@ cmd_flow_parsed(const struct buffer *in)
        case CREATE:
                port_flow_create(in->port, &in->args.vc.attr,
                                 in->args.vc.pattern, in->args.vc.actions,
-                                &in->args.vc.tunnel_ops);
+                                &in->args.vc.tunnel_ops, in->args.vc.user_id);
                break;
        case DESTROY:
                port_flow_destroy(in->port, in->args.destroy.rule_n,
-                                 in->args.destroy.rule);
+                                 in->args.destroy.rule,
+                                 in->args.destroy.is_user_id);
                break;
        case FLUSH:
                port_flow_flush(in->port);
@@ -11614,11 +11672,13 @@ cmd_flow_parsed(const struct buffer *in)
        case DUMP_ONE:
        case DUMP_ALL:
                port_flow_dump(in->port, in->args.dump.mode,
-                               in->args.dump.rule, in->args.dump.file);
+                               in->args.dump.rule, in->args.dump.file,
+                               in->args.dump.is_user_id);
                break;
        case QUERY:
                port_flow_query(in->port, in->args.query.rule,
-                               &in->args.query.action);
+                               &in->args.query.action,
+                               in->args.query.is_user_id);
                break;
        case LIST:
                port_flow_list(in->port, in->args.list.group_n,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 167cb246c5..51cc480762 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -3303,7 +3303,8 @@ 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,
-                const struct tunnel_ops *tunnel_ops)
+                const struct tunnel_ops *tunnel_ops,
+                uintptr_t user_id)
 {
        struct rte_flow *flow;
        struct rte_port *port;
@@ -3351,17 +3352,23 @@ port_flow_create(portid_t port_id,
        }
        pf->next = port->flow_list;
        pf->id = id;
+       pf->user_id = user_id;
        pf->flow = flow;
        port->flow_list = pf;
        if (tunnel_ops->enabled)
                port_flow_tunnel_offload_cmd_release(port_id, tunnel_ops, pft);
-       printf("Flow rule #%"PRIu64" created\n", pf->id);
+       if (user_id)
+               printf("Flow rule #%"PRIu64" created, user-id 0x%"PRIx64"\n",
+                      pf->id, pf->user_id);
+       else
+               printf("Flow rule #%"PRIu64" created\n", pf->id);
        return 0;
 }
 
 /** Destroy a number of flow rules. */
 int
-port_flow_destroy(portid_t port_id, uint32_t n, const uintptr_t *rule)
+port_flow_destroy(portid_t port_id, uint32_t n, const uintptr_t *rule,
+                 bool is_user_id)
 {
        struct rte_port *port;
        struct port_flow **tmp;
@@ -3379,7 +3386,7 @@ port_flow_destroy(portid_t port_id, uint32_t n, const 
uintptr_t *rule)
                        struct rte_flow_error error;
                        struct port_flow *pf = *tmp;
 
-                       if (rule[i] != pf->id)
+                       if (rule[i] != (is_user_id ? pf->user_id : pf->id))
                                continue;
                        /*
                         * Poisoning to make sure PMDs update it in case
@@ -3390,7 +3397,13 @@ port_flow_destroy(portid_t port_id, uint32_t n, const 
uintptr_t *rule)
                                ret = port_flow_complain(&error);
                                continue;
                        }
-                       printf("Flow rule #%"PRIu64" destroyed\n", pf->id);
+                       if (is_user_id)
+                               printf("Flow rule #%"PRIu64" destroyed, "
+                                      "user-id 0x%"PRIx64"\n",
+                                      pf->id, pf->user_id);
+                       else
+                               printf("Flow rule #%"PRIu64" destroyed\n",
+                                      pf->id);
                        *tmp = pf->next;
                        free(pf);
                        break;
@@ -3436,7 +3449,7 @@ port_flow_flush(portid_t port_id)
 /** Dump flow rules. */
 int
 port_flow_dump(portid_t port_id, bool dump_all, uintptr_t rule_id,
-               const char *file_name)
+               const char *file_name, bool is_user_id)
 {
        int ret = 0;
        FILE *file = stdout;
@@ -3454,7 +3467,8 @@ port_flow_dump(portid_t port_id, bool dump_all, uintptr_t 
rule_id,
                port = &ports[port_id];
                pflow = port->flow_list;
                while (pflow) {
-                       if (rule_id != pflow->id) {
+                       if (rule_id !=
+                           (is_user_id ? pflow->user_id : pflow->id)) {
                                pflow = pflow->next;
                        } else {
                                tmpFlow = pflow->flow;
@@ -3496,7 +3510,7 @@ port_flow_dump(portid_t port_id, bool dump_all, uintptr_t 
rule_id,
 /** Query a flow rule. */
 int
 port_flow_query(portid_t port_id, uintptr_t rule,
-               const struct rte_flow_action *action)
+               const struct rte_flow_action *action, bool is_user_id)
 {
        struct rte_flow_error error;
        struct rte_port *port;
@@ -3514,7 +3528,7 @@ port_flow_query(portid_t port_id, uintptr_t rule,
                return -EINVAL;
        port = &ports[port_id];
        for (pf = port->flow_list; pf; pf = pf->next)
-               if (pf->id == rule)
+               if ((is_user_id ? pf->user_id : pf->id) == rule)
                        break;
        if (!pf) {
                fprintf(stderr, "Flow rule #%"PRIu64" not found\n", rule);
@@ -3634,7 +3648,7 @@ port_flow_aged(portid_t port_id, uint8_t destroy)
                               ctx.pf->rule.attr->egress ? 'e' : '-',
                               ctx.pf->rule.attr->transfer ? 't' : '-');
                        if (destroy && !port_flow_destroy(port_id, 1,
-                                                         &ctx.pf->id))
+                                                         &ctx.pf->id, false))
                                total++;
                        break;
                case ACTION_AGE_CONTEXT_TYPE_INDIRECT_ACTION:
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index ba29d97293..b18ebeaf83 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -216,6 +216,7 @@ struct port_flow {
        struct port_flow *next; /**< Next flow in list. */
        struct port_flow *tmp; /**< Temporary linking. */
        uintptr_t id; /**< Flow rule ID. */
+       uintptr_t user_id; /**< User rule ID. */
        struct rte_flow *flow; /**< Opaque flow object returned by PMD. */
        struct rte_flow_conv_rule rule; /**< Saved flow rule description. */
        enum age_action_context_type age_type; /**< Age action context type. */
@@ -979,17 +980,20 @@ 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,
-                    const struct tunnel_ops *tunnel_ops);
+                    const struct tunnel_ops *tunnel_ops,
+                    uintptr_t user_id);
 int port_action_handle_query(portid_t port_id, uint32_t id);
 void update_age_action_context(const struct rte_flow_action *actions,
                     struct port_flow *pf);
 int mcast_addr_pool_destroy(portid_t port_id);
-int port_flow_destroy(portid_t port_id, uint32_t n, const uintptr_t *rule);
+int port_flow_destroy(portid_t port_id, uint32_t n, const uintptr_t *rule,
+                     bool is_user_id);
 int port_flow_flush(portid_t port_id);
 int port_flow_dump(portid_t port_id, bool dump_all,
-                       uintptr_t rule, const char *file_name);
+                       uintptr_t rule, const char *file_name,
+                       bool is_user_id);
 int port_flow_query(portid_t port_id, uintptr_t rule,
-                   const struct rte_flow_action *action);
+                   const struct rte_flow_action *action, bool is_user_id);
 void port_flow_list(portid_t port_id, uint32_t n, const uint32_t *group);
 void port_flow_aged(portid_t port_id, uint8_t destroy);
 const char *port_flow_tunnel_type(struct rte_flow_tunnel *tunnel);
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst 
b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 5a88933635..92cf7d5adf 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3010,12 +3010,14 @@ following sections.
 
    flow create {port_id}
        [group {group_id}] [priority {level}] [ingress] [egress] [transfer]
-       pattern {item} [/ {item} [...]] / end
+       [user_id {user_id}] pattern {item} [/ {item} [...]] / end
        actions {action} [/ {action} [...]] / end
 
 - Destroy specific flow rules::
 
-   flow destroy {port_id} rule {rule_id} [...]
+   flow destroy {port_id} rule {rule_id} [...] [user_id]
+   [user_id] is used as an optional flag to indicate the rule_id is the
+   user_id assigned in "flow create".
 
 - Destroy all flow rules::
 
@@ -3023,7 +3025,9 @@ following sections.
 
 - Query an existing flow rule::
 
-   flow query {port_id} {rule_id} {action}
+   flow query {port_id} {rule_id} {action} [user_id]
+   [user_id] is used as an optional flag to indicate the rule_id is the
+   user_id assigned in "flow create".
 
 - List existing flow rules sorted by priority, filtered by group
   identifiers::
@@ -3040,7 +3044,9 @@ following sections.
 
   for one flow::
 
-   flow dump {port_id} rule {rule_id} {output_file}
+   flow dump {port_id} rule {rule_id} {output_file} [user_id]
+   [user_id] is used as an optional flag to indicate the rule_id is the
+   user_id assigned in "flow create".
 
 - List and destroy aged flow rules::
 
-- 
2.25.1

Reply via email to