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-boun...@dpdk.org] On Behalf Of Adrien Mazarguil
> Sent: Friday, March 23, 2018 8:58 PM
> To: dev@dpdk.org
> Cc: sta...@dpdk.org; Lu, Wenzhuo <wenzhuo...@intel.com>; Wu, Jingjing
> <jingjing...@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: sta...@dpdk.org
> 
> Signed-off-by: Adrien Mazarguil <adrien.mazarg...@6wind.com>
> Cc: Wenzhuo Lu <wenzhuo...@intel.com>
> Cc: Jingjing Wu <jingjing...@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

Reply via email to