diff mbox series

[1/2] common/cnxk: add support for rte flow item raw

Message ID 20210712064901.1619583-1-psatheesh@marvell.com (mailing list archive)
State Accepted, archived
Delegated to: Jerin Jacob
Headers show
Series [1/2] common/cnxk: add support for rte flow item raw | expand

Checks

Context Check Description
ci/checkpatch success coding style OK

Commit Message

Satheesh Paul July 12, 2021, 6:49 a.m. UTC
From: Satheesh Paul <psatheesh@marvell.com>

Add roc API for rte_flow_item_raw to parse custom L2 and L3 protocols.

Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
Reviewed-by: Kiran Kumar Kokkilagadda <kirankumark@marvell.com>
---
 drivers/common/cnxk/roc_mbox.h      | 24 ++++++--
 drivers/common/cnxk/roc_nix_ops.c   | 14 +++++
 drivers/common/cnxk/roc_npc.h       | 11 ++++
 drivers/common/cnxk/roc_npc_parse.c | 86 +++++++++++++++++++++++++++--
 drivers/common/cnxk/roc_npc_priv.h  |  9 +--
 drivers/common/cnxk/roc_npc_utils.c |  6 +-
 drivers/common/cnxk/roc_utils.c     |  2 +-
 7 files changed, 136 insertions(+), 16 deletions(-)

Comments

Jerin Jacob July 13, 2021, 11:18 a.m. UTC | #1
On Mon, Jul 12, 2021 at 12:19 PM <psatheesh@marvell.com> wrote:
>
> From: Satheesh Paul <psatheesh@marvell.com>
>
> Add roc API for rte_flow_item_raw to parse custom L2 and L3 protocols.
>
> Signed-off-by: Satheesh Paul <psatheesh@marvell.com>
> Reviewed-by: Kiran Kumar Kokkilagadda <kirankumark@marvell.com>


Applied to dpdk-next-net-mrvl/for-next-net. Thanks


> ---
>  drivers/common/cnxk/roc_mbox.h      | 24 ++++++--
>  drivers/common/cnxk/roc_nix_ops.c   | 14 +++++
>  drivers/common/cnxk/roc_npc.h       | 11 ++++
>  drivers/common/cnxk/roc_npc_parse.c | 86 +++++++++++++++++++++++++++--
>  drivers/common/cnxk/roc_npc_priv.h  |  9 +--
>  drivers/common/cnxk/roc_npc_utils.c |  6 +-
>  drivers/common/cnxk/roc_utils.c     |  2 +-
>  7 files changed, 136 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
> index 9c529d754..b254f005a 100644
> --- a/drivers/common/cnxk/roc_mbox.h
> +++ b/drivers/common/cnxk/roc_mbox.h
> @@ -278,14 +278,28 @@ struct ready_msg_rsp {
>         uint16_t __io rclk_freq; /* RCLK frequency */
>  };
>
> +enum npc_pkind_type {
> +       NPC_RX_VLAN_EXDSA_PKIND = 56ULL,
> +       NPC_RX_CHLEN24B_PKIND,
> +       NPC_RX_CPT_HDR_PKIND,
> +       NPC_RX_CHLEN90B_PKIND,
> +       NPC_TX_HIGIG_PKIND,
> +       NPC_RX_HIGIG_PKIND,
> +       NPC_RX_EXDSA_PKIND,
> +       NPC_RX_EDSA_PKIND,
> +       NPC_TX_DEF_PKIND,
> +};
> +
>  /* Struct to set pkind */
>  struct npc_set_pkind {
>         struct mbox_msghdr hdr;
> -#define ROC_PRIV_FLAGS_DEFAULT BIT_ULL(0)
> -#define ROC_PRIV_FLAGS_EDSA    BIT_ULL(1)
> -#define ROC_PRIV_FLAGS_HIGIG   BIT_ULL(2)
> -#define ROC_PRIV_FLAGS_LEN_90B BIT_ULL(3)
> -#define ROC_PRIV_FLAGS_CUSTOM  BIT_ULL(63)
> +#define ROC_PRIV_FLAGS_DEFAULT   BIT_ULL(0)
> +#define ROC_PRIV_FLAGS_EDSA      BIT_ULL(1)
> +#define ROC_PRIV_FLAGS_HIGIG     BIT_ULL(2)
> +#define ROC_PRIV_FLAGS_LEN_90B   BIT_ULL(3)
> +#define ROC_PRIV_FLAGS_EXDSA     BIT_ULL(4)
> +#define ROC_PRIV_FLAGS_VLAN_EXDSA BIT_ULL(5)
> +#define ROC_PRIV_FLAGS_CUSTOM    BIT_ULL(63)
>         uint64_t __io mode;
>  #define PKIND_TX BIT_ULL(0)
>  #define PKIND_RX BIT_ULL(1)
> diff --git a/drivers/common/cnxk/roc_nix_ops.c b/drivers/common/cnxk/roc_nix_ops.c
> index eeb85a54f..0e28302e7 100644
> --- a/drivers/common/cnxk/roc_nix_ops.c
> +++ b/drivers/common/cnxk/roc_nix_ops.c
> @@ -378,6 +378,8 @@ roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type)
>             switch_header_type != ROC_PRIV_FLAGS_EDSA &&
>             switch_header_type != ROC_PRIV_FLAGS_HIGIG &&
>             switch_header_type != ROC_PRIV_FLAGS_LEN_90B &&
> +           switch_header_type != ROC_PRIV_FLAGS_EXDSA &&
> +           switch_header_type != ROC_PRIV_FLAGS_VLAN_EXDSA &&
>             switch_header_type != ROC_PRIV_FLAGS_CUSTOM) {
>                 plt_err("switch header type is not supported");
>                 return NIX_ERR_PARAM;
> @@ -399,6 +401,18 @@ roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type)
>         if (req == NULL)
>                 return rc;
>         req->mode = switch_header_type;
> +
> +       if (switch_header_type == ROC_PRIV_FLAGS_LEN_90B) {
> +               req->mode = ROC_PRIV_FLAGS_CUSTOM;
> +               req->pkind = NPC_RX_CHLEN90B_PKIND;
> +       } else if (switch_header_type == ROC_PRIV_FLAGS_EXDSA) {
> +               req->mode = ROC_PRIV_FLAGS_CUSTOM;
> +               req->pkind = NPC_RX_EXDSA_PKIND;
> +       } else if (switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
> +               req->mode = ROC_PRIV_FLAGS_CUSTOM;
> +               req->pkind = NPC_RX_VLAN_EXDSA_PKIND;
> +       }
> +
>         req->dir = PKIND_RX;
>         rc = mbox_process_msg(mbox, (void *)&rsp);
>         if (rc)
> diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
> index 2c0a536c9..bab25fd72 100644
> --- a/drivers/common/cnxk/roc_npc.h
> +++ b/drivers/common/cnxk/roc_npc.h
> @@ -36,6 +36,7 @@ enum roc_npc_item_type {
>         ROC_NPC_ITEM_TYPE_CPT_HDR,
>         ROC_NPC_ITEM_TYPE_L3_CUSTOM,
>         ROC_NPC_ITEM_TYPE_QINQ,
> +       ROC_NPC_ITEM_TYPE_RAW,
>         ROC_NPC_ITEM_TYPE_END,
>  };
>
> @@ -47,6 +48,16 @@ struct roc_npc_item_info {
>         const void *last; /* For range */
>  };
>
> +struct roc_npc_flow_item_raw {
> +       uint32_t relative : 1; /**< Look for pattern after the previous item. */
> +       uint32_t search : 1;   /**< Search pattern from offset. */
> +       uint32_t reserved : 30; /**< Reserved, must be set to zero. */
> +       int32_t offset;         /**< Absolute or relative offset for pattern. */
> +       uint16_t limit;         /**< Search area limit for start of pattern. */
> +       uint16_t length;        /**< Pattern length. */
> +       const uint8_t *pattern; /**< Byte string to look for. */
> +};
> +
>  #define ROC_NPC_MAX_ACTION_COUNT 12
>
>  enum roc_npc_action_type {
> diff --git a/drivers/common/cnxk/roc_npc_parse.c b/drivers/common/cnxk/roc_npc_parse.c
> index d07f91db3..8125035dd 100644
> --- a/drivers/common/cnxk/roc_npc_parse.c
> +++ b/drivers/common/cnxk/roc_npc_parse.c
> @@ -136,14 +136,46 @@ npc_parse_la(struct npc_parse_state *pst)
>         return npc_update_parse_state(pst, &info, lid, lt, 0);
>  }
>
> +static int
> +npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
> +                         const struct roc_npc_flow_item_raw *raw_mask,
> +                         struct npc_parse_item_info *info, uint8_t *spec_buf,
> +                         uint8_t *mask_buf)
> +{
> +       uint32_t custom_hdr_size = 0;
> +
> +       memset(spec_buf, 0, NPC_MAX_RAW_ITEM_LEN);
> +       memset(mask_buf, 0, NPC_MAX_RAW_ITEM_LEN);
> +       custom_hdr_size = raw_spec->offset + raw_spec->length;
> +
> +       memcpy(spec_buf + raw_spec->offset, raw_spec->pattern,
> +              raw_spec->length);
> +
> +       if (raw_mask->pattern) {
> +               memcpy(mask_buf + raw_spec->offset, raw_mask->pattern,
> +                      raw_spec->length);
> +       } else {
> +               memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length);
> +       }
> +
> +       info->len = custom_hdr_size;
> +       info->spec = spec_buf;
> +       info->mask = mask_buf;
> +
> +       return 0;
> +}
> +
>  int
>  npc_parse_lb(struct npc_parse_state *pst)
>  {
>         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;
> +       uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
> +       uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
>         char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
>         struct npc_parse_item_info info;
> -       int lid, lt, lflags;
> +       int lid, lt, lflags, len = 0;
>         int nr_vlans = 0;
>         int rc;
>
> @@ -221,13 +253,35 @@ npc_parse_lb(struct npc_parse_state *pst)
>                 info.len = pst->pattern->size;
>                 lt = NPC_LT_LB_STAG_QINQ;
>                 lflags = NPC_F_STAG_CTAG;
> +       } else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) {
> +               raw_spec = pst->pattern->spec;
> +               if (raw_spec->relative)
> +                       return 0;
> +               len = raw_spec->length + raw_spec->offset;
> +               if (len > NPC_MAX_RAW_ITEM_LEN)
> +                       return -EINVAL;
> +
> +               if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
> +                       lt = NPC_LT_LB_VLAN_EXDSA;
> +               } else if (pst->npc->switch_header_type ==
> +                          ROC_PRIV_FLAGS_EXDSA) {
> +                       lt = NPC_LT_LB_EXDSA;
> +               } else {
> +                       return -EINVAL;
> +               }
> +
> +               npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
> +                                                 pst->pattern->spec,
> +                                         (const struct roc_npc_flow_item_raw *)
> +                                                 pst->pattern->mask,
> +                                         &info, raw_spec_buf, raw_mask_buf);
> +
> +               info.hw_hdr_len = 0;
>         } else {
>                 return 0;
>         }
>
>         info.hw_mask = &hw_mask;
> -       info.spec = NULL;
> -       info.mask = NULL;
>         npc_get_hw_supp_mask(pst, &info, lid, lt);
>
>         rc = npc_parse_item_basic(pst->pattern, &info);
> @@ -340,9 +394,12 @@ npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
>  int
>  npc_parse_lc(struct npc_parse_state *pst)
>  {
> +       const struct roc_npc_flow_item_raw *raw_spec;
> +       uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
> +       uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
>         uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
>         struct npc_parse_item_info info;
> -       int lid, lt;
> +       int lid, lt, len = 0;
>         int rc;
>
>         if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
> @@ -378,6 +435,26 @@ npc_parse_lc(struct npc_parse_state *pst)
>                 lt = NPC_LT_LC_CUSTOM0;
>                 info.len = pst->pattern->size;
>                 break;
> +       case ROC_NPC_ITEM_TYPE_RAW:
> +               raw_spec = pst->pattern->spec;
> +               if (!raw_spec->relative)
> +                       return 0;
> +
> +               len = raw_spec->length + raw_spec->offset;
> +               if (len > NPC_MAX_RAW_ITEM_LEN)
> +                       return -EINVAL;
> +
> +               npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
> +                                                 pst->pattern->spec,
> +                                         (const struct roc_npc_flow_item_raw *)
> +                                                 pst->pattern->mask,
> +                                         &info, raw_spec_buf, raw_mask_buf);
> +
> +               lid = NPC_LID_LC;
> +               lt = NPC_LT_LC_NGIO;
> +               info.hw_mask = &hw_mask;
> +               npc_get_hw_supp_mask(pst, &info, lid, lt);
> +               break;
>         default:
>                 /* No match at this layer */
>                 return 0;
> @@ -388,6 +465,7 @@ npc_parse_lc(struct npc_parse_state *pst)
>
>         npc_get_hw_supp_mask(pst, &info, lid, lt);
>         rc = npc_parse_item_basic(pst->pattern, &info);
> +
>         if (rc != 0)
>                 return rc;
>
> diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
> index 484c3aeb1..5b884e3fd 100644
> --- a/drivers/common/cnxk/roc_npc_priv.h
> +++ b/drivers/common/cnxk/roc_npc_priv.h
> @@ -5,10 +5,11 @@
>  #ifndef _ROC_NPC_PRIV_H_
>  #define _ROC_NPC_PRIV_H_
>
> -#define NPC_IH_LENGTH    8
> -#define NPC_TPID_LENGTH          2
> -#define NPC_HIGIG2_LENGTH 16
> -#define NPC_COUNTER_NONE  (-1)
> +#define NPC_IH_LENGTH       8
> +#define NPC_TPID_LENGTH             2
> +#define NPC_HIGIG2_LENGTH    16
> +#define NPC_MAX_RAW_ITEM_LEN 16
> +#define NPC_COUNTER_NONE     (-1)
>
>  #define NPC_RSS_GRPS 8
>
> diff --git a/drivers/common/cnxk/roc_npc_utils.c b/drivers/common/cnxk/roc_npc_utils.c
> index 5c97588e6..5fcb56c35 100644
> --- a/drivers/common/cnxk/roc_npc_utils.c
> +++ b/drivers/common/cnxk/roc_npc_utils.c
> @@ -130,7 +130,8 @@ npc_parse_item_basic(const struct roc_npc_item_info *item,
>         }
>
>         /* We have valid spec */
> -       info->spec = item->spec;
> +       if (item->type != ROC_NPC_ITEM_TYPE_RAW)
> +               info->spec = item->spec;
>
>         /* If mask is not set, use default mask, err if default mask is
>          * also NULL.
> @@ -140,7 +141,8 @@ npc_parse_item_basic(const struct roc_npc_item_info *item,
>                         return NPC_ERR_PARAM;
>                 info->mask = info->def_mask;
>         } else {
> -               info->mask = item->mask;
> +               if (item->type != ROC_NPC_ITEM_TYPE_RAW)
> +                       info->mask = item->mask;
>         }
>
>         /* mask specified must be subset of hw supported mask
> diff --git a/drivers/common/cnxk/roc_utils.c b/drivers/common/cnxk/roc_utils.c
> index 542252fe4..9cb8708a7 100644
> --- a/drivers/common/cnxk/roc_utils.c
> +++ b/drivers/common/cnxk/roc_utils.c
> @@ -113,7 +113,7 @@ roc_error_msg_get(int errorcode)
>                 err_msg = "NPC invalid spec";
>                 break;
>         case NPC_ERR_INVALID_MASK:
> -               err_msg = "NPC  invalid mask";
> +               err_msg = "NPC invalid mask";
>                 break;
>         case NPC_ERR_INVALID_KEX:
>                 err_msg = "NPC invalid key";
> --
> 2.25.4
>
diff mbox series

Patch

diff --git a/drivers/common/cnxk/roc_mbox.h b/drivers/common/cnxk/roc_mbox.h
index 9c529d754..b254f005a 100644
--- a/drivers/common/cnxk/roc_mbox.h
+++ b/drivers/common/cnxk/roc_mbox.h
@@ -278,14 +278,28 @@  struct ready_msg_rsp {
 	uint16_t __io rclk_freq; /* RCLK frequency */
 };
 
+enum npc_pkind_type {
+	NPC_RX_VLAN_EXDSA_PKIND = 56ULL,
+	NPC_RX_CHLEN24B_PKIND,
+	NPC_RX_CPT_HDR_PKIND,
+	NPC_RX_CHLEN90B_PKIND,
+	NPC_TX_HIGIG_PKIND,
+	NPC_RX_HIGIG_PKIND,
+	NPC_RX_EXDSA_PKIND,
+	NPC_RX_EDSA_PKIND,
+	NPC_TX_DEF_PKIND,
+};
+
 /* Struct to set pkind */
 struct npc_set_pkind {
 	struct mbox_msghdr hdr;
-#define ROC_PRIV_FLAGS_DEFAULT BIT_ULL(0)
-#define ROC_PRIV_FLAGS_EDSA    BIT_ULL(1)
-#define ROC_PRIV_FLAGS_HIGIG   BIT_ULL(2)
-#define ROC_PRIV_FLAGS_LEN_90B BIT_ULL(3)
-#define ROC_PRIV_FLAGS_CUSTOM  BIT_ULL(63)
+#define ROC_PRIV_FLAGS_DEFAULT	  BIT_ULL(0)
+#define ROC_PRIV_FLAGS_EDSA	  BIT_ULL(1)
+#define ROC_PRIV_FLAGS_HIGIG	  BIT_ULL(2)
+#define ROC_PRIV_FLAGS_LEN_90B	  BIT_ULL(3)
+#define ROC_PRIV_FLAGS_EXDSA	  BIT_ULL(4)
+#define ROC_PRIV_FLAGS_VLAN_EXDSA BIT_ULL(5)
+#define ROC_PRIV_FLAGS_CUSTOM	  BIT_ULL(63)
 	uint64_t __io mode;
 #define PKIND_TX BIT_ULL(0)
 #define PKIND_RX BIT_ULL(1)
diff --git a/drivers/common/cnxk/roc_nix_ops.c b/drivers/common/cnxk/roc_nix_ops.c
index eeb85a54f..0e28302e7 100644
--- a/drivers/common/cnxk/roc_nix_ops.c
+++ b/drivers/common/cnxk/roc_nix_ops.c
@@ -378,6 +378,8 @@  roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type)
 	    switch_header_type != ROC_PRIV_FLAGS_EDSA &&
 	    switch_header_type != ROC_PRIV_FLAGS_HIGIG &&
 	    switch_header_type != ROC_PRIV_FLAGS_LEN_90B &&
+	    switch_header_type != ROC_PRIV_FLAGS_EXDSA &&
+	    switch_header_type != ROC_PRIV_FLAGS_VLAN_EXDSA &&
 	    switch_header_type != ROC_PRIV_FLAGS_CUSTOM) {
 		plt_err("switch header type is not supported");
 		return NIX_ERR_PARAM;
@@ -399,6 +401,18 @@  roc_nix_switch_hdr_set(struct roc_nix *roc_nix, uint64_t switch_header_type)
 	if (req == NULL)
 		return rc;
 	req->mode = switch_header_type;
+
+	if (switch_header_type == ROC_PRIV_FLAGS_LEN_90B) {
+		req->mode = ROC_PRIV_FLAGS_CUSTOM;
+		req->pkind = NPC_RX_CHLEN90B_PKIND;
+	} else if (switch_header_type == ROC_PRIV_FLAGS_EXDSA) {
+		req->mode = ROC_PRIV_FLAGS_CUSTOM;
+		req->pkind = NPC_RX_EXDSA_PKIND;
+	} else if (switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
+		req->mode = ROC_PRIV_FLAGS_CUSTOM;
+		req->pkind = NPC_RX_VLAN_EXDSA_PKIND;
+	}
+
 	req->dir = PKIND_RX;
 	rc = mbox_process_msg(mbox, (void *)&rsp);
 	if (rc)
diff --git a/drivers/common/cnxk/roc_npc.h b/drivers/common/cnxk/roc_npc.h
index 2c0a536c9..bab25fd72 100644
--- a/drivers/common/cnxk/roc_npc.h
+++ b/drivers/common/cnxk/roc_npc.h
@@ -36,6 +36,7 @@  enum roc_npc_item_type {
 	ROC_NPC_ITEM_TYPE_CPT_HDR,
 	ROC_NPC_ITEM_TYPE_L3_CUSTOM,
 	ROC_NPC_ITEM_TYPE_QINQ,
+	ROC_NPC_ITEM_TYPE_RAW,
 	ROC_NPC_ITEM_TYPE_END,
 };
 
@@ -47,6 +48,16 @@  struct roc_npc_item_info {
 	const void *last; /* For range */
 };
 
+struct roc_npc_flow_item_raw {
+	uint32_t relative : 1; /**< Look for pattern after the previous item. */
+	uint32_t search : 1;   /**< Search pattern from offset. */
+	uint32_t reserved : 30; /**< Reserved, must be set to zero. */
+	int32_t offset;		/**< Absolute or relative offset for pattern. */
+	uint16_t limit;		/**< Search area limit for start of pattern. */
+	uint16_t length;	/**< Pattern length. */
+	const uint8_t *pattern; /**< Byte string to look for. */
+};
+
 #define ROC_NPC_MAX_ACTION_COUNT 12
 
 enum roc_npc_action_type {
diff --git a/drivers/common/cnxk/roc_npc_parse.c b/drivers/common/cnxk/roc_npc_parse.c
index d07f91db3..8125035dd 100644
--- a/drivers/common/cnxk/roc_npc_parse.c
+++ b/drivers/common/cnxk/roc_npc_parse.c
@@ -136,14 +136,46 @@  npc_parse_la(struct npc_parse_state *pst)
 	return npc_update_parse_state(pst, &info, lid, lt, 0);
 }
 
+static int
+npc_flow_raw_item_prepare(const struct roc_npc_flow_item_raw *raw_spec,
+			  const struct roc_npc_flow_item_raw *raw_mask,
+			  struct npc_parse_item_info *info, uint8_t *spec_buf,
+			  uint8_t *mask_buf)
+{
+	uint32_t custom_hdr_size = 0;
+
+	memset(spec_buf, 0, NPC_MAX_RAW_ITEM_LEN);
+	memset(mask_buf, 0, NPC_MAX_RAW_ITEM_LEN);
+	custom_hdr_size = raw_spec->offset + raw_spec->length;
+
+	memcpy(spec_buf + raw_spec->offset, raw_spec->pattern,
+	       raw_spec->length);
+
+	if (raw_mask->pattern) {
+		memcpy(mask_buf + raw_spec->offset, raw_mask->pattern,
+		       raw_spec->length);
+	} else {
+		memset(mask_buf + raw_spec->offset, 0xFF, raw_spec->length);
+	}
+
+	info->len = custom_hdr_size;
+	info->spec = spec_buf;
+	info->mask = mask_buf;
+
+	return 0;
+}
+
 int
 npc_parse_lb(struct npc_parse_state *pst)
 {
 	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;
+	uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
+	uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
 	char hw_mask[NPC_MAX_EXTRACT_HW_LEN];
 	struct npc_parse_item_info info;
-	int lid, lt, lflags;
+	int lid, lt, lflags, len = 0;
 	int nr_vlans = 0;
 	int rc;
 
@@ -221,13 +253,35 @@  npc_parse_lb(struct npc_parse_state *pst)
 		info.len = pst->pattern->size;
 		lt = NPC_LT_LB_STAG_QINQ;
 		lflags = NPC_F_STAG_CTAG;
+	} else if (pst->pattern->type == ROC_NPC_ITEM_TYPE_RAW) {
+		raw_spec = pst->pattern->spec;
+		if (raw_spec->relative)
+			return 0;
+		len = raw_spec->length + raw_spec->offset;
+		if (len > NPC_MAX_RAW_ITEM_LEN)
+			return -EINVAL;
+
+		if (pst->npc->switch_header_type == ROC_PRIV_FLAGS_VLAN_EXDSA) {
+			lt = NPC_LT_LB_VLAN_EXDSA;
+		} else if (pst->npc->switch_header_type ==
+			   ROC_PRIV_FLAGS_EXDSA) {
+			lt = NPC_LT_LB_EXDSA;
+		} else {
+			return -EINVAL;
+		}
+
+		npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
+						  pst->pattern->spec,
+					  (const struct roc_npc_flow_item_raw *)
+						  pst->pattern->mask,
+					  &info, raw_spec_buf, raw_mask_buf);
+
+		info.hw_hdr_len = 0;
 	} else {
 		return 0;
 	}
 
 	info.hw_mask = &hw_mask;
-	info.spec = NULL;
-	info.mask = NULL;
 	npc_get_hw_supp_mask(pst, &info, lid, lt);
 
 	rc = npc_parse_item_basic(pst->pattern, &info);
@@ -340,9 +394,12 @@  npc_check_lc_ip_tunnel(struct npc_parse_state *pst)
 int
 npc_parse_lc(struct npc_parse_state *pst)
 {
+	const struct roc_npc_flow_item_raw *raw_spec;
+	uint8_t raw_spec_buf[NPC_MAX_RAW_ITEM_LEN];
+	uint8_t raw_mask_buf[NPC_MAX_RAW_ITEM_LEN];
 	uint8_t hw_mask[NPC_MAX_EXTRACT_HW_LEN];
 	struct npc_parse_item_info info;
-	int lid, lt;
+	int lid, lt, len = 0;
 	int rc;
 
 	if (pst->pattern->type == ROC_NPC_ITEM_TYPE_MPLS)
@@ -378,6 +435,26 @@  npc_parse_lc(struct npc_parse_state *pst)
 		lt = NPC_LT_LC_CUSTOM0;
 		info.len = pst->pattern->size;
 		break;
+	case ROC_NPC_ITEM_TYPE_RAW:
+		raw_spec = pst->pattern->spec;
+		if (!raw_spec->relative)
+			return 0;
+
+		len = raw_spec->length + raw_spec->offset;
+		if (len > NPC_MAX_RAW_ITEM_LEN)
+			return -EINVAL;
+
+		npc_flow_raw_item_prepare((const struct roc_npc_flow_item_raw *)
+						  pst->pattern->spec,
+					  (const struct roc_npc_flow_item_raw *)
+						  pst->pattern->mask,
+					  &info, raw_spec_buf, raw_mask_buf);
+
+		lid = NPC_LID_LC;
+		lt = NPC_LT_LC_NGIO;
+		info.hw_mask = &hw_mask;
+		npc_get_hw_supp_mask(pst, &info, lid, lt);
+		break;
 	default:
 		/* No match at this layer */
 		return 0;
@@ -388,6 +465,7 @@  npc_parse_lc(struct npc_parse_state *pst)
 
 	npc_get_hw_supp_mask(pst, &info, lid, lt);
 	rc = npc_parse_item_basic(pst->pattern, &info);
+
 	if (rc != 0)
 		return rc;
 
diff --git a/drivers/common/cnxk/roc_npc_priv.h b/drivers/common/cnxk/roc_npc_priv.h
index 484c3aeb1..5b884e3fd 100644
--- a/drivers/common/cnxk/roc_npc_priv.h
+++ b/drivers/common/cnxk/roc_npc_priv.h
@@ -5,10 +5,11 @@ 
 #ifndef _ROC_NPC_PRIV_H_
 #define _ROC_NPC_PRIV_H_
 
-#define NPC_IH_LENGTH	  8
-#define NPC_TPID_LENGTH	  2
-#define NPC_HIGIG2_LENGTH 16
-#define NPC_COUNTER_NONE  (-1)
+#define NPC_IH_LENGTH	     8
+#define NPC_TPID_LENGTH	     2
+#define NPC_HIGIG2_LENGTH    16
+#define NPC_MAX_RAW_ITEM_LEN 16
+#define NPC_COUNTER_NONE     (-1)
 
 #define NPC_RSS_GRPS 8
 
diff --git a/drivers/common/cnxk/roc_npc_utils.c b/drivers/common/cnxk/roc_npc_utils.c
index 5c97588e6..5fcb56c35 100644
--- a/drivers/common/cnxk/roc_npc_utils.c
+++ b/drivers/common/cnxk/roc_npc_utils.c
@@ -130,7 +130,8 @@  npc_parse_item_basic(const struct roc_npc_item_info *item,
 	}
 
 	/* We have valid spec */
-	info->spec = item->spec;
+	if (item->type != ROC_NPC_ITEM_TYPE_RAW)
+		info->spec = item->spec;
 
 	/* If mask is not set, use default mask, err if default mask is
 	 * also NULL.
@@ -140,7 +141,8 @@  npc_parse_item_basic(const struct roc_npc_item_info *item,
 			return NPC_ERR_PARAM;
 		info->mask = info->def_mask;
 	} else {
-		info->mask = item->mask;
+		if (item->type != ROC_NPC_ITEM_TYPE_RAW)
+			info->mask = item->mask;
 	}
 
 	/* mask specified must be subset of hw supported mask
diff --git a/drivers/common/cnxk/roc_utils.c b/drivers/common/cnxk/roc_utils.c
index 542252fe4..9cb8708a7 100644
--- a/drivers/common/cnxk/roc_utils.c
+++ b/drivers/common/cnxk/roc_utils.c
@@ -113,7 +113,7 @@  roc_error_msg_get(int errorcode)
 		err_msg = "NPC invalid spec";
 		break;
 	case NPC_ERR_INVALID_MASK:
-		err_msg = "NPC  invalid mask";
+		err_msg = "NPC invalid mask";
 		break;
 	case NPC_ERR_INVALID_KEX:
 		err_msg = "NPC invalid key";