[dpdk-dev] [PATCH v1 5/9] app/testpmd: fix RSS flow action configuration
Zhao1, Wei
wei.zhao1 at intel.com
Mon May 7 08:53:57 CEST 2018
Hi, Adrien Mazarguil
Once we apply this patch ,we will meet an abnormal issue, rte_flow command will cause core dump.
If we do not apply it, this will disappear. I have check this issue, it seems there is something wrong in function
of port_flow_new() in Config.c file, core dump happen here every time.
This is find out by Peng yuan first, she will tell you how reappear this issue.
> -----Original Message-----
> From: dev [mailto:dev-bounces at dpdk.org] On Behalf Of Adrien Mazarguil
> Sent: Friday, March 23, 2018 8:58 PM
> To: dev at dpdk.org
> Cc: stable at dpdk.org; Lu, Wenzhuo <wenzhuo.lu at intel.com>; Wu, Jingjing
> <jingjing.wu at intel.com>
> Subject: [dpdk-dev] [PATCH v1 5/9] app/testpmd: fix RSS flow action
> configuration
>
> Except for a list of queues, RSS configuration (hash key and fields) cannot be
> specified from the flow command line and testpmd does not provide safe
> defaults either.
>
> In order to validate their implementation with testpmd, PMDs had to
> interpret its NULL RSS configuration parameters somehow, however this has
> never been valid to begin with.
>
> This patch makes testpmd always provide default values.
>
> Fixes: 05d34c6e9d2c ("app/testpmd: add queue actions to flow command")
> Cc: stable at dpdk.org
>
> Signed-off-by: Adrien Mazarguil <adrien.mazarguil at 6wind.com>
> Cc: Wenzhuo Lu <wenzhuo.lu at intel.com>
> Cc: Jingjing Wu <jingjing.wu at intel.com>
> ---
> app/test-pmd/cmdline_flow.c | 104 +++++++++++++++++++++++++----
> app/test-pmd/config.c | 141 +++++++++++++++++++++++++++-----------
> -
> 2 files changed, 192 insertions(+), 53 deletions(-)
>
> diff --git a/app/test-pmd/cmdline_flow.c b/app/test-pmd/cmdline_flow.c
> index c2cf415ef..890c36d8e 100644
> --- a/app/test-pmd/cmdline_flow.c
> +++ b/app/test-pmd/cmdline_flow.c
> @@ -184,13 +184,19 @@ enum index {
> #define ITEM_RAW_SIZE \
> (offsetof(struct rte_flow_item_raw, pattern) +
> ITEM_RAW_PATTERN_SIZE)
>
> -/** Number of queue[] entries in struct rte_flow_action_rss. */ -#define
> ACTION_RSS_NUM 32
> -
> -/** Storage size for struct rte_flow_action_rss including queues. */ -
> #define ACTION_RSS_SIZE \
> - (offsetof(struct rte_flow_action_rss, queue) + \
> - sizeof(*((struct rte_flow_action_rss *)0)->queue) *
> ACTION_RSS_NUM)
> +/** Maximum number of queue indices in struct rte_flow_action_rss. */
> +#define ACTION_RSS_QUEUE_NUM 32
> +
> +/** Storage for struct rte_flow_action_rss including external data. */
> +union action_rss_data {
> + struct rte_flow_action_rss conf;
> + struct {
> + uint8_t conf_data[offsetof(struct rte_flow_action_rss,
> queue)];
> + uint16_t queue[ACTION_RSS_QUEUE_NUM];
> + struct rte_eth_rss_conf rss_conf;
> + uint8_t rss_key[RSS_HASH_KEY_LENGTH];
> + } s;
> +};
>
> /** Maximum number of subsequent tokens and arguments on the stack.
> */ #define CTX_STACK_SIZE 16 @@ -316,6 +322,13 @@ struct token {
> .size = (sz), \
> })
>
> +/** Static initializer for ARGS() with arbitrary offset and size. */
> +#define ARGS_ENTRY_ARB(o, s) \
> + (&(const struct arg){ \
> + .offset = (o), \
> + .size = (s), \
> + })
> +
> /** Same as ARGS_ENTRY() using network byte ordering. */ #define
> ARGS_ENTRY_HTON(s, f) \
> (&(const struct arg){ \
> @@ -650,6 +663,9 @@ static int parse_vc_spec(struct context *, const struct
> token *,
> const char *, unsigned int, void *, unsigned int);
> static int parse_vc_conf(struct context *, const struct token *,
> const char *, unsigned int, void *, unsigned int);
> +static int parse_vc_action_rss(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);
> @@ -1573,9 +1589,9 @@ static const struct token token_list[] = {
> [ACTION_RSS] = {
> .name = "rss",
> .help = "spread packets among several queues",
> - .priv = PRIV_ACTION(RSS, ACTION_RSS_SIZE),
> + .priv = PRIV_ACTION(RSS, sizeof(union action_rss_data)),
> .next = NEXT(action_rss),
> - .call = parse_vc,
> + .call = parse_vc_action_rss,
> },
> [ACTION_RSS_QUEUES] = {
> .name = "queues",
> @@ -2004,6 +2020,64 @@ parse_vc_conf(struct context *ctx, const struct
> token *token,
> return len;
> }
>
> +/** Parse RSS action. */
> +static int
> +parse_vc_action_rss(struct context *ctx, const struct token *token,
> + const char *str, unsigned int len,
> + void *buf, unsigned int size)
> +{
> + struct buffer *out = buf;
> + struct rte_flow_action *action;
> + union action_rss_data *action_rss_data;
> + unsigned int i;
> + int ret;
> +
> + ret = parse_vc(ctx, token, str, len, buf, size);
> + if (ret < 0)
> + return ret;
> + /* Nothing else to do if there is no buffer. */
> + if (!out)
> + return ret;
> + if (!out->args.vc.actions_n)
> + return -1;
> + action = &out->args.vc.actions[out->args.vc.actions_n - 1];
> + /* Point to selected object. */
> + ctx->object = out->args.vc.data;
> + ctx->objmask = NULL;
> + /* Set up default configuration. */
> + action_rss_data = ctx->object;
> + *action_rss_data = (union action_rss_data){
> + .conf = (struct rte_flow_action_rss){
> + .rss_conf = &action_rss_data->s.rss_conf,
> + .num = RTE_MIN(nb_rxq,
> ACTION_RSS_QUEUE_NUM),
> + },
> + };
> + action_rss_data->s.rss_conf = (struct rte_eth_rss_conf){
> + .rss_key = action_rss_data->s.rss_key,
> + .rss_key_len = sizeof(action_rss_data->s.rss_key),
> + .rss_hf = rss_hf,
> + };
> + strncpy((void *)action_rss_data->s.rss_key,
> + "testpmd's default RSS hash key",
> + sizeof(action_rss_data->s.rss_key));
> + for (i = 0; i < action_rss_data->conf.num; ++i)
> + action_rss_data->conf.queue[i] = i;
> + if (!port_id_is_invalid(ctx->port, DISABLED_WARN) &&
> + ctx->port != (portid_t)RTE_PORT_ALL) {
> + if (rte_eth_dev_rss_hash_conf_get
> + (ctx->port, &action_rss_data->s.rss_conf) < 0) {
> + struct rte_eth_dev_info info;
> +
> + rte_eth_dev_info_get(ctx->port, &info);
> + action_rss_data->s.rss_conf.rss_key_len =
> + RTE_MIN(sizeof(action_rss_data->s.rss_key),
> + info.hash_key_size);
> + }
> + }
> + action->conf = &action_rss_data->conf;
> + return ret;
> +}
> +
> /**
> * Parse queue field for RSS action.
> *
> @@ -2015,6 +2089,7 @@ parse_vc_action_rss_queue(struct context *ctx,
> const struct token *token,
> void *buf, unsigned int size)
> {
> static const enum index next[] = NEXT_ENTRY(ACTION_RSS_QUEUE);
> + union action_rss_data *action_rss_data;
> int ret;
> int i;
>
> @@ -2028,9 +2103,13 @@ parse_vc_action_rss_queue(struct context *ctx,
> const struct token *token,
> ctx->objdata &= 0xffff;
> return len;
> }
> - if (i >= ACTION_RSS_NUM)
> + if (i >= ACTION_RSS_QUEUE_NUM)
> return -1;
> - if (push_args(ctx, ARGS_ENTRY(struct rte_flow_action_rss,
> queue[i])))
> + if (push_args(ctx,
> + ARGS_ENTRY_ARB(offsetof(struct rte_flow_action_rss,
> + queue) +
> + i * sizeof(action_rss_data->s.queue[i]),
> + sizeof(action_rss_data->s.queue[i]))))
> return -1;
> ret = parse_int(ctx, token, str, len, NULL, 0);
> if (ret < 0) {
> @@ -2045,7 +2124,8 @@ parse_vc_action_rss_queue(struct context *ctx,
> const struct token *token,
> ctx->next[ctx->next_num++] = next;
> if (!ctx->object)
> return len;
> - ((struct rte_flow_action_rss *)ctx->object)->num = i;
> + action_rss_data = ctx->object;
> + action_rss_data->conf.num = i;
> return len;
> }
>
> diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index
> 4bb255c62..a4b54f86a 100644
> --- a/app/test-pmd/config.c
> +++ b/app/test-pmd/config.c
> @@ -982,31 +982,52 @@ static const struct {
> MK_FLOW_ITEM(GENEVE, sizeof(struct rte_flow_item_geneve)), };
>
> -/** Compute storage space needed by item specification. */ -static void -
> flow_item_spec_size(const struct rte_flow_item *item,
> - size_t *size, size_t *pad)
> +/** Pattern item specification types. */ enum item_spec_type {
> + ITEM_SPEC,
> + ITEM_LAST,
> + ITEM_MASK,
> +};
> +
> +/** Compute storage space needed by item specification and copy it. */
> +static size_t flow_item_spec_copy(void *buf, const struct rte_flow_item
> +*item,
> + enum item_spec_type type)
> {
> - if (!item->spec) {
> - *size = 0;
> + size_t size = 0;
> +
> + const void *item_spec =
> + type == ITEM_SPEC ? item->spec :
> + type == ITEM_LAST ? item->last :
> + type == ITEM_MASK ? item->mask :
> + NULL;
> +
> + if (!item_spec)
> goto empty;
> - }
> switch (item->type) {
> union {
> const struct rte_flow_item_raw *raw;
> - } spec;
> + } src;
> + union {
> + struct rte_flow_item_raw *raw;
> + } dst;
>
> case RTE_FLOW_ITEM_TYPE_RAW:
> - spec.raw = item->spec;
> - *size = offsetof(struct rte_flow_item_raw, pattern) +
> - spec.raw->length * sizeof(*spec.raw->pattern);
> + src.raw = item_spec;
> + dst.raw = buf;
> + size = offsetof(struct rte_flow_item_raw, pattern) +
> + src.raw->length * sizeof(*src.raw->pattern);
> + if (dst.raw)
> + memcpy(dst.raw, src.raw, size);
> break;
> default:
> - *size = flow_item[item->type].size;
> + size = flow_item[item->type].size;
> + if (buf)
> + memcpy(buf, item_spec, size);
> break;
> }
> empty:
> - *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size;
> + return RTE_ALIGN_CEIL(size, sizeof(double));
> }
>
> /** Generate flow_action[] entry. */
> @@ -1036,31 +1057,72 @@ static const struct {
> MK_FLOW_ACTION(METER, sizeof(struct
> rte_flow_action_meter)), };
>
> -/** Compute storage space needed by action configuration. */ -static void -
> flow_action_conf_size(const struct rte_flow_action *action,
> - size_t *size, size_t *pad)
> +/** Compute storage space needed by action configuration and copy it.
> +*/ static size_t flow_action_conf_copy(void *buf, const struct
> +rte_flow_action *action)
> {
> - if (!action->conf) {
> - *size = 0;
> + size_t size = 0;
> +
> + if (!action->conf)
> goto empty;
> - }
> switch (action->type) {
> union {
> const struct rte_flow_action_rss *rss;
> - } conf;
> + } src;
> + union {
> + struct rte_flow_action_rss *rss;
> + } dst;
> + size_t off;
>
> case RTE_FLOW_ACTION_TYPE_RSS:
> - conf.rss = action->conf;
> - *size = offsetof(struct rte_flow_action_rss, queue) +
> - conf.rss->num * sizeof(*conf.rss->queue);
> + src.rss = action->conf;
> + dst.rss = buf;
> + off = 0;
> + if (dst.rss)
> + *dst.rss = (struct rte_flow_action_rss){
> + .num = src.rss->num,
> + };
> + off += offsetof(struct rte_flow_action_rss, queue);
> + if (src.rss->num) {
> + size = sizeof(*src.rss->queue) * src.rss->num;
> + if (dst.rss)
> + memcpy(dst.rss->queue, src.rss->queue,
> size);
> + off += size;
> + }
> + off = RTE_ALIGN_CEIL(off, sizeof(double));
> + if (dst.rss) {
> + dst.rss->rss_conf = (void *)((uintptr_t)dst.rss + off);
> + *(struct rte_eth_rss_conf *)(uintptr_t)
> + dst.rss->rss_conf = (struct
> rte_eth_rss_conf){
> + .rss_key_len = src.rss->rss_conf-
> >rss_key_len,
> + .rss_hf = src.rss->rss_conf->rss_hf,
> + };
> + }
> + off += sizeof(*src.rss->rss_conf);
> + if (src.rss->rss_conf->rss_key_len) {
> + off = RTE_ALIGN_CEIL(off, sizeof(double));
> + size = sizeof(*src.rss->rss_conf->rss_key) *
> + src.rss->rss_conf->rss_key_len;
> + if (dst.rss) {
> + ((struct rte_eth_rss_conf *)(uintptr_t)
> + dst.rss->rss_conf)->rss_key =
> + (void *)((uintptr_t)dst.rss + off);
> + memcpy(dst.rss->rss_conf->rss_key,
> + src.rss->rss_conf->rss_key,
> + size);
> + }
> + off += size;
> + }
> + size = off;
> break;
> default:
> - *size = flow_action[action->type].size;
> + size = flow_action[action->type].size;
> + if (buf)
> + memcpy(buf, action->conf, size);
> break;
> }
> empty:
> - *pad = RTE_ALIGN_CEIL(*size, sizeof(double)) - *size;
> + return RTE_ALIGN_CEIL(size, sizeof(double));
> }
>
> /** Generate a port_flow entry from attributes/pattern/actions. */ @@ -
> 1073,7 +1135,6 @@ port_flow_new(const struct rte_flow_attr *attr,
> const struct rte_flow_action *action;
> struct port_flow *pf = NULL;
> size_t tmp;
> - size_t pad;
> size_t off1 = 0;
> size_t off2 = 0;
> int err = ENOTSUP;
> @@ -1091,24 +1152,23 @@ port_flow_new(const struct rte_flow_attr *attr,
> if (pf)
> dst = memcpy(pf->data + off1, item, sizeof(*item));
> off1 += sizeof(*item);
> - flow_item_spec_size(item, &tmp, &pad);
> if (item->spec) {
> if (pf)
> - dst->spec = memcpy(pf->data + off2,
> - item->spec, tmp);
> - off2 += tmp + pad;
> + dst->spec = pf->data + off2;
> + off2 += flow_item_spec_copy
> + (pf ? pf->data + off2 : NULL, item,
> ITEM_SPEC);
> }
> if (item->last) {
> if (pf)
> - dst->last = memcpy(pf->data + off2,
> - item->last, tmp);
> - off2 += tmp + pad;
> + dst->last = pf->data + off2;
> + off2 += flow_item_spec_copy
> + (pf ? pf->data + off2 : NULL, item,
> ITEM_LAST);
> }
> if (item->mask) {
> if (pf)
> - dst->mask = memcpy(pf->data + off2,
> - item->mask, tmp);
> - off2 += tmp + pad;
> + dst->mask = pf->data + off2;
> + off2 += flow_item_spec_copy
> + (pf ? pf->data + off2 : NULL, item,
> ITEM_MASK);
> }
> off2 = RTE_ALIGN_CEIL(off2, sizeof(double));
> } while ((item++)->type != RTE_FLOW_ITEM_TYPE_END); @@ -
> 1125,12 +1185,11 @@ port_flow_new(const struct rte_flow_attr *attr,
> if (pf)
> dst = memcpy(pf->data + off1, action,
> sizeof(*action));
> off1 += sizeof(*action);
> - flow_action_conf_size(action, &tmp, &pad);
> if (action->conf) {
> if (pf)
> - dst->conf = memcpy(pf->data + off2,
> - action->conf, tmp);
> - off2 += tmp + pad;
> + dst->conf = pf->data + off2;
> + off2 += flow_action_conf_copy
> + (pf ? pf->data + off2 : NULL, action);
> }
> off2 = RTE_ALIGN_CEIL(off2, sizeof(double));
> } while ((action++)->type != RTE_FLOW_ACTION_TYPE_END);
> --
> 2.11.0
More information about the dev
mailing list