app/testpmd: fix missing RSS fields in flow action
authorAdrien Mazarguil <adrien.mazarguil@6wind.com>
Thu, 19 Apr 2018 10:07:40 +0000 (12:07 +0200)
committerFerruh Yigit <ferruh.yigit@intel.com>
Fri, 27 Apr 2018 14:54:56 +0000 (15:54 +0100)
Users cannot override the default RSS settings when entering a RSS action,
only a list of queues can be provided.

This patch enables them to set a RSS hash key and types for a flow rule.

Fixes: 05d34c6e9d2c ("app/testpmd: add queue actions to flow command")
Cc: stable@dpdk.org
Signed-off-by: Adrien Mazarguil <adrien.mazarguil@6wind.com>
Acked-by: Nelio Laranjeiro <nelio.laranjeiro@6wind.com>
Acked-by: Ferruh Yigit <ferruh.yigit@intel.com>
app/test-pmd/cmdline_flow.c
app/test-pmd/config.c
app/test-pmd/testpmd.h
doc/guides/testpmd_app_ug/testpmd_funcs.rst

index d37c5f3..fcd76b5 100644 (file)
@@ -167,6 +167,10 @@ enum index {
        ACTION_DUP,
        ACTION_DUP_INDEX,
        ACTION_RSS,
+       ACTION_RSS_TYPES,
+       ACTION_RSS_TYPE,
+       ACTION_RSS_KEY,
+       ACTION_RSS_KEY_LEN,
        ACTION_RSS_QUEUES,
        ACTION_RSS_QUEUE,
        ACTION_PF,
@@ -223,6 +227,9 @@ struct context {
 struct arg {
        uint32_t hton:1; /**< Use network byte ordering. */
        uint32_t sign:1; /**< Value is signed. */
+       uint32_t bounded:1; /**< Value is bounded. */
+       uintmax_t min; /**< Minimum value if bounded. */
+       uintmax_t max; /**< Maximum value if bounded. */
        uint32_t offset; /**< Relative offset from ctx->object. */
        uint32_t size; /**< Field size. */
        const uint8_t *mask; /**< Bit-mask to use instead of offset/size. */
@@ -329,6 +336,16 @@ struct token {
                .size = (s), \
        })
 
+/** Same as ARGS_ENTRY_ARB() with bounded values. */
+#define ARGS_ENTRY_ARB_BOUNDED(o, s, i, a) \
+       (&(const struct arg){ \
+               .bounded = 1, \
+               .min = (i), \
+               .max = (a), \
+               .offset = (o), \
+               .size = (s), \
+       })
+
 /** Same as ARGS_ENTRY() using network byte ordering. */
 #define ARGS_ENTRY_HTON(s, f) \
        (&(const struct arg){ \
@@ -635,6 +652,9 @@ static const enum index action_dup[] = {
 };
 
 static const enum index action_rss[] = {
+       ACTION_RSS_TYPES,
+       ACTION_RSS_KEY,
+       ACTION_RSS_KEY_LEN,
        ACTION_RSS_QUEUES,
        ACTION_NEXT,
        ZERO,
@@ -666,6 +686,9 @@ static int parse_vc_conf(struct context *, const struct token *,
 static int parse_vc_action_rss(struct context *, const struct token *,
                               const char *, unsigned int, void *,
                               unsigned int);
+static int parse_vc_action_rss_type(struct context *, const struct token *,
+                                   const char *, unsigned int, void *,
+                                   unsigned int);
 static int parse_vc_action_rss_queue(struct context *, const struct token *,
                                     const char *, unsigned int, void *,
                                     unsigned int);
@@ -721,6 +744,8 @@ 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);
+static int comp_vc_action_rss_type(struct context *, const struct token *,
+                                  unsigned int, char *, unsigned int);
 static int comp_vc_action_rss_queue(struct context *, const struct token *,
                                    unsigned int, char *, unsigned int);
 
@@ -1593,6 +1618,43 @@ static const struct token token_list[] = {
                .next = NEXT(action_rss),
                .call = parse_vc_action_rss,
        },
+       [ACTION_RSS_TYPES] = {
+               .name = "types",
+               .help = "RSS hash types",
+               .next = NEXT(action_rss, NEXT_ENTRY(ACTION_RSS_TYPE)),
+       },
+       [ACTION_RSS_TYPE] = {
+               .name = "{type}",
+               .help = "RSS hash type",
+               .call = parse_vc_action_rss_type,
+               .comp = comp_vc_action_rss_type,
+       },
+       [ACTION_RSS_KEY] = {
+               .name = "key",
+               .help = "RSS hash key",
+               .next = NEXT(action_rss, NEXT_ENTRY(STRING)),
+               .args = ARGS(ARGS_ENTRY_ARB
+                            (((uintptr_t)&((union action_rss_data *)0)->
+                              s.rss_conf.rss_key_len),
+                             sizeof(((struct rte_eth_rss_conf *)0)->
+                                    rss_key_len)),
+                            ARGS_ENTRY_ARB
+                            (((uintptr_t)((union action_rss_data *)0)->
+                              s.rss_key),
+                             RSS_HASH_KEY_LENGTH)),
+       },
+       [ACTION_RSS_KEY_LEN] = {
+               .name = "key_len",
+               .help = "RSS hash key length in bytes",
+               .next = NEXT(action_rss, NEXT_ENTRY(UNSIGNED)),
+               .args = ARGS(ARGS_ENTRY_ARB_BOUNDED
+                            (((uintptr_t)&((union action_rss_data *)0)->
+                              s.rss_conf.rss_key_len),
+                             sizeof(((struct rte_eth_rss_conf *)0)->
+                                    rss_key_len),
+                             0,
+                             RSS_HASH_KEY_LENGTH)),
+       },
        [ACTION_RSS_QUEUES] = {
                .name = "queues",
                .help = "queue indices to use",
@@ -2075,6 +2137,50 @@ parse_vc_action_rss(struct context *ctx, const struct token *token,
        return ret;
 }
 
+/**
+ * Parse type field for RSS action.
+ *
+ * Valid tokens are type field names and the "end" token.
+ */
+static int
+parse_vc_action_rss_type(struct context *ctx, const struct token *token,
+                         const char *str, unsigned int len,
+                         void *buf, unsigned int size)
+{
+       static const enum index next[] = NEXT_ENTRY(ACTION_RSS_TYPE);
+       union action_rss_data *action_rss_data;
+       unsigned int i;
+
+       (void)token;
+       (void)buf;
+       (void)size;
+       if (ctx->curr != ACTION_RSS_TYPE)
+               return -1;
+       if (!(ctx->objdata >> 16) && ctx->object) {
+               action_rss_data = ctx->object;
+               action_rss_data->s.rss_conf.rss_hf = 0;
+       }
+       if (!strcmp_partial("end", str, len)) {
+               ctx->objdata &= 0xffff;
+               return len;
+       }
+       for (i = 0; rss_type_table[i].str; ++i)
+               if (!strcmp_partial(rss_type_table[i].str, str, len))
+                       break;
+       if (!rss_type_table[i].str)
+               return -1;
+       ctx->objdata = 1 << 16 | (ctx->objdata & 0xffff);
+       /* Repeat token. */
+       if (ctx->next_num == RTE_DIM(ctx->next))
+               return -1;
+       ctx->next[ctx->next_num++] = next;
+       if (!ctx->object)
+               return len;
+       action_rss_data = ctx->object;
+       action_rss_data->s.rss_conf.rss_hf |= rss_type_table[i].rss_type;
+       return len;
+}
+
 /**
  * Parse queue field for RSS action.
  *
@@ -2341,6 +2447,11 @@ parse_int(struct context *ctx, const struct token *token,
                strtoumax(str, &end, 0);
        if (errno || (size_t)(end - str) != len)
                goto error;
+       if (arg->bounded &&
+           ((arg->sign && ((intmax_t)u < (intmax_t)arg->min ||
+                           (intmax_t)u > (intmax_t)arg->max)) ||
+            (!arg->sign && (u < arg->min || u > arg->max))))
+               goto error;
        if (!ctx->object)
                return len;
        if (arg->mask) {
@@ -2434,7 +2545,7 @@ parse_string(struct context *ctx, const struct token *token,
        buf = (uint8_t *)ctx->object + arg_data->offset;
        /* Output buffer is not necessarily NUL-terminated. */
        memcpy(buf, str, len);
-       memset((uint8_t *)buf + len, 0x55, size - len);
+       memset((uint8_t *)buf + len, 0x00, size - len);
        if (ctx->objmask)
                memset((uint8_t *)ctx->objmask + arg_data->offset, 0xff, len);
        return len;
@@ -2730,6 +2841,26 @@ comp_rule_id(struct context *ctx, const struct token *token,
        return i;
 }
 
+/** Complete type field for RSS action. */
+static int
+comp_vc_action_rss_type(struct context *ctx, const struct token *token,
+                       unsigned int ent, char *buf, unsigned int size)
+{
+       unsigned int i;
+
+       (void)ctx;
+       (void)token;
+       for (i = 0; rss_type_table[i].str; ++i)
+               ;
+       if (!buf)
+               return i + 1;
+       if (ent < i)
+               return snprintf(buf, size, "%s", rss_type_table[ent].str);
+       if (ent == i)
+               return snprintf(buf, size, "end");
+       return -1;
+}
+
 /** Complete queue field for RSS action. */
 static int
 comp_vc_action_rss_queue(struct context *ctx, const struct token *token,
index 401564f..0de4e35 100644 (file)
@@ -73,12 +73,7 @@ static const struct {
        },
 };
 
-struct rss_type_info {
-       char str[32];
-       uint64_t rss_type;
-};
-
-static const struct rss_type_info rss_type_table[] = {
+const struct rss_type_info rss_type_table[] = {
        { "ipv4", ETH_RSS_IPV4 },
        { "ipv4-frag", ETH_RSS_FRAG_IPV4 },
        { "ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP },
@@ -99,7 +94,12 @@ static const struct rss_type_info rss_type_table[] = {
        { "vxlan", ETH_RSS_VXLAN },
        { "geneve", ETH_RSS_GENEVE },
        { "nvgre", ETH_RSS_NVGRE },
-
+       { "ip", ETH_RSS_IP },
+       { "udp", ETH_RSS_UDP },
+       { "tcp", ETH_RSS_TCP },
+       { "sctp", ETH_RSS_SCTP },
+       { "tunnel", ETH_RSS_TUNNEL },
+       { NULL, 0 },
 };
 
 static void
@@ -1836,7 +1836,7 @@ port_rss_hash_conf_show(portid_t port_id, char rss_info[], int show_rss_key)
        }
 
        rss_conf.rss_hf = 0;
-       for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+       for (i = 0; rss_type_table[i].str; i++) {
                if (!strcmp(rss_info, rss_type_table[i].str))
                        rss_conf.rss_hf = rss_type_table[i].rss_type;
        }
@@ -1865,7 +1865,7 @@ port_rss_hash_conf_show(portid_t port_id, char rss_info[], int show_rss_key)
                return;
        }
        printf("RSS functions:\n ");
-       for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+       for (i = 0; rss_type_table[i].str; i++) {
                if (rss_hf & rss_type_table[i].rss_type)
                        printf("%s ", rss_type_table[i].str);
        }
@@ -1889,7 +1889,7 @@ port_rss_hash_key_update(portid_t port_id, char rss_type[], uint8_t *hash_key,
        rss_conf.rss_key = NULL;
        rss_conf.rss_key_len = hash_key_len;
        rss_conf.rss_hf = 0;
-       for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+       for (i = 0; rss_type_table[i].str; i++) {
                if (!strcmp(rss_type_table[i].str, rss_type))
                        rss_conf.rss_hf = rss_type_table[i].rss_type;
        }
index 98d84da..0709198 100644 (file)
@@ -79,6 +79,19 @@ struct pkt_burst_stats {
 };
 #endif
 
+/** Information for a given RSS type. */
+struct rss_type_info {
+       const char *str; /**< Type name. */
+       uint64_t rss_type; /**< Type value. */
+};
+
+/**
+ * RSS type information table.
+ *
+ * An entry with a NULL type name terminates the list.
+ */
+extern const struct rss_type_info rss_type_table[];
+
 /**
  * The data structure associated with a forwarding stream between a receive
  * port/queue and a transmit port/queue.
index a766ac7..cb6f201 100644 (file)
@@ -3406,6 +3406,14 @@ This section lists supported actions and their attributes, if any.
 
 - ``rss``: spread packets among several queues.
 
+  - ``types [{RSS hash type} [...]] end``: RSS hash types, allowed tokens
+    are the same as `set_hash_input_set`_, an empty list means none (0).
+
+  - ``key {string}``: RSS hash key, overrides ``key_len``.
+
+  - ``key_len {unsigned}``: RSS hash key length in bytes, can be used in
+    conjunction with ``key`` to pad or truncate it.
+
   - ``queues [{unsigned} [...]] end``: queue indices to use.
 
 - ``pf``: redirect packets to physical device function.