This commits add support for calculating the encap hash.

Command structure:
flow hash {port} encap {target field} pattern {item} [/ {item} [...] ] / end

Example:
calculate hash to be used by VXLAN encapsulation.
flow hash 0 encap hash_field_sport  pattern ipv4 dst is 7.7.7.7 src is 8.8.8.8  
/ udp dst is 5678 src is 1234  / end

Signed-off-by: Ori Kam <or...@nvidia.com>
Acked-by: Dariusz Sosnowski <dsosnow...@nvidia.com>

---
 app/test-pmd/cmdline_flow.c                 | 57 +++++++++++++++++++--
 app/test-pmd/config.c                       | 30 +++++++++++
 app/test-pmd/testpmd.h                      |  3 ++
 doc/guides/testpmd_app_ug/testpmd_funcs.rst | 21 +++++++-
 4 files changed, 106 insertions(+), 5 deletions(-)

diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
index a4131e1b39..844840fe2d 100644
--- a/app/test-pmd/cmdline_flow.c
+++ b/app/test-pmd/cmdline_flow.c
@@ -219,6 +219,10 @@ enum index {
        HASH_CALC_TABLE,
        HASH_CALC_PATTERN_INDEX,
        HASH_CALC_PATTERN,
+       HASH_CALC_ENCAP,
+       HASH_CALC_DEST,
+       ENCAP_HASH_FIELD_SRC_PORT,
+       ENCAP_HASH_FIELD_GRE_FLOW_ID,
 
        /* Tunnel arguments. */
        TUNNEL_CREATE,
@@ -1220,6 +1224,8 @@ struct buffer {
                        uint32_t pattern_n;
                        uint32_t actions_n;
                        uint8_t *data;
+                       enum rte_flow_encap_hash_field field;
+                       uint8_t encap_hash;
                } vc; /**< Validate/create arguments. */
                struct {
                        uint64_t *rule;
@@ -2618,6 +2624,18 @@ static const enum index action_nat64[] = {
        ZERO,
 };
 
+static const enum index next_hash_subcmd[] = {
+       HASH_CALC_TABLE,
+       HASH_CALC_ENCAP,
+       ZERO,
+};
+
+static const enum index next_hash_encap_dest_subcmd[] = {
+       ENCAP_HASH_FIELD_SRC_PORT,
+       ENCAP_HASH_FIELD_GRE_FLOW_ID,
+       ZERO,
+};
+
 static int parse_set_raw_encap_decap(struct context *, const struct token *,
                                     const char *, unsigned int,
                                     void *, unsigned int);
@@ -3875,7 +3893,7 @@ static const struct token token_list[] = {
        [HASH] = {
                .name = "hash",
                .help = "calculate hash for a given pattern in a given template 
table",
-               .next = NEXT(NEXT_ENTRY(HASH_CALC_TABLE), 
NEXT_ENTRY(COMMON_PORT_ID)),
+               .next = NEXT(next_hash_subcmd, NEXT_ENTRY(COMMON_PORT_ID)),
                .args = ARGS(ARGS_ENTRY(struct buffer, port)),
                .call = parse_hash,
        },
@@ -3889,6 +3907,12 @@ static const struct token token_list[] = {
                                        args.vc.table_id)),
                .call = parse_hash,
        },
+       [HASH_CALC_ENCAP] = {
+               .name = "encap",
+               .help = "calculates encap hash",
+               .next = NEXT(next_hash_encap_dest_subcmd),
+               .call = parse_hash,
+       },
        [HASH_CALC_PATTERN_INDEX] = {
                .name = "pattern_template",
                .help = "specify pattern template id",
@@ -3898,6 +3922,18 @@ static const struct token token_list[] = {
                                        args.vc.pat_templ_id)),
                .call = parse_hash,
        },
+       [ENCAP_HASH_FIELD_SRC_PORT] = {
+               .name = "hash_field_sport",
+               .help = "the encap hash field is src port",
+               .next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
+               .call = parse_hash,
+       },
+       [ENCAP_HASH_FIELD_GRE_FLOW_ID] = {
+               .name = "hash_field_flow_id",
+               .help = "the encap hash field is NVGRE flow id",
+               .next = NEXT(NEXT_ENTRY(ITEM_PATTERN)),
+               .call = parse_hash,
+       },
        /* Top-level command. */
        [INDIRECT_ACTION] = {
                .name = "indirect_action",
@@ -11075,6 +11111,15 @@ parse_hash(struct context *ctx, const struct token 
*token,
                ctx->object = out->args.vc.pattern;
                ctx->objmask = NULL;
                return len;
+       case HASH_CALC_ENCAP:
+               out->args.vc.encap_hash = 1;
+               return len;
+       case ENCAP_HASH_FIELD_SRC_PORT:
+               out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT;
+               return len;
+       case ENCAP_HASH_FIELD_GRE_FLOW_ID:
+               out->args.vc.field = RTE_FLOW_ENCAP_HASH_FIELD_NVGRE_FLOW_ID;
+               return len;
        default:
                return -1;
        }
@@ -13068,9 +13113,13 @@ cmd_flow_parsed(const struct buffer *in)
                port_queue_flow_pull(in->port, in->queue);
                break;
        case HASH:
-               port_flow_hash_calc(in->port, in->args.vc.table_id,
-                                   in->args.vc.pat_templ_id,
-                                   in->args.vc.pattern);
+               if (!in->args.vc.encap_hash)
+                       port_flow_hash_calc(in->port, in->args.vc.table_id,
+                                           in->args.vc.pat_templ_id,
+                                           in->args.vc.pattern);
+               else
+                       port_flow_hash_calc_encap(in->port, in->args.vc.field,
+                                                 in->args.vc.pattern);
                break;
        case QUEUE_AGED:
                port_queue_flow_aged(in->port, in->queue,
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index cad7537bc6..e26b5bd18d 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -3339,6 +3339,36 @@ port_flow_hash_calc(portid_t port_id, uint32_t table_id,
        return 0;
 }
 
+/** Calculate the encap hash result for a given pattern. */
+int
+port_flow_hash_calc_encap(portid_t port_id,
+                         enum rte_flow_encap_hash_field encap_hash_field,
+                         const struct rte_flow_item pattern[])
+{
+       struct rte_flow_error error;
+       int ret = 0;
+       uint16_t hash = 0;
+       uint8_t len = encap_hash_field == RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT ? 
2 : 1;
+
+       if (port_id_is_invalid(port_id, ENABLED_WARN) ||
+           port_id == (portid_t)RTE_PORT_ALL) {
+               printf("Failed to calculate encap hash - not a valid port");
+               return -EINVAL;
+       }
+
+       ret = rte_flow_calc_encap_hash(port_id, pattern, encap_hash_field, len,
+                                      (uint8_t *)&hash, &error);
+       if (ret < 0) {
+               printf("Failed to calculate encap hash");
+               return ret;
+       }
+       if (encap_hash_field == RTE_FLOW_ENCAP_HASH_FIELD_SRC_PORT)
+               printf("encap hash result %#x\n", hash);
+       else
+               printf("encap hash result %#x\n", *(uint8_t *)&hash);
+       return 0;
+}
+
 /** Pull queue operation results from the queue. */
 static int
 port_queue_aged_flow_destroy(portid_t port_id, queueid_t queue_id,
diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h
index 9b10a9ea1c..e18546c46e 100644
--- a/app/test-pmd/testpmd.h
+++ b/app/test-pmd/testpmd.h
@@ -1016,6 +1016,9 @@ int port_queue_flow_push(portid_t port_id, queueid_t 
queue_id);
 int port_queue_flow_pull(portid_t port_id, queueid_t queue_id);
 int port_flow_hash_calc(portid_t port_id, uint32_t table_id,
                        uint8_t pattern_template_index, const struct 
rte_flow_item pattern[]);
+int port_flow_hash_calc_encap(portid_t port_id,
+                             enum rte_flow_encap_hash_field encap_hash_field,
+                             const struct rte_flow_item pattern[]);
 void port_queue_flow_aged(portid_t port_id, uint32_t queue_id, uint8_t 
destroy);
 int port_flow_validate(portid_t port_id,
                       const struct rte_flow_attr *attr,
diff --git a/doc/guides/testpmd_app_ug/testpmd_funcs.rst 
b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
index 08a0b59535..bf48f01b0a 100644
--- a/doc/guides/testpmd_app_ug/testpmd_funcs.rst
+++ b/doc/guides/testpmd_app_ug/testpmd_funcs.rst
@@ -3297,7 +3297,7 @@ The usual error message is shown when operations results 
cannot be pulled::
 Calculating hash
 ~~~~~~~~~~~~~~~~
 
-``flow hash`` calculates the hash for a given pattern.
+``flow hash {port_id} template_table`` calculates the hash for a given pattern.
 It is bound to ``rte_flow_calc_table_hash()``::
 
    flow hash {port_id} template_table {table_id}
@@ -3316,6 +3316,25 @@ Otherwise, it will show an error message of the form::
 This command uses the same pattern items as ``flow create``,
 their format is described in `Creating flow rules`_.
 
+
+Simulate encap hash calculation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``flow hash {port_id} encap`` adds hash query, that returns the hash value
+that the HW will calculate when encapsulating a packet.
+
+   flow hash {port_id} encap {target field} pattern {item} [/ {item} [...]] / 
end
+
+If successful, it will show::
+
+   encap hash result #[...]
+
+The value will be shown as uint16_t without endian conversion.
+
+Otherwise it will show an error message of the form::
+
+   Failed to calculate encap hash - [...]
+
 Creating a tunnel stub for offload
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-- 
2.34.1

Reply via email to