patches for DPDK stable branches
 help / color / mirror / Atom feed
* [PATCH 21.11] common/cnxk: fix dual VLAN parsing
@ 2023-03-01  5:07 psatheesh
  0 siblings, 0 replies; 3+ messages in thread
From: psatheesh @ 2023-03-01  5:07 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: stable, Satheesh Paul

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: c34ea71b878d ("common/cnxk: add NPC parsing API")

[ upstream fix 474124865694177da3d4e0a60c4686c6d5ac1e56 ]

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
 drivers/common/cnxk/roc_npc.h       |  19 +++
 drivers/common/cnxk/roc_npc_parse.c | 214 +++++++++++++++++++++++-----
 drivers/common/cnxk/roc_npc_priv.h  |   6 +
 drivers/common/cnxk/roc_npc_utils.c |   2 +-
 4 files changed, 206 insertions(+), 35 deletions(-)

diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index e13d557136..1b3aadf34a 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -58,6 +58,25 @@ struct roc_npc_flow_item_raw {
 	const uint8_t *pattern; /**< Byte string to look for. */
 };
 
+struct roc_vlan_hdr {
+	uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */
+	uint16_t eth_proto; /**< Ethernet type of encapsulated frame. */
+} __plt_packed;
+
+PLT_STD_C11
+struct roc_npc_flow_item_vlan {
+	union {
+		struct {
+			uint16_t tci;	     /**< Tag control information. */
+			uint16_t inner_type; /**< Inner EtherType or TPID. */
+		};
+		struct roc_vlan_hdr hdr;
+	};
+	uint32_t has_more_vlan : 1;
+	/**< Packet header contains at least one more VLAN, after this VLAN. */
+	uint32_t reserved : 31; /**< Reserved, must be zero. */
+};
+
 #define ROC_NPC_MAX_ACTION_COUNT 19
 
 enum roc_npc_action_type {
diff --git a/drivers/common/cnxk/roc_npc_parse.c b/drivers/common/cnxk/roc_npc_parse.c
index 9742ac90f7..849fadb662 100644
--- a/drivers/common/cnxk/roc_npc_parse.c
+++ b/drivers/common/cnxk/roc_npc_parse.c
@@ -168,6 +168,184 @@ npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
 	return 0;
 }
 
+#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)
 {
@@ -179,7 +357,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;
@@ -196,41 +373,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 = pst->pattern->size;
-
-		pattern = pst->pattern;
-		while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
-			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;
-			break;
-		case 2:
-			lt = NPC_LT_LB_STAG_QINQ;
-			lflags = NPC_F_STAG_CTAG;
-			break;
-		case 3:
-			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 74e0fb2ece..54e96157cc 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -67,6 +67,11 @@
 #define NPC_ACTION_MAX_VLAN_PARAMS    3
 #define NPC_ACTION_MAX_VLANS_STRIPPED 2
 
+#define NPC_LTYPE_OFFSET_START 7
+/* LB OFFSET : START + LA (2b flags + 1b ltype) + LB (2b flags) */
+#define NPC_LTYPE_LB_OFFSET (NPC_LTYPE_OFFSET_START + 5)
+#define NPC_LFLAG_LB_OFFSET (NPC_LTYPE_OFFSET_START + 3)
+
 struct npc_action_vtag_info {
 	uint16_t vlan_id;
 	uint16_t vlan_ethtype;
@@ -402,6 +407,7 @@ int npc_update_parse_state(struct npc_parse_state *pst,
 			   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);
diff --git a/drivers/common/cnxk/roc_npc_utils.c b/drivers/common/cnxk/roc_npc_utils.c
index f971bcfd75..2f5d003b94 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] 3+ messages in thread

* Re: [PATCH 21.11] common/cnxk: fix dual VLAN parsing
  2023-03-16  4:08 psatheesh
@ 2023-03-20 16:15 ` Kevin Traynor
  0 siblings, 0 replies; 3+ messages in thread
From: Kevin Traynor @ 2023-03-20 16:15 UTC (permalink / raw)
  To: psatheesh, Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: stable

On 16/03/2023 04:08, psatheesh@marvell.com wrote:
> From: Satheesh Paul <psatheesh@marvell.com>
> 
> [ upstream fix 474124865694177da3d4e0a60c4686c6d5ac1e56 ]
> 
> 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: c34ea71b878d ("common/cnxk: add NPC parsing API")
> 
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> ---
>   drivers/common/cnxk/roc_npc.h       |  19 +++
>   drivers/common/cnxk/roc_npc_parse.c | 214 +++++++++++++++++++++++-----
>   drivers/common/cnxk/roc_npc_priv.h  |   6 +
>   drivers/common/cnxk/roc_npc_utils.c |   2 +-
>   4 files changed, 206 insertions(+), 35 deletions(-)
> 

Thanks Satheesh, pushed to 21.11 branch.
Kevin.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 21.11] common/cnxk: fix dual VLAN parsing
@ 2023-03-16  4:08 psatheesh
  2023-03-20 16:15 ` Kevin Traynor
  0 siblings, 1 reply; 3+ messages in thread
From: psatheesh @ 2023-03-16  4:08 UTC (permalink / raw)
  To: Nithin Dabilpuram, Kiran Kumar K, Sunil Kumar Kori, Satha Rao
  Cc: stable, ktraynor, Satheesh Paul

From: Satheesh Paul <psatheesh@marvell.com>

[ upstream fix 474124865694177da3d4e0a60c4686c6d5ac1e56 ]

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: c34ea71b878d ("common/cnxk: add NPC parsing API")

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
---
 drivers/common/cnxk/roc_npc.h       |  19 +++
 drivers/common/cnxk/roc_npc_parse.c | 214 +++++++++++++++++++++++-----
 drivers/common/cnxk/roc_npc_priv.h  |   6 +
 drivers/common/cnxk/roc_npc_utils.c |   2 +-
 4 files changed, 206 insertions(+), 35 deletions(-)

diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index e13d557136..1b3aadf34a 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -58,6 +58,25 @@ struct roc_npc_flow_item_raw {
 	const uint8_t *pattern; /**< Byte string to look for. */
 };
 
+struct roc_vlan_hdr {
+	uint16_t vlan_tci; /**< Priority (3) + CFI (1) + Identifier Code (12) */
+	uint16_t eth_proto; /**< Ethernet type of encapsulated frame. */
+} __plt_packed;
+
+PLT_STD_C11
+struct roc_npc_flow_item_vlan {
+	union {
+		struct {
+			uint16_t tci;	     /**< Tag control information. */
+			uint16_t inner_type; /**< Inner EtherType or TPID. */
+		};
+		struct roc_vlan_hdr hdr;
+	};
+	uint32_t has_more_vlan : 1;
+	/**< Packet header contains at least one more VLAN, after this VLAN. */
+	uint32_t reserved : 31; /**< Reserved, must be zero. */
+};
+
 #define ROC_NPC_MAX_ACTION_COUNT 19
 
 enum roc_npc_action_type {
diff --git a/drivers/common/cnxk/roc_npc_parse.c b/drivers/common/cnxk/roc_npc_parse.c
index 9742ac90f7..849fadb662 100644
--- a/drivers/common/cnxk/roc_npc_parse.c
+++ b/drivers/common/cnxk/roc_npc_parse.c
@@ -168,6 +168,184 @@ npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
 	return 0;
 }
 
+#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)
 {
@@ -179,7 +357,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;
@@ -196,41 +373,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 = pst->pattern->size;
-
-		pattern = pst->pattern;
-		while (pattern->type == ROC_NPC_ITEM_TYPE_VLAN) {
-			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;
-			break;
-		case 2:
-			lt = NPC_LT_LB_STAG_QINQ;
-			lflags = NPC_F_STAG_CTAG;
-			break;
-		case 3:
-			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 74e0fb2ece..54e96157cc 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -67,6 +67,11 @@
 #define NPC_ACTION_MAX_VLAN_PARAMS    3
 #define NPC_ACTION_MAX_VLANS_STRIPPED 2
 
+#define NPC_LTYPE_OFFSET_START 7
+/* LB OFFSET : START + LA (2b flags + 1b ltype) + LB (2b flags) */
+#define NPC_LTYPE_LB_OFFSET (NPC_LTYPE_OFFSET_START + 5)
+#define NPC_LFLAG_LB_OFFSET (NPC_LTYPE_OFFSET_START + 3)
+
 struct npc_action_vtag_info {
 	uint16_t vlan_id;
 	uint16_t vlan_ethtype;
@@ -402,6 +407,7 @@ int npc_update_parse_state(struct npc_parse_state *pst,
 			   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);
diff --git a/drivers/common/cnxk/roc_npc_utils.c b/drivers/common/cnxk/roc_npc_utils.c
index f971bcfd75..2f5d003b94 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.39.2


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-03-20 16:15 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-03-01  5:07 [PATCH 21.11] common/cnxk: fix dual VLAN parsing psatheesh
2023-03-16  4:08 psatheesh
2023-03-20 16:15 ` Kevin Traynor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).