[dpdk-dev] [PATCH v2 4/4] common/cnxk: fix dual VLAN parsing issue

Jerin Jacob jerinjacobk at gmail.com
Wed Jan 11 17:58:11 CET 2023


On Wed, Jan 11, 2023 at 11:09 AM <psatheesh at marvell.com> wrote:
>
> From: Satheesh Paul <psatheesh at marvell.com>
>
> Flow parsing was not handling pattern matching on the
> fields of inner VLAN even though MKEX profile could be
> extracting inner VLAN fields. Code has been modified
> to handle matching fields on two VLAN tags.
>
> Fixes: c34ea71b878 ("common/cnxk: add NPC parsing API")
> Cc: stable at dpdk.org
>
> Signed-off-by: Satheesh Paul <psatheesh at marvell.com>
> Reviewed-by: Kiran Kumar K <kirankumark at marvell.com>


Series applied to dpdk-next-net-mrvl/for-next-net. Thanks

> ---
>  drivers/common/cnxk/roc_npc_parse.c | 240 +++++++++++++++++++++-------
>  drivers/common/cnxk/roc_npc_priv.h  |  16 +-
>  drivers/common/cnxk/roc_npc_utils.c |   2 +-
>  3 files changed, 186 insertions(+), 72 deletions(-)
>
> diff --git a/drivers/common/cnxk/roc_npc_parse.c b/drivers/common/cnxk/roc_npc_parse.c
> index c1af5f3087..d8f9271fa8 100644
> --- a/drivers/common/cnxk/roc_npc_parse.c
> +++ b/drivers/common/cnxk/roc_npc_parse.c
> @@ -239,10 +239,185 @@ npc_parse_la(struct npc_parse_state *pst)
>
>  #define NPC_MAX_SUPPORTED_VLANS 3
>
> +static int
> +npc_parse_vlan_count(const struct roc_npc_item_info *pattern,
> +                    const struct roc_npc_item_info **pattern_list,
> +                    const struct roc_npc_flow_item_vlan **vlan_items, int *vlan_count)
> +{
> +       *vlan_count = 0;
> +       while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
> +               if (*vlan_count > NPC_MAX_SUPPORTED_VLANS - 1)
> +                       return NPC_ERR_PATTERN_NOTSUP;
> +
> +               /* Don't support ranges */
> +               if (pattern->last != NULL)
> +                       return NPC_ERR_INVALID_RANGE;
> +
> +               /* If spec is NULL, both mask and last must be NULL, this
> +                * makes it to match ANY value (eq to mask = 0).
> +                * Setting either mask or last without spec is an error
> +                */
> +               if (pattern->spec == NULL) {
> +                       if (pattern->last != NULL && pattern->mask != NULL)
> +                               return NPC_ERR_INVALID_SPEC;
> +               }
> +
> +               pattern_list[*vlan_count] = pattern;
> +               vlan_items[*vlan_count] = pattern->spec;
> +               (*vlan_count)++;
> +
> +               pattern++;
> +               pattern = npc_parse_skip_void_and_any_items(pattern);
> +       }
> +
> +       return 0;
> +}
> +
> +static int
> +npc_parse_vlan_ltype_get(struct npc_parse_state *pst,
> +                        const struct roc_npc_flow_item_vlan **vlan_item, int vlan_count,
> +                        int *ltype, int *lflags)
> +{
> +       switch (vlan_count) {
> +       case 1:
> +               *ltype = NPC_LT_LB_CTAG;
> +               if (vlan_item[0] && vlan_item[0]->has_more_vlan)
> +                       *ltype = NPC_LT_LB_STAG_QINQ;
> +               break;
> +       case 2:
> +               if (vlan_item[1] && vlan_item[1]->has_more_vlan) {
> +                       if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] &
> +                             0x3ULL << NPC_LFLAG_LB_OFFSET))
> +                               return NPC_ERR_PATTERN_NOTSUP;
> +
> +                       /* This lflag value will match either one of
> +                        * NPC_F_LB_L_WITH_STAG_STAG,
> +                        * NPC_F_LB_L_WITH_QINQ_CTAG,
> +                        * NPC_F_LB_L_WITH_QINQ_QINQ and
> +                        * NPC_F_LB_L_WITH_ITAG (0b0100 to 0b0111). For
> +                        * NPC_F_LB_L_WITH_ITAG, ltype is NPC_LT_LB_ETAG
> +                        * hence will not match.
> +                        */
> +
> +                       *lflags = NPC_F_LB_L_WITH_QINQ_CTAG & NPC_F_LB_L_WITH_QINQ_QINQ &
> +                                 NPC_F_LB_L_WITH_STAG_STAG;
> +               }
> +               *ltype = NPC_LT_LB_STAG_QINQ;
> +               break;
> +       case 3:
> +               if (vlan_item[2] && vlan_item[2]->has_more_vlan)
> +                       return NPC_ERR_PATTERN_NOTSUP;
> +               if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] & 0x3ULL << NPC_LFLAG_LB_OFFSET))
> +                       return NPC_ERR_PATTERN_NOTSUP;
> +               *ltype = NPC_LT_LB_STAG_QINQ;
> +               *lflags = NPC_F_STAG_STAG_CTAG;
> +               break;
> +       default:
> +               return NPC_ERR_PATTERN_NOTSUP;
> +       }
> +
> +       return 0;
> +}
> +
> +static int
> +npc_update_vlan_parse_state(struct npc_parse_state *pst, const struct roc_npc_item_info *pattern,
> +                           int lid, int lt, uint8_t lflags, int vlan_count)
> +{
> +       uint8_t vlan_spec[NPC_MAX_SUPPORTED_VLANS * sizeof(struct roc_vlan_hdr)];
> +       uint8_t vlan_mask[NPC_MAX_SUPPORTED_VLANS * sizeof(struct roc_vlan_hdr)];
> +       int rc = 0, i, offset = NPC_TPID_LENGTH;
> +       struct npc_parse_item_info parse_info;
> +       char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
> +
> +       memset(vlan_spec, 0, sizeof(struct roc_vlan_hdr) * NPC_MAX_SUPPORTED_VLANS);
> +       memset(vlan_mask, 0, sizeof(struct roc_vlan_hdr) * NPC_MAX_SUPPORTED_VLANS);
> +       memset(&parse_info, 0, sizeof(parse_info));
> +
> +       if (vlan_count > 2)
> +               vlan_count = 2;
> +
> +       for (i = 0; i < vlan_count; i++) {
> +               if (pattern[i].spec)
> +                       memcpy(vlan_spec + offset, pattern[i].spec, sizeof(struct roc_vlan_hdr));
> +               if (pattern[i].mask)
> +                       memcpy(vlan_mask + offset, pattern[i].mask, sizeof(struct roc_vlan_hdr));
> +
> +               offset += 4;
> +       }
> +
> +       parse_info.def_mask = NULL;
> +       parse_info.spec = vlan_spec;
> +       parse_info.mask = vlan_mask;
> +       parse_info.def_mask = NULL;
> +       parse_info.hw_hdr_len = 0;
> +
> +       lid = NPC_LID_LB;
> +       parse_info.hw_mask = hw_mask;
> +
> +       if (lt == NPC_LT_LB_CTAG)
> +               parse_info.len = sizeof(struct roc_vlan_hdr) + NPC_TPID_LENGTH;
> +
> +       if (lt == NPC_LT_LB_STAG_QINQ)
> +               parse_info.len = sizeof(struct roc_vlan_hdr) * 2 + NPC_TPID_LENGTH;
> +
> +       memset(hw_mask, 0, sizeof(hw_mask));
> +
> +       parse_info.hw_mask = &hw_mask;
> +       npc_get_hw_supp_mask(pst, &parse_info, lid, lt);
> +
> +       rc = npc_mask_is_supported(parse_info.mask, parse_info.hw_mask, parse_info.len);
> +       if (!rc)
> +               return NPC_ERR_INVALID_MASK;
> +
> +       /* Point pattern to last item consumed */
> +       pst->pattern = pattern;
> +       return npc_update_parse_state(pst, &parse_info, lid, lt, lflags);
> +}
> +
> +static int
> +npc_parse_lb_vlan(struct npc_parse_state *pst)
> +{
> +       const struct roc_npc_flow_item_vlan *vlan_items[NPC_MAX_SUPPORTED_VLANS];
> +       const struct roc_npc_item_info *pattern_list[NPC_MAX_SUPPORTED_VLANS];
> +       const struct roc_npc_item_info *last_pattern;
> +       int vlan_count = 0, rc = 0;
> +       int lid, lt, lflags;
> +
> +       lid = NPC_LID_LB;
> +       lflags = 0;
> +       last_pattern = pst->pattern;
> +
> +       rc = npc_parse_vlan_count(pst->pattern, pattern_list, vlan_items, &vlan_count);
> +       if (rc)
> +               return rc;
> +
> +       rc = npc_parse_vlan_ltype_get(pst, vlan_items, vlan_count, &lt, &lflags);
> +       if (rc)
> +               return rc;
> +
> +       if (vlan_count == 3) {
> +               if (pattern_list[2]->spec != NULL && pattern_list[2]->mask != NULL &&
> +                   pattern_list[2]->last != NULL)
> +                       return NPC_ERR_PATTERN_NOTSUP;
> +
> +               /* Matching can be done only for two tags. */
> +               vlan_count = 2;
> +               last_pattern++;
> +       }
> +
> +       rc = npc_update_vlan_parse_state(pst, pattern_list[0], lid, lt, lflags, vlan_count);
> +       if (rc)
> +               return rc;
> +
> +       if (vlan_count > 1)
> +               pst->pattern = last_pattern + vlan_count;
> +
> +       return 0;
> +}
> +
>  int
>  npc_parse_lb(struct npc_parse_state *pst)
>  {
> -       const struct roc_npc_flow_item_vlan *vlan_item[NPC_MAX_SUPPORTED_VLANS];
>         const struct roc_npc_item_info *pattern = pst->pattern;
>         const struct roc_npc_item_info *last_pattern;
>         const struct roc_npc_flow_item_raw *raw_spec;
> @@ -251,7 +426,6 @@ npc_parse_lb(struct npc_parse_state *pst)
>         char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
>         struct npc_parse_item_info info;
>         int lid, lt, lflags, len = 0;
> -       int nr_vlans = 0;
>         int rc;
>
>         info.def_mask = NULL;
> @@ -268,68 +442,10 @@ npc_parse_lb(struct npc_parse_state *pst)
>                 /* RTE vlan is either 802.1q or 802.1ad,
>                  * this maps to either CTAG/STAG. We need to decide
>                  * based on number of VLANS present. Matching is
> -                * supported on first tag only.
> +                * supported on first two tags.
>                  */
> -               info.hw_mask = NULL;
> -               info.len = sizeof(vlan_item[0]->hdr);
> -
> -               pattern = pst->pattern;
> -               while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
> -                       if (nr_vlans > NPC_MAX_SUPPORTED_VLANS - 1)
> -                               return NPC_ERR_PATTERN_NOTSUP;
> -
> -                       vlan_item[nr_vlans] = pattern->spec;
> -                       nr_vlans++;
>
> -                       /* Basic validation of Second/Third vlan item */
> -                       if (nr_vlans > 1) {
> -                               rc = npc_parse_item_basic(pattern, &info);
> -                               if (rc != 0)
> -                                       return rc;
> -                       }
> -                       last_pattern = pattern;
> -                       pattern++;
> -                       pattern = npc_parse_skip_void_and_any_items(pattern);
> -               }
> -
> -               switch (nr_vlans) {
> -               case 1:
> -                       lt = NPC_LT_LB_CTAG;
> -                       if (vlan_item[0] && vlan_item[0]->has_more_vlan)
> -                               lt = NPC_LT_LB_STAG_QINQ;
> -                       break;
> -               case 2:
> -                       if (vlan_item[1] && vlan_item[1]->has_more_vlan) {
> -                               if (!(pst->npc->keyx_supp_nmask[pst->nix_intf] &
> -                                     0x3ULL << NPC_LFLAG_LB_OFFSET))
> -                                       return NPC_ERR_PATTERN_NOTSUP;
> -
> -                               /* This lflag value will match either one of
> -                                * NPC_F_LB_L_WITH_STAG_STAG,
> -                                * NPC_F_LB_L_WITH_QINQ_CTAG,
> -                                * NPC_F_LB_L_WITH_QINQ_QINQ and
> -                                * NPC_F_LB_L_WITH_ITAG (0b0100 to 0b0111). For
> -                                * NPC_F_LB_L_WITH_ITAG, ltype is NPC_LT_LB_ETAG
> -                                * hence will not match.
> -                                */
> -
> -                               lflags = NPC_F_LB_L_WITH_QINQ_CTAG &
> -                                        NPC_F_LB_L_WITH_QINQ_QINQ &
> -                                        NPC_F_LB_L_WITH_STAG_STAG;
> -                       } else {
> -                               lflags = NPC_F_LB_L_WITH_CTAG;
> -                       }
> -                       lt = NPC_LT_LB_STAG_QINQ;
> -                       break;
> -               case 3:
> -                       if (vlan_item[2] && vlan_item[2]->has_more_vlan)
> -                               return NPC_ERR_PATTERN_NOTSUP;
> -                       lt = NPC_LT_LB_STAG_QINQ;
> -                       lflags = NPC_F_STAG_STAG_CTAG;
> -                       break;
> -               default:
> -                       return NPC_ERR_PATTERN_NOTSUP;
> -               }
> +               return npc_parse_lb_vlan(pst);
>         } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_E_TAG) {
>                 /* we can support ETAG and match a subsequent CTAG
>                  * without any matching support.
> diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
> index fe19329a7f..2a7d3137fb 100644
> --- a/drivers/common/cnxk/roc_npc_priv.h
> +++ b/drivers/common/cnxk/roc_npc_priv.h
> @@ -418,17 +418,15 @@ int npc_mcam_alloc_entry(struct npc *npc, struct roc_npc_flow *mcam,
>  int npc_mcam_alloc_entries(struct mbox *mbox, int ref_mcam, int *alloc_entry, int req_count,
>                            int prio, int *resp_count, bool is_conti);
>
> -int npc_mcam_ena_dis_entry(struct npc *npc, struct roc_npc_flow *mcam,
> -                          bool enable);
> +int npc_mcam_ena_dis_entry(struct npc *npc, struct roc_npc_flow *mcam, bool enable);
>  int npc_mcam_write_entry(struct mbox *mbox, struct roc_npc_flow *mcam);
>  int npc_flow_enable_all_entries(struct npc *npc, bool enable);
> -int npc_update_parse_state(struct npc_parse_state *pst,
> -                          struct npc_parse_item_info *info, int lid, int lt,
> -                          uint8_t flags);
> -void npc_get_hw_supp_mask(struct npc_parse_state *pst,
> -                         struct npc_parse_item_info *info, int lid, int lt);
> -int npc_parse_item_basic(const struct roc_npc_item_info *item,
> -                        struct npc_parse_item_info *info);
> +int npc_update_parse_state(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
> +                          int lt, uint8_t flags);
> +void npc_get_hw_supp_mask(struct npc_parse_state *pst, struct npc_parse_item_info *info, int lid,
> +                         int lt);
> +int npc_mask_is_supported(const char *mask, const char *hw_mask, int len);
> +int npc_parse_item_basic(const struct roc_npc_item_info *item, struct npc_parse_item_info *info);
>  int npc_parse_meta_items(struct npc_parse_state *pst);
>  int npc_parse_mark_item(struct npc_parse_state *pst);
>  int npc_parse_pre_l2(struct npc_parse_state *pst);
> diff --git a/drivers/common/cnxk/roc_npc_utils.c b/drivers/common/cnxk/roc_npc_utils.c
> index 8bdabc116d..fda3073cba 100644
> --- a/drivers/common/cnxk/roc_npc_utils.c
> +++ b/drivers/common/cnxk/roc_npc_utils.c
> @@ -88,7 +88,7 @@ npc_get_hw_supp_mask(struct npc_parse_state *pst,
>         }
>  }
>
> -static inline int
> +inline int
>  npc_mask_is_supported(const char *mask, const char *hw_mask, int len)
>  {
>         /*
> --
> 2.35.3
>


More information about the stable mailing list