* Re: [dpdk-dev] [PATCH v2 4/4] common/cnxk: fix dual VLAN parsing issue
2023-01-11 5:38 ` [dpdk-dev] [PATCH v2 4/4] common/cnxk: fix dual VLAN parsing issue psatheesh
@ 2023-01-11 16:58 ` Jerin Jacob
0 siblings, 0 replies; 2+ messages in thread
From: Jerin Jacob @ 2023-01-11 16:58 UTC (permalink / raw)
To: psatheesh
Cc: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao,
dev, stable
On Wed, Jan 11, 2023 at 11:09 AM <psatheesh@marvell.com> wrote:
>
> From: Satheesh Paul <psatheesh@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@dpdk.org
>
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> Reviewed-by: Kiran Kumar K <kirankumark@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, <, &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
>
^ permalink raw reply [flat|nested] 2+ messages in thread